我该如何在Racket中创建一种新语言?

9
我想创建一种新语言,其语法与Typed Racket相同,但执行时会做两件事:
  1. 按照Typed Racket的要求运行给定的程序
  2. 如果类型检查通过,则将输入转换为另一种语言(比如Python)。我计划编写一个从Typed Racket形式到Python语法的翻译器。
你有任何关于如何开始或指向一些框架代码的建议吗?我已经阅读了这个教程,但它主要讲述了创建新语法,而在我的情况下并不需要。
我知道如何编写Racket代码来将一种语言翻译成另一种语言,但我不知道如何同时实现上述两个功能:先将其作为另一种语言运行,然后对相同的输入进行其他操作。

1
这不完全是您想要的,但我认为它可能会有所帮助。 https://github.com/shinh/elvm 这是一种IR(中间表示)语言,可以编译成通用Lisp、Python和其他大约30种语言(其中大多数是小众语言)。而且还有一个C编译器可以输出这个IR。 - stefkin
通常在创建新语言时,步骤是将语法转换为 racket 支持的基础语言,然后 racket 将完成其余工作,但似乎你并不想在 racket 中创建新语言,所以我觉得这个问题有误导性。也许你应该研究一下 Whalesong,它更符合你的目标。 - Sylwester
1个回答

6

听起来你想要创建一个带有新的#%module-begin形式的语言。这个形式可以由阅读器插入(当你在文件顶部使用#lang ....行时),也可以由语言手动编写模块时插入。无论哪种方式,它通常与你的语言定义相关联。此宏可以完全访问整个模块的未展开语法。因此,例如这样的宏:

(provide (rename-out [-module-begin #%module-begin]))
(define-simple-macro (-module-begin body ...)
  (#%module-begin
    (writeln '(body ...))
    body ...))

我希望您能创建一种编程语言,它可以做到以下两点:

  1. 将代码体(作为s表达式)打印出来,以及

  2. 在定义该语言的#%module-begin中运行该代码体。

您可以看到如何使用这种技术两次获取程序体,并对其进行两种不同的操作。因此,让我们尝试运行此示例。首先,将上面的示例放入名为“mylang.rkt”的文件中:

#lang racket
(provide (rename-out [-module-begin #%module-begin])
         (except-out (all-from-out racket) #%module-begin))
(require syntax/parse/define)
(define-simple-macro (-module-begin body ...)
  (#%module-begin
    (writeln '(body ...))
    body ...))

现在我们可以像这样用mylang编写程序:

#lang s-exp "mylang.rkt"
(+ 1 2)

当你运行它时,你会得到类似这样的结果:

((+ 1 2))
3

首先它会输出程序文本,然后运行它。

您可以在我撰写的一篇论文中了解更多关于这个过程的内容,该论文讨论了Video语言的这个方面。您可能还会发现美丽的Racket这本书有一些你会发现有用的例子。


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