From b425a59db53ceca5fd9d86f18662088d29a8521a Mon Sep 17 00:00:00 2001 From: Moritz Gmeiner Date: Wed, 28 Aug 2024 23:58:55 +0200 Subject: [PATCH] added closures --- lib/environment.ml | 3 +-- lib/interpreter.ml | 7 +++--- lib/parser.ml | 1 - lib/value.ml | 13 ++++++---- lox.t/run.t | 63 +++++++++++++++++++++++++++++++++------------- 5 files changed, 59 insertions(+), 28 deletions(-) diff --git a/lib/environment.ml b/lib/environment.ml index b4fb914..ad4f258 100644 --- a/lib/environment.ml +++ b/lib/environment.ml @@ -6,8 +6,7 @@ module Hashtbl = struct 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 } +type environment = Value.environment module Env = struct type t = environment diff --git a/lib/interpreter.ml b/lib/interpreter.ml index 581086c..8c4f7f0 100644 --- a/lib/interpreter.ml +++ b/lib/interpreter.ml @@ -140,7 +140,7 @@ let rec interpret_expr (env : environment) (expr_node : expr_node) : lox_value i RuntimeError.make pos msg |> error else match fn args with Ok value -> Ok value | Error s -> RuntimeError.make pos s |> error) - | Function { name; arity; arg_names; body } -> ( + | Function { name; env; arity; arg_names; body } -> ( let args_len = List.length args in if args_len <> arity then let msg = @@ -149,7 +149,8 @@ let rec interpret_expr (env : environment) (expr_node : expr_node) : lox_value i in RuntimeError.make pos msg |> error else - let env = Env.push_frame env in + (* let env = Env.push_frame env in *) + let env = Env.enter env in let () = List.iter2 (fun name value -> assert (Env.define env name value)) arg_names args in @@ -190,7 +191,7 @@ and interpret_stmt (env : environment) (stmt_node : stmt_node) : unit interprete in RuntimeError.make pos msg |> error | FunDecl { name; arg_names; body } -> - let fn = make_lox_function name arg_names body in + let fn = make_lox_function name env arg_names body in let success = Env.define env name fn in if success then Ok () else diff --git a/lib/parser.ml b/lib/parser.ml index 993db83..e4a1cfd 100644 --- a/lib/parser.ml +++ b/lib/parser.ml @@ -419,7 +419,6 @@ and fun_declaration (state : state) : stmt_result = let* () = consume state RightParen in let* body = with_is_in_fun block state in make_fun_decl pos name arg_names body |> Result.ok -(* make_nil pos |> make_expr_stmt pos |> Result.ok *) and declaration (state : state) : stmt_result = match peek_tt state with diff --git a/lib/value.ml b/lib/value.ml index 1ba4e21..ecb7f81 100644 --- a/lib/value.ml +++ b/lib/value.ml @@ -1,12 +1,12 @@ type lox_function = { name : string; + env : environment; arity : int; - (* env : Environment.environment; [@printer fun fmt _ -> fprintf fmt ""] *) arg_names : string list; body : Stmt.stmt_node; [@printer fun fmt _ -> fprintf fmt ""] } -type native_function = { +and native_function = { name : string; arity : int; fn : lox_value list -> (lox_value, string) result; @@ -20,6 +20,9 @@ and lox_value = | Bool of bool | Nil +and env_table = (string, lox_value) Hashtbl.t +and environment = { globals : env_table ref; locals : env_table list } + let string_of_lox_value lox_value = match lox_value with | Function { name; arity; _ } -> Printf.sprintf "" name arity @@ -40,7 +43,7 @@ let type_string_of_lox_value lox_value = let lox_value_to_bool lox_value = match lox_value with Bool b -> b | Nil -> false | _ -> true -let make_lox_function (name : string) (arg_names : string list) (body : Stmt.stmt_node) : lox_value - = +let make_lox_function (name : string) (env : environment) (arg_names : string list) + (body : Stmt.stmt_node) : lox_value = let arity = List.length arg_names in - Function { name; arity; arg_names; body } + Function { name; env; arity; arg_names; body } diff --git a/lox.t/run.t b/lox.t/run.t index f249202..313dbff 100644 --- a/lox.t/run.t +++ b/lox.t/run.t @@ -205,19 +205,28 @@ $ mlox class/reference_self.lox file closure/assign_to_closure.lox -$ mlox closure/assign_to_closure.lox + $ mlox closure/assign_to_closure.lox + local + after f + after f + after g file closure/assign_to_shadowed_later.lox $ mlox closure/assign_to_shadowed_later.lox +inner +assigned file closure/close_over_function_parameter.lox -$ mlox closure/close_over_function_parameter.lox + $ mlox closure/close_over_function_parameter.lox + param file closure/close_over_later_variable.lox -$ mlox closure/close_over_later_variable.lox + $ mlox closure/close_over_later_variable.lox + b + a file closure/close_over_method_parameter.lox @@ -225,35 +234,48 @@ $ mlox closure/close_over_method_parameter.lox file closure/closed_closure_in_function.lox -$ mlox closure/closed_closure_in_function.lox + $ mlox closure/closed_closure_in_function.lox + local file closure/nested_closure.lox -$ mlox closure/nested_closure.lox + $ mlox closure/nested_closure.lox + a + b + c file closure/open_closure_in_function.lox -$ mlox closure/open_closure_in_function.lox + $ mlox closure/open_closure_in_function.lox + local file closure/reference_closure_multiple_times.lox -$ mlox closure/reference_closure_multiple_times.lox + $ mlox closure/reference_closure_multiple_times.lox + a + a file closure/reuse_closure_slot.lox -$ mlox closure/reuse_closure_slot.lox + $ mlox closure/reuse_closure_slot.lox + a file closure/shadow_closure_with_local.lox -$ mlox closure/shadow_closure_with_local.lox + $ mlox closure/shadow_closure_with_local.lox + closure + shadow + closure file closure/unused_closure.lox -$ mlox closure/unused_closure.lox + $ mlox closure/unused_closure.lox + ok file closure/unused_later_closure.lox -$ mlox closure/unused_later_closure.lox + $ mlox closure/unused_later_closure.lox + a file comments/line_at_eof.lox @@ -532,9 +554,9 @@ file function/extra_arguments.lox file function/local_mutual_recursion.lox - $ mlox function/local_mutual_recursion.lox - RuntimeError at line 4, column 11: name "isOdd" is not defined - [1] +$ mlox function/local_mutual_recursion.lox +RuntimeError at line 4, column 11: name "isOdd" is not defined +[1] file function/local_recursion.lox $ mlox function/local_recursion.lox @@ -1079,7 +1101,8 @@ file print/missing_argument.lox file regression/40.lox -$ mlox regression/40.lox + $ mlox regression/40.lox + false file regression/394.lox @@ -1268,6 +1291,8 @@ file variable/duplicate_parameter.lox file variable/early_bound.lox $ mlox variable/early_bound.lox +outer +outer file variable/in_middle_of_block.lox @@ -1379,7 +1404,10 @@ $ mlox while/class_in_body.lox file while/closure_in_body.lox -$ mlox while/closure_in_body.lox + $ mlox while/closure_in_body.lox + 1 + 2 + 3 file while/fun_in_body.lox @@ -1390,7 +1418,8 @@ file while/fun_in_body.lox file while/return_closure.lox -$ mlox while/return_closure.lox + $ mlox while/return_closure.lox + i file while/return_inside.lox