Можно ли реализовать в PLT-Redex выражение, подобное let *?

Недавно я начал использовать PLT-Redex, и мне интересно, может ли кто-нибудь дать мне несколько указаний о том, как реализовать выражение let *, как в Racket.

Прямо сейчас я могу писать простые выражения let вроде этого

(let (x (+ 2 4)) in (* x 2))
(let (x (+ 2 4)) in (let (y (* x 2)) in y))

Однако, если я попробую сложные выражения let, подобные приведенным ниже (см. Тест 4 и 5 в моем коде), я получу несколько выходных значений:

(let (x (+ 2 4)) in (let (y (* x 2)) in (* y y)))
(let (x (+ 2 4)) in (let (y (* x 2)) in (let (y (* x 2)) in (let (z (+ y 5)) in (+ (+ x y) z)))))

Я хотел бы переписать приведенное выше выражение так

(let* ([x (+ 2 4)]
       [y (* x 2)]
       [z (+ y 5)]
    (+ (+ x y) z))

Ниже представлена ​​моя текущая реализация Redex на случай, если кто-то захочет помочь.

Заранее спасибо Умберто

#lang racket
(require redex)

(define-language L
  (e ::=
     v
     x
     (let (x e) in e)
     (e ...)
     (aop e e))

  (v ::= number integer string boolean)
  (x  ::= variable-not-otherwise-mentioned)
  (aop ::= + - / *)

  (p (e ...))
  (P (e ... E e ...))
  
  (E ::= 
     hole
     (let (x E) in e)
     (aop E e))

);; 


(define-metafunction L
  [(subst (x_1 any_1 x_1)) any_1]
  [(subst (x_1 any_1 x_a)) x_a]

  [(subst (x any (let (x e_x) in e_body)))
   (let (x (subst (x any e_x))) in e_body)]

  [(subst (x any (let (x_a e_xa) in e_body)))
   (let (x_a  (subst (x any e_xa))) in (subst (x any e_body)))]

  [(subst (x any (aop e_1 e_2)))
   (aop (subst (x any e_1)) (subst (x any e_2)))]

  [(subst (x any v_2)) v_2]
);;

(define L-R
  (reduction-relation
   L            
   #:domain p
 
   (--> 
    (in-hole P (/ number_1 0))
    ,(error 'DivisionByZeroError)
    "error")
   
   (--> 
    (in-hole P (+ number_1 number_2))
    (in-hole P ,(+ (term number_1) (term number_2)))
    "add")
   
   (-->
    (in-hole P (* number_1 number_2))
    (in-hole P ,(* (term number_1) (term number_2)))
    "multiply")
   
   (-->
    (in-hole P (/ number_1 number_2))
    (in-hole P ,(/ (term number_1) (term number_2)))
    "divide")
   
   (--> 
    (in-hole P (- number_1 number_2))
    (in-hole P ,(- (term number_1) (term number_2)))
    "subtract")

    (-->
     (in-hole P (let (x_1 e_1) in e_2))
     (in-hole P (subst (x_1 e_1 e_2))) 
    "let")
));;;

(define (test-syntax)
  ;; Test 1
  (test-->> L-R
            (term  ((+ 2 3)))
            (term  (5)))
  
 ;; Test 2
  (test-->> L-R
            (term  ((let (x (+ 2 4)) in (* x 2))))
            (term  (12)))
  
  ;; Test 3
  (test-->> L-R
            (term  ((let (x (+ 2 4)) in (let (y (* x 2)) in y))))
            (term  (12)))
  
  ;; Test 4 ERROR
;  (test-->> L-R
;            (term  ((let (x (+ 2 4)) in (let (y (* x 2)) in (* y y)))))
;            (term  (144)))


  ;; Test 5 ERROR
;  (test-->> L-R
;            (term  ((let (x (+ 2 4)) in (let (y (* x 2)) in (let (y (* x 2)) in (let (z (+ y 5)) in (+ (+ x y) z)))))))
;            (term  (35)))


);;


(test-syntax)
(module+ test
  (test-results))

0 ответов

Другие вопросы по тегам