diff --git a/impls/sml/env.sml b/impls/sml/env.sml index 5e4adcd0..91814e15 100644 --- a/impls/sml/env.sml +++ b/impls/sml/env.sml @@ -1,5 +1,13 @@ -datatype mal_env = ENV of (string * mal_type) list +type mal_defs = (string * mal_type) list -fun lookup (ENV fs) s = - fs |> List.find (eq s o #1) - |> Option.map #2 +datatype mal_env = ENV of mal_defs + | INNER of (mal_defs * mal_env) + +fun get (d:mal_defs) s = + d |> List.find (eq s o #1) |> Option.map #2 + +fun set s v (d:mal_defs) = + (s, v) :: (d |> List.filter (not o eq s o #1)) + +fun lookup (INNER (d, out)) s = (case get d s of NONE => lookup out s | x => x) + | lookup (ENV d) s = get d s diff --git a/impls/sml/step3_env.sml b/impls/sml/step3_env.sml index 93972570..e9b562f2 100644 --- a/impls/sml/step3_env.sml +++ b/impls/sml/step3_env.sml @@ -40,20 +40,20 @@ fun malMinus (INT b, INT a) = INT (a - b) fun malDiv (INT b, INT a) = INT (a div b) | malDiv _ = raise NotApplicable "can only divide integers" -val initEnv = ENV [ - ("+", FN (foldl malPlus (INT 0))), - ("*", FN (foldl malTimes (INT 1))), - ("-", FN ( - fn [x] => malMinus (x, INT 0) - | x::xs => foldr malMinus x xs - | _ => raise NotApplicable "'-' requires at least one argument" - )), - ("/", FN ( - fn [x] => malDiv (x, INT 1) - | x::xs => foldr malDiv x xs - | _ => raise NotApplicable "'/' requires at least one argument" - )) -] +val initEnv = + [] |> set "+" + (FN (foldl malPlus (INT 0))) + |> set "*" + (FN (foldl malTimes (INT 1))) + |> set "-" + (FN (fn [x] => malMinus (x, INT 0) + | x::xs => foldr malMinus x xs + | _ => raise NotApplicable "'-' requires arguments")) + |> set "/" + (FN (fn [x] => malDiv (x, INT 1) + | x::xs => foldr malDiv x xs + | _ => raise NotApplicable "'/' requires arguments")) + |> ENV fun repl () = let open TextIO