2016-09-26 64 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