将Lisp转换为C ++

我正在研究一种基于lisp(非常小的方案子集)编译成C ++的玩具语言,我试图弄清楚如何表示let表达式,
(let ((var 10)
      (test 12))
  (+ 1 1)
  var)
起初我认为执行所有exprs然后返回最后一个,但是返回会杀死我的嵌套let表达式的能力,那么表示let的方法是什么? 此外,任何关于源到源转换的资源都是适用的,我已经用Google搜索了,但我所能得到的只是90分钟的方案编译器。     
已邀请:
扩展
let
的一种方法是将其视为
lambda
((lambda (var test) (+ 1 1) var) 10 12)
然后,将其转换为C ++中的函数和相应的调用:
int lambda_1(int var, int test) {
    1 + 1;
    return var;
}

lambda_1(10, 12);
所以在更大的背景下:
(display (let ((var 10)
               (test 12))
           (+ 1 1)
           var))
display(lambda_1(10, 12));
还有很多细节,例如需要从
let
中访问
let
之外的词法变量。由于C ++没有词法嵌套函数(例如,与Pascal不同),因此需要额外的实现。     
我将尝试解释一种编译嵌套的简单方法
lambda
s。自格雷格解释将
let
扩展为
lambda
非常好,我根本不会解决
let
,我会假设
let
是 派生形式或宏,并扩展为
lambda
形式 立即打电话。 将Lisp或Scheme函数直接编译为C或C ++函数 由于其他海报提出的问题,这将是棘手的。取决于 方法,得到的C或C ++将无法识别(甚至 很可读)。 在完成计算机程序的结构和解释之后,我编写了一个Lisp-to-C编译器(这是最后的练习之一,实际上我作弊,只是写了一个从SICP字节代码到C的翻译器)。它发出的C子集根本不使用C函数来处理Lisp函数。这是因为 SICP第5章中的注册机语言确实较低 比C. 假设您有某种形式的环境,它将名称绑定到值,您可以像这样定义函数调用的关键:使用绑定到参数的形式参数扩展函数定义的环境,然后评估函数的主体这个新环境中的功能。 在SICP的编译器中,环境保存在全局变量中,还有其他变量 保存函数调用的参数列表的全局变量,如 以及正在调用的过程对象(过程对象包括指向定义它的环境的指针),以及在函数返回时跳转到的标签。 请记住,当你编译一个
lambda
表达式时,那里 是你在编译时知道的两个语法组件:正式的 参数和
lambda
的主体。 编译函数时,发出的代码看起来像 这个伪代码:
some-label
*env* = definition env of *proc*
*env* = extend [formals] *argl* *env*
result of compiling [body]
...
jump *continue*
......其中
*env*
*argl*
是持有的全局变量 环境和参数列表,
extend
是一些功能(这可以 是一个适当的C ++函数),它扩展了环境
*env*
*argl*
中的名称与
[formals]
中的值配对。 然后,当运行编译的代码时,就会调用它
lambda
你的代码中的其他地方,调用约定是放置 将参数列表评估为
*argl*
变量的结果,将返回标签放在
*continue*
变量中,然后跳转到
some-label
。 在嵌套的
lambda
s的情况下,发出的代码看起来像什么 像这样:
some-label
*env* = definition env of *proc*
*env* = extend [formals-outer] *argl* *env*
another-label
*env* = definition env of *proc*
*env* = extend [formals-inner] *argl* *env*
result of compiling [body-inner]
...
jump *continue*
rest of result of compiling [body-outer]
... somewhere in here there might be a jump to another-label
jump *continue*
这有点难以解释,我确信我做得很混乱 它的工作。我想不出一个体面的例子,不涉及我基本上粗略地描述了SICP的整个第5章。由于我花时间写这个答案,我将发布它,但我很抱歉,如果它无可救药地混淆。 我强烈推荐SICP和Lisp in Small Pieces。 SICP涵盖了初学者的metacircular解释,以及解释器上的一些变体,以及我设法在上面进行混淆和修改的字节码编译器。这只是最后两章,前三章也同样出色。这是一本很棒的书。如果你还没有,那就绝对阅读它。 LiSP包括一些用Scheme编写的解释器,一个用于字节代码的编译器和一个用于C的编译器。我正处于它的中间,可以放心地说它是一本深入,丰富的书,非常值得任何对实现感兴趣的人Lisp这点可能有点过时,但对于像我这样的初学者来说,它仍然很有价值。它比SICP更先进,所以要小心。它在指称语义学中间包含了一个章节,基本上就在我的脑海中。 其他一些说明: Darius Bacon的自托管Lisp to C编译器 lambda lifting,这是我认为Marc Feeley使用的更先进的技术     
如果您正在寻找帮助进行源到源翻译的工具,我建议使用ANTLR。这是最优秀的。 但是,您需要考虑如何从松散类型的语言(lisp)转换为松散类型较少的语言(c)。例如,在你的问题中,
10
的类型是什么? A
short
int
? A
double
?     

要回复问题请先登录注册