输入报价到循环并不匹配预期的效果

时间:2016-09-26 22:19:02

标签: factor-lang concatenative-language

我试图编写一个文本编辑器来模仿ed的输入格式。在ed中,您一次只输入一行输入,并在输入一行.时结束。这就是我想出的:

0 [
    [ readln [ "." = not ] keep swap ] dip 1 + swap
] loop
nip 1 - narray

此片段一次从用户输入一行,当它到达单个点时停止,并返回一个字符串数组。

我自己不会有任何错误,但是一旦我试着把它写成一个字:

: getinput ( -- input )
    0 [
        [ readln [ "." = not ] keep swap ] dip 1 + swap
    ] loop
    nip 1 -
    narray
;

我收到以下错误:

The input quotation to “loop” doesn't match its expected effect
Input                            Expected         Got
[ ~quotation~ dip 1 + swap ] ( ... -- ... ? ) ( x -- x x x )
(U) Quotation: [ c-to-factor -> ]
...

我认为这可能与编译器没有关心堆栈声明有关,因为它不是一个单词而不是它的时候。修改循环下的堆栈是不是很不开心?我知道call( ),但如果我需要在这里使用它,怎么做?

编辑:我也尝试了以下内容:

:: getinput ( -- input )
    0 :> count!
    [ [ "." = not ] keep swap ]
    [ readln count 1 + count! ] do while
    drop count 1 - narray
;

我得到了类似的错误,但堆栈效果略有不同:

The input quotations to “while” don't match their expected effects
Input                                                               Expected         Got
[ ~quotation~ keep swap ]                                           ( ..a -- ..b ? ) ( x -- x x )
[ _ 1 load-locals readln 0 get-local local-value 1 + 0 get-local... ( ..b -- ..a )   ( -- x )
(U) Quotation: [ c-to-factor -> ]
...

再一次,很好,但总的来说,它没有编译。

2 个答案:

答案 0 :(得分:1)

较少的环形交叉口,不使用当地人,huzzah

! get input as array of lines
: getinput ( -- input )
    { } [
        readln
        ! stop on .
        [ "." = ] keep swap
        [
            drop f
        ] [
             1array append
             t
        ] if
    ] loop
;

我认为这个错误与因子有相当严格的堆栈效应的事实有关,即使是简单的分支。

答案 1 :(得分:1)

在侦听器中编写代码时没有遇到任何错误的原因是因为它是使用天真的编译器编译的,它不会优化代码并且不会检查堆栈效果。

例如,在监听器中,您可以运行clear但该单词具有什么堆栈效果?这取决于数据包中有多少项目!如果有三个效果为( x x x -- ),则两个( x x -- )或一个( x -- )。尝试将clear放入一个单词并进行编译。你不能因为优化编译器不知道它的堆栈效应是什么。

您的代码存在同样的问题:

0 [
    [ readln [ "." = not ] keep swap ] dip 1 + swap
] loop

它的堆叠效果取决于用户在周期之前输入的行数。因此可以是( -- x x x )( -- )(零行),( -- x )等等。它显示的错误消息可能并不完全清楚,但这个问题是它的来源。

你重写循环的方式,Factor可以静态地确定它的堆栈效果并编译你的代码:

[ readln [ "." = ] keep swap [ drop f ] [ 1array append t ] if ] infer.
( x -- x x )

另请注意,loop是实现迭代的低级词,您几乎不需要使用它。例如,您可以使用produce组合子:

[ readln dup "." = not ] [ ] produce