Reputation: 397
I have a type
type expr =
Const of int
| Var of string
| Bin of expr * binop * expr
also
type binop =
Plus
| Minus
| Mul
| Div
and
type value =
Int of int
| Closure of env * string option * string * expr
Binop performs an operation on two exprs and I need to write an eval function that takes in a closure and expr and returns a value
ex.
let evn = [("z1",Int 0);("x",Int 1);("y",Int 2);("z",Int 3);("z1",Int 4)];;
val evn : (string * Nano.value) list =
[("z1", Int 0); ("x", Int 1); ("y", Int 2); ("z", Int 3); ("z1", Int 4)]
# let e1 = Bin(Bin(Var "x",Plus,Var "y"), Minus, Bin(Var "z",Plus,Var "z1"));;
val e1 : Nano.expr =
Bin (Bin (Var "x", Plus, Var "y"), Minus, Bin (Var "z", Plus, Var "z1"))
# eval (evn, e1);;
- : Nano.value = Int 0
The issue Im having is that the function needs to return INT int instead of an actual into value.
This is what I wrote so far
let rec eval (evn,e) = match e with
| Const a -> Int a
| Var x-> Int (lookup (x,evn) )
| Bin( Var x, Plus, Var y) -> Int ( eval(evn,Var x) + eval(evn,Var y) )
| Bin( Var x, Minus, Var y) -> Int ( eval(evn,Var x) + eval(evn,Var y) )
| Bin( Var x, Mul, Var y) -> Int ( eval(evn,Var x) + eval(evn,Var y) )
| Bin( Var x, Div, Var y) -> Int ( eval(evn,Var x) + eval(evn,Var y) )
;;
lookup looks up x in the closure evn and returns its value the issue Im having is I need to perform integer operations in the bin matches but since eval returns types of value I cant do that. How would I change the code in the last four matches to make it be able to do the arithmetic and return type Int of int after that's done?
Upvotes: 3
Views: 2997
Reputation: 1619
let rec eval (evn,e) = match e with
| Const a -> Int a
| Var x-> Int (lookup (x,evn) )
| Bin( el, Plus, er) ->
let Int cl=eval (evn,el ) and Int cr=eval (evn,er ) in
Int (cl+cr)
| Bin( el, Minus, er) ->
let Int cl=eval (evn,el ) and Int cr=eval (evn,er ) in
Int (cl-cr)
| Bin( el, Mul, er) ->
let Int cl=eval (evn,el ) and Int cr=eval (evn,er ) in
Int (cl*cr)
| Bin( el, Div, er) ->
let Int cl=eval (evn,el ) and Int cr=eval (evn,er ) in
Int (cl/cr)
Upvotes: 2
Reputation: 3847
You need something like
let x =
match eval (evn, Var x) with
| Int x -> x
| _ -> failwith "runtime error"
in
let y =
match eval (evn, Var y) with
| Int y -> y
| _ -> failwith "runtime error"
in
Int (x + y)
in each of the match cases. You should probably factor out this pattern-match into a function that you can call repeatedly:
let get_int = function
| Int i -> i
| _ -> failwith "runtime error: expected an integer"
... Int ((eval (evn, e1) |> get_int) + (eval (evn, e2) |> get_int))
It should make sense that you have to do this runtime check in your evaluator – in your representation, there is no reason why a variable can't be mapped to a closure in evn
instead of an integer.
Also note that, contrary to your question, evn
itself is not a closure. It's usually called the "environment". The closures are the values constructed by Closure
, and they carry environments, among other things – I think you simply had a typo, though.
I'm assuming that you will generalize the Var x
and Var y
to two expressions e
and e'
in the future, of course.
Upvotes: 2