我很好奇r7rs中定义的方案宏的实现。很多东西含糊不清或难以理解。
首先我想知道-宏扩展器是在编译任何代码之前调用的,因此编译器看不到任何关键字吗?还是在编译时立即调用扩展器?
其次,文档说具有卫生性和参照透明性,扩展器需要本着词法作用域的精神进行make绑定。但是了解这些绑定意味着扩展器需要了解OS
和lambda
的存在,否则我会理解。这与认为编译器和扩展器需要分开,而扩展器不了解现有关键字的想法相反。
我将不胜感激。
答案 0 :(得分:3)
我的答案来自Racket,但我相信我要告诉您的内容适用于R7RS。如果我弄错了,请提前道歉。
1)宏扩展阶段通常被认为是编译器的一部分。编辑:...但这很大程度上是一个术语问题。更好的答案可能是说扩展发生在将字符序列解析为s表达式树的“读取”阶段之后,但在其余编译阶段之前。
2)您完全正确(emem),卫生需要对绑定形式有先验知识,新绑定的名称出现在(对于每种绑定形式)何处以及新名称在范围内。请记住,其他形式也可以扩展为绑定形式,一般情况下,可以通过处理卫生的方式来实现卫生。
答案 1 :(得分:1)
这些是很好的问题。多年来,我一直在思考相同的问题,而我想到的是,编译器需要在编译时就知道lambda的范围和工作原理。这不难。
另一件事是,引入了不是来自模式或宏的词法范围的绑定的每个宏扩展都应替换为唯一的东西。这样可以确保递归扩展不会互相干扰标识符。
如果您看一下DrRackets扩展,您会看到,虽然名称相同,但是它们会用颜色标记标识符,并将鼠标悬停在它们上面会显示哪个来自哪个扩展。这与重命名相同,只是多余的数据不会污染名称的外观。
关于“这些天”中最热门的编译器的精彩视频必须是2013 nanopass talk by Andy Keep。如果您查看第一步中在34:27
处生成的代码,它会重命名标识符,因此不会重复。代码是available online,我猜它缺少宏:-)
答案 2 :(得分:0)
好的... https://www.scheme.com/tspl4/syntax.html声称扩展阶段是在编译阶段之前,与编译分开,但是我一直认为这是重复的工作,要跟踪范围,我认为专家不会错,我我错过了一些东西。
因此,如果我可以确信即时进行转换会更好,那么我会做到的。
其他事情...
通过重命名,如果扩展器产生lambda
,则参数和对参数的引用是否总是被重命名(因为此时它们不被视为宏规范的词法环境的一部分)?我想我会附加%000A或类似的丑陋内容,每次都会增加。
看起来像语法规则一样,也需要define
的知识。如果存在顶级定义,并且产生对其的引用的语法扩展需要知道它是否存在于顶级范围中。如果定义是在宏transfomer定义之后发生的,我是否可以说这是语法错误?
是否需要了解Scheme语言的其他任何特殊属性,或者仅仅是lambda
和define
(我想不出一种摆脱define
的方法)。 / p>