2016-09-26 8 views
2

入力形式edを模倣するテキストエディタを作成しようとしています。 edでは、一度に1行ずつ入力し、1行に1つの.を入力すると終了します。ここに私が思い付いたものです:ループへの入力の引用が期待される効果と一致しません

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

このスニペットは時にユーザ1つのラインからの入力を取得し、それは単一のドットに達したときに停止し、文字列の配列を返します。

私はすぐに私は言葉にそれを配置しようとして、それは自分自身でいたときにすべてのエラーを取得しますが、しないでください:

: 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

少ないロータリーや地元の人々を使用していない、huzzah

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

私はエラーが要因でも、簡単な分岐で、かなり厳格なスタック効果のものを持っているという事実としなければならなかったと思います。

+1

ニースを、ちょうどスタックはローカル変数や関数の引数としてではなく、任意のデータ構造と同じ目的のために使用されていると思います。私はこの小さな調整をお勧めしたい:1) 'dup '。" = ''の代わりに ''。 =]スワップを維持する。 2) '1array append'の代わりに' {} 'と' suffix! 'の代わりに 'V {} clone'を使います。結果として配列が必要な場合は、最後に '> array'を実行することができます。この方法では、追加するたびに新しいものを割り当てることはありません。 (接尾辞と追加の違いは、突然変異の有無に関係なく適用されます)。 –

1

リスナーにコードを書き込むときにエラーが発生しない理由は、コードを最適化しないナイーブなコンパイラでコンパイルされ、スタック効果をチェックしないためです。

たとえば、リスナーではclearを実行できますが、その単語にはどのようなスタック効果がありますか?これは、データストアにあるアイテムの数によって異なります。効果が3つある場合、(x x x --)、2つの(x x --)または1つの(x --)です。試してclearを単語に入れてコンパイルしてください。最適化コンパイラはスタック効果が何であるか分かりません。

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

それは、ユーザが期間前に入力した行数に依存スタック効果です:

あなたのコードでは、同じ問題を抱えています。したがって、(-- x x x),(--)(0行)、(-- x)などとなります。表示されているエラーメッセージは完全にはっきりしていないかもしれませんが、この問題はその原因です。

あなたがループを書き換えてきた道、ファクターは静的にそのスタック効果を決定し、あなたのコードにコンパイルすることができます。また、

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

なおloopは反復を実装するための低レベルの言葉であり、あなたが必要とすることはほとんどないはずですそれを使用する。たとえば、あなたがproduceコンビネータ使用することができます

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

最適化の説明とスタック効果の確認方法をおかげされて、本当に助かります。 – user1610406

関連する問題