2016-09-26 66 views
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 -> ] 
... 

再次,对自己罚款,但总而言之,它不会编译。

回答

1

少弯路,并且不使用本地人,好哇

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

我认为错误不得不做的因子有相当严格的烟囱效应的东西事实上,即使是简单的分支。

+1

不错,只是觉得该堆栈用于同样用途的本地变量和函数参数,而不是任意的数据结构。我建议这个小调整:1)'dup“。” ='而不是'[“。” =]保持交换。 2)'V {} clone'而不是'{}'和'suffix!'而不是'1array append'。如果你需要一个数组作为结果,你可以在末尾执行'> array'。这样你就不会在每个追加上分配一个新的。 (后缀和附加的区别适用于有或没有突变)。 –

1

在监听器中编写代码时没有得到任何错误的原因是因为它是用朴素的编译器编译的,它不优化代码并且不检查堆栈效果。

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

您的代码有同样的问题:

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

这是对用户的期限之前有多少行进入烟囱效应依赖。所以它可以是(-- x x x),(--)(零线),(-- x)等等。它显示的错误信息可能并不完全清楚,但这个问题是它的来源。

您已经重写循环的方式,因子可以静态地确定它的烟囱效应和编译代码:

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

还要注意loop是实现迭代一个低级别的话,你应该几乎不必使用它。例如,你可以使用produce组合子:

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

感谢您澄清优化以及如何检查堆栈效果,这确实有所帮助。 – user1610406