Updated BAE.
This commit is contained in:
+34
-19
@@ -10,9 +10,13 @@
|
||||
| { - <BAE> <BAE> ... }
|
||||
| { / <BAE> <BAE> ... }
|
||||
| { = <BAE> <BAE> }
|
||||
| { <BAE> is <BAE> } -- Sugar.
|
||||
| { < <BAE> <BAE> }
|
||||
| { <BAE> is less than <BAE> } -- Sugar.
|
||||
| { <= <BAE> <BAE> }
|
||||
| { <BAE> is less than or equal to <BAE> } -- Sugar.
|
||||
| { with { <id> <BAE> } <BAE> }
|
||||
| { with <id> as <BAE> <BAE> } -- Sugar.
|
||||
| { if <BAE> <BAE> <BAE> }
|
||||
| { if <BAE> then <BAE> else <BAE> } -- Sugar.
|
||||
| { and <BAE> <BAE> } -- Sugar.
|
||||
@@ -40,13 +44,14 @@
|
||||
[Call BAE BAE]
|
||||
[Id Symbol])
|
||||
|
||||
; This is a little strange.
|
||||
(define-type LambdaContents
|
||||
[Par Symbol]
|
||||
[Body BAE])
|
||||
|
||||
(define-type Primitive = (U Number Boolean (Listof LambdaContents)))
|
||||
|
||||
(define reserved-names (list 'F 'T '+ '* '- '/ '= '< '<= 'with 'if 'then 'else 'lambda 'λ 'of))
|
||||
(define reserved-names (list 'F 'T '+ '* '- '/ '= 'is '< 'less 'than '<= 'or 'equal 'to 'with 'if 'then 'else 'lambda 'of 'and 'not 'as))
|
||||
|
||||
(define pf (Bool #f))
|
||||
(define pt (Bool #t))
|
||||
@@ -67,8 +72,12 @@
|
||||
[(list '- fst args ...) (Sub (parse-sexpr fst) (parse-sexprs args))]
|
||||
[(list '/ fst args ...) (Div (parse-sexpr fst) (parse-sexprs args))]
|
||||
[(list '= l r) (Eq (parse-sexpr l) (parse-sexpr r))]
|
||||
[(list l 'is r) (Eq (parse-sexpr l) (parse-sexpr r))]
|
||||
[(list '< l r) (Lt (parse-sexpr l) (parse-sexpr r))]
|
||||
[(list l 'is 'less 'than r) (Lt (parse-sexpr l) (parse-sexpr r))]
|
||||
[(list '<= l r) (Lte (parse-sexpr l) (parse-sexpr r))]
|
||||
[(list l 'is 'less 'than 'or 'equal 'to r) (Lte (parse-sexpr l) (parse-sexpr r))]
|
||||
[(list 'with (symbol: name) 'as val body) (With name (parse-sexpr val) (parse-sexpr body))]
|
||||
[(cons 'with more)
|
||||
(match sexpr
|
||||
[(list 'with (list (symbol: name) named) body)
|
||||
@@ -77,7 +86,9 @@
|
||||
[(list 'if p b a) (If (parse-sexpr p) (parse-sexpr b) (parse-sexpr a))]
|
||||
[(list 'if p 'then b 'else a) (If (parse-sexpr p) (parse-sexpr b) (parse-sexpr a))]
|
||||
[(list 'and a b) (If (parse-sexpr a) (If (parse-sexpr b) pt pf) pf)]
|
||||
[(list a 'and b) (If (parse-sexpr a) (If (parse-sexpr b) pt pf) pf)]
|
||||
[(list 'or a b) (If (parse-sexpr a) pt (If (parse-sexpr b) pt pf))]
|
||||
[(list a 'or b) (If (parse-sexpr a) pt (If (parse-sexpr b) pt pf))]
|
||||
[(list 'not a) (If (parse-sexpr a) pf pt)]
|
||||
[(list 'lambda (symbol: arg) body) (Lambda arg (parse-sexpr body))]
|
||||
[(list f 'of arg) (Call (parse-sexpr f) (parse-sexpr arg))]
|
||||
@@ -242,7 +253,10 @@
|
||||
bound-id
|
||||
;; see the above `value-bae' helper
|
||||
(value->bae (eval named-expr)))))]
|
||||
[(Lambda par body) (list (Par par) (Body body))] ; No lambda primitive, but this branch shouldn't happen anyway. Return dummy value for now.
|
||||
[(Lambda par body)
|
||||
(if (member par reserved-names)
|
||||
(error 'eval "Can't create parameter binding to reserved name '~s'." par)
|
||||
(list (Par par) (Body body)))]
|
||||
[(Call f arg) (eval-call (value->bae (eval f)) arg)]
|
||||
[(Id name) (error 'eval "free identifier: ~s" name)]))
|
||||
|
||||
@@ -251,34 +265,31 @@
|
||||
(define (run str)
|
||||
(eval (parse str)))
|
||||
|
||||
; Because we'ren't writing a lazy language, need to use the Z combinator to delay evaluation of f (otherwise it'd never terminate).
|
||||
; As we'ren't writing a lazy language, we need to use the Z combinator to delay evaluation of f (otherwise it'd never terminate). This factorial function also isn't tail recursive cause it's hard enough for me to understand already ;-;.
|
||||
; Z = λf.(λx.(f λv.((x x) v)))(λx.(f λv.((x x) v)))
|
||||
; factorial = (Y (λself.λn.if (<= n 1) 1 (* n (self (- n 1)))))
|
||||
|
||||
(test (run "
|
||||
{with
|
||||
|
||||
{Z {lambda f {
|
||||
{with Z as {lambda f {
|
||||
{lambda x {f of {lambda v {{x of x} of v}}}}
|
||||
of
|
||||
{lambda x {f of {lambda v {{x of x} of v}}}}
|
||||
}}}
|
||||
|
||||
{with
|
||||
|
||||
{factorial {Z of
|
||||
{lambda self {lambda n
|
||||
{if {<= n 1} 1 {* n {self of {- n 1}}}}
|
||||
}
|
||||
}}}
|
||||
|
||||
{factorial of 5}
|
||||
|
||||
}}
|
||||
") => 120)
|
||||
|
||||
{with factorial as {Z of
|
||||
{lambda self {lambda n
|
||||
{if {n is less than or equal to 1} then 1 else {* n {self of {- n 1}}}}
|
||||
}
|
||||
}}
|
||||
|
||||
{{{factorial of 4} is 24} and
|
||||
{{factorial of 5} is 120}}}}") => #t)
|
||||
|
||||
(test (run "{{lambda f {f of 1}} of {lambda x {+ x 1}}}") => 2)
|
||||
(test (run "{{lambda x {+ x 1}} of 2}") => 3)
|
||||
(test (run "{{lambda + {+ + +}} of 2}") =error> "Can't create parameter binding to reserved name '+'.")
|
||||
(test (run "{1 of 1}") =error> "eval-call: Expected lambda expression to call, instead got: (Num 1).")
|
||||
(test (run "{with {x 2} {x of 1}}") =error> "eval-call: Expected lambda expression to call, instead got: (Num 2).")
|
||||
|
||||
(test (run "{and T T}") => #t)
|
||||
(test (run "{and F aaaaaaaaaa}") => #f)
|
||||
@@ -298,8 +309,10 @@
|
||||
(test (run "{< 1 2}") => #t)
|
||||
(test (run "{< 2 2}") => #f)
|
||||
(test (run "{< 2 1}") => #f)
|
||||
(test (run "{1 is 2}") => #f)
|
||||
(test (run "{= 1 2}") => #f)
|
||||
(test (run "{= 2 2}") => #t)
|
||||
(test (run "{2 is 2}") => #t)
|
||||
(test (run "{<= 1 2}") => #t)
|
||||
(test (run "{<= 2 2}") => #t)
|
||||
(test (run "{<= 2 1}") => #f)
|
||||
@@ -322,6 +335,8 @@
|
||||
(test (run "{/ 3 2 1}") => 3/2)
|
||||
(test (run "{/ 1 2 3}") => 1/6)
|
||||
|
||||
(test (run "{+ x 1}") =error> "eval: free identifier: x")
|
||||
|
||||
;; tests (for simple expressions)
|
||||
(test (run "5") => 5)
|
||||
(test (run "{+ 5 5}") => 10)
|
||||
|
||||
Reference in New Issue
Block a user