Advertisement
Guest User

Untitled

a guest
Jun 19th, 2017
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 6.87 KB | None | 0 0
  1. #lang pl
  2. #|
  3.  The grammar:
  4.  <FLANG> ::= <num>
  5.            | True
  6.            | False
  7.            | { + <FLANG> <FLANG> }
  8.            | { - <FLANG> <FLANG> }
  9.            | { * <FLANG> <FLANG> }
  10.            | { / <FLANG> <FLANG> }
  11.            | { > <FLANG> <FLANG> }
  12.            | { = <FLANG> <FLANG> }
  13.            | { if <FLANG> then <FLANG> else <FLANG> }
  14.            | { with { <id> <FLANG> } <FLANG> }
  15.            | <id>
  16.            | { fun { <id> } <FLANG> }
  17.            | { call <FLANG> <FLANG> }
  18. |#
  19. (define-type FLANG
  20.   [Num Number]
  21.   [Add FLANG FLANG]
  22.   [Sub FLANG FLANG]
  23.   [Mul FLANG FLANG]
  24.   [Div FLANG FLANG]
  25.   [Id Symbol]
  26.   [With Symbol FLANG FLANG]
  27.   [Fun Symbol FLANG]
  28.   [Call FLANG FLANG]
  29.   [Bool Boolean]
  30.   [Eq FLANG FLANG]
  31.   [Geq FLANG FLANG]
  32.   [If FLANG FLANG FLANG])
  33. (: parse-sexpr : Sexpr -> FLANG)
  34. ;; to convert s-expressions into FLANGs
  35. (define (parse-sexpr sexpr)
  36.   (match sexpr
  37.     [(number: n) (Num n)]
  38.     ['True  (Bool #t)]
  39.     ['False (Bool #f)]
  40.     [(symbol: name) (Id name)]
  41.     [(cons 'with more)
  42.      (match sexpr
  43.        [(list 'with (list (symbol: name) named) body)
  44.         (With name (parse-sexpr named) (parse-sexpr body))]
  45.        [else (error 'parse-sexpr "bad `with' syntax in ~s" sexpr)])]
  46.     [(cons 'fun more)
  47.      (match sexpr
  48.        [(list 'fun (list (symbol: name)) body)
  49.         (Fun name (parse-sexpr body))]
  50.        [else (error 'parse-sexpr "bad `fun' syntax in ~s" sexpr)])]
  51.     [(cons 'if more)
  52.      (match sexpr
  53.        [(list 'if conition 'then result1 'else result2)
  54.         (If (parse-sexpr conition) (parse-sexpr result1) (parse-sexpr result2))]
  55.        [else (error 'parse-sexpr "bad `if' syntax in ~s" sexpr)])]
  56.     [(list '+ lhs rhs) (Add (parse-sexpr lhs) (parse-sexpr rhs))]
  57.     [(list '- lhs rhs) (Sub (parse-sexpr lhs) (parse-sexpr rhs))]
  58.     [(list '* lhs rhs) (Mul (parse-sexpr lhs) (parse-sexpr rhs))]
  59.     [(list '/ lhs rhs) (Div (parse-sexpr lhs) (parse-sexpr rhs))]
  60.     [(list '> lhs rhs) (Geq (parse-sexpr lhs) (parse-sexpr rhs))]
  61.     [(list '= lhs rhs) (Eq (parse-sexpr lhs) (parse-sexpr rhs))]
  62.     [(list 'call fun arg) (Call (parse-sexpr fun) (parse-sexpr arg))]
  63.     [else (error 'parse-sexpr "bad syntax in ~s" sexpr)]))
  64. (: parse : String -> FLANG)
  65. ;; parses a string containing a FLANG expression to a FLANG AST
  66. (define (parse str)
  67.   (parse-sexpr (string->sexpr str)))
  68.  
  69.  
  70. ;; ================= Q1.2 ======================
  71.  
  72. ;; =============================================
  73.  
  74. #| Evaluation rules:
  75.               eval(N,env) = N
  76.               eval(True,env) = #t
  77.               eval(False,env) = #f
  78.               eval({+ E1 E2},env) = eval(E1,env) + eval(E2,env)
  79.               eval({- E1 E2},env) = eval(E1,env) - eval(E2,env)
  80.               eval({* E1 E2},env) = eval(E1,env) * eval(E2,env)
  81.               eval({/ E1 E2},env) = eval(E1,env) / eval(E2,env)
  82.               eval({> E1 E2},env) = eval(E1,env) > eval(E2,env)
  83.               eval({= E1 E2},env) = eval(E1,env) = eval(E2,env)
  84.               eval(x,env) = lookup(x,env)
  85.               eval(if Ec then Ey else En)= eval(En, env) if eval(Ec) = #f
  86.                                            eval(Ey, env) otherwise
  87.               eval({with {x E1} E2},env) = eval(E2,extend(x,eval(E1,env),env))
  88.               eval({fun {x} E},env) = <{fun {x} E}, env>
  89.               eval({call E1 E2},env1) = eval(Ef,extend(x,eval(E2,env1),env2))
  90.               if eval(E1,env1) = <{fun {x} Ef}, env2> = error! otherwise
  91.  |#
  92. ;; Types for environments, values, and a lookup function
  93. (define-type ENV
  94.   [EmptyEnv]
  95.   [Extend Symbol VAL ENV])
  96. (define-type VAL
  97.   [NumV Number]
  98.   [FunV Symbol FLANG ENV]
  99.   [BoolV Boolean])
  100. (: lookup : Symbol ENV -> VAL)
  101. (define (lookup name env)
  102.   (cases env
  103.     [(EmptyEnv) (error 'lookup "no binding for ~s" name)]
  104.     [(Extend id val rest-env)
  105.      (if (eq? id name) val (lookup name rest-env))]))
  106. (: arith-op : (Number Number -> Number) VAL VAL -> VAL)
  107. ;; gets a Racket numeric binary operator, and uses it within a NumV
  108. ;; wrapper
  109. (define (arith-op op val1 val2)
  110.   (: NumV->number : VAL -> Number)
  111.   (define (NumV->number v)
  112.     (cases v
  113.       [(NumV n) n]
  114.       [else (error 'arith-op "expects a number, got: ~s" v)]))
  115.   (NumV (op (NumV->number val1) (NumV->number val2))))
  116. (: logic-op : (Number Number -> Boolean) VAL VAL -> VAL)
  117. ;; gets a Racket logic binary operator, and uses it within a NumV
  118. ;; wrapper to return the result inside a BoolV wrapper.
  119. (define (logic-op op val1 val2)
  120.   (: NumV->number : VAL -> Number)
  121.   (define (NumV->number v)
  122.     (cases v
  123.       [(NumV n) n]
  124.       [else (error 'logic-op "expects a number, got: ~s" v)]))
  125.   (BoolV (op (NumV->number val1) (NumV->number val2))))
  126. (: extract-bool-val : VAL -> Boolean)
  127. ;; Return #f if the wrapped value is False, and #t otherwise
  128. (define (extract-bool-val val)
  129.   (cases val
  130.     [(BoolV b) b]
  131.     [else (error 'extract-bool-val "expects a boolean, got: ~s" val)]))
  132. (: eval : FLANG ENV -> VAL)
  133. ;; evaluates FLANG expressions by reducing them to values
  134. (define (eval expr env)
  135.   (cases expr
  136.     [(Num n) (NumV n)]
  137.     [(Bool b) (extract-bool-val b)]
  138.     [(Add l r) (arith-op + (eval l env) (eval r env))]
  139.     [(Sub l r) (arith-op - (eval l env) (eval r env))]
  140.     [(Mul l r) (arith-op * (eval l env) (eval r env))]
  141.     [(Div l r) (arith-op / (eval l env) (eval r env))]
  142.     [(Eq l r) (logic-op = (eval l env) (eval r env))]
  143.     [(Geq l r) (logic-op > (eval l env) (eval r env))]
  144.     [(If cond do-yes do-no)
  145.      (if (eval cond env)
  146.          (eval do-yes env)
  147.          (eval do-no env))]
  148.     [(With bound-id named-expr bound-body)
  149.      (eval bound-body
  150.            (Extend bound-id (eval named-expr env) env))]
  151.     [(Id name) (lookup name env)]
  152.     [(Fun bound-id bound-body)
  153.      (FunV bound-id bound-body env)]
  154.     [(Call fun-expr arg-expr)
  155.      (let ([fval (eval fun-expr env)])
  156.        (cases fval
  157.          [(FunV bound-id bound-body f-env)
  158.           (eval bound-body
  159.                 (Extend bound-id (eval arg-expr env) f-env))]
  160.          [else (error 'eval "`call' expects a function, got: ~s"
  161.                       fval)]))]))
  162. (: run : String -> Number)
  163. ;; evaluate a FLANG program contained in a string
  164. (define (run str)
  165.   (let ([result (eval (parse str) (EmptyEnv))])
  166.     (cases result
  167.       [(NumV n) n]
  168.       [else (error 'run
  169.                    "evaluation returned a non-number: ~s" result)])))
  170.  
  171.  
  172. (test (run "{ if True then 3 else 4 }") => 3)
  173. (test (run "{ if {= 2 4} then 3 else 4 }") => 4)
  174. (test (run "{ if {= 2 4} then { call 3 5 } else 4 }") => 4)
  175. (test (run "{with {is-5? {fun {x} {= x 5}}} {with {foo {fun {x} {if {call is-5? {+ x 1}}then 4 else 0}}} {call foo 123}}}") => 0)
  176. (test (run "{with {is-5? {fun {x} {= x 5}}} {with {foo {fun {x} {if {call is-5? {+ x 1}}4 0}}} {call foo 123}}}") =error> "parse-sexpr: bad `if' syntax in (if (call is-5? (+ x 1)) 4 0)")
  177. (test (run "{with {x {> 3 4}} {with {foo {fun {y} {if x then True else y}}} {call foo 5}}}") => 5)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement