Answered step by step
Verified Expert Solution
Question
1 Approved Answer
Extend the language below to allow the declaration of any number of mututally recursive unary procedures, for example: letrec even(x) = if zero?(x) then 1
Extend the language below to allow the declaration of any number of mututally recursive unary procedures, for example:
letrec
even(x) = if zero?(x) then 1 else (odd -(x,1))
odd(x) = if zero?(x) then 0 else (even -(x,1))
in (odd 13)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
type Var = string type Vars = Var list [] type Env = | Empty | Extend of var:Var * value:ExpVal * saved_env:Env | ExtendStar of vars:Vars * values:ExpVal list * saved_env:Env // 3.16 | ExtendRec of proc_name:Var * bound_var:Var * proc_body:Exp * saved_env:Env with static member apply search_var = function | Empty -> failwith search_var | Extend(saved_var, saved_val, _) when saved_var = search_var -> saved_val | Extend(_,_, saved_env) -> (Env.apply search_var saved_env) | ExtendStar([], _, saved_env) | ExtendStar(_, [], saved_env) -> Env.apply search_var saved_env | ExtendStar(var::rest_vars, value::rest_values, e) when var = search_var -> value | ExtendStar(var::rest_vars, value::rest_values, saved_env) -> let saved_env1 = ExtendStar(rest_vars, rest_values, saved_env) Env.apply search_var saved_env1 | ExtendRec(pname, bvar, pbody, saved_env) as env when search_var = pname -> ExpVal.Proc(Proc.Procedure(bvar, pbody, env)) | ExtendRec(_,_,_,saved_env) -> Env.apply search_var saved_env // 3.9 and ValList = | Empty | Cons of ExpVal * ValList with static member car = function | Cons(f,_) -> f | _ -> failwith "can't car on empty" static member cdr = function | Cons(_,r) -> ExpVal.List r | _ -> failwith "can't cdr an empty" static member isNull = function | Empty -> ExpVal.Bool true | _ -> ExpVal.Bool false and Proc = | Procedure of var:Var * body:Exp * saved_env:Env with //page 79 ... np1 static member applyProcedure (Proc.Procedure(var, body, saved_env)) value = Exp.valueOf (Env.Extend(var,value,saved_env)) body // np2 //ExpVal = INT + BOOL + LIST + PROC and ExpVal = | Num of int | Bool of bool | List of ValList // 3.9 | Proc of Proc with static member toNum = function | ExpVal.Num n -> n | _ -> failwith "bad transform" static member toBool = function | ExpVal.Bool b -> b | _ -> failwith "bad transform" static member toList = function | ExpVal.List l -> l | _ -> failwith "bad transform" // 3.9 static member toProc = function | ExpVal.Proc f -> f | _ -> failwith "bad transform" and Exp = | Const of int | IsZero of Exp | If of Exp * Exp * Exp | Diff of Exp * Exp | Var of Var | Let of Vars * Exp list * Exp // 3.16 modified | LetStar of Vars * Exp list * Exp // 3.17 | Minus of Exp // 3.6 | Add of Exp * Exp // 3.7 | Mult of Exp * Exp // 3.7 | IntDiv of Exp * Exp // 3.7 | IsEqual of Exp * Exp // 3.8 | IsGreater of Exp * Exp // 3.8 | IsLess of Exp * Exp // 3.8 | Cons of Exp * Exp // 3.9 | Car of Exp // 3.9 | Cdr of Exp // 3.9 | IsNull of Exp // 3.9 | EmptyList // 3.9 | List of Exp list // 3.10 | Proc of var:Var * body:Exp // page 80 | Call of rator:Exp * rand:Exp // page 80 | LetRec of pname:Var * bvar:Var * pbody:Exp * body:Exp // page 82 with static member valueOf env = function | Exp.Const(n) -> ExpVal.Num(n) | Exp.IsZero(exp) -> let num = (ExpVal.toNum (Exp.valueOf env exp)) ExpVal.Bool(num=0) | Exp.Var(var) -> (Env.apply var env) | Exp.Diff(exp1, exp2) -> let num1 = (ExpVal.toNum (Exp.valueOf env exp1)) let num2 = (ExpVal.toNum (Exp.valueOf env exp2)) ExpVal.Num((-) num1 num2) | Exp.Minus(exp) -> // 3.6 (ExpVal.Num (-1 * (ExpVal.toNum (Exp.valueOf env exp)))) | Exp.Add(exp1, exp2) -> // 3.7 let num1 = (ExpVal.toNum (Exp.valueOf env exp1)) let num2 = (ExpVal.toNum (Exp.valueOf env exp2)) ExpVal.Num((+) num1 num2) | Exp.Mult(exp1, exp2) -> // 3.7 let num1 = (ExpVal.toNum (Exp.valueOf env exp1)) let num2 = (ExpVal.toNum (Exp.valueOf env exp2)) ExpVal.Num((*) num1 num2) | Exp.IntDiv(exp1, exp2) -> // 3.7 let num1 = (ExpVal.toNum (Exp.valueOf env exp1)) let num2 = (ExpVal.toNum (Exp.valueOf env exp2)) ExpVal.Num((/) num1 num2) | Exp.IsEqual(exp1, exp2) -> // 3.8 let num1 = (ExpVal.toNum (Exp.valueOf env exp1)) let num2 = (ExpVal.toNum (Exp.valueOf env exp2)) ExpVal.Bool((=) num1 num2) | Exp.IsGreater(exp1, exp2) -> // 3.8 let num1 = (ExpVal.toNum (Exp.valueOf env exp1)) let num2 = (ExpVal.toNum (Exp.valueOf env exp2)) ExpVal.Bool((>) num1 num2) | Exp.IsLess(exp1, exp2) -> // 3.8 let num1 = (ExpVal.toNum (Exp.valueOf env exp1)) let num2 = (ExpVal.toNum (Exp.valueOf env exp2)) ExpVal.Bool((<) num1 num2) | Exp.If(exp1, exp2, exp3) -> let bool = (ExpVal.toBool (Exp.valueOf env exp1)) let num1() = (ExpVal.toNum (Exp.valueOf env exp2)) let num2() = (ExpVal.toNum (Exp.valueOf env exp3)) if bool then ExpVal.Num(num1()) else ExpVal.Num(num2()) | Exp.Let(vars, loe, exp2) -> // 3.16 let vals = loe |> List.map (Exp.valueOf env) //using same original env for each exp in loe let env1 = Env.ExtendStar(vars, vals, env) (Exp.valueOf env1 exp2) | Exp.LetStar(vars, loe, exp2) -> let extender (env1, col_vals) var exp = let value = (Exp.valueOf env1 exp) let env2 = (Env.Extend(var, value, env1)) (env2, value::col_vals) let values = // grab just vals to place in ExtendStar let _, vals = loe |> List.fold2 extender (env, []) vars vals |> List.rev Exp.valueOf (Env.ExtendStar(vars, values, env)) exp2 // np4 | Exp.EmptyList -> // 3.9 ExpVal.List(ValList.Empty) | Exp.Cons(exp1, exp2) -> // 3.9 let val1 = (Exp.valueOf env exp1) let val2 = (Exp.valueOf env exp2) let val_list = ExpVal.toList val2 ExpVal.List(ValList.Cons(val1, val_list)) | Exp.Car(exp) -> // 3.9 let val1 = (Exp.valueOf env exp) ValList.car(ExpVal.toList(val1)) | Exp.Cdr(exp) -> // 3.9 let val1 = (Exp.valueOf env exp) ValList.cdr(ExpVal.toList(val1)) | Exp.IsNull(exp) -> // 3.9 let val1 = (Exp.valueOf env exp) ValList.isNull(ExpVal.toList(val1)) | Exp.List(loe) -> let exp_vals = (loe |> List.map (Exp.valueOf env)) |> List.rev let val_list_folder expval1 expval2 = ExpVal.List(ValList.Cons(expval2, ExpVal.toList(expval1))) List.fold val_list_folder (ExpVal.List(ValList.Empty)) exp_vals | Exp.Proc(var, body) -> (ExpVal.Proc(Proc.Procedure(var, body, env))) | Exp.Call(rator, rand) -> let val1 = (Exp.valueOf env rator) let val2 = (Exp.valueOf env rand) let proc = ExpVal.toProc val1 Proc.applyProcedure proc val2 | Exp.LetRec(pname, bvar, pbody, lrBody) -> let env1 = Env.ExtendRec(pname, bvar, pbody, env) Exp.valueOf env1 lrBody [] type Program = | A of Exp with static member valueOfProgram (A exp) = (Exp.valueOf Env.Empty exp)
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started