From 26c6f3d7bf6dde85fde2cbed2be8949b003f2c86 Mon Sep 17 00:00:00 2001 From: Hyeonung Baek Date: Tue, 22 Feb 2022 17:01:39 +0900 Subject: [PATCH] multiple arguments for function --- ast.ml | 13 +++---------- eval.ml | 43 +++++++++++++++++++++++++++---------------- parser.ml | 3 +-- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/ast.ml b/ast.ml index 6a764c2..8db8724 100644 --- a/ast.ml +++ b/ast.ml @@ -6,7 +6,7 @@ type t = | Nbool of bool | Nstring of string | Nsymbol of string - | Nfunction of string * t + | Nfunction of string list * t | Nexternal of string | Var of string | Let of string * t @@ -46,13 +46,6 @@ let binop left op right = (* print ast LISP style. *) let print ast = - let rec cascade = function - | Nfunction (arg, e) -> - let args, e = cascade e in - arg :: args, e - | e -> [], e - in - let pr = Printf.printf in let rec aux = function | Nothing -> pr "" @@ -61,8 +54,7 @@ let print ast = | Nbool b -> pr "%b" b | Nstring s -> pr "\"%s\"" s | Nsymbol s -> pr "#%s" s - | Nfunction (arg, e) -> - let args, e = cascade e in + | Nfunction (arg::args, e) -> pr "(lambda (%s" arg; List.iter (pr " %s") args; pr ") "; aux e; pr ")" @@ -84,5 +76,6 @@ let print ast = pr "(if"; f co; f th; f el; pr ")" | Apply (f, args) -> pr "("; aux f; List.iter (fun a -> pr " "; aux a) args; pr ")" + | _ -> invalid_arg "Ast.print" in aux ast; pr "\n" diff --git a/eval.ml b/eval.ml index 3984692..ccf01c7 100644 --- a/eval.ml +++ b/eval.ml @@ -7,8 +7,8 @@ type value = | Bool of bool | String of string | Symbol of string - (* (name), arg, expression, name *) - | Function of string option * string * expr * env + (* (name), bound variables, expression, environment *) + | Function of string option * string list * expr * env | External of string | Nop (* return of system operations (will be deprecated) *) @@ -309,30 +309,41 @@ let rec eval global env ast = | Bool false -> aux el | v -> raise @@ Type.Invalid (Value.typeof v) end - | Apply (v, args) -> apply global env v args + | Apply (v, args) -> + let args = List.map (eval global env) args in + apply global env v args | _ -> failwith "Eval.eval" (* apply args to result of expr *) and apply global env expr args = match eval global env expr with - | Function (itself, var, body, local_env) as f -> + | Function (itself, vars, body, local_env) as f -> begin match args with | [] -> f - | a::args -> - let value = eval global env a in - let env = (* binding itself into env for recursion *) - itself - |> Option.fold - ~none: local_env - ~some: (fun n -> Env.bind (n, f) local_env) - |> Env.bind (var, value) + | args -> + let rec aux e = function + | [], [] -> [], [], e + | vars, [] -> vars, [], e + | [], args -> [], args, e + | v::vars, a::args -> + let e = Env.bind (v, a) e in + aux e (vars, args) in - apply global env body args + let vars, args, env = aux local_env (vars, args) in + let env = (* binding itself into env for recursion *) + itself |> Option.fold + ~none: env + ~some: (fun n -> Env.bind (n, f) env) + in + if vars <> [] then (* partially-applied function *) + Function (None, vars, body, env) + else if args <> [] then (* reapply *) + apply global env body args + else (* eval (vars = [], args = []) *) + eval global env body end - | External f -> - let args = List.map (eval global env) args in - External.apply f args + | External f -> External.apply f args | v -> if args = [] then v else raise @@ Type.Invalid (Value.typeof v) diff --git a/parser.ml b/parser.ml index 8e06d4b..5a7be02 100644 --- a/parser.ml +++ b/parser.ml @@ -215,8 +215,7 @@ and lambda seq = let vars, seq = more any_ident seq in let _, seq = token Right_arrow seq in let e, seq = expr min_int seq in - List.fold_right (fun v f -> Nfunction (v, f)) (v0::vars) e, - seq) + Nfunction (v0::vars, e), seq) (* ifexpr := "if" expr "then" expr "else" expr *) and ifexpr seq =