diff --git a/lib/environment.ml b/lib/environment.ml index 2d64561..b4fb914 100644 --- a/lib/environment.ml +++ b/lib/environment.ml @@ -1,36 +1,38 @@ open Value -type env_table = (string, lox_value) Hashtbl.t -type environment = { globals : env_table; locals : env_table list } - module Hashtbl = struct include Stdlib.Hashtbl let contains tbl key = find_opt tbl key |> Option.is_some end +type env_table = (string, lox_value) Hashtbl.t +type environment = { globals : env_table ref; locals : env_table list } + module Env = struct type t = environment - let make () : t = { globals = Hashtbl.create 0; locals = [] } + let make () : t = { globals = ref (Hashtbl.create 0); locals = [] } let enter (env : t) : t = let tbl = Hashtbl.create 0 in { env with locals = tbl :: env.locals } - let exit (env : t) : t = - assert (not (List.is_empty env.locals)); - { env with locals = List.tl env.locals } + let push_frame (env : t) : t = { env with locals = [] } |> enter + + (* let exit (env : t) : t = + assert (not (List.is_empty env.locals)); + { env with locals = List.tl env.locals } *) let define_global (env : t) (name : string) (value : lox_value) = - Hashtbl.replace env.globals name value + Hashtbl.replace !(env.globals) name value - let get_global (env : t) (name : string) : lox_value option = Hashtbl.find_opt env.globals name + let get_global (env : t) (name : string) : lox_value option = Hashtbl.find_opt !(env.globals) name (* Check if `name` is defined in either locals or globals *) let is_defined (env : t) (name : string) : bool = let _is_defined tbl = Hashtbl.contains tbl name in - List.fold_left (fun acc tbl -> acc || _is_defined tbl) false (env.globals :: env.locals) + List.fold_left (fun acc tbl -> acc || _is_defined tbl) false (!(env.globals) :: env.locals) let define (env : t) (name : string) (value : lox_value) : bool = if List.is_empty env.locals then ( @@ -53,7 +55,7 @@ module Env = struct true) else _update tail in - if _update env.locals then () else Hashtbl.replace env.globals name value + if _update env.locals then () else Hashtbl.replace !(env.globals) name value let get (env : t) (name : string) : lox_value option = let rec _get tbls = @@ -63,5 +65,5 @@ module Env = struct match Hashtbl.find_opt tbl name with Some x -> Some x | None -> _get tail) in let val_opt = _get env.locals in - match val_opt with Some x -> Some x | None -> Hashtbl.find_opt env.globals name + match val_opt with Some x -> Some x | None -> Hashtbl.find_opt !(env.globals) name end