From 23892acf6d597fa495cdca2278300ea566840ae6 Mon Sep 17 00:00:00 2001 From: Hyeonung Baek Date: Sat, 12 Feb 2022 03:18:00 +0900 Subject: [PATCH] Refactor env to list --- eval.ml | 48 +++++++++++++++++------------------------------- main.ml | 9 ++++----- 2 files changed, 21 insertions(+), 36 deletions(-) diff --git a/eval.ml b/eval.ml index aedc480..1985479 100644 --- a/eval.ml +++ b/eval.ml @@ -14,10 +14,7 @@ type value = and expr = Ast.t (* environment for eval *) -and env = { - vars : (string, value) Hashtbl.t; - parent : env option; -} +and env = (string * value) list exception No_operation exception Too_many_arguments @@ -80,26 +77,16 @@ end module Env = struct type t = env - let init_global () = { - vars = Hashtbl.create 100; - parent = None; - } + let empty = [] - let make parent = { - vars = Hashtbl.create 100; - parent = Some parent; - } + let get_opt e name = + List.assoc_opt name e - let rec get_opt e name = - match Hashtbl.find_opt e.vars name with - | None -> Option.bind e.parent (fun p -> get_opt p name) - | Some _ as v -> v + let bind v e = + v::e - let set e name value = - Hashtbl.replace e.vars name value - - let add_seq e seq = - Hashtbl.add_seq e.vars seq + let bind_seq seq e = + List.of_seq seq @ e end (* operators *) @@ -275,9 +262,8 @@ let rec eval env ast = | Some v -> v end | Letin (v, e, f) -> - let nenv = Env.make env in - Env.set nenv v (aux e); - eval nenv f + let env = Env.bind (v, aux e) env in + eval env f | Unary (op, t) -> let t = aux t in @@ -299,9 +285,8 @@ let rec eval env ast = begin match args with | [] -> f | a::args -> - let nenv = Env.make env in - Env.set nenv var (aux a); - eval nenv @@ Apply (e, args) + let env = Env.bind (var, aux a) env in + eval env @@ Apply (e, args) end | External f -> let args = List.map aux args in @@ -333,9 +318,10 @@ let rec eval env ast = in aux ast -let eval_top env ast = +let eval_top env_ref ast = match ast with | Let (var, e) -> - let v = eval env e in - Env.set env var v; var, v - | ast -> "-", eval env ast + let v = eval !env_ref e in + env_ref := Env.bind (var, v) !env_ref; + var, v + | ast -> "-", eval !env_ref ast diff --git a/main.ml b/main.ml index 0fa1b4c..77654f2 100644 --- a/main.ml +++ b/main.ml @@ -28,10 +28,9 @@ let stdlib = [ |> List.to_seq |> Seq.map (fun v -> v, External v) +(* global environment *) let g = - let g = Env.init_global () in - Env.add_seq g stdlib; - g + ref @@ Env.bind_seq stdlib Env.empty (* read-eval-print *) let rep env : unit = @@ -44,14 +43,14 @@ let rep env : unit = match v with | Nop -> () | _ -> - Env.set env "ans" v; + g := Env.bind ("ans", v) !g; printf "%s: %s = %s\n" var (Type.to_string @@ Value.typeof v) (Value.to_string v) exception Reset_line (* used to indicate ^C is pressed *) let init_repl () = - Env.set g "ans" (Int 0); + g := Env.bind ("ans", Int 0) !g; (* treat Ctrl-C as to reset line *) let reset_line _ = raise Reset_line in Sys.(set_signal sigint (Signal_handle reset_line))