这是一个困扰我一段时间的问题,我想知道这里是否有人可以提供帮助。
我有一个名为 lambdaLVar 的语言的 PLT Redex 模型,它或多或少是一种普通的无类型 lambda 演算,但扩展了包含“晶格变量”或 LVars 的存储。LVar 是一个变量,其值只能随时间增加,其中“增加”的含义由语言用户指定的部分有序集合(又名格)给出。因此 lambdaLVar 实际上是一个语言家族——用一个格子实例化它,你就会得到一种语言;用不同的格子,你得到另一个。你可以看看这里的代码;重要的东西在lambdaLVar.rkt中。
在 lambdaLVar 的纸上定义中,语言定义由用户指定的格参数化。很长一段时间以来,我都想在 Redex 模型中做同样的参数化,但到目前为止,我还没有弄清楚如何做。部分麻烦在于语言的语法取决于用户如何实例化格:格的元素成为语法中的终结符。我不知道如何在 Redex 中表达一个在格上抽象的语法。
同时,我尝试使 lambdaLVar.rkt 尽可能模块化。该文件中定义的语言专门用于特定的格:自然数max
作为最小上界(lub)操作。(或者,等效地,按 . 排序的自然数<=
。这是一个非常无聊的格子。)特定于该格子的代码的唯一部分是(define lub-op max)
靠近顶部的行,并natural
出现在语法中。(有一个lub
根据用户指定的函数定义的元lub-op
函数。后者只是一个 Racket 函数,因此lub
必须转义到 Racket 才能调用lub-op
。)
除非能够以一种对晶格选择抽象的方式实际指定 lambdaLVar,否则我似乎应该能够编写一个具有最简单晶格的 lambdaLVar 版本——只有 Bot 和 Top 元素,其中Bot <= Top -- 然后define-extended-language
用来添加更多东西。例如,我可以定义一种名为 lambdaLVar-nats 的语言,它专门用于我描述的 naturals lattice:
;; 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
我为 lambdaLVar 所拥有的关系,我可以定义几个包装器:
(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
是,它应该重新解释 and 中的规则slow-rr
,fast-rr
但使用 lambdaLVar-nats。将所有这些放在一起,我尝试使用新的扩展缩减关系之一运行我拥有的测试套件:
> (program-test-suite nats-slow-rr)
我收到的第一件事是违反合同的投诉:small-step-base: input (((l 3)) new) at position 1 does not match its contract
. small-step-base 的契约线是 just #:contract (small-step-base Config Config)
,其中Config
是一个语法非终结符,如果在 lambdaLVar-nats 下重新解释比在 lambdaLVar 下重新解释,它具有新的含义,因为特定的格子的东西。作为一个实验,我摆脱了 和 的small-step-base
合同small-step-slow
。
然后我能够实际运行我的 19 个测试程序,但其中有 10 个失败了。也许不足为奇的是,所有失败的程序都是以某种方式使用自然数值 LVar 的程序。(其余的是完全不与 LVar 存储交互的“纯”程序。)因此,失败的测试正是使用扩展语法的测试。
所以我一直在跟踪兔子洞,似乎 Redex 想要我扩展所有现有的判断形式和元函数,以与 lambdaLVar-nats 而不是 lambdaLVar 相关联。这是有道理的,据我所知,它似乎对判断形式有效,但是对于元函数我遇到了麻烦:我希望新的元函数重载同名的旧元函数(因为现有的判断形式正在使用它) 并且似乎没有办法做到这一点。如果我必须重命名元函数,那就达不到目的了,因为无论如何我都必须编写全新的判断形式。我想我想要的是一种元函数调用的后期绑定!
简而言之,我的问题是: Redex 中是否有任何方法可以以我想要的方式参数化语言的定义,或者以某种方式扩展语言的定义,从而满足我的需求?我最终只需要编写生成 Redex 的宏吗?
谢谢阅读!