signature evaluator = sig datatype utm = UtmBool of bool (* boolean constant *) | UtmInt of int (* integer constant *) | UtmStr of string (* string constant *) | UtmVar of string (* variable *) | UtmIf of utm * utm * utm (* if-then-else term *) | UtmOp of string * utm list (* built-in operator *) | UtmApp of utm * utm (* application *) | UtmLet of string * utm * utm (* let-binding *) | UtmLetrec of string * utm * utm (* letrec-binding *) | UtmTup of utm list (* tuple *) | UtmPro of utm * int (* projection *) | UtmFix of utm (* fixed point *) | UtmExn of string (* exception *) | UtmTry of utm * (utm * utm) list (* try ... with ... *) (* nonrecursive function *) | UtmFn of string list * utm (* recursive function *) | UtmFun of string * string list * utm (* mutually recursive functions *) | UtmFuns of (string * string list * utm) list | UtmChoose of utm * int val erase: Parser.ttm -> utm datatype evalctx = EChold | ECif of evalctx * utm * utm | ECop of string * utm list * evalctx * utmlist | ECapp1 of evalctx * utm | ECapp2 of utm * evalctx | EClet of string * evalctx * utm | ECtup of utm list * evalctx * utm list | ECpro of evalctx * int | ECfix of evalctx | ECtry of evalctx * (utm * utm) list | ECchoose of evalctx * int (* * the function 'compose' composes an evaluation context with * a term *) val compose: evalctx * utm -> utm (* * the function 'decompose' decomposes a nonvalue into an * evaluation context and a redex. *) val decompose: utm -> evalctx * utm (* the 'reduce' function reduces a redex into its reduction *) val reduce: utm -> utm (* the function 'eval1' does one step evaluation *) val eval1: utm -> utm (* the function 'evaluate' evaluates a term to a value *) val evaluate: utm -> utm end structure Evaluator :> EVALUATOR = struct (* ... your implementation ... *) fun eval1 (t: utm) = let val (E, r) = decompose t in compose (E, reduce r) end (* ... your implementation ... *) end