我该如何设计和实现一种编程语言?

12

这个问题与以下内容有关:

过去几年,我一直在思考我使用的语言喜欢和不喜欢的事情。我一直想编写自己的语言,但从未实现过。

我也拥有Lego RCX和NXT,但大多数时候我从未让我的机器人做任何事情,因为它们具有限制性的可视化编程环境。

我认为我将为NXT设计我的编程语言,因为已经有了大量通用语言,而NXT为我提供了具体的问题和目标,希望能够提供一个好的沙箱来玩耍。

现在该怎么办?我从哪里开始?我需要知道什么?

如果可能,我会使用Python或Clojure编写编译器。有一个NXT的SDK,但也有一个汇编语言。哪种方法最好/最容易?

Lego NXT拥有小屏幕,USB和蓝牙,它有4个传感器端口(数字和模拟),3个输出端口和2个ARM处理器,一个主处理器和一个协处理器。http://mindstormsnxt.blogspot.com/2006/08/whats-inside-nxt-brick.html

编程NXT将涉及处理数据和事件,因此某种单一数据流/反应式风格似乎是适当的。它还应该很好地处理并行任务,因此我考虑使用函数式编程。我目前也在考虑基于堆栈的方法。

在我的头脑中,我已经试图统一这些概念并想出示例代码。我正在考虑一个树而不是堆栈,其中函数分支可以并行运行。例如:

# implicit main stack
5 5 +
# 10

# quoted branch or list
[1 -]
# 10 [1 -]

# eval list and recur until false
loop
# [9 8 7 6 5 4 3 2 1 0]

# define stack as a function
[1 = [1 8 motor] [1 0 motor] if] fn
# [9 8 7 6 5 4 3 2 1 0] <function>

# define function as a symbol
"handle-press" def
# [9 8 7 6 5 4 3 2 1 0]

# reactively loop over infinite lazy stack returned by sensor
# in a parallel branch
|4 sensor handle-press for|
# [9 8 7 6 5 4 3 2 1 0] [8 nil nil nil 8 ...]

显然,在这个推理过程中仍然存在明显的漏洞,但我还是发布了这个草图,以引发一些有帮助的回答和讨论。

可能是重复的问题:学习编写编译器,https://dev59.com/sXRB5IYBdhLWcg3w9b19,https://dev59.com/P3RC5IYBdhLWcg3wD8tV?lq=1,https://dev59.com/KEbRa4cB1Zd3GeqPwQAn? - nawfal
4个回答

23
现在怎么办?我该从哪里开始?我需要知道什么?
首先要学习更多编程语言。
学习几种语言后,购买一本关于编译器的书。有很多选择。你可以通过谷歌来获取帮助。不过你购买哪一本并不重要。你需要阅读几本书。
当你了解了这些语言并且阅读了关于编译器的书籍后,接下来要做以下事情:
  1. 构建你需要的运行时库。使用一些适合的语言例如C或Python等实现它们。

  2. 一旦你有真正工作的运行时库。真的,完全可以工作。真的。那么你就可以考虑语法和词法分析和编译了。这些都是困难的问题,但并没有让你的运行时库工作起来那么困难。

玩弄语法(即领域特定语言)是个很诱人的干扰因素。许多人改进语法却没有可用的运行时库。所以他们的“语言”是不完整的,因为它什么也做不了。
首先让你的语言做点什么。

1
写一个自托管语言怎么样?使用主机语言的运行时呢? - Pepijn
@Pepijn:“自托管语言”?你是指像LISP或Forth这样的语言,其中语言是用它本身编写的吗?你想知道什么?也许你应该开一个新问题。首先,确定你想了解的具体事情。然后在Google上搜索这些内容。然后在这里提出问题以澄清任何令人困惑的地方。 - S.Lott
你能否对“1. 构建运行时库”进行更多的解释?在我看来,“运行时库”这个术语很广泛(可能是内置于语言中的任何东西)。你指的是哪种类型的运行时库? - Vladimir Keleshev
@Halst:“你指的是什么类型的运行时库?”运行时库可以是语言内置的任何东西。首先要做的是获得可工作的东西,稍后再调整语法。对于“可工作”,您必须选择一个主题领域、域或重点等。避免模糊地描述编程语言将要做的事情非常重要;选择一些东西——任何东西——并获得运行时支持并使其正常工作。 - S.Lott
如果不知道IR指令,就无法进行实时传输。中间表示自然而然地从CT和DT中产生。命令来自于域的概念/想法。如果你想要一种特定于领域的语言,那么机器并不是现实。不要让机器设计语言。你想让用户理解的域和概念应该成为命令。IR指令集应该尽可能接近命令,以获得最快的解释器。很抱歉我不能回答问题,因为问题已关闭。 - user985399

5
不要害怕编写编译器,它可以编译到现有语言而不是目标代码。例如,轻量级C++是一种基于此思想的C++-> C编译器(尽管在某些地方C++执行相同的工作):http://linux.wareseeker.com/Programming/lightweight-c-1.3.2.zip/331414 如果您对如何改进编程有一个小而聪明的想法,这是一种快速获胜的方法。
搜索引擎也存在类似的情况。如果我说我可以比Google做得更好,也许我可以使用Google mashup来重新组织Google的结果集,而不需要购买343个Zigabytes的存储空间来建立第二个Google,只是为了将结果数量从10个更改为15个。(不幸的是,如果我有不同的排名或爬行想法,这种方法就不起作用了。)
也许Twitter是一个更好的例子。通过使用Twitter API编写自己的Twitter。(当然,仅当您的想法适合Twitter的基本模型时。)
我们正在开发数据流引擎(参见Wikipedia:flow-based programming,dataflow programming)。我们开发了一种非常轻量级的新语言,它具有3种指令类型(组件创建,参数设置,消息声明)和2种块类型(组件声明和实现)。它被编译成C++代码,因此编译器很简单,结果非常快。此外,有几种情况下,我们的语言脚本是从配置生成的,或者更加优雅,它支持元编程。
我们应该打破1步(源->可执行文件)和0步(源脚本是可执行文件)的编译语言; 3-4级很容易概述,并且 - 如果我们做得正确 - 它可以使开发更有效。

有没有地方可以阅读关于你们的数据流引擎的内容?它是否与数字硬件相关?不管怎样,这对我来说是一个有趣的话题。 - Vladimir Keleshev
请访问homeaut.com,如有任何问题,请随时发送电子邮件。 - ern0

5
最简单的方法是使用连结式编程语言,例如ForthFactor或自己设计的编程语言。
Forth解释器非常容易实现,并且不需要占用超过几KB的空间;这对于Lego设备至关重要。您需要了解Forth解释器的工作原理。例如,在Starting Forth第9章中有介绍。

5

阅读有关语言设计的有趣书籍!

Clojure的作者推荐阅读Christian Queinnec的《lisp in small Pieces》。Clojure阅读列表涵盖了许多影响Clojure语言设计的书籍。

Clojure阅读列表


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接