multiple arguments for function
This commit is contained in:
parent
8c029cd0d8
commit
26c6f3d7bf
3 changed files with 31 additions and 28 deletions
13
ast.ml
13
ast.ml
|
@ -6,7 +6,7 @@ type t =
|
||||||
| Nbool of bool
|
| Nbool of bool
|
||||||
| Nstring of string
|
| Nstring of string
|
||||||
| Nsymbol of string
|
| Nsymbol of string
|
||||||
| Nfunction of string * t
|
| Nfunction of string list * t
|
||||||
| Nexternal of string
|
| Nexternal of string
|
||||||
| Var of string
|
| Var of string
|
||||||
| Let of string * t
|
| Let of string * t
|
||||||
|
@ -46,13 +46,6 @@ let binop left op right =
|
||||||
|
|
||||||
(* print ast LISP style. *)
|
(* print ast LISP style. *)
|
||||||
let print ast =
|
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 pr = Printf.printf in
|
||||||
let rec aux = function
|
let rec aux = function
|
||||||
| Nothing -> pr ""
|
| Nothing -> pr ""
|
||||||
|
@ -61,8 +54,7 @@ let print ast =
|
||||||
| Nbool b -> pr "%b" b
|
| Nbool b -> pr "%b" b
|
||||||
| Nstring s -> pr "\"%s\"" s
|
| Nstring s -> pr "\"%s\"" s
|
||||||
| Nsymbol s -> pr "#%s" s
|
| Nsymbol s -> pr "#%s" s
|
||||||
| Nfunction (arg, e) ->
|
| Nfunction (arg::args, e) ->
|
||||||
let args, e = cascade e in
|
|
||||||
pr "(lambda (%s" arg;
|
pr "(lambda (%s" arg;
|
||||||
List.iter (pr " %s") args;
|
List.iter (pr " %s") args;
|
||||||
pr ") "; aux e; pr ")"
|
pr ") "; aux e; pr ")"
|
||||||
|
@ -84,5 +76,6 @@ let print ast =
|
||||||
pr "(if"; f co; f th; f el; pr ")"
|
pr "(if"; f co; f th; f el; pr ")"
|
||||||
| Apply (f, args) ->
|
| Apply (f, args) ->
|
||||||
pr "("; aux f; List.iter (fun a -> pr " "; aux a) args; pr ")"
|
pr "("; aux f; List.iter (fun a -> pr " "; aux a) args; pr ")"
|
||||||
|
| _ -> invalid_arg "Ast.print"
|
||||||
in
|
in
|
||||||
aux ast; pr "\n"
|
aux ast; pr "\n"
|
||||||
|
|
41
eval.ml
41
eval.ml
|
@ -7,8 +7,8 @@ type value =
|
||||||
| Bool of bool
|
| Bool of bool
|
||||||
| String of string
|
| String of string
|
||||||
| Symbol of string
|
| Symbol of string
|
||||||
(* (name), arg, expression, name *)
|
(* (name), bound variables, expression, environment *)
|
||||||
| Function of string option * string * expr * env
|
| Function of string option * string list * expr * env
|
||||||
| External of string
|
| External of string
|
||||||
| Nop (* return of system operations (will be deprecated) *)
|
| Nop (* return of system operations (will be deprecated) *)
|
||||||
|
|
||||||
|
@ -309,30 +309,41 @@ let rec eval global env ast =
|
||||||
| Bool false -> aux el
|
| Bool false -> aux el
|
||||||
| v -> raise @@ Type.Invalid (Value.typeof v)
|
| v -> raise @@ Type.Invalid (Value.typeof v)
|
||||||
end
|
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"
|
| _ -> failwith "Eval.eval"
|
||||||
|
|
||||||
(* apply args to result of expr *)
|
(* apply args to result of expr *)
|
||||||
and apply global env expr args =
|
and apply global env expr args =
|
||||||
match eval global env expr with
|
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
|
begin match args with
|
||||||
| [] -> f
|
| [] -> f
|
||||||
| a::args ->
|
| args ->
|
||||||
let value = eval global env a in
|
let rec aux e = function
|
||||||
let env = (* binding itself into env for recursion *)
|
| [], [] -> [], [], e
|
||||||
itself
|
| vars, [] -> vars, [], e
|
||||||
|> Option.fold
|
| [], args -> [], args, e
|
||||||
~none: local_env
|
| v::vars, a::args ->
|
||||||
~some: (fun n -> Env.bind (n, f) local_env)
|
let e = Env.bind (v, a) e in
|
||||||
|> Env.bind (var, value)
|
aux e (vars, args)
|
||||||
in
|
in
|
||||||
|
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
|
apply global env body args
|
||||||
|
else (* eval (vars = [], args = []) *)
|
||||||
|
eval global env body
|
||||||
end
|
end
|
||||||
| External f ->
|
| External f -> External.apply f args
|
||||||
let args = List.map (eval global env) args in
|
|
||||||
External.apply f args
|
|
||||||
| v ->
|
| v ->
|
||||||
if args = [] then v
|
if args = [] then v
|
||||||
else raise @@ Type.Invalid (Value.typeof v)
|
else raise @@ Type.Invalid (Value.typeof v)
|
||||||
|
|
|
@ -215,8 +215,7 @@ and lambda seq =
|
||||||
let vars, seq = more any_ident seq in
|
let vars, seq = more any_ident seq in
|
||||||
let _, seq = token Right_arrow seq in
|
let _, seq = token Right_arrow seq in
|
||||||
let e, seq = expr min_int seq in
|
let e, seq = expr min_int seq in
|
||||||
List.fold_right (fun v f -> Nfunction (v, f)) (v0::vars) e,
|
Nfunction (v0::vars, e), seq)
|
||||||
seq)
|
|
||||||
|
|
||||||
(* ifexpr := "if" expr "then" expr "else" expr *)
|
(* ifexpr := "if" expr "then" expr "else" expr *)
|
||||||
and ifexpr seq =
|
and ifexpr seq =
|
||||||
|
|
Loading…
Add table
Reference in a new issue