implemented function calls

This commit is contained in:
Moritz Gmeiner 2024-08-28 17:29:36 +02:00
commit b717b91ee5
3 changed files with 94 additions and 21 deletions

View file

@ -87,17 +87,37 @@ let rec interpret_expr (env : environment) (expr_node : expr_node) :
in
let* args = List.fold_left f (Ok []) args in
let args = List.rev args in
(* let args_s =
List.fold_left (fun acc value -> acc ^ " " ^ string_of_lox_value value) "" args
in
Printf.eprintf "Called %s with args%s\n%!" (string_of_lox_value callee) args_s; *)
match callee with
| Function (NativeFunction { name; arity; fn }) ->
let args_len = List.length args in
if args_len <> arity then
let msg =
Printf.sprintf "Native Function %s has arity %d, but was called with %d args" name
args_len arity
in
RuntimeError.make pos msg |> Result.error
else fn args |> Result.map_error (RuntimeError.make pos)
| Function (LoxFunction { name; arity; arg_names; body }) ->
let args_len = List.length args in
if args_len <> arity then
let msg =
Printf.sprintf "Function %s has arity %d, but was called with %d args" name args_len
arity
in
RuntimeError.make pos msg |> Result.error
else
let env = Env.push_frame env in
let () =
List.iter2 (fun name value -> assert (Env.define env name value)) arg_names args
in
let* () = interpret_stmt env body in
Ok Nil
| _ ->
ignore args;
let msg = Printf.sprintf "%s object is not callable" (type_string_of_lox_value callee) in
RuntimeError.make pos msg |> Result.error)
let rec interpret_stmt (env : environment) (stmt_node : stmt_node) : (unit, runtime_error) result =
and interpret_stmt (env : environment) (stmt_node : stmt_node) : (unit, runtime_error) result =
let { pos; stmt } = stmt_node in
ignore pos;
match stmt with
@ -116,7 +136,19 @@ let rec interpret_stmt (env : environment) (stmt_node : stmt_node) : (unit, runt
let success = Env.define env name init in
if success then Ok ()
else
let msg = Printf.sprintf "Tried to define %s, but was already defined" name in
let msg =
Printf.sprintf "Tried to define %s, but a variable of that name was already defined" name
in
RuntimeError.make pos msg |> Result.error
| FunDecl { name; arg_names; body } ->
let fn = make_lox_function name arg_names body in
let success = Env.define env name fn in
if success then Ok ()
else
let msg =
Printf.sprintf
"Tried to define function %s, but a variable of that name was already defined" name
in
RuntimeError.make pos msg |> Result.error
| Block stmts ->
let env = Env.enter env in