Skip to content

Instantly share code, notes, and snippets.

@flexchar
Created December 21, 2018 06:05
Show Gist options
  • Save flexchar/ad32da588c555ffb2daec538c938617b to your computer and use it in GitHub Desktop.
Save flexchar/ad32da588c555ffb2daec538c938617b to your computer and use it in GitHub Desktop.
#lang plai
(define-type FWAE
[num (n number?)]
[add (lhs FWAE?) (rhs FWAE?)]
[sub (lhs FWAE?) (rhs FWAE?)]
[with (name symbol?) (named-expr FWAE?) (body FWAE?)]
[id (name symbol?)]
[fun (param symbol?) (body FWAE?)]
[app (fun-expr FWAE?) (arg-expr FWAE?)]
)
(define-type DefrdSub
[mtSub]
[aSub (name symbol?) (value FWAE-Value?) (ds DefrdSub?)])
(define-type FWAE-Value
[numV (n number?)]
[closureV (param symbol?)
(body FWAE?)
(ds DefrdSub?)])
; lookup: symbol defrdSub -> FWAE-Value
(define (lookup name ds)
(type-case DefrdSub ds
[mtSub () (id name)]
[aSub (bound-name bound-value rest-ds)
(if (symbol=? bound-name name)
bound-value
(lookup name rest-ds))]))
; [contract] parse: input -> FWAE
(define (parse INPUT)
(define (matcher fun-expr arg)
(match fun-expr
[(list 'fun body) (fun (first body) (parse arg) ) ]
[(list 'with body) (app (fun (first body) (parse arg)) (parse (second body)))]
[else (printf "syntax error ~a \n" fun-expr)]
)
)
; (printf "given INPUT: ~a \n \n" (list? INPUT)) ;debuging line
(match INPUT
[(? number?) (num INPUT)]
[(? symbol?) (id INPUT)]
[(list-no-order '+ b c) (add (parse b) (parse c))]
[(list-no-order '- b c) (sub (parse b) (parse c))]
[(list id _) (app (parse (first INPUT)) (parse (second INPUT)))]
[(list fun-expr ... arg) (matcher fun-expr arg)]
[else (error 'parse "bad syntax: ~a" INPUT)]
)
)
; num-op: (num num -> num) -> (FWAE FWAE -> FWAE)
(define (num-op op)
(lambda (x y)
(numV (op (numV-n x) (numV-n y)))))
(define num+ (num-op +))
(define num- (num-op -))
; [purpose] interpreters and excecutes the FWAE
(define (interp expr [ds (mtSub)])
(type-case FWAE expr
[num (n) (numV n)]
[add (l r) (num+ (interp l ds) (interp r ds))]
[sub (l r) (num- (interp l ds) (interp r ds))]
[id (v) (lookup v ds)]
[fun (bound-id bound-body) (closureV bound-id bound-body ds)]
[app (fun-expr arg-expr)
(local ([define fun-val (interp fun-expr ds)])
(interp (closureV-body fun-val)
(aSub (closureV-param fun-val)
(interp arg-expr ds)
(closureV-ds fun-val))))]
[else (error 'interp "syntax error \n")]
)
)
; [tests]
; No. 1
(test (interp (parse '(+ 5 3))) (numV 8))
(test (interp (parse '(+ (+ 1 2) 3))) (numV 6))
; No. 2
(test (parse '(fun (y) (+ x y))) (fun 'y (add (id 'x) (id 'y))))
(test (parse '( (fun (x) (+ x 7)) -7 )) (app (fun 'x (add (id 'x) (num 7))) (num -7)))
; No. 3
(test (interp (parse 'a)) (id 'a))
; No. 4
(test (interp (parse '((fun (x) (+ x 2)) 8))) (numV 10))
; No. 5
(test (interp (parse '((with (x 1) (fun (y) (- x y))) 0))) (numV 1))
; No. 6
(test (interp (app (fun 'x (add (id 'x) (num 1))) (num -1))) (numV 0))
(test (parse '(with (x 5) (fun (y) (+ x y)) ) ) (app (fun 'x (fun 'y (add (id 'x) (id 'y)))) (num 5)))
(test (parse '( ( with (x 5) (fun (y) (+ x y)) ) 1 )) (app (app (fun 'x (fun 'y (add (id 'x) (id 'y)))) (num 5)) (num 1)))
(test (interp (parse '((with (x 5) (fun (y) (with (x 2) (+ x y)))) 1))) (numV 3))
; No. 7
(test (interp (parse '((with (x 2) (fun (y) (- x y))) 1))) (numV 1))
(test (interp (parse '((with (x 1) (fun (y) (with (x 6) (- x y)))) 1))) (numV 5))
; No. 8
(test (interp (parse '((with (x 1) (fun (y) (with (x 6) (- x y)))) 1))) (numV 5))
(test (interp (app (fun 'x (add (id 'x) (num 0))) (num 0))) (numV 0))
; No. 9
(test (interp (parse '((with (x 1) (fun (y) (- x y))) 1))) (numV 0))
(test (interp (app (fun 'x (sub (id 'x) (num 0))) (num 0))) (numV 0))
; No. 10
(test (interp (parse '((with (x 1) (fun (y) (with (x 6) (- x y)))) 1))) (numV 5))
(test (interp (app (fun 'x (add (id 'x) (num 0))) (num 0))) (numV 0))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment