将 Lisp 转换为 C++
Transforming Lisp to C++
我正在研究一种基于lisp(非常小的方案子集(编译为C++的玩具语言,我正在尝试弄清楚如何表示let表达式,
(let ((var 10)
(test 12))
(+ 1 1)
var)
起初我以为执行所有 exprs 然后返回最后一个,但返回会杀死我嵌套 let 表达式的能力,表示 let 的方法是什么?
此外,任何关于源到源转换的资源都是适用的,我已经用谷歌搜索过,但我所能做的就是 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
·自从格雷格解释将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
的情况下,发出的代码看起来会有所作为喜欢这个:
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涵盖了初学者的元循环解释,以及解释器上的许多变体,以及我设法在上面混淆和破坏的字节码编译器。这只是最后两章,前三章也一样好。这是一本很棒的书。如果您还没有阅读,请绝对阅读它。
L.i.S.P包括许多用Scheme编写的解释器,一个编译器到字节码和一个编译器到C。我正在其中,可以自信地说,这是一本深刻而丰富的书,值得任何对Lisp实现感兴趣的人花时间。在这一点上它可能有点过时了,但对于像我这样的初学者来说,它仍然很有价值。不过,它比 SICP 更先进,所以要小心。它包括中间关于指称语义的一章,基本上就在我头上。
其他一些注意事项:
Darius Bacon的自托管Lisp to C编译器
λ提升,我认为马克·菲利使用了一种更高级的技术
如果您正在寻找帮助源到源翻译的工具,我推荐 ANTLR。 这是最优秀的。
但是,您需要考虑如何从松散类型语言 (lisp( 翻译成不太松散类型的语言 (c(。 例如,在您的问题中,10
的类型是什么? short
? int
? double
?
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中使用nlohmann从类到json的转换
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- 复制列表初始化的隐式转换的等级是多少
- 正在将指针转换为范围
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 是否可以从int转换为enum类类型
- 了解 GLM- openGL 中的相机转换
- 将无符号char*转换为std::istream*C++