Clem是一种基于堆栈的最小编程语言,具有一流的功能。您的目标是为Clem语言编写一个解释器。它应正确执行参考实现中包含的所有示例,可从此处获得。
- 像往常一样,存在标准漏洞。
- 按字节数最小的条目获胜。
克莱姆语言
Clem是具有一流功能的基于堆栈的编程语言。学习Clem的最好方法是clem
不带参数地运行解释器。它将以交互模式启动,使您可以使用可用的命令进行播放。要运行示例程序,请键入clem example.clm
where example是程序的名称。这个简短的教程应该足以让您入门。
主要有两类功能。原子功能和复合功能。复合函数是由其他复合函数和原子函数组成的列表。请注意,复合函数不能包含自身。
原子功能
第一类原子函数是常数。甲恒定仅仅是一个整数值。例如-10。当解释器遇到常量时,它将其推入堆栈。clem
现在运行。键入-10
在提示符下。你应该看到
> -10
001: (-10)
>
该值001
描述了函数在堆栈中的位置,并且(-10)
是您刚刚输入的常数。现在+11
,在提示符下输入。你应该看到
> +11
002: (-10)
001: (11)
>
请注意,它(-10)
已移动到堆栈中的第二个位置,(11)
现在占据了第一个位置。这就是堆栈的本质!您会注意到这-
也是减量命令。无论何时-
或+
在数字之前,它们表示该数字的符号,而不是相应的命令。所有其他原子函数都是命令。共有14个:
@ Rotate the top three functions on the stack
# Pop the function on top of the stack and push it twice
$ Swap the top two functions on top of the stack
% Pop the function on top of the stack and throw it away
/ Pop a compound function. Split off the first function, push what's left,
then push the first function.
. Pop two functions, concatenate them and push the result
+ Pop a function. If its a constant then increment it. Push it
- Pop a function. If its a constant then decrement it. Push it
< Get a character from STDIN and push it to the stack. Pushes -1 on EOF.
> Pop a function and print its ASCII character if its a constant
c Pop a function and print its value if its a constant
w Pop a function from the stack. Peek at the top of the stack. While it is
a non-zero constant, execute the function.
在提示符下键入命令将执行该命令。键入#
在提示(重复的命令)。你应该看到
> #
003: (-10)
002: (11)
001: (11)
>
请注意(11)已被复制。现在%
,在提示符下输入(drop命令)。你应该看到
> %
002: (-10)
001: (11)
>
要将命令压入堆栈,只需将其括在括号中即可。键入(-)
在提示符下。这会将递减运算符推入堆栈。你应该看到
> (-)
003: (-10)
002: (11)
001: (-)
>
复合功能
您也可以将多个原子函数括在括号中以形成复合函数。当您在提示符下输入复合函数时,它将被推入堆栈。键入($+$)
在提示符下。你应该看到
> ($+$)
004: (-10)
003: (11)
002: (-)
001: ($ + $)
>
从技术上讲,堆栈上的所有内容都是复合函数。但是,堆栈上的某些复合函数由单个原子函数组成(在这种情况下,为方便起见,我们将它们视为原子函数)。在堆栈上操作复合函数时,.
命令(并置)通常很有用。键入.
现在。你应该看到
> .
003: (-10)
002: (11)
001: (- $ + $)
>
请注意,堆栈上的第一个功能和第二个功能已连接在一起,并且堆栈上的第二个功能在结果列表中排在第一位。要执行堆栈上的函数(无论是原子函数还是复合函数),我们必须发出w
命令(while)。w
只要堆栈上的第二个函数为非零常数,该命令就会弹出堆栈上的第一个函数并重复执行。尝试预测如果键入会发生什么w
。现在,键入w
。你应该看到
> w
002: (1)
001: (0)
>
那是您所期望的吗?坐在堆栈顶部的两个数字相加,并且它们的和仍然保留。让我们再试一次。首先,我们将键入0并将其推为10 %10
。你应该看到
> %10
002: (1)
001: (10)
>
现在,我们将一次输入整个函数,但最后将添加一个额外的函数%
以消除零。键入(-$+$)w%
在提示符下。你应该看到
> (-$+$)w%
001: (11)
>
(请注意,该算法仅在堆栈上的第一个常数为正数时有效)。
弦乐
字符串也存在。它们主要是语法糖,但可能非常有用。当解释器遇到字符串时,它将每个字符从最后到第一个压入堆栈。键入%
以删除上一个示例中的11。现在,0 10 "Hi!"
在提示符下键入。在0
将插入一个NULL终止和10
将插入新行字符。你应该看到
> 0 10 "Hi!"
005: (0)
004: (10)
003: (33)
002: (105)
001: (72)
>
键入(>)w
以从堆栈中打印字符,直到遇到NULL终止符。你应该看到
> (>)w
Hi!
001: (0)
>
结论
希望这应该足以让您开始使用口译员。语言设计应相对简单明了。让我知道是否有任何不清楚的地方:)故意遗漏了一些内容:必须对值进行签名并至少包含 16位,堆栈必须足够大以运行所有引用程序,等等。许多细节尚未确定之所以选择此处,是因为发布的完整语言规范过大(我还没有写过:P)。如有疑问,请模仿参考实现。