Refactor function evaluation; now can partially apply

This commit is contained in:
백현웅 2022-02-11 02:54:21 +09:00
parent b2251d26d5
commit 138d12e899
3 changed files with 30 additions and 19 deletions

16
ast.ml
View file

@ -5,7 +5,7 @@ type t =
| Nbool of bool | Nbool of bool
| Nstring of string | Nstring of string
| Nsymbol of string | Nsymbol of string
| Nfunction of string list * t | Nfunction of string * t
| Nexternal of string | Nexternal of string
| Var of string | Var of string
| Let of string * t | Let of string * t
@ -50,6 +50,13 @@ 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
| Nint n -> pr "%d" n | Nint n -> pr "%d" n
@ -57,9 +64,10 @@ 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 (args, e) -> | Nfunction (arg, e) ->
pr "(lambda (%s" @@ List.hd args; let args, e = cascade e in
List.iter (pr " %s") @@ List.tl args; pr "(lambda (%s" arg;
List.iter (pr " %s") args;
pr ") "; aux e; pr ")" pr ") "; aux e; pr ")"
| Nexternal e -> pr "(extern %s)" e | Nexternal e -> pr "(extern %s)" e

30
eval.ml
View file

@ -7,7 +7,7 @@ type value =
| Bool of bool | Bool of bool
| String of string | String of string
| Symbol of string | Symbol of string
| Function of string list * expr * env | Function of string * expr * env
| External of string | External of string
| Nop (* return of system operations (will be deprecated) *) | Nop (* return of system operations (will be deprecated) *)
@ -58,8 +58,7 @@ module Value = struct
| Bool b -> string_of_bool b | Bool b -> string_of_bool b
| String s -> "\"" ^ s ^ "\"" | String s -> "\"" ^ s ^ "\""
| Symbol s -> "symbol " ^ s | Symbol s -> "symbol " ^ s
| Function (vars, _, _) -> | Function _ -> "<fun>"
Printf.sprintf "function with %d arguments" @@ List.length vars
| External f -> "external " ^ f | External f -> "external " ^ f
| Nop -> "nop" | Nop -> "nop"
@ -268,9 +267,7 @@ let rec eval env ast =
| Nbool b -> Bool b | Nbool b -> Bool b
| Nstring s -> String s | Nstring s -> String s
| Nsymbol s -> Symbol s | Nsymbol s -> Symbol s
| Nfunction (args, e) -> | Nfunction (arg, e) -> Function (arg, e, env)
let nenv = Env.make env in
Function (args, e, nenv)
| Nexternal f -> External f | Nexternal f -> External f
| Var v -> begin match Env.get_opt env v with | Var v -> begin match Env.get_opt env v with
@ -295,19 +292,24 @@ let rec eval 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 (v, args) ->
begin match aux v with begin match aux v with
| Function (vars, e, env) -> | Function (var, e, env) as f ->
assert_same_length vars args; begin match args with
let args = List.map aux args in | [] -> f
let nenv = Env.make env in | a::args ->
List.combine vars args let nenv = Env.make env in
|> List.iter (fun (v, a) -> Env.set nenv v a); Env.set nenv var (aux a);
eval nenv e eval nenv @@ Apply (e, args)
end
| External f -> | External f ->
let args = List.map aux args in let args = List.map aux args in
External.apply f args External.apply f args
| v -> raise @@ Type.Invalid (Value.typeof v) | v ->
if args = []
then v
else raise @@ Type.Invalid (Value.typeof v)
end end
| Set_binop_pre (op, l) -> | Set_binop_pre (op, l) ->

View file

@ -232,7 +232,8 @@ 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
Nfunction (v0::vars, e), seq List.fold_right (fun v f -> Nfunction (v, f)) (v0::vars) e,
seq
(* ifexpr := "if" expr "then" expr "else" expr *) (* ifexpr := "if" expr "then" expr "else" expr *)
and ifexpr seq = and ifexpr seq =