mirror of
https://github.com/MorizzG/MLox.git
synced 2025-12-06 04:22:41 +00:00
global and local variables with scope
also reworked arg parsing, now has --debug flag
This commit is contained in:
parent
222de81a19
commit
77e57cd8c2
8 changed files with 341 additions and 95 deletions
67
lib/environment.ml
Normal file
67
lib/environment.ml
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
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
|
||||
|
||||
module Env = struct
|
||||
type t = environment
|
||||
|
||||
let make () : t = { globals = 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 define_global (env : t) (name : string) (value : lox_value) =
|
||||
Hashtbl.replace env.globals name value
|
||||
|
||||
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)
|
||||
|
||||
let define (env : t) (name : string) (value : lox_value) : bool =
|
||||
if List.is_empty env.locals then (
|
||||
define_global env name value;
|
||||
true)
|
||||
else
|
||||
let tbl = List.hd env.locals in
|
||||
if Hashtbl.contains tbl name then false
|
||||
else (
|
||||
Hashtbl.add tbl name value;
|
||||
true)
|
||||
|
||||
let update (env : t) (name : string) (value : lox_value) =
|
||||
let rec _update tbls =
|
||||
match tbls with
|
||||
| [] -> false
|
||||
| tbl :: tail ->
|
||||
if Hashtbl.contains tbl name then (
|
||||
Hashtbl.replace tbl name value;
|
||||
true)
|
||||
else _update tail
|
||||
in
|
||||
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 =
|
||||
match tbls with
|
||||
| [] -> None
|
||||
| tbl :: tail -> (
|
||||
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
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue