使用 Gforth 的解释器指令在单词定义中添加新行
New lines in word definition using interpreter directives of Gforth
我正在使用 Gforth 的解释器指令(非 ANS 标准)控制结构,如手册部分 5.13.4 Interpreter Directives 中所述。我基本上想使用循环词来创建一个包含文字的动态大小的词。例如,我想出了这个定义:
: foo
[ 10 ] [FOR]
1
[NEXT]
;
然而这会在 [FOR]
之后产生一个 地址对齐异常 (是的,我知道你根本不应该在 Forth 中使用 for 循环。这只是为了一个简单的例子)。
最后发现你必须把循环写成一行才能保证它们的正确执行。这样做
: foo [ 10 [FOR] ] 1 [ [NEXT] ] ;
而是按预期工作。 运行 see foo
产量:
: foo
1 1 1 1 1 1 1 1 1 1 1 ; ok
这正是我想要的。
有没有办法在单词定义中换行?我想写的词要复杂得多,为了演示我需要更好地格式化它们。
最好直接使用直接词。例如,
: ones ( n -- ) 0 ?do 1 postpone literal loop ; immediate
: foo ( -- ten ones ) [ 10 ] ones ;
与 SEE FOO
的结果与您的示例相同。使用POSTPONE
,尤其是Gforth的]] .. [[
语法,重复的代码可以随心所欲。
多行 [FOR]
需要做四件事:
使用REFILL
阅读后续行。
保存读入行,因为您需要一个一个地评估它们以保留行预期的解析行为(例如来自注释:\
)。
当您匹配终止符 [NEXT]
.
时,停止逐行阅读并循环
注意在[NEXT]
之后留下>IN,这样解释才能正常继续。
您可能仍然 运行 遇到一些代码问题,例如代码检查 SOURCE-ID
。
有关使用 REFILL 跨多行解析的示例,这里是 Gerry a recent posting from CLF 的代码:
: line, ( u1 caddr2 u2 -- u3 )
tuck here swap chars dup allot move +
;
: <text> ( "text" -- caddr u )
here 0
begin
refill
while
bl word count s" </text>" compare
while
0 >in ! source line, bl c, 1+
repeat then
;
这会收集 <text>
和 </text>
之间的所有内容,它们各占一行,就像 HERE 文档一样,同时还会添加空格。为了以简单的方式保存 [FOR]
的各个行,我建议将 0 作为标记留在数据堆栈上,然后将 SAVE-MEM
行放在它上面。
我正在使用 Gforth 的解释器指令(非 ANS 标准)控制结构,如手册部分 5.13.4 Interpreter Directives 中所述。我基本上想使用循环词来创建一个包含文字的动态大小的词。例如,我想出了这个定义:
: foo
[ 10 ] [FOR]
1
[NEXT]
;
然而这会在 [FOR]
之后产生一个 地址对齐异常 (是的,我知道你根本不应该在 Forth 中使用 for 循环。这只是为了一个简单的例子)。
最后发现你必须把循环写成一行才能保证它们的正确执行。这样做
: foo [ 10 [FOR] ] 1 [ [NEXT] ] ;
而是按预期工作。 运行 see foo
产量:
: foo
1 1 1 1 1 1 1 1 1 1 1 ; ok
这正是我想要的。
有没有办法在单词定义中换行?我想写的词要复杂得多,为了演示我需要更好地格式化它们。
最好直接使用直接词。例如,
: ones ( n -- ) 0 ?do 1 postpone literal loop ; immediate
: foo ( -- ten ones ) [ 10 ] ones ;
与 SEE FOO
的结果与您的示例相同。使用POSTPONE
,尤其是Gforth的]] .. [[
语法,重复的代码可以随心所欲。
多行 [FOR]
需要做四件事:
使用
REFILL
阅读后续行。保存读入行,因为您需要一个一个地评估它们以保留行预期的解析行为(例如来自注释:
\
)。当您匹配终止符
[NEXT]
. 时,停止逐行阅读并循环
注意在
[NEXT]
之后留下>IN,这样解释才能正常继续。
您可能仍然 运行 遇到一些代码问题,例如代码检查 SOURCE-ID
。
有关使用 REFILL 跨多行解析的示例,这里是 Gerry a recent posting from CLF 的代码:
: line, ( u1 caddr2 u2 -- u3 )
tuck here swap chars dup allot move +
;
: <text> ( "text" -- caddr u )
here 0
begin
refill
while
bl word count s" </text>" compare
while
0 >in ! source line, bl c, 1+
repeat then
;
这会收集 <text>
和 </text>
之间的所有内容,它们各占一行,就像 HERE 文档一样,同时还会添加空格。为了以简单的方式保存 [FOR]
的各个行,我建议将 0 作为标记留在数据堆栈上,然后将 SAVE-MEM
行放在它上面。