Stefan pushed to branch master at Stefan / Typer
Commits:
133a2261 by Stefan Monnier at 2016-11-30T17:28:01-05:00
Streamline the integer binary ops slightly
* btl/builtins.typer (_+_, _*_): Adapt to new builtin names.
(_-_, _/_): New builtins.
* src/eval.ml (add_binary_iop): Rename from _generic_binary_iop;
Rewrite. Register the primitive into builtin_functions.
(iadd_impl, isub_impl, imult_impl, idiv_impl): Don't give them names.
(typer_builtins_impl): Remove.
(<toplevel>): Don't manually add _+_ and _*_ to builtin_functions.
* src/lparse.ml (sform_built_in): Check builtin_functions to make sure
the built-in actually exists.
- - - - -
3 changed files:
- btl/builtins.typer
- src/eval.ml
- src/lparse.ml
Changes:
=====================================
btl/builtins.typer
=====================================
--- a/btl/builtins.typer
+++ b/btl/builtins.typer
@@ -39,8 +39,10 @@ Unit = inductive_ Unit unit;
unit = inductive-cons Unit unit;
% Basic operators
-_+_ = Built-in "_+_" (Int -> Int -> Int);
-_*_ = Built-in "_*_" (Int -> Int -> Int);
+_+_ = Built-in "Int.+" (Int -> Int -> Int);
+_-_ = Built-in "Int.-" (Int -> Int -> Int);
+_*_ = Built-in "Int.*" (Int -> Int -> Int);
+_/_ = Built-in "Int./" (Int -> Int -> Int);
Bool = inductive_ (Boolean) (True) (False);
True = inductive-cons Bool True;
=====================================
src/eval.ml
=====================================
--- a/src/eval.ml
+++ b/src/eval.ml
@@ -122,23 +122,19 @@ let elexp_fatal = debug_message fatal elexp_name elexp_string
* Builtins
*)
(* Builtin of builtin * string * ltype *)
-let _generic_binary_iop name f loc (depth : eval_debug_info)
- (args_val: value_type list) =
-
- let l, r = match args_val with
- | [l; r] -> l, r
- | _ -> error loc (name ^ " expects 2 Integers arguments") in
+let add_binary_iop name f =
+ let name = "Int." ^ name in
+ let f loc (depth : eval_debug_info) (args_val: value_type list) =
+ match args_val with
+ | [Vint(v); Vint(w)] -> Vint (f v w)
+ | _ -> error loc ("`" ^ name ^ "` expects 2 Integers arguments") in
+ add_builtin_function name f 2
- match l, r with
- | Vint(v), Vint(w) -> Vint(f v w)
- | _ ->
- debug_messages fatal loc (name ^ " expects Integers as arguments") [
- "(" ^ name ^ " " ^ (value_string l) ^ " " ^ (value_string r) ^ ")";]
-let iadd_impl = _generic_binary_iop "Integer::add" (fun a b -> a + b)
-let isub_impl = _generic_binary_iop "Integer::sub" (fun a b -> a - b)
-let imult_impl = _generic_binary_iop "Integer::mult" (fun a b -> a * b)
-let idiv_impl = _generic_binary_iop "Integer::div" (fun a b -> a / b)
+let _ = add_binary_iop "+" (+);
+ add_binary_iop "-" (-);
+ add_binary_iop "*" ( * );
+ add_binary_iop "/" (/)
let make_symbol loc depth args_val =
(* symbol is a simple string *)
@@ -311,12 +307,11 @@ and eval_call loc i f args =
(* return result of eval *)
| _, [] -> f
- | Vcons (n, fields), _ ->
- let e = Vcons(n, List.append fields args) in
- (* value_print e; print_string "\n"; *) e
+ | Vcons (n, fields), _
+ -> Vcons (n, List.append fields args)
- | Closure (x, e, ctx), v::vs ->
- let rec bindargs e vs ctx = match (vs, e) with
+ | Closure (x, e, ctx), v::vs
+ -> let rec bindargs e vs ctx = match (vs, e) with
| (v::vs, Lambda ((_, x), e))
(* "Uncurry" on the fly. *)
-> bindargs e vs (add_rte_variable (Some x) v ctx)
@@ -324,44 +319,39 @@ and eval_call loc i f args =
| _ -> eval_call loc i (_eval e ctx i) vs in
bindargs e vs (add_rte_variable (Some x) v ctx)
- | Vbuiltin (name), args ->
- (* FIXME: If there are fewer args, build a closure.
- * FIXME: If there are too many args, pass it to the
- * return value! *)
- (* lookup the built-in implementation and call it *)
- (try let (builtin, arity) = SMap.find name !builtin_functions in
- let nargs = List.length args in
- if nargs = arity then
- builtin loc i args (* Fast common case. *)
- else if nargs > arity then
- let rec split n vs acc = match (n, vs) with
- | 0, _ -> let v = eval_call loc i f (List.rev acc) in
- eval_call loc i v vs
- | _, (v::vs) -> split (n - 1) vs (v::acc)
- | _ -> error loc "Impossible!"
- in split nargs args []
- else
- let rec buildctx args ctx = match args with
- | [] -> ctx
- | arg::args -> buildctx args (add_rte_variable None arg ctx) in
- let rec buildargs n =
- if n >= 0
- then (Var ((loc, "<dummy>"), n))::buildargs (n - 1)
- else [] in
- let rec buildbody n =
- if n > 0 then
- Lambda ((loc, "<dummy>"), buildbody (n - 1))
- else Call (Builtin (dloc, name), buildargs (arity - 1)) in
- Closure ("<dummy>",
- buildbody (arity - nargs - 1),
- buildctx args Myers.nil)
-
- with Not_found ->
- error loc ("Requested Built-in `" ^ name ^ "` does not exist")
+ | Vbuiltin (name), args
+ -> (try let (builtin, arity) = SMap.find name !builtin_functions in
+ let nargs = List.length args in
+ if nargs = arity then
+ builtin loc i args (* Fast common case. *)
+ else if nargs > arity then
+ let rec split n vs acc = match (n, vs) with
+ | 0, _ -> let v = eval_call loc i f (List.rev acc) in
+ eval_call loc i v vs
+ | _, (v::vs) -> split (n - 1) vs (v::acc)
+ | _ -> error loc "Impossible!"
+ in split nargs args []
+ else
+ let rec buildctx args ctx = match args with
+ | [] -> ctx
+ | arg::args -> buildctx args (add_rte_variable None arg ctx) in
+ let rec buildargs n =
+ if n >= 0
+ then (Var ((loc, "<dummy>"), n))::buildargs (n - 1)
+ else [] in
+ let rec buildbody n =
+ if n > 0 then
+ Lambda ((loc, "<dummy>"), buildbody (n - 1))
+ else Call (Builtin (dloc, name), buildargs (arity - 1)) in
+ Closure ("<dummy>",
+ buildbody (arity - nargs - 1),
+ buildctx args Myers.nil)
+
+ with Not_found ->
+ error loc ("Requested Built-in `" ^ name ^ "` does not exist")
| e -> error loc ("Exception thrown from primitive `" ^ name ^"`"))
- | _ ->
- value_fatal loc f "Trying to call a non-function!"
+ | _ -> value_fatal loc f "Trying to call a non-function!"
and eval_case ctx i loc target pat dflt =
(* Eval target *)
@@ -426,26 +416,6 @@ and _eval_decls (decls: (vdef * elexp) list)
(* -------------------------------------------------------------------------- *)
(* Builtin Implementation (Some require eval) *)
-and typer_builtins_impl = [
- ("_+_" , iadd_impl);
- ("_*_" , imult_impl);
- ("block_" , make_block);
- ("symbol_" , make_symbol);
- ("string_" , make_string);
- ("integer_" , make_integer);
- ("float_" , make_float);
- ("node_" , make_node);
- ("sexp_dispatch_", sexp_dispatch);
- ("string_eq" , string_eq);
- ("int_eq" , int_eq);
- ("sexp_eq" , sexp_eq);
- ("open" , open_impl);
- ("bind" , bind_impl);
- ("run-io" , run_io);
- ("read" , read_impl);
- ("write" , write_impl);
-]
-
and bind_impl loc depth args_val =
match args_val with
| [Vcommand (cmd); callback]
@@ -567,8 +537,6 @@ and print_eval_trace trace =
let _ = List.iter (fun (name, f, arity) -> add_builtin_function name f arity)
[
- ("_+_" , iadd_impl, 2);
- ("_*_" , imult_impl, 2);
("block_" , make_block, 1);
("symbol_" , make_symbol, 1);
("string_" , make_string, 1);
=====================================
src/lparse.ml
=====================================
--- a/src/lparse.ml
+++ b/src/lparse.ml
@@ -44,7 +44,7 @@ open Lexp
open Env
open Debruijn
module DB = Debruijn
-open Eval
+module EV = Eval
open Grammar
module BI = Builtin
@@ -74,7 +74,7 @@ let fatal = msg_fatal "LPARSE"
(* Print Lexp name followed by the lexp in itself, finally throw an exception *)
let debug_message error_type type_name type_string loc expr message =
- debug_messages error_type loc
+ EV.debug_messages error_type loc
message [
(type_name expr) ^ ": " ^ (type_string expr);
]
@@ -165,7 +165,7 @@ let elab_check_def (ctx : elab_context) var lxp ltype =
then
elab_check_proper_type ctx ltype (Some var)
else
- (debug_messages fatal loc "Type check error: ¡¡ctx_define error!!" [
+ (EV.debug_messages fatal loc "Type check error: ¡¡ctx_define error!!" [
lexp_string lxp ^ " !: " ^ lexp_string ltype;
" because";
lexp_string ltype' ^ " != " ^ lexp_string ltype])
@@ -868,11 +868,11 @@ and lexp_expand_macro_ macro_funct sargs ctx expand_fun : value_type =
let macro = mkCall (macro_expand, args) in
let emacro = OL.erase_type macro in
- let rctx = from_lctx ctx in
+ let rctx = EV.from_lctx ctx in
(* eval macro *)
- let vxp = try _eval emacro rctx ([], [])
- with e -> print_eval_trace None; raise e in
+ let vxp = try EV._eval emacro rctx ([], [])
+ with e -> EV.print_eval_trace None; raise e in
(* Return results *)
(* Vint/Vstring/Vfloat might need to be converted to sexp *)
vxp
@@ -1089,6 +1089,8 @@ let sform_built_in ctx loc sargs =
let meta_ctx, _ = !global_substitution in
let ltp' = OL.lexp_close meta_ctx (ectx_to_lctx ctx) ltp in
let bi = mkBuiltin ((loc, name), ltp', None) in
+ if not (SMap.mem name (!EV.builtin_functions)) then
+ sexp_error loc ("Unknown built-in `" ^ name ^ "`");
BI.add_builtin_cst name bi;
bi
@@ -1175,7 +1177,7 @@ let default_lctx =
lctx in
lctx
-let default_rctx = from_lctx default_lctx
+let default_rctx = EV.from_lctx default_lctx
(* String Parsing
* --------------------------------------------------------- *)
@@ -1211,12 +1213,12 @@ let lexp_decl_str str lctx =
let _eval_expr_str str lctx rctx silent =
let lxps = lexp_expr_str str lctx in
let elxps = List.map OL.erase_type lxps in
- (eval_all elxps rctx silent)
+ (EV.eval_all elxps rctx silent)
let eval_expr_str str lctx rctx = _eval_expr_str str lctx rctx false
let eval_decl_str str lctx rctx =
let lxps, lctx = lexp_decl_str str lctx in
let elxps = (List.map OL.clean_decls lxps) in
- (eval_decls_toplevel elxps rctx), lctx
+ (EV.eval_decls_toplevel elxps rctx), lctx
View it on GitLab: https://gitlab.com/monnier/typer/commit/133a2261c1981cf4344a2be3ad47e6ee55b…
Stefan pushed to branch master at Stefan / Typer
Commits:
cda68e29 by Stefan Monnier at 2016-11-30T13:43:14-05:00
Fix partial application of builtins
* src/eval.ml (builtin_functions): Rename from _builtin_lookup.
Add arity info for each primitive.
(add_builtin_function): New function.
(_eval): Eval `Call` args before calling eval_call.
(get_predef_eval): Remove unused.
(eval_call): Rewrite. Signal an error if a builtin throws an
exception: since Typer's language is total this should only happen
if there's a bug in Typer's own code.
(bind_impl): Use eval_call; simplify.
(get_builtin_impl): Remove. Pre-fill builtin_functions instead.
* src/elexp.ml (elexp_string): Add deb-indices in output.
* tests/eval_test.ml ("Partial Application"): Also test partial
application of builtins.
- - - - -
3 changed files:
- src/elexp.ml
- src/eval.ml
- tests/eval_test.ml
Changes:
=====================================
src/elexp.ml
=====================================
--- a/src/elexp.ml
+++ b/src/elexp.ml
@@ -118,7 +118,7 @@ and elexp_string lxp =
match lxp with
| Imm(s) -> sexp_string s
| Builtin((_, s)) -> s
- | Var((_, s), _) -> s
+ | Var((_, s), i) -> s ^ "[" ^ string_of_int i ^ "]"
| Cons((_, s)) -> s
| Lambda((_, s), b) -> "lambda " ^ s ^ " -> " ^ (elexp_string b)
=====================================
src/eval.ml
=====================================
--- a/src/eval.ml
+++ b/src/eval.ml
@@ -52,8 +52,15 @@ let dloc = dummy_location
let _global_eval_trace = ref ([], [])
let _global_eval_ctx = ref make_runtime_ctx
let _eval_max_recursion_depth = ref 255
-let _builtin_lookup = ref (SMap.empty : (location -> eval_debug_info
- -> value_type list -> value_type) SMap.t)
+
+let builtin_functions
+ = ref (SMap.empty : ((location -> eval_debug_info
+ -> value_type list -> value_type)
+ (* The primitive's arity. *)
+ * int) SMap.t)
+
+let add_builtin_function name f arity =
+ builtin_functions := SMap.add name (f, arity) (!builtin_functions)
let append_eval_trace trace (expr : elexp) =
let (a, b) = trace in
@@ -278,8 +285,12 @@ let rec _eval lxp (ctx : Env.runtime_env) (trace : eval_debug_info): (value_type
eval inst nctx
(* Function call *)
- | Call (lname, args) ->
- eval_call ctx (append_typer_trace trace lxp) lname args
+ | Call (f, args)
+ (* FIXME: Add the trace only once we enter the function? *)
+ -> let ntrace = append_typer_trace trace lxp in
+ eval_call (elexp_location f) ntrace
+ (_eval f ctx ntrace)
+ (List.map (fun e -> _eval e ctx ntrace) args)
(* Case *)
| Case (loc, target, pat, dflt)
@@ -288,11 +299,6 @@ let rec _eval lxp (ctx : Env.runtime_env) (trace : eval_debug_info): (value_type
| Type -> Vcons((tloc, "Unit"), [])
-and get_predef_eval name ctx =
- let r = (get_rte_size ctx) - !builtin_size in
- let v = mkSusp (get_predef_raw name) (S.shift r) in
- _eval (OL.erase_type v) ctx ([], [])
-
and eval_var ctx lxp v =
let ((loc, name), idx) = v in
try get_rte_variable (Some name) (idx) ctx
@@ -300,36 +306,62 @@ and eval_var ctx lxp v =
elexp_fatal loc lxp
("Variable: " ^ name ^ (str_idx idx) ^ " was not found ")
-and eval_call ctx i lname eargs =
- let loc = elexp_location lname in
- let f = _eval lname ctx i in
-
- (* standard function *)
- let rec eval_call f args ctx =
- match f, args with
- | Vcons (n, []), _ ->
- let e = Vcons(n, args) in
- (* value_print e; print_string "\n"; *) e
-
- (* we add an argument to the closure *)
- | Closure (n, lxp, ctx), hd::tl ->
- let nctx = add_rte_variable (Some n) hd ctx in
- let ret = _eval lxp nctx i in
- eval_call ret tl nctx
-
- | Vbuiltin (str), args ->
- (* lookup the built-in implementation and call it *)
- (get_builtin_impl str loc) loc i args
-
- (* return result of eval *)
- | _, [] -> f
-
- | _ ->
- value_fatal loc f "Cannot eval function" in
-
- (* eval function here *)
- let args = List.map (fun e -> _eval e ctx i) eargs in
- eval_call f args ctx
+and eval_call loc i f args =
+ match f, args with
+ (* return result of eval *)
+ | _, [] -> f
+
+ | Vcons (n, fields), _ ->
+ let e = Vcons(n, List.append fields args) in
+ (* value_print e; print_string "\n"; *) e
+
+ | Closure (x, e, ctx), v::vs ->
+ let rec bindargs e vs ctx = match (vs, e) with
+ | (v::vs, Lambda ((_, x), e))
+ (* "Uncurry" on the fly. *)
+ -> bindargs e vs (add_rte_variable (Some x) v ctx)
+ | ([], _) -> _eval e ctx i
+ | _ -> eval_call loc i (_eval e ctx i) vs in
+ bindargs e vs (add_rte_variable (Some x) v ctx)
+
+ | Vbuiltin (name), args ->
+ (* FIXME: If there are fewer args, build a closure.
+ * FIXME: If there are too many args, pass it to the
+ * return value! *)
+ (* lookup the built-in implementation and call it *)
+ (try let (builtin, arity) = SMap.find name !builtin_functions in
+ let nargs = List.length args in
+ if nargs = arity then
+ builtin loc i args (* Fast common case. *)
+ else if nargs > arity then
+ let rec split n vs acc = match (n, vs) with
+ | 0, _ -> let v = eval_call loc i f (List.rev acc) in
+ eval_call loc i v vs
+ | _, (v::vs) -> split (n - 1) vs (v::acc)
+ | _ -> error loc "Impossible!"
+ in split nargs args []
+ else
+ let rec buildctx args ctx = match args with
+ | [] -> ctx
+ | arg::args -> buildctx args (add_rte_variable None arg ctx) in
+ let rec buildargs n =
+ if n >= 0
+ then (Var ((loc, "<dummy>"), n))::buildargs (n - 1)
+ else [] in
+ let rec buildbody n =
+ if n > 0 then
+ Lambda ((loc, "<dummy>"), buildbody (n - 1))
+ else Call (Builtin (dloc, name), buildargs (arity - 1)) in
+ Closure ("<dummy>",
+ buildbody (arity - nargs - 1),
+ buildctx args Myers.nil)
+
+ with Not_found ->
+ error loc ("Requested Built-in `" ^ name ^ "` does not exist")
+ | e -> error loc ("Exception thrown from primitive `" ^ name ^"`"))
+
+ | _ ->
+ value_fatal loc f "Trying to call a non-function!"
and eval_case ctx i loc target pat dflt =
(* Eval target *)
@@ -415,31 +447,11 @@ and typer_builtins_impl = [
]
and bind_impl loc depth args_val =
-
- let io, cb = match args_val with
- | [io; callback] -> io, callback
- | _ -> error loc "bind expects two arguments" in
-
- (* build Vcommand from io function *)
- let cmd = match io with
- | Vcommand (cmd) -> cmd
- | _ -> error loc "bind first arguments must be a monad" in
-
- (* bind returns another Vcommand *)
- Vcommand (fun () ->
- (* get callback *)
- let body, ctx = match cb with
- | Closure(_, body, ctx) -> body, ctx
- | _ -> error loc "A Closure was expected" in
-
- (* run given command *)
- let underlying = cmd () in
-
- (* add evaluated IO to arg list *)
- let nctx = add_rte_variable None underlying ctx in
-
- (* eval callback *)
- _eval body nctx depth)
+ match args_val with
+ | [Vcommand (cmd); callback]
+ -> (* bind returns another Vcommand *)
+ Vcommand (fun () -> eval_call loc depth callback [cmd ()])
+ | _ -> error loc "Wrong number of args or wrong first arg value in `bind`"
and run_io loc depth args_val =
@@ -457,18 +469,6 @@ and run_io loc depth args_val =
(* return given type *)
ltp
-and get_builtin_impl str loc =
- (* Make built-in lookup table *)
- (match (SMap.is_empty !_builtin_lookup) with
- | true ->
- _builtin_lookup := (List.fold_left (fun lkup (name, f) ->
- SMap.add name f lkup) SMap.empty typer_builtins_impl)
- | _ -> ());
-
- try SMap.find str !_builtin_lookup
- with Not_found ->
- error loc ("Requested Built-in \"" ^ str ^ "\" does not exist")
-
(* Sexp -> (Sexp -> List Sexp -> Sexp) -> (String -> Sexp) ->
(String -> Sexp) -> (Int -> Sexp) -> (Float -> Sexp) -> (List Sexp -> Sexp)
-> Sexp *)
@@ -565,6 +565,27 @@ and print_eval_trace trace =
let (a, b) = !_global_eval_trace in
print_trace " EVAL TRACE " trace a
+let _ = List.iter (fun (name, f, arity) -> add_builtin_function name f arity)
+ [
+ ("_+_" , iadd_impl, 2);
+ ("_*_" , imult_impl, 2);
+ ("block_" , make_block, 1);
+ ("symbol_" , make_symbol, 1);
+ ("string_" , make_string, 1);
+ ("integer_" , make_integer, 1);
+ ("float_" , make_float, 1);
+ ("node_" , make_node, 2);
+ ("sexp_dispatch_", sexp_dispatch, 7);
+ ("string_eq" , string_eq, 2);
+ ("int_eq" , int_eq, 2);
+ ("sexp_eq" , sexp_eq, 2);
+ ("open" , open_impl, 2);
+ ("bind" , bind_impl, 2);
+ ("run-io" , run_io, 2);
+ ("read" , read_impl, 2);
+ ("write" , write_impl, 2);
+ ]
+
let eval lxp ctx = _eval lxp ctx ([], [])
let debug_eval lxp ctx =
=====================================
tests/eval_test.ml
=====================================
--- a/tests/eval_test.ml
+++ b/tests/eval_test.ml
@@ -230,12 +230,12 @@ let _ = test_eval_eqv_named
"add : Int -> Int -> Int;
add = lambda x y -> (x + y);
- inc : Int -> Int;
- inc = add 1;"
+ inc1 = add 1;
+ inc2 = _+_ 2;"
- "inc 1; inc 2; inc 3;"
+ "inc1 1; inc2 2; inc1 3;"
- "2; 3; 4"
+ "2; 4; 4"
(*
* Lists
View it on GitLab: https://gitlab.com/monnier/typer/commit/cda68e292e4c6d2c7b1b9e0a37a9f0154fd…
Stefan pushed to branch master at Stefan / Typer
Commits:
96d9936b by Stefan Monnier at 2016-11-30T12:11:59-05:00
* src/eval.ml: Don't pass `ctx` to builtins
(none_fun): Remove, unused.
(typer_eval): Remove function and corresponding builtin.
(_builtin_lookup): Change type.
- - - - -
1 changed file:
- src/eval.ml
Changes:
=====================================
src/eval.ml
=====================================
--- a/src/eval.ml
+++ b/src/eval.ml
@@ -52,7 +52,8 @@ let dloc = dummy_location
let _global_eval_trace = ref ([], [])
let _global_eval_ctx = ref make_runtime_ctx
let _eval_max_recursion_depth = ref 255
-let _builtin_lookup = ref SMap.empty
+let _builtin_lookup = ref (SMap.empty : (location -> eval_debug_info
+ -> value_type list -> value_type) SMap.t)
let append_eval_trace trace (expr : elexp) =
let (a, b) = trace in
@@ -113,12 +114,9 @@ let elexp_fatal = debug_message fatal elexp_name elexp_string
(*
* Builtins
*)
-let none_fun : (location -> eval_debug_info -> value_type list -> runtime_env -> value_type)
- = (fun loc args_val ctx -> error loc "Requested Built-in was not implemented")
-
(* Builtin of builtin * string * ltype *)
let _generic_binary_iop name f loc (depth : eval_debug_info)
- (args_val: value_type list) (ctx: runtime_env) =
+ (args_val: value_type list) =
let l, r = match args_val with
| [l; r] -> l, r
@@ -135,7 +133,7 @@ let isub_impl = _generic_binary_iop "Integer::sub" (fun a b -> a - b)
let imult_impl = _generic_binary_iop "Integer::mult" (fun a b -> a * b)
let idiv_impl = _generic_binary_iop "Integer::div" (fun a b -> a / b)
-let make_symbol loc depth args_val ctx =
+let make_symbol loc depth args_val =
(* symbol is a simple string *)
let lxp = match args_val with
| [r] -> r
@@ -145,7 +143,7 @@ let make_symbol loc depth args_val ctx =
| Vstring(str) -> Vsexp(Symbol(loc, str))
| _ -> value_error loc lxp "symbol_ expects one string as argument"
-let make_node loc depth args_val ctx =
+let make_node loc depth args_val =
let op, tlist = match args_val with
| [Vsexp(op); lst] -> op, lst
@@ -162,12 +160,12 @@ let make_node loc depth args_val ctx =
| Vint (i) -> Integer(dloc, i)
| Vstring (s) -> String(dloc, s)
| _ ->
- print_rte_ctx ctx;
+ (* print_rte_ctx ctx; *)
value_error loc g "node_ expects 'List Sexp' second as arguments") args in
Vsexp(Node(op, s))
-let make_string loc depth args_val ctx =
+let make_string loc depth args_val =
let lxp = match args_val with
| [r] -> r
| _ -> error loc "string_ expects 1 argument" in
@@ -176,7 +174,7 @@ let make_string loc depth args_val ctx =
| Vstring(str) -> Vsexp(String(loc, str))
| _ -> value_error loc lxp "string_ expects one string as argument"
-let make_integer loc depth args_val ctx =
+let make_integer loc depth args_val =
let lxp = match args_val with
| [r] -> r
| _ -> error loc "integer_ expects 1 argument" in
@@ -185,29 +183,29 @@ let make_integer loc depth args_val ctx =
| Vint(str) -> Vsexp(Integer(loc, str))
| _ -> value_error loc lxp "integer_ expects one string as argument"
-let make_float loc depth args_val ctx = Vdummy
-let make_block loc depth args_val ctx = Vdummy
+let make_float loc depth args_val = Vdummy
+let make_block loc depth args_val = Vdummy
let ttrue = Vcons((dloc, "True"), [])
let tfalse = Vcons((dloc, "False"), [])
let btyper b = if b then ttrue else tfalse
-let string_eq loc depth args_val ctx =
+let string_eq loc depth args_val =
match args_val with
| [Vstring(s1); Vstring(s2)] -> btyper (s1 = s2)
| _ -> error loc "string_eq expects 2 strings"
-let int_eq loc depth args_val ctx =
+let int_eq loc depth args_val =
match args_val with
| [Vint(s1); Vint(s2)] -> btyper (s1 = s2)
| _ -> error loc "int_eq expects 2 integer"
-let sexp_eq loc depth args_val ctx =
+let sexp_eq loc depth args_val =
match args_val with
| [Vsexp (s1); Vsexp (s2)] -> btyper (sexp_equal s1 s2)
| _ -> error loc "sexp_eq expects 2 sexp"
-let open_impl loc depth args_val ctx =
+let open_impl loc depth args_val =
let file, mode = match args_val with
| [Vstring(file_name); Vstring(mode)] -> file_name, mode
@@ -220,7 +218,7 @@ let open_impl loc depth args_val ctx =
| "w" -> Vout(open_out file)
| _ -> error loc "wrong open mode")
-let read_impl loc depth args_val ctx =
+let read_impl loc depth args_val =
let channel = match args_val with
| [Vin(c); _] -> c
@@ -231,7 +229,7 @@ let read_impl loc depth args_val ctx =
let line = input_line channel in
Vstring(line)
-let write_impl loc depth args_val ctx =
+let write_impl loc depth args_val =
let channel, msg = match args_val with
| [Vout(c); Vstring(msg)] -> c, msg
@@ -321,7 +319,7 @@ and eval_call ctx i lname eargs =
| Vbuiltin (str), args ->
(* lookup the built-in implementation and call it *)
- (get_builtin_impl str loc) loc i args ctx
+ (get_builtin_impl str loc) loc i args
(* return result of eval *)
| _, [] -> f
@@ -409,7 +407,6 @@ and typer_builtins_impl = [
("string_eq" , string_eq);
("int_eq" , int_eq);
("sexp_eq" , sexp_eq);
- ("eval_" , typer_eval);
("open" , open_impl);
("bind" , bind_impl);
("run-io" , run_io);
@@ -417,7 +414,7 @@ and typer_builtins_impl = [
("write" , write_impl);
]
-and bind_impl loc depth args_val ctx =
+and bind_impl loc depth args_val =
let io, cb = match args_val with
| [io; callback] -> io, callback
@@ -444,7 +441,7 @@ and bind_impl loc depth args_val ctx =
(* eval callback *)
_eval body nctx depth)
-and run_io loc depth args_val ctx =
+and run_io loc depth args_val =
let io, ltp = match args_val with
| [io; ltp] -> io, ltp
@@ -460,17 +457,6 @@ and run_io loc depth args_val ctx =
(* return given type *)
ltp
-and typer_eval loc depth args ctx =
- let arg = match args with
- | [a] -> a
- | _ -> error loc "eval_ expects a single argument" in
- (* I need to be able to lexp sexp but I don't have lexp ctx *)
- match arg with
- (* Nodes that can be evaluated *)
- | Closure (_, body, ctx) -> _eval body ctx depth
- (* Leaf *)
- | _ -> arg
-
and get_builtin_impl str loc =
(* Make built-in lookup table *)
(match (SMap.is_empty !_builtin_lookup) with
@@ -486,7 +472,7 @@ and get_builtin_impl str loc =
(* Sexp -> (Sexp -> List Sexp -> Sexp) -> (String -> Sexp) ->
(String -> Sexp) -> (Int -> Sexp) -> (Float -> Sexp) -> (List Sexp -> Sexp)
-> Sexp *)
-and sexp_dispatch loc depth args ctx =
+and sexp_dispatch loc depth args =
let eval a b = _eval a b depth in
let sxp, nd, sym, str, it, flt, blk, rctx = match args with
| [sxp; Closure(_, nd, rctx); Closure(_, sym, _);
View it on GitLab: https://gitlab.com/monnier/typer/commit/96d9936b1029c1f07e29bd0696596ef1b74…
Stefan pushed to branch master at Stefan / Typer
Commits:
43ddd912 by Stefan Monnier at 2016-11-28T13:31:18-05:00
* src/lparse.ml: Rewrite "Built-in" as a special form
* src/lparse.ml (handle_funcall): Don't treat `Built-in` specially.
(sform_built_in): New function.
(special_forms): Use it.
(default_lctx): Remove manual construction of "Built-in" builtin.
- - - - -
1 changed file:
- src/lparse.ml
Changes:
=====================================
src/lparse.ml
=====================================
--- a/src/lparse.ml
+++ b/src/lparse.ml
@@ -787,28 +787,8 @@ and infer_call (func: pexp) (sargs: sexp list) ctx =
^ "` to non-function (type = " ^ lexp_string ltp ^ ")") in
let handle_funcall () =
- (* Here we use lexp_whnf on actual code, but it's OK
- * because we only use the result when it's a "predefined constant". *)
- match OL.lexp_whnf body (ectx_to_lctx ctx) meta_ctx with
- | Builtin((_, "Built-in"), _, _) (* FIXME: Should be a Special-Form! *)
- -> (
- (* ------ SPECIAL ------ *)
- match !_parsing_internals, sargs with
- | true, [String (_, str); stp] ->
- let ptp = pexp_parse stp in
- let ltp, _ = infer ptp ctx in
- mkBuiltin((loc, str), ltp, None), ltp
-
- | true, _ -> error loc "Wrong Usage of `Built-in`";
- dlxp, dltype
-
- | false, _ -> error loc "Use of `Built-in` in user code";
- dlxp, dltype)
-
- | e ->
- (* Process Arguments. *)
- let largs, ret_type = handle_fun_args [] sargs SMap.empty ltp in
- mkCall (body, List.rev largs), ret_type in
+ let largs, ret_type = handle_fun_args [] sargs SMap.empty ltp in
+ mkCall (body, List.rev largs), ret_type in
let handle_macro_call () =
let sxp = match lexp_expand_macro body sargs ctx with
@@ -1097,6 +1077,20 @@ let sform_decltype ctx loc sargs =
| _ -> error loc "decltype expects one argument";
dlxp
+let sform_built_in ctx loc sargs =
+ match !_parsing_internals, sargs with
+ | true, [String (_, str); stp] ->
+ let ptp = pexp_parse stp in
+ let ltp, _ = infer ptp ctx in
+ mkBuiltin((loc, str), ltp, None)
+
+ | true, _ -> error loc "Wrong Usage of `Built-in`";
+ dlxp
+
+ | false, _ -> error loc "Use of `Built-in` in user code";
+ dlxp
+
+
(* Only print var info *)
and lexp_print_var_info ctx =
let ((m, _), env, _) = ctx in
@@ -1118,6 +1112,7 @@ and lexp_print_var_info ctx =
(* Register special forms. *)
let _ = List.iter add_special_form
[
+ ("Built-in", sform_built_in);
(* FIXME: We should add here `let_in_`, `case_`, etc... *)
("get-attribute", sform_get_attribute);
("new-attribute", sform_new_attribute);
@@ -1140,9 +1135,6 @@ let default_lctx =
-> if String.get key 0 = '-' then ctx
else ctx_define ctx (dloc, key) e t)
(!BI.lmap) lctx in
- (* FIXME: Add builtins directly here. *)
- let lxp = mkBuiltin((dloc, "Built-in"), DB.type0, None) in
- let lctx = ctx_define lctx (dloc, "Built-in") lxp DB.type0 in
(* Read BTL files *)
let pres = prelex_file (!btl_folder ^ "builtins.typer") in
View it on GitLab: https://gitlab.com/monnier/typer/commit/43ddd912b822ca553efc5ccdd2e59ea7aa9…
Stefan pushed to branch master at Stefan / Typer
Commits:
7535ecf7 by Stefan Monnier at 2016-11-28T13:23:40-05:00
* src/lparse.ml (special_forms): Remove last arg, move context 1st
- - - - -
1 changed file:
- src/lparse.ml
Changes:
=====================================
src/lparse.ml
=====================================
--- a/src/lparse.ml
+++ b/src/lparse.ml
@@ -91,7 +91,7 @@ let global_substitution = ref (empty_meta_subst, [])
(** Builtin Macros i.e, special forms. *)
type special_forms_map =
- (location -> sexp list -> elab_context -> lexp -> lexp) SMap.t
+ (elab_context -> location -> sexp list -> lexp) SMap.t
let special_forms : special_forms_map ref = ref SMap.empty
let type_special_form = BI.new_builtin_type "Special-Form" type0
@@ -749,7 +749,7 @@ and infer_call (func: pexp) (sargs: sexp list) ctx =
let default = Var((dloc, pname), pidx) in
(* lookup default attribute of ltp *)
- let attr = get_attribute loc [default; arg_type] ctx arg_type in
+ let attr = get_attribute ctx loc [default; arg_type] in
(* FIXME: The `default` attribute table shouldn't contain elements of
* type `Macro` but elements of type `something -> Sexp`.
* The point of the `Macro` type is to be able to distinguish
@@ -834,7 +834,7 @@ and infer_call (func: pexp) (sargs: sexp list) ctx =
match OL.lexp_whnf body (ectx_to_lctx ctx) meta_ctx with
| Builtin ((_, name), _, _) ->
(* Special form. *)
- let e = (get_special_form loc name) loc sargs ctx ltp in
+ let e = (get_special_form loc name) ctx loc sargs in
let meta_ctx, _ = !global_substitution in
(* FIXME: We don't actually need to typecheck `e`, we just need
* to find its type. *)
@@ -1018,9 +1018,10 @@ and lexp_parse_sexp (ctx: elab_context) (e : sexp) : lexp =
let e, _ = infer (pexp_parse e) ctx in e
(* --------------------------------------------------------------------------
- * Special form implementation
+ * Special forms implementation
* -------------------------------------------------------------------------- *)
-and new_attribute_impl loc sargs ctx ftype =
+
+and sform_new_attribute ctx loc sargs =
let ltp = match sargs with
| [t] -> lexp_parse_sexp ctx t
| _ -> fatal loc "new-attribute expects a single Type argument" in
@@ -1030,7 +1031,7 @@ and new_attribute_impl loc sargs ctx ftype =
* instead. *)
Builtin ((loc, "new-attribute"), ltp, Some AttributeMap.empty)
-and add_attribute_impl loc (sargs : sexp list) ctx ftype =
+and sform_add_attribute ctx loc (sargs : sexp list) =
let n = get_size ctx in
let table, var, attr = match List.map (lexp_parse_sexp ctx) sargs with
| [table; Var((_, name), idx); attr] -> table, (n - idx, name), attr
@@ -1045,7 +1046,7 @@ and add_attribute_impl loc (sargs : sexp list) ctx ftype =
let table = AttributeMap.add var attr map in
Builtin ((loc, "add-attribute"), attr_type, Some table)
-and get_attribute loc largs ctx ftype =
+and get_attribute ctx loc largs =
let ctx_n = get_size ctx in
let table, var = match largs with
| [table; Var((_, name), idx)] -> table, (ctx_n - idx, name)
@@ -1059,10 +1060,10 @@ and get_attribute loc largs ctx ftype =
let lxp = AttributeMap.find var map in
(lxp : lexp)
-and get_attribute_impl loc (sargs : sexp list) ctx ftype =
- get_attribute loc (List.map (lexp_parse_sexp ctx) sargs) ctx ftype
+and sform_get_attribute ctx loc (sargs : sexp list) =
+ get_attribute ctx loc (List.map (lexp_parse_sexp ctx) sargs)
-and has_attribute_impl loc (sargs : sexp list) ctx ftype =
+and sform_has_attribute ctx loc (sargs : sexp list) =
let n = get_size ctx in
let table, var = match List.map (lexp_parse_sexp ctx) sargs with
| [table; Var((_, name), idx)] -> table, (n - idx, name)
@@ -1078,7 +1079,7 @@ and has_attribute_impl loc (sargs : sexp list) ctx ftype =
with Not_found ->
BI.get_predef "False" ctx
-and declexpr_impl loc sargs ctx ftype =
+and sform_declexpr ctx loc sargs =
match List.map (lexp_parse_sexp ctx) sargs with
| [Var((_, vn), vi)]
-> (match DB.env_lookup_expr ctx ((loc, vn), vi) with
@@ -1089,7 +1090,7 @@ and declexpr_impl loc sargs ctx ftype =
dlxp
-let decltype_impl loc sargs ctx ftype =
+let sform_decltype ctx loc sargs =
match List.map (lexp_parse_sexp ctx) sargs with
| [Var((_, vn), vi)]
-> DB.env_lookup_type ctx ((loc, vn), vi)
@@ -1118,13 +1119,13 @@ and lexp_print_var_info ctx =
let _ = List.iter add_special_form
[
(* FIXME: We should add here `let_in_`, `case_`, etc... *)
- ("get-attribute", get_attribute_impl);
- ("new-attribute", new_attribute_impl);
- ("has-attribute", has_attribute_impl);
- ("add-attribute", add_attribute_impl);
+ ("get-attribute", sform_get_attribute);
+ ("new-attribute", sform_new_attribute);
+ ("has-attribute", sform_has_attribute);
+ ("add-attribute", sform_add_attribute);
(* FIXME: These should be functions! *)
- ("decltype", decltype_impl);
- ("declexpr", declexpr_impl);
+ ("decltype", sform_decltype);
+ ("declexpr", sform_declexpr);
]
(* Default context with builtin types
View it on GitLab: https://gitlab.com/monnier/typer/commit/7535ecf78f40ddd3f69110531b41fb95a77…
Stefan pushed to branch master at Stefan / Typer
Commits:
7443ad30 by Stefan Monnier at 2016-11-28T13:14:13-05:00
Change special forms's args to be sexps rather than lexps
* src/builtin.ml (declexpr_impl, decltype_impl): Move to lparse.ml.
* src/lparse.ml (special_forms_map): Rename from macromap.
Change special forms's args to be sexps rather than lexps.
Adjust all users accordingly.
(lexp_parse_all): Rewrite using List.map.
(lexp_parse_sexp): New function.
- - - - -
2 changed files:
- src/builtin.ml
- src/lparse.ml
Changes:
=====================================
src/builtin.ml
=====================================
--- a/src/builtin.ml
+++ b/src/builtin.ml
@@ -168,30 +168,6 @@ let is_lbuiltin idx ctx =
else
false
-let declexpr_impl loc largs ctx ftype =
-
- let (vi, vn) = match largs with
- | [Var((_, vn), vi)] -> (vi, vn)
- | _ -> error loc "declexpr expects one argument" in
-
- let lxp = match DB.env_lookup_expr ctx ((loc, vn), vi) with
- | Some lxp -> lxp
- | None -> error loc "no expr available" in
- (* ltp and ftype should be the same
- let ltp = env_lookup_type ctx ((loc, vn), vi) in *)
- lxp
-
-
-let decltype_impl loc largs ctx ftype =
-
- let (vi, vn) = match largs with
- | [Var((_, vn), vi)] -> (vi, vn)
- | _ -> error loc "decltype expects one argument" in
-
- let ltype = DB.env_lookup_type ctx ((loc, vn), vi) in
- (* mkSusp prop (S.shift (var_i + 1)) *)
- ltype
-
(* Map of lexp builtin elements accessible via (## <name>). *)
let lmap = ref (SMap.empty : (L.lexp * L.ltype) SMap.t)
=====================================
src/lparse.ml
=====================================
--- a/src/lparse.ml
+++ b/src/lparse.ml
@@ -90,10 +90,10 @@ let value_fatal = debug_message fatal value_name value_string
let global_substitution = ref (empty_meta_subst, [])
(** Builtin Macros i.e, special forms. *)
-type macromap =
- (location -> lexp list -> elab_context -> lexp -> lexp) SMap.t
+type special_forms_map =
+ (location -> sexp list -> elab_context -> lexp -> lexp) SMap.t
-let special_forms : macromap ref = ref SMap.empty
+let special_forms : special_forms_map ref = ref SMap.empty
let type_special_form = BI.new_builtin_type "Special-Form" type0
let add_special_form (name, func) =
@@ -749,7 +749,7 @@ and infer_call (func: pexp) (sargs: sexp list) ctx =
let default = Var((dloc, pname), pidx) in
(* lookup default attribute of ltp *)
- let attr = get_attribute_impl loc [default; arg_type] ctx arg_type in
+ let attr = get_attribute loc [default; arg_type] ctx arg_type in
(* FIXME: The `default` attribute table shouldn't contain elements of
* type `Macro` but elements of type `something -> Sexp`.
* The point of the `Macro` type is to be able to distinguish
@@ -834,9 +834,7 @@ and infer_call (func: pexp) (sargs: sexp list) ctx =
match OL.lexp_whnf body (ectx_to_lctx ctx) meta_ctx with
| Builtin ((_, name), _, _) ->
(* Special form. *)
- let pargs = List.map pexp_parse sargs in
- let largs = lexp_parse_all pargs ctx in
- let e = (get_special_form loc name) loc largs ctx ltp in
+ let e = (get_special_form loc name) loc sargs ctx ltp in
let meta_ctx, _ = !global_substitution in
(* FIXME: We don't actually need to typecheck `e`, we just need
* to find its type. *)
@@ -1014,32 +1012,31 @@ and lexp_p_decls pdecls ctx: ((vdef * lexp * ltype) list list * elab_context) =
decls :: declss, nnctx
and lexp_parse_all (p: pexp list) (ctx: elab_context) : lexp list =
+ List.map (fun pe -> let e, _ = infer pe ctx in e) p
- let rec loop (plst: pexp list) ctx (acc: lexp list) =
- match plst with
- | [] -> (List.rev acc)
- | pe :: plst -> let lxp, _ = infer pe ctx in
- (loop plst ctx (lxp::acc)) in
-
- (loop p ctx [])
+and lexp_parse_sexp (ctx: elab_context) (e : sexp) : lexp =
+ let e, _ = infer (pexp_parse e) ctx in e
(* --------------------------------------------------------------------------
* Special form implementation
* -------------------------------------------------------------------------- *)
-and new_attribute_impl loc largs ctx ftype =
- let ltp = match largs with
- | [ltp] -> ltp
+and new_attribute_impl loc sargs ctx ftype =
+ let ltp = match sargs with
+ | [t] -> lexp_parse_sexp ctx t
| _ -> fatal loc "new-attribute expects a single Type argument" in
+ (* FIXME: This creates new values for type `ltp` (very wrong if `ltp`
+ * is False, for example): Should be a type like `AttributeMap t`
+ * instead. *)
Builtin ((loc, "new-attribute"), ltp, Some AttributeMap.empty)
-and add_attribute_impl loc largs ctx ftype =
- let meta_ctx, _ = !global_substitution in
+and add_attribute_impl loc (sargs : sexp list) ctx ftype =
let n = get_size ctx in
- let table, var, attr = match largs with
+ let table, var, attr = match List.map (lexp_parse_sexp ctx) sargs with
| [table; Var((_, name), idx); attr] -> table, (n - idx, name), attr
| _ -> fatal loc "add-attribute expects 3 arguments (table; var; attr)" in
+ let meta_ctx, _ = !global_substitution in
let map, attr_type = match OL.lexp_whnf table (ectx_to_lctx ctx) meta_ctx with
| Builtin (_, attr_type, Some map)-> map, attr_type
| _ -> fatal loc "add-attribute expects a table as first argument" in
@@ -1048,13 +1045,13 @@ and add_attribute_impl loc largs ctx ftype =
let table = AttributeMap.add var attr map in
Builtin ((loc, "add-attribute"), attr_type, Some table)
-and get_attribute_impl loc largs ctx ftype =
- let meta_ctx, _ = !global_substitution in
+and get_attribute loc largs ctx ftype =
let ctx_n = get_size ctx in
let table, var = match largs with
| [table; Var((_, name), idx)] -> table, (ctx_n - idx, name)
| _ -> fatal loc "get-attribute expects 2 arguments (table; var)" in
+ let meta_ctx, _ = !global_substitution in
let map = match OL.lexp_whnf table (ectx_to_lctx ctx) meta_ctx with
| Builtin (_, attr_type, Some map) -> map
| _ -> fatal loc "get-attribute expects a table as first argument" in
@@ -1062,13 +1059,16 @@ and get_attribute_impl loc largs ctx ftype =
let lxp = AttributeMap.find var map in
(lxp : lexp)
-and has_attribute_impl loc largs ctx ftype =
- let meta_ctx, _ = !global_substitution in
+and get_attribute_impl loc (sargs : sexp list) ctx ftype =
+ get_attribute loc (List.map (lexp_parse_sexp ctx) sargs) ctx ftype
+
+and has_attribute_impl loc (sargs : sexp list) ctx ftype =
let n = get_size ctx in
- let table, var = match largs with
+ let table, var = match List.map (lexp_parse_sexp ctx) sargs with
| [table; Var((_, name), idx)] -> table, (n - idx, name)
| _ -> fatal loc "get-attribute expects 2 arguments (table; var)" in
+ let meta_ctx, _ = !global_substitution in
let map, attr_type = match OL.lexp_whnf table (ectx_to_lctx ctx) meta_ctx with
| Builtin (_, attr_type, Some map) -> map, attr_type
| lxp -> lexp_fatal loc lxp "get-attribute expects a table as first argument" in
@@ -1078,6 +1078,24 @@ and has_attribute_impl loc largs ctx ftype =
with Not_found ->
BI.get_predef "False" ctx
+and declexpr_impl loc sargs ctx ftype =
+ match List.map (lexp_parse_sexp ctx) sargs with
+ | [Var((_, vn), vi)]
+ -> (match DB.env_lookup_expr ctx ((loc, vn), vi) with
+ | Some lxp -> lxp
+ | None -> error loc "no expr available";
+ dlxp)
+ | _ -> error loc "declexpr expects one argument";
+ dlxp
+
+
+let decltype_impl loc sargs ctx ftype =
+ match List.map (lexp_parse_sexp ctx) sargs with
+ | [Var((_, vn), vi)]
+ -> DB.env_lookup_type ctx ((loc, vn), vi)
+ | _ -> error loc "decltype expects one argument";
+ dlxp
+
(* Only print var info *)
and lexp_print_var_info ctx =
let ((m, _), env, _) = ctx in
@@ -1105,8 +1123,8 @@ let _ = List.iter add_special_form
("has-attribute", has_attribute_impl);
("add-attribute", add_attribute_impl);
(* FIXME: These should be functions! *)
- ("decltype", BI.decltype_impl);
- ("declexpr", BI.declexpr_impl);
+ ("decltype", decltype_impl);
+ ("declexpr", declexpr_impl);
]
(* Default context with builtin types
View it on GitLab: https://gitlab.com/monnier/typer/commit/7443ad300f394133b6bcb8ca6544cb59892…
Stefan pushed to branch master at Stefan / Typer
Commits:
1e05e7c1 by Stefan Monnier at 2016-11-28T11:42:57-05:00
Fix WHNF of Let and recognize negative integers
* src/lexer.ml (nexttoken): Recognize negative integer.
* src/opslexp.ml (lexp_whnf): Really return WHNF for `Let`.
* tests/eval_test.ml ("Let"): Use negative integer, to test them.
("Lists"): Add tests using a different definition of List.
- - - - -
3 changed files:
- src/lexer.ml
- src/opslexp.ml
- tests/eval_test.ml
Changes:
=====================================
src/lexer.ml
=====================================
--- a/src/lexer.ml
+++ b/src/lexer.ml
@@ -49,7 +49,11 @@ let nexttoken (stt : token_env) (pts : pretoken list) bpos cpos
| (Preblock (sl, bpts, el) :: pts) -> (Block (sl, bpts, el), pts, 0, 0)
| (Prestring (loc, str) :: pts) -> (String (loc, str), pts, 0, 0)
| (Pretoken ({file;line;column}, name) :: pts')
- -> if digit_p name.[bpos] then
+ -> let char = name.[bpos] in
+ if digit_p char
+ || (char = '-' (* FIXME: Handle '+' as well! *)
+ && bpos + 1 < String.length name
+ && digit_p (name.[bpos + 1])) then
let rec lexnum bp cp (np : num_part) =
if bp >= String.length name then
((if np == NPint then
=====================================
src/opslexp.ml
=====================================
--- a/src/opslexp.ml
+++ b/src/opslexp.ml
@@ -63,6 +63,7 @@ let lookup_value = DB.lctx_lookup_value
* `let x₂ = e₂ in e₂`) will be interpreted in the remaining context,
* which already provides "x₁".
*)
+(* FXIME: This creates an O(N^2) tree from an O(N) `let`! *)
let rec lexp_defs_subst l s defs = match defs with
| [] -> s
| (_, lexp, _) :: defs'
@@ -138,7 +139,7 @@ let lexp_whnf e (ctx : DB.lexp_context) meta_ctx : lexp =
(* FIXME: I'd really prefer to use "native" recursive substitutions, using
* ideally a trick similar to the db_offsets in lexp_context! *)
| Let (l, defs, body)
- -> push_susp body (lexp_defs_subst l S.identity defs)
+ -> lexp_whnf (push_susp body (lexp_defs_subst l S.identity defs)) ctx
| e -> e
=====================================
tests/eval_test.ml
=====================================
--- a/tests/eval_test.ml
+++ b/tests/eval_test.ml
@@ -79,8 +79,8 @@ let _ = test_eval_eqv_named
"c = 3; e = 1; f = 2; d = 4;"
- "let a = 10; x = 50; y = 60; b = 20;
- in a + b;" (* == *) "30"
+ "let a = -5; x = 50; y = 60; b = 20;
+ in a + b;" (* == *) "15"
let _ = test_eval_eqv_named
"Let2"
@@ -246,7 +246,13 @@ let _ = test_eval_eqv_named
"my_list = cons 1
(cons 2
(cons 3
- (cons 4 nil)))"
+ (cons 4 nil)));
+ List' = let L : Type -> Type;
+ L = inductive_ (L (a : Type)) (nil) (cons a (L a))
+ in L;
+ cons' = inductive-cons List' cons;
+ nil' = inductive-cons List' nil;
+ my_list' = (cons' 1 nil');"
"length my_list;
head my_list;
View it on GitLab: https://gitlab.com/monnier/typer/commit/1e05e7c18a4dd35979426187a063f82fdcd…
Stefan pushed to branch master at Stefan / Typer
Commits:
f9a5b2f2 by Stefan Monnier at 2016-11-26T11:23:49-05:00
Add new ##... syntax to refer to existing builtins
* src/builtin.ml (lmap): New var.
(add_builtin_cst): New function.
* src/lexp.ml (mkSusp): Don't bother suspending immediates.
(lexp_unparse): Use Pbuiltin.
(_lexp_to_str): Use the ##... syntax.
* src/lparse.ml (macromap): Adjust to earlier change.
(make_macro_map): Use it.
(infer): Handle Pbuiltin.
* src/pexp.ml (pexp): Add Pbuiltin constructor.
(pexp_parse): Recognize new ##... syntax.
(pexp_location, pexp_unparse): Handle it.
* src/prelexer.ml (string_sub): Move to util.ml.
- - - - -
8 changed files:
- DESIGN
- src/builtin.ml
- src/lexp.ml
- src/lparse.ml
- src/pexp.ml
- src/prelexer.ml
- src/util.ml
- tests/eval_test.ml
Changes:
=====================================
DESIGN
=====================================
--- a/DESIGN
+++ b/DESIGN
@@ -1219,22 +1219,30 @@ For IO the macro would return "bind e1 e2", whereas for "a * b" it would use
Here's an example of a use of partial functions:
- type Exp (e : Env) :=
- Var i (t : lookup i e)
+ type Exp (e : Env)
+ | Var i (t : lookup i e)
where "lookup" might fail. Without partial functions, we have to use
a relational style, as in:
- type Exp (e : Env) :=
- Var i (_: lookup i e t) t
+ type Exp (e : Env)
+ | Var i (_: lookup i e t) t
In the present case, we could make "lookup" return False, but if we change
it to:
- type Exp (e : Env) (τ : EType) :=
- SetVar i (v : Exp Env (lookup i e))
+ type Exp (e : Env) (τ : EType)
+ | SetVar i (v : Exp Env (lookup i e))
-Suddenly, this doesn't work any more.
+Suddenly, this doesn't work any more. We would then have to do something
+like, have `lookup` return an `Option` and then do:
+
+ type Exp (e : Env) (τ : EType)
+ | SetVar i (v : (case lookup i e
+ | Some t => Exp Env t
+ | None -> False))
+
+It would be neat to have some way to "automate" this.
* Erasable constructors
=====================================
src/builtin.ml
=====================================
--- a/src/builtin.ml
+++ b/src/builtin.ml
@@ -1,9 +1,6 @@
-(*
- * Typer Compiler
+(* builtin.ml --- Infrastructure to define built-in primitives
*
- * ---------------------------------------------------------------------------
- *
- * Copyright (C) 2011-2016 Free Software Foundation, Inc.
+ * Copyright (C) 2016 Free Software Foundation, Inc.
*
* Author: Pierre Delaunay <pierre.delaunay(a)hec.ca>
* Keywords: languages, lisp, dependent types.
@@ -25,8 +22,34 @@
*
* ---------------------------------------------------------------------------
*
- * Description:
- * Hold built-in types definition and built-in functions implementation
+ * There are several different issues with how to make the compiler's code
+ * interact with code defined in Typer:
+ *
+ * ** Exporting primitives
+ *
+ * I.e. how to give a name and a type to a primitive implemented in OCaml
+ *
+ * There are several conflicting desires, here: we'd generally want the name,
+ * the type (and the association) to be close to the primitive's definition, so
+ * that adding a new primitive doesn't require changes in many files.
+ *
+ * But it's also good to have the type written in some Typer file, both for
+ * the convenience of writing the code in Typer syntax with typer-mode support,
+ * and also because error messages can easily refer to that file, so it can be
+ * used for user-documentation.
+ *
+ * ** Importing definitions
+ *
+ * Sometimes we want some part of the core to be defined in Typer and used
+ * from OCaml. Examples are the type `Macro` along with the `expand-macro`
+ * function or the type Bool/true/false used with various primitives.
+ *
+ * ** Intertwined dependencies
+ *
+ * The various importing/exporting might need to be interlaced. Some exported
+ * functions's types will want to refer to imported types, while some imported
+ * definitions may want to refer to exported definitions. So we'd like to be
+ * able to do them in "any" order.
*
* ---------------------------------------------------------------------------*)
@@ -34,6 +57,8 @@ open Util
open Sexp (* Integer/Float *)
open Pexp (* arg_kind *)
+module L = Lexp
+module OL = Opslexp
open Lexp
module DB = Debruijn
@@ -168,9 +193,11 @@ let decltype_impl loc largs ctx ftype =
(* mkSusp prop (S.shift (var_i + 1)) *)
ltype
+(* Map of lexp builtin elements accessible via (## <name>). *)
+let lmap = ref (SMap.empty : (L.lexp * L.ltype) SMap.t)
-
-
-
-
-
+let add_builtin_cst (name : string) (e : lexp)
+ = let map = !lmap in
+ assert (not (SMap.mem name map));
+ let t = OL.check VMap.empty Myers.nil e in
+ lmap := SMap.add name (e, t) map
=====================================
src/lexp.ml
=====================================
--- a/src/lexp.ml
+++ b/src/lexp.ml
@@ -166,6 +166,8 @@ let rec mkSusp e s =
* There's no deep technical rason for that:
* it just seemed like a good idea to do it eagerly when it's easy. *)
match e with
+ (* FIXME: `Builtin` shouuld be treated like `Imm`. *)
+ | Imm _ -> e
| Susp (e, s') -> mkSusp e (scompose s' s)
| Var (l,v) -> slookup s l v
| Metavar (vn, s', vd, t) -> mkMetavar (vn, scompose s' s, vd, mkSusp t s)
@@ -349,10 +351,7 @@ let rec lexp_unparse lxp =
match lxp with
| Susp _ as e -> lexp_unparse (nosusp e)
| Imm (sexp) -> Pimm (sexp)
- | Builtin ((loc, name), _, None) -> Pvar((loc, name))
- | Builtin ((loc, name), ltp, _ )
- -> Pcall(Pvar((loc, name)), [pexp_unparse (lexp_unparse ltp)])
-
+ | Builtin (s, _, _) -> Pbuiltin s
| Var ((loc, name), _) -> Pvar((loc, name))
| Cons (t, ctor) -> Pcons (lexp_unparse t, ctor)
| Lambda (kind, vdef, ltp, body) ->
@@ -655,15 +654,16 @@ and _lexp_to_str ctx exp =
^ "| " ^ (match v with None -> "_" | Some (_,name) -> name)
^ " => " ^ (lexp_to_stri 1 df))
- | Builtin ((_, name), _, _) -> name
+ | Builtin ((_, name), _, _) -> "##" ^ name
- | Sort (_, Stype (SortLevel SLz)) -> "Type_0"
- | Sort (_, Stype _) -> "Type_?"
- | Sort (_, StypeOmega) -> "Type_ω"
- | Sort (_, StypeLevel) -> "Type_Level"
+ | Sort (_, Stype (SortLevel SLz)) -> "##Type"
+ | Sort (_, Stype (SortLevel (SLsucc (SortLevel SLz)))) -> "##Type1"
+ | Sort (_, StypeLevel) -> "##TypeLevel"
+ | Sort (_, Stype _) -> "##Type_?" (* FIXME! *)
+ | Sort (_, StypeOmega) -> "##Type_ω" (* FIXME: Should never happen! *)
- | SortLevel (SLz) -> "<Level0>"
- | SortLevel (SLsucc e) -> "<LevelS?>"
+ | SortLevel (SLz) -> "##TypeLevel.z"
+ | SortLevel (SLsucc e) -> "##TypeLevel.succ"
and lexp_str_ctor ctx ctors =
SMap.fold (fun key value str
=====================================
src/lparse.ml
=====================================
--- a/src/lparse.ml
+++ b/src/lparse.ml
@@ -43,10 +43,11 @@ open Lexp
open Env
open Debruijn
+module DB = Debruijn
open Eval
open Grammar
-open Builtin
+module BI = Builtin
module Unif = Unification
@@ -113,7 +114,7 @@ let elab_check_sort (ctx : elab_context) lsort var ltp =
(* Builtin Macro i.e, special forms *)
type macromap =
- (location -> lexp list -> elab_context -> lexp -> (lexp * lexp)) SMap.t
+ (location -> lexp list -> elab_context -> lexp -> lexp) SMap.t
let elab_check_proper_type (ctx : elab_context) ltp var =
let meta_ctx, _ = !global_substitution in
@@ -247,6 +248,12 @@ let rec infer (p : pexp) (ctx : elab_context): lexp * ltype =
| _ -> pexp_error tloc p "Could not find type";
dltype)
+ | Pbuiltin (l,name)
+ -> (try SMap.find name (! BI.lmap)
+ with Not_found
+ -> pexp_error l p ("Unknown builtin `" ^ name ^ "`");
+ dlxp, dltype)
+
(* Symbol i.e identifier. *)
| Pvar (loc, name)
-> (try
@@ -808,7 +815,7 @@ and infer_call (func: pexp) (sargs: sexp list) ctx =
infer pxp ctx in
(* This is the builtin Macro type *)
- let macro_type, macro_disp = match get_predef_option "Macro" ctx with
+ let macro_type, macro_disp = match BI.get_predef_option "Macro" ctx with
| Some lxp -> OL.lexp_whnf lxp (ectx_to_lctx ctx) meta_ctx, true
(* When type.typer is being parsed and the predef is not yet available *)
| None -> dltype, false in
@@ -867,9 +874,9 @@ and lexp_expand_dmacro macro_funct sargs ctx
and lexp_expand_macro_ macro_funct sargs ctx expand_fun : value_type =
(* Build the function to be called *)
- let macro_expand = get_predef expand_fun ctx in
+ let macro_expand = BI.get_predef expand_fun ctx in
let args = [(Aexplicit, macro_funct);
- (Aexplicit, (olist2tlist_lexp sargs ctx))] in
+ (Aexplicit, (BI.olist2tlist_lexp sargs ctx))] in
let macro = mkCall (macro_expand, args) in
let emacro = OL.erase_type macro in
@@ -901,7 +908,7 @@ and lexp_decls_macro (loc, mname) sargs ctx: (pdecl list * elab_context) =
let ret = lexp_expand_dmacro body sargs ctx in
(* convert typer list to ocaml *)
- let decls = tlist2olist [] ret in
+ let decls = BI.tlist2olist [] ret in
(* extract sexp from result *)
let decls = List.map (fun g ->
@@ -1023,8 +1030,8 @@ and lexp_parse_all (p: pexp list) (ctx: elab_context) : lexp list =
* -------------------------------------------------------------------------- *)
and builtin_macro = [
(* FIXME: These should be functions! *)
- ("decltype", decltype_impl);
- ("declexpr", declexpr_impl);
+ ("decltype", BI.decltype_impl);
+ ("declexpr", BI.declexpr_impl);
(* FIXME: These are not macros but `special-forms`.
* We should add here `let_in_`, `case_`, etc... *)
("get-attribute", get_attribute_impl);
@@ -1033,7 +1040,7 @@ and builtin_macro = [
("add-attribute", add_attribute_impl);
]
-and make_macro_map unit =
+and make_macro_map unit : macromap =
List.fold_left (fun map (name, funct) ->
SMap.add name funct map) SMap.empty builtin_macro
@@ -1095,9 +1102,9 @@ and has_attribute_impl loc largs ctx ftype =
| lxp -> lexp_fatal loc lxp "get-attribute expects a table as first argument" in
try let _ = AttributeMap.find var map in
- (get_predef "True" ctx)
+ BI.get_predef "True" ctx
with Not_found ->
- (get_predef "False" ctx)
+ BI.get_predef "False" ctx
(* Only print var info *)
and lexp_print_var_info ctx =
@@ -1154,7 +1161,7 @@ let default_lctx, default_rctx =
List.iter (fun name ->
let idx = senv_lookup name lctx in
let v = Var((dloc, name), idx) in
- set_predef name (Some v)) predef_name;
+ BI.set_predef name (Some v)) BI.predef_name;
(* -- DONE -- *)
lctx
with e ->
=====================================
src/pexp.ml
=====================================
--- a/src/pexp.ml
+++ b/src/pexp.ml
@@ -39,6 +39,7 @@ type pvar = symbol
type pexp =
(* | Psort of location * sort *)
| Pimm of sexp (* Used for strings, ... *)
+ | Pbuiltin of symbol
| Pvar of pvar
| Phastype of location * pexp * pexp
| Pmetavar of pvar
@@ -70,6 +71,7 @@ let rec pexp_location e =
match e with
(* | Psort (l,_) -> l *)
| Pimm s -> sexp_location s
+ | Pbuiltin (l,_) -> l
| Pvar (l,_) -> l
| Phastype (l,_,_) -> l
| Pmetavar (l, _) -> l
@@ -97,6 +99,18 @@ let rec pexp_parse (s : sexp) : pexp =
(* | Symbol (l, "Type") -> Psort (l, Type) *)
| Symbol (l, name) when String.length name > 0 && String.get name 0 == '?'
-> Pmetavar (l, String.sub name 1 (String.length name - 1))
+ | Symbol (l, name) when String.length name > 2
+ && String.get name 0 == '#'
+ && String.get name 1 == '#'
+ -> Pbuiltin (l, string_sub name 2 (String.length name))
+ (* | Node (Symbol (start, "##"), [Symbol s])
+ * -> Pbuiltin s
+ * | Node (Symbol (start, "##"), [e])
+ * -> pexp_error (sexp_location e) "Non-symbol argument to `##`";
+ * Pmetavar (start, "")
+ * | Node (Symbol (start, "##"), _)
+ * -> pexp_error start "`##` takes exactly one argument";
+ * Pmetavar (start, "") *)
| Symbol s -> Pvar s
| Node (Symbol (start, "_:_"), [e; t])
-> Phastype (start, pexp_parse e, pexp_parse t)
@@ -297,8 +311,10 @@ and pexp_unparse (e : pexp) : sexp =
(* | Psort (l,Ext) -> Symbol (l, "%Ext%") *)
(* | Psort (l,Type) -> Symbol (l, "%Type%") *)
| Pimm s -> s
+ | Pbuiltin (l,name) -> Symbol (l, "##" ^ name)
+ (* | Pbuiltin ((l,_) as s) -> Node (Symbol (l, "##"), [Symbol s]) *)
| Pvar v -> Symbol v
- | Pmetavar (l,name) -> Symbol (l,"?"^name)
+ | Pmetavar (l,name) -> Symbol (l, "?" ^ name)
| Phastype (l,e,t)
-> Node (Symbol (l, "_:_"), [pexp_unparse e; pexp_unparse t])
| Plet (start, decls, body) ->
@@ -406,6 +422,7 @@ let pexp_print e = print_string (pexp_string e)
let pexp_name e =
match e with
| Pimm _ -> "Pimm"
+ | Pbuiltin _ -> "Pbuiltin"
| Pvar (_,_) -> "Pvar"
| Phastype (_,_,_) -> "Phastype"
| Pmetavar (_, _) -> "Pmetavar"
=====================================
src/prelexer.ml
=====================================
--- a/src/prelexer.ml
+++ b/src/prelexer.ml
@@ -46,8 +46,6 @@ type pretoken =
(* FIXME: Add syntax for char constants (maybe 'c'). *)
(* FIXME: Handle multiline strings. *)
-let string_sub str b e = String.sub str b (e - b)
-
let inc_cp (cp:charpos) (c:char) =
(* Count char positions in utf-8: don't count the non-leading bytes. *)
if utf8_head_p c then cp+1 else cp
=====================================
src/util.ml
=====================================
--- a/src/util.ml
+++ b/src/util.ml
@@ -90,6 +90,7 @@ let debug_msg expr =
let not_implemented_error () = internal_error "not implemented"
let string_implode chars = String.concat "" (List.map (String.make 1) chars)
+let string_sub str b e = String.sub str b (e - b)
let opt_map f x = match x with None -> None | Some x -> Some (f x)
=====================================
tests/eval_test.ml
=====================================
--- a/tests/eval_test.ml
+++ b/tests/eval_test.ml
@@ -190,7 +190,7 @@ let _ = test_eval_eqv_named
three = succ two;
plus : Nat -> Nat -> Nat;
- plus = lambda (x : Nat) -> lambda (y : Nat) -> case x
+ plus x y = case x
| zero => y
| succ z => succ (plus z y);")
View it on GitLab: https://gitlab.com/monnier/typer/commit/f9a5b2f2efe0fa1028e95035146e88e137d…