循环输入的引用与预期效果不符

Input quotation to loop doesn't match expected effect

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

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

此代码段一次一行地从用户那里获取输入,当它到达一个点时停止,并且 returns 一个字符串数组。

单独使用时我没有遇到任何错误,但是当我尝试将其放入一个单词时:

: 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 -> ]
...

同样,它本身很好,但总之,它无法编译。

少迂回,不使用当地人,huzzah

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

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

在侦听器中编写代码时没有出现任何错误的原因是因为它是使用不优化代码且不检查堆栈效应的原始编译器编译的。

例如,在监听器中你可以运行 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