Stuff.
This commit is contained in:
+37
-12
@@ -7,8 +7,9 @@
|
|||||||
#| The AST:
|
#| The AST:
|
||||||
<TOY> ::= <num>
|
<TOY> ::= <num>
|
||||||
| <id>
|
| <id>
|
||||||
| { bind {{ <id> <TOY> } ... } <TOY> }
|
| { bind {{ <id> <TOY> } ... } <TOY> ... }
|
||||||
| { fun { <id> ... } <TOY> }
|
| { bindrec {{ <id> <TOY> } ... } <TOY> ... }
|
||||||
|
| { fun { <id> ... } <TOY> ... }
|
||||||
| { <TOY> <TOY> ... }
|
| { <TOY> <TOY> ... }
|
||||||
| { if <TOY> <TOY> <TOY> }
|
| { if <TOY> <TOY> <TOY> }
|
||||||
| { set! <id> <TOY> }
|
| { set! <id> <TOY> }
|
||||||
@@ -18,8 +19,9 @@
|
|||||||
(define-type TOY
|
(define-type TOY
|
||||||
[Num Number]
|
[Num Number]
|
||||||
[Id Symbol]
|
[Id Symbol]
|
||||||
[Bind (Listof Symbol) (Listof TOY) TOY]
|
[Bind (Listof Symbol) (Listof TOY) (Listof TOY)]
|
||||||
[Fun (Listof Symbol) TOY]
|
[Bindrec (Listof Symbol) (Listof TOY) (Listof TOY)]
|
||||||
|
[Fun (Listof Symbol) (Listof TOY)]
|
||||||
[Call TOY (Listof TOY)]
|
[Call TOY (Listof TOY)]
|
||||||
[If TOY TOY TOY]
|
[If TOY TOY TOY]
|
||||||
[Set Symbol TOY])
|
[Set Symbol TOY])
|
||||||
@@ -42,16 +44,19 @@
|
|||||||
[(number: n) (Num n)]
|
[(number: n) (Num n)]
|
||||||
[(symbol: name) (Id name)]
|
[(symbol: name) (Id name)]
|
||||||
|
|
||||||
; Bind.
|
; Bindrec.
|
||||||
[(cons 'bind more)
|
[(cons (and binder (or 'bind 'bindrec)) more) ; `binder` bound to 'bind or 'bindrec.
|
||||||
(match sexpr
|
(match sexpr
|
||||||
[(list 'bind (list (list (symbol: names) (sexpr: nameds))
|
[(list b (list (list (symbol: names) (sexpr: nameds)) ...) body ...)
|
||||||
...)
|
(if (not (null? body))
|
||||||
body)
|
|
||||||
(if (unique-list? names)
|
(if (unique-list? names)
|
||||||
(Bind names (map parse-sexpr nameds) (parse-sexpr body))
|
((if (symbol=? b 'bind) Bind Bindrec)
|
||||||
(error 'parse-sexpr "duplicate `bind' names: ~s" names))]
|
names
|
||||||
[else (error 'parse-sexpr "bad `bind' syntax in ~s" sexpr)])]
|
(map parse-sexpr nameds)
|
||||||
|
(last (map parse-sexpr body)))
|
||||||
|
(error 'parse-sexpr "duplicate `~s' names: ~s" binder names))
|
||||||
|
(error 'parse-sexpr "bind expression missing body: ~s" sexpr))]
|
||||||
|
[else (error 'parse-sexpr "bad `~s' syntax in ~s" binder sexpr)])]
|
||||||
|
|
||||||
; Function definition.
|
; Function definition.
|
||||||
[(cons 'fun more)
|
[(cons 'fun more)
|
||||||
@@ -120,6 +125,16 @@
|
|||||||
env)
|
env)
|
||||||
(error 'extend "arity mismatch for names: ~s" names)))
|
(error 'extend "arity mismatch for names: ~s" names)))
|
||||||
|
|
||||||
|
(: extend-rec : (Listof Symbol) (Listof TOY) ENV -> ENV)
|
||||||
|
(define (extend-rec names vals env)
|
||||||
|
(define newenv (extend names (map (lambda (_) (VoidV)) vals) env))
|
||||||
|
(for-each (lambda ([name : Symbol] [val : TOY])
|
||||||
|
(set-box! (lookup name newenv) (eval val newenv)))
|
||||||
|
names vals)
|
||||||
|
newenv)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(: lookup : Symbol ENV -> (Boxof VAL))
|
(: lookup : Symbol ENV -> (Boxof VAL))
|
||||||
;; lookup a symbol in an environment, frame by frame,
|
;; lookup a symbol in an environment, frame by frame,
|
||||||
;; return its value or throw an error if it isn't bound
|
;; return its value or throw an error if it isn't bound
|
||||||
@@ -181,6 +196,8 @@
|
|||||||
[(Id name) (unbox (lookup name env))]
|
[(Id name) (unbox (lookup name env))]
|
||||||
[(Bind names exprs bound-body)
|
[(Bind names exprs bound-body)
|
||||||
(eval bound-body (extend names (map eval* exprs) env))]
|
(eval bound-body (extend names (map eval* exprs) env))]
|
||||||
|
[(Bindrec names exprs bound-body)
|
||||||
|
(eval bound-body (extend-rec names exprs env))]
|
||||||
[(Fun names bound-body)
|
[(Fun names bound-body)
|
||||||
(FunV names bound-body env)]
|
(FunV names bound-body env)]
|
||||||
[(Call fun-expr arg-exprs)
|
[(Call fun-expr arg-exprs)
|
||||||
@@ -214,6 +231,14 @@
|
|||||||
;;; ----------------------------------------------------------------
|
;;; ----------------------------------------------------------------
|
||||||
;;; Tests
|
;;; Tests
|
||||||
|
|
||||||
|
(test (run "{bindrec {{fact {fun {n}
|
||||||
|
{if {= 0 n}
|
||||||
|
1
|
||||||
|
{* n {fact {- n 1}}}}}}}
|
||||||
|
|
||||||
|
{fact 5}}")
|
||||||
|
=> 120)
|
||||||
|
|
||||||
(test (run "
|
(test (run "
|
||||||
{bind {{x 10}}
|
{bind {{x 10}}
|
||||||
{bind {{y {set! x 1}}}
|
{bind {{y {set! x 1}}}
|
||||||
|
|||||||
Reference in New Issue
Block a user