开发动态语言


11

我已经为非常简单的语言创建了几个手写的编译器,但是现在我想尝试开发一种动态语言,类似于简化的Python或Ruby。但是,我很容易将头放在编译器的工作方式上。原始编译器只是翻译。但是如果语言是动态的,我将无法做到这一点。我必须编写一个解释器或VM,以便在运行时跟踪信息并为我做更多的工作。

简而言之,考虑到我知道编译器的工作原理,但又想迁移到创建解释器,是否应该检查任何资源?那里有一些用于动态语言的虚拟机,但是我自己开发自己的没有问题。这些全都是出于我的个人经验。

我正在寻找有关如何从编译器转到解释器的信息。如果我已经为X语言编写了编译器,但是现在要编写解释器,该做什么呢?在此过程中是否有资源?

我不希望涉及编译器或虚拟机如何工作的大量或抽象资源。我有很多关于这个主题的教科书。我在网上找到的所有资源都假设您有0位经验,因此从词法或句法分析入手,或者它们非常抽象。我有一个正在运行的编译器,但是现在我想将其转换为解释器,并为语言添加动态功能。

我找不到有关此过程的资源,它的范围可能太有限,或者解释器的“后端”中的资源没有太过理论,这就是我在此处发布的原因。


1
有很多这样的资源。注意,编译器和解释器之间的界线比您想象的要模糊得多。C#4.0编译器和其他许多编译器一样,都支持动态编程。
罗伯特·哈维

@RobertHarvey是的,我要的是获取资源来构建自己的运行时/解释器/虚拟机。.Net解释器太复杂了,我无法以此为基础!
奥斯汀·亨利


1
并检查这个SO问题,其中有一些评论还提到了其他一些非常有趣的问题...
yannis 2012年

Answers:


4

首先了解实现口译员的知识。我推荐PLAI(编程语言:应用程序和解释)。它可以很快进入解释的范畴,而无需花太多时间在语法上。

对于您的语言,您将能够重用编译器的前端(主要是解析器)和运行时库(GC,数据结构,原始操作等)。

当然,您还可以使用编译器实现动态语言,该编译器生成的代码可以处理(某些)与解释器中相同的数据结构。例如,在解释器中,您可以将全局变量实现为字符串索引的哈希表。在编译器中,您会将全局变量引用编译为使用同一表进行查找的代码。相反,您可以将词法变量编译为更有效的表示形式(“本机”参数和闭包结构引用)。


5

如果您想学习为动态语言实现解释器的基础知识,那么我无法想象有比第一种动态解释型编程语言Lisp的起源更好的起点。

约翰·麦卡锡(John McCarthy)在1960年的原始论文中定义了Lisp必需的5个原始函数。当然,麦卡锡只打算把他关于Lisp的论文作为学术活动。是一名研究生,他eval参加了集会,并创建了第一个Lisp口译员。保罗·格雷厄姆(Paul Graham)识别七个基本体:quote,atom,eq,cons,car,cdr和cond。

问题是,您真的可以使用任何语言来实现Lisp。一旦实现eval,就很容易设置REPL,并且您具有交互式解释器。人们已经无聊或好奇,以C,Java,Ruby,Python和许多其他语言来实现Lisps。并非总是故意的;记住格林斯潘的第十条规则很重要:

任何足够复杂的C或Fortran程序都包含一个临时的,非正式指定的,bug缠身的,缓慢实现的Common Lisp一半。

我并不是说您的最终目标应该是Lisp实施;但是在学习实现动态语言时,谐音有其好处;当您可以学习惯用语法与使用词法分析器/解析器的语言的AST相同的语言时,为什么还要处理语法问题?

无论如何...只是一个建议。但是有充分的理由说明,自C以来,大多数出色的编程语言至少都具有Lisp性质。


1
我希望我可以接受两个答案。谢谢,我想我真的会实现Lisp解释器。它易于解析,具有大量文档和现有代码,应该为我提供工作基础。不幸的是,我参加了一个使用Scheme的本科课程,这使我脱颖而出;)
Austin Henley 2012年

1
我现在很想将我的语言编译成我自己的Lisp方言!
奥斯汀·亨利


0

我将其(〜600行C#)放在公共域中,该域支持quote / list / apply / eval / test / etc,并允许轻松自定义类似Lisp的语法和/或语义内置函数:

https://repl.it/CdjV/3

例如:

        var factorial = (Lambda)language.
            Evaluate
            (@"
                ( => ( n ) (
                        ? ( != n 0 )
                        ( * n ( this ( - n 1 ) ) )
                        1
                    )
                )
            ");

        var sw = new System.Diagnostics.Stopwatch();
        var n = 12;
        var r = 0;
        int k;
        sw.Start();
        for (k = 0; k < 10000; k++)
        {
            r = (int)factorial.Invoke(null, n);
        }
        sw.Stop();
        Console.WriteLine("{0}! = {1}", n, r);
        Console.WriteLine();
        Console.WriteLine("in {0} ms (for {1} times)", sw.ElapsedMilliseconds, k.ToString("0,0"));

'HTH,


0

假设您了解一些Scheme(例如,已经阅读SICP)或Lisp,那么我推荐Queinnec的Lisp In Small Pieces书。它解释了类似Lisp的解释器和编译器的几种变体(包括字节码或C语言)。

另外,请阅读Scott的《编程语言实用指南》,最新的《Dragon Book》GC手册,《 Pierce的类型和编程语言》

我正在寻找有关如何从编译器转到解释器的信息。

然后,部分评估(和二村预测)和延续通过风格可能是相关的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.