如何实现我正在编写的语言的执行?

时间:2015-11-16 01:11:37

标签: c# compiler-construction delegates stack-overflow

我正在使用C#编写自己的编程语言,只是为了好玩。它被称为SPL。它只有12个关键字/命令/指令,仅此而已。我确切地知道每个命令将要做什么。这是类图:

enter image description here

当然没有完成。但我们的想法是,我们有一个运行时ISplRuntime。命令所做的所有事情都是在运行时完成的。例如,OutputCommandISplRuntime.Current中的内容(仅object)输出到ISplRuntime.Output(这是TextWriter)。

到目前为止一切顺利。但是我需要实现IGotoCommand,就像C#中的goto关键字一样。我将制作三种类型的东西。但我无法弄清楚如何改变程序的流程。

以下是我尝试的想法:

RunNextCommand()中添加名为ISplRuntime的方法。在每个命令的Execute()方法结束时,请致电RunNextCommand。但是,如果用户编写了大量SPL代码,则堆栈跟踪将变得越来越大,从而导致堆栈溢出。

将代理人添加到ISplRuntime。每次命令执行完毕,Invoke()代表。代理将查找要执行的下一个命令,并在Execute()上调用ICommand。但我不确定这是否也会导致堆栈溢出。 是否会导致堆栈溢出?

我仍然不确定这是否是正确的方法。我只想要一个关于如何做这种事情的一般答案,因为这是我第一次写一种语言。另请告诉我使用委托是否会导致堆栈溢出。

2 个答案:

答案 0 :(得分:7)

  

我正在使用C#编写自己的编程语言,只是为了好玩。

真棒!

  

在ISplRuntime中添加一个名为RunNextCommand()的方法。在每个命令的Execute()方法结束时,调用RunNextCommand。

即使在您意识到堆叠溢出之前,您应该意识到您对RunNextCommand的描述不符合它所说的。您所描述的内容称为RunRemainderOfProgram。这表明在这个设计中出现了一些问题。

  

向ISplRuntime添加委托。每次命令执行完毕后,调用()委托。委托将查找要执行的下一个命令,并在该ICommand上调用Execute()。但我不确定这是否也会导致堆栈溢出。它会导致堆栈溢出吗?

我不明白为什么会这样。所以这里的想法是RunNextCommand作为最后一个动作设置一个委托,当被调用时,它会执行下一个命令吗?

您在此发明的内容称为延续。指令的延续是“接下来会发生什么?”目前的执行点。

  

我仍然不确定这是否是正确的方法。我只是想要一个关于如何做这种事情的一般答案,因为这是我第一次写一种语言。

有许多方法可以构建一个解释器,这基本上就是你在这里所做的。我会继续尝试,看看哪些有效,哪些无效。

研究如何在虚拟机和实际机器中解决此问题可能会有所帮助。在这些机器中,每个指令都有一个与之相关的唯一编号; “goto”包含要运行的下一条指令的编号。有一个称为“指令指针”的特殊变量,它具有当前运行指令的编号。如果当前指令是goto,则IP被设置为goto指示的值;如果不是,则IP递增到下一条指令,依此类推。然后主循环“查找当前IP的指令,执行它,设置新IP,重复”。

  

另请告诉我使用委托是否会导致堆栈溢出。

很难预测我们看不到的程序的行为,而你还没有写过。尝试一下,你会很快发现你是否写了一个无限的递归。

祝你好运!

答案 1 :(得分:3)

通常,你只需做一个循环;在循环内,在当前行执行命令,然后对所有非流控制命令增加当前行。对于goto,只需将当前行设置为参数即可。没有堆栈问题,因为流不是递归的 - 一切都是从指令循环(在给定类图的情况下属于运行时)中启动的。