我有一个包含多个变体的ExprC语言,我希望能够解释seqC变体。 seqC变量返回给定表达式列表中的最后一个表达式。
(define-type ExprC
[numC (n : number)]
[idC (s : symbol)]
[plusC (left : ExprC) (right : ExprC)]
[multC (left : ExprC) (right : ExprC)]
[letC (id : symbol) (value : ExprC) (expr : ExprC)]
[appC (func : ExprC) (arg : ExprC)]
[lamC (param : symbol) (body : ExprC)]
[boxC (val : ExprC)]
[unboxC (bx : ExprC)]
[setboxC (bx : ExprC) (val : ExprC)]
[seqC (e : (listof ExprC)]
)
目前,我能够解读基本序列,例如:
(test (interp (seqC (list (numC 1) (numC 2) (numC 3))) mt-env mt-store)
(v*s (numV 3) mt-store))
然而,当我尝试更复杂的序列时,例如这个不断设置框的值的那个" x":
(test (interp {letC 'x {boxC {numC 1}} {seqC {list {setboxC {idC 'x}
{plusC {numC 2}
{unboxC {idC 'x}}}}
{setboxC {idC 'x}
{multC {numC 4}
{unboxC {idC 'x}}}}
{setboxC {idC 'x}
{plusC {numC 1}
{unboxC {idC 'x}}}}
{unboxC {idC 'x}}}}} mt-env mt-store)
(v*s (numV 13) (mem 2 (list (cell 1 (numV 13))
(cell 1 (numV 12))
(cell 1 (numV 3))
(cell 2 (boxV 1))
(cell 1 (numV 1))))))
它只评估第一个表达式并返回该值,而不是执行每个set / unbox并返回最终值。错误陈述:
(bad (interp (letC 'x (boxC (numC 1))
(seqC (list (setboxC (idC 'x) (plusC (numC 2) (unboxC (idC 'x))))
(setboxC (idC 'x) (multC (numC 4) (unboxC (idC 'x))))
(setboxC (idC 'x) (plusC (numC 1) (unboxC (idC 'x))))
(unboxC (idC 'x))))) mt-env mt-store)
//Value the interpreter is getting
(v*s (numV 3) (mem 2 (list (cell 1 (numV 3)) (cell 2 (boxV 1)) (cell 1 (numV 1)))))
//Value it should be
(v*s (numV 13) (mem 2 (list (cell 1 (numV 13)) (cell 1 (numV 12))
(cell 1 (numV 3)) (cell 2 (boxV 1)) (cell 1 (numV 1)))))
我对seqC的翻译如下:
(define (interp [expr : ExprC] [env : Env] [sto : Store]) : Result
(type-case ExprC expr
...
[seqC (m) (type-case Result (interp (firstE m) env sto)
[v*s (first-v first-s)
(cond
[(empty? (rest m)) ;no more left to be sequenced
(v*s first-v first-s)]
[(not (empty? (rest m))) ;not empty
(interp (lastE m) env first-s)])])] ;call function on next item in list
firstE和lastE只是一个基本的辅助函数,它返回给定ExprC列表中的第一个或最后一个表达式。如果您需要更多信息来理解代码,请告诉我,我可以提供/解释它。
答案 0 :(得分:2)
您的代码与您的评论不符。你说你想“在列表中的下一个项目上调用函数”,但你的代码只是直接解释最后一个元素,跳过m
中的(中间)元素,这显然是错误的。
如果你以递归的方式思考,你会发现根本不需要lastE
。在递归的每个步骤中,您将解释序列中的第一个元素。如果(rest m)
为空,那么很酷,您只需返回该值即可。否则,您可以构造一个包含seqC
的{{1}}并对其进行解释(使用新商店)。