2

我正在尝试编写一个文本编辑器来模仿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 -> ]
...

同样,它本身很好,但总而言之,它不能编译。

4

2 回答 2

1

更少的回旋处,不使用当地人,huzzah

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

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

于 2016-09-27T01:37:52.060 回答
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
于 2016-09-30T11:57:42.683 回答