PLT Redex:参数化语言定义

时间:2013-04-03 23:43:15

标签: racket formal-semantics plt-redex

这是一个一直困扰着我的问题,我想知道这里是否有人可以提供帮助。

我有一个名为lambdaLVar的PLT Redex模型,它或多或少是一个花园种类的无类型lambda演算,但扩展了包含“格子变量”或LVars的商店。 LVar是一个变量,其值只能随时间增加,其中“增加”的含义由语言用户指定的部分有序集(也称为格子)给出。因此lambdaLVar实际上是一个语言系列 - 用一个格子实例化它,你得到一种语言;有一个不同的格子,你得到另一个。您可以查看代码here;重要的是lambdaLVar.rkt

在lambdaLVar的纸上定义中,语言定义由用户指定的晶格参数化。很长一段时间,我想在Redex模型中进行相同类型的参数化,但到目前为止,我还没弄清楚如何。部分麻烦在于语言的语法取决于用户如何实例化格子:格子的元素成为语法中的终端。我不知道如何在Redex中表达语法上的抽象语法。

与此同时,我试图将lambdaLVar.rkt尽可能地模块化。该文件中定义的语言专用于特定晶格:自然数,max作为最小上限(lub)运算。 (或者,等价地,由<=排序的自然数。这是一个非常无聊的格子。)特定于该格子的代码的唯一部分是顶部附近的行(define lub-op max),{{1出现在语法中。 (有一个natural元函数是根据用户指定的lub函数定义的。后者只是一个Racket函数,因此lub-op必须转出到Racket来调用{{ 1}}。)

除非能够以对格子选择抽象的方式实际指定lambdaLVar,看起来我应该能够编写一个lambdaLVar的版本,其中最简单的格子 - 只有Bot和Top元素,其中Bot&lt; = Top - 然后使用lub添加更多内容。例如,我可以定义一种名为lambdaLVar-nats的语言,它专门用于我描述的自然格:

lub-op

然后,为了替换我对lambdaLVar的两个约简关系define-extended-language;; Grammar for elements of a lattice of natural numbers. (define-extended-language lambdaLVar-nats lambdaLVar (StoreVal .... ;; Extend the original language natural)) ;; All we have to specify is the lub operation; leq is implicitly <= (define-metafunction/extension lub lambdaLVar-nats lub-nats : d d -> d [(lub-nats d_1 d_2) ,(max (term d_1) (term d_2))]) ,我可以定义几个包装器:

slow-rr

我对fast-rr文档的理解是它应该重新解释(define nats-slow-rr (extend-reduction-relation slow-rr lambdaLVar-nats)) (define nats-fast-rr (extend-reduction-relation fast-rr lambdaLVar-nats)) extend-reduction-relation中的规则,但是使用lambdaLVar-nats。把所有这些放在一起,我尝试运行我所拥有的测试套件,其中一个是新的扩展缩减关系:

slow-rr

我得到的第一件事是合同违规投诉:fast-rr。小步长的契约行只是> (program-test-suite nats-slow-rr) ,其中small-step-base: input (((l 3)) new) at position 1 does not match its contract是一个语法非终结符,如果在lambdaLVar-nats下重新解释,则具有新含义,而不是在lambdaLVar下重新解释,因为特定的格子东西。作为一项实验,我在#:contract (small-step-base Config Config)Config上删除了合同。

然后我能够实际运行我的19个测试程序,但其中10个失败了。也许不出所料,所有失败的程序都是以某种方式使用自然数值LVars的程序。 (其余的是“纯粹的”程序,根本不与LVars的存储交互。)因此,失败的测试正是那些使用扩展语法的测试。

所以我一直跟着兔子洞,似乎Redex希望我将所有现有的判断形式和元函数扩展为与lambdaLVar-nats而不是lambdaLVar相关联。这是有道理的,据我所知,它似乎对于判断形式是可行的,但是对于元函数我遇到了麻烦:我希望新的元函数重载同名的旧元函数(因为现有的判断形式正在使用它)似乎没有办法做到这一点。如果我必须重命名元函数,它就会失败,因为无论如何我都要编写全新的判断形式。我想我想要的是一种元函数调用的后期绑定!

我的问题简而言之: Redex中是否有任何方法可以按照我想要的方式参数化语言的定义,或以某种方式扩展语言的定义我想要?我最终只需要编写生成Redex的宏吗?

感谢阅读!

1 个答案:

答案 0 :(得分:4)

我问了Racket用户邮件列表;线程开始here。总结最终的讨论:在今天的Redex中,答案是没有,没有办法以我想要的方式参数化语言定义。但是,应该在未来版本的Redex中可以使用模块系统,该模块系统现在正在使用中。

尝试使用Redex现有的扩展表单(define-extended-languageextend-reduction-relation等)并不会像我在这里尝试的那样使用它,因为 - 正如我发现的那样 - - 原始元函数不会被传递重新解释为使用扩展语言。但是模块系统显然也会对此有所帮助,因为它可以让你将元函数,判断形式和简化关系打包在一起并同时扩展它们(参见讨论here)。

所以,目前,答案确实是编写一个生成Redex的宏。这样的事情有效:

(define-syntax-rule (define-lambdaLVar-language name lub-op lattice-values ...)
  (begin
    ;; Entire original Redex model goes here, with `natural` replaced with
    ;; `lattice-values ...`, and instances of `...` replaced with `(... ...)`
))

然后你可以用例如:

来实例化特定的格子
(define-lambdaLVar-language lambdaLVar-nat max natural)

我希望Redex尽快获得模块,但与此同时,这似乎运作良好。