I'm trying to write a text editor to mimic the input format of ed
. In ed
, you write your input one line at a time and finish when you input a single .
on a line. Here's what I came up with:
0 [
[ readln [ "." = not ] keep swap ] dip 1 + swap
] loop
nip 1 - narray
This snippet gets input from the user one line at a time, stops when it reaches a single dot, and returns an array of strings.
I don't get any errors when it's on its own, but as soon as I try to put it into a word:
: getinput ( -- input )
0 [
[ readln [ "." = not ] keep swap ] dip 1 + swap
] loop
nip 1 -
narray
;
I get the following error:
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 -> ]
...
I think it might be something to do with the compiler not caring about the stack declaration when it's not in a word as opposed to when it is. Is it unhappy about modifying the stack underneath loop? I know about call( )
, but if I need to use it here, how?
Edit: I also just tried the following:
:: getinput ( -- input )
0 :> count!
[ [ "." = not ] keep swap ]
[ readln count 1 + count! ] do while
drop count 1 - narray
;
I get a similar error, however the stack effects are slightly different:
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 -> ]
...
Again, fine on its own, but in a word, it doesn't compile.
Less roundabout and doesn't use locals, huzzah
! get input as array of lines
: getinput ( -- input )
{ } [
readln
! stop on .
[ "." = ] keep swap
[
drop f
] [
1array append
t
] if
] loop
;
I think the error had to do with the fact that factor has pretty strict stack effect stuff, even with simple branching.