This is an unofficial fork of OchaCaml for Homebrew Formula.
This Gist is not maintained. See ymyzk/ochacaml for latest information.
- Character encoding: EUC-JP -> UTF-8
- Generate a diff file using
git diff
This is an unofficial fork of OchaCaml for Homebrew Formula.
git diff| diff --git a/config/m.h b/config/m.h | |
| index abb6f05..9a40d22 100644 | |
| --- a/config/m.h | |
| +++ b/config/m.h | |
| @@ -1,3 +1,3 @@ | |
| #define CAML_SIXTYFOUR | |
| #undef CAML_BIG_ENDIAN | |
| -#define CAML_ALIGNMENT | |
| +#undef CAML_ALIGNMENT | |
| diff --git a/config/s.h b/config/s.h | |
| index 3842729..57b708c 100644 | |
| --- a/config/s.h | |
| +++ b/config/s.h | |
| @@ -3,6 +3,7 @@ | |
| #endif | |
| #define HAS_MEMMOVE | |
| #define HAS_BCOPY | |
| +#define HAS_MEMCPY | |
| #define sighandler_return_type void | |
| #define BSD_SIGNALS | |
| #define HAS_RENAME | |
| diff --git a/contrib/Makefile b/contrib/Makefile | |
| index 3e067b5..43a72e6 100644 | |
| --- a/contrib/Makefile | |
| +++ b/contrib/Makefile | |
| @@ -4,8 +4,8 @@ | |
| # See the file INDEX for a description of the packages and their requirements. | |
| # Remember that "libunix" is required for | |
| # "debugger", "libgraph", "camltk", "camltk4", and "search_isos". | |
| -PACKAGES=libunix libgraph debugger libnum libstr mletags \ | |
| - camlmode lorder profiler camltk4 camlsearch | |
| +PACKAGES=libunix debugger libnum libstr mletags \ | |
| + camlmode lorder profiler camlsearch | |
| # caml-tex | |
| # caml-latex2e | |
| # camltk | |
| diff --git a/src/Makefile b/src/Makefile | |
| index 02fcc79..b04dfe4 100644 | |
| --- a/src/Makefile | |
| +++ b/src/Makefile | |
| @@ -9,13 +9,13 @@ CC=gcc | |
| # This option circumvents a gcc bug on some platforms (680x0, 80386). | |
| # If you are using Linux with libc6 (RedHat 5, Debian 2), add -D__FAVOR_BSD | |
| # This option avoids signal-related problems. | |
| -OPTS=-fno-defer-pop -D__FAVOR_BSD | |
| +OPTS=-fno-defer-pop -D__FAVOR_BSD -no-cpp-precomp | |
| # Extra libraries that have to be linked with the runtime system. | |
| # The math library "-lm" is linked by default. | |
| # On most machines, nothing else is needed. | |
| # Under Solaris: -lsocket -lnsl | |
| -LIBS= | |
| +LIBS= -lm | |
| # How to call the C preprocessor on a file that does not have the .c extension. | |
| # That's /lib/cpp on most machines, sometimes /usr/bin/cpp, | |
| @@ -26,7 +26,7 @@ LIBS= | |
| # not all Unix C preprocessors define it. | |
| # If your cpp is too fussy, make tools/clprepro and use this: | |
| # CPP=../../src/tools/clprepro -Dunix | |
| -CPP=/lib/cpp -P -traditional -Dunix | |
| +CPP=/usr/bin/cpp -P -traditional -Dunix | |
| # The directory where public executables will be installed | |
| BINDIR=/usr/local/bin | |
| diff --git a/src/compiler/back.ml b/src/compiler/back.ml | |
| index a4a9bf9..4842a2a 100644 | |
| --- a/src/compiler/back.ml | |
| +++ b/src/compiler/back.ml | |
| @@ -17,10 +17,10 @@ let rec is_return = function | |
| (* Label generation *) | |
| -let label_counter = ref 0;; | |
| +let label_counter = ref 1 (* 0 *);; | |
| let reset_label () = | |
| - label_counter := 0 | |
| + label_counter := 1 (* 0 *) | |
| and new_label () = | |
| incr label_counter; !label_counter | |
| ;; | |
| @@ -175,8 +175,9 @@ let test_for_atom = function | |
| ;; | |
| (* To keep track of function bodies that remain to be compiled. *) | |
| +(* 最後の bool は、shift/reset の引数かどうかを表す *) | |
| -let still_to_compile = (stack__new () : (lambda * int) stack__t);; | |
| +let still_to_compile = (stack__new () : (lambda * int * bool) stack__t);; | |
| (* The translator from lambda terms to lists of instructions. | |
| @@ -197,6 +198,23 @@ let rec compile_expr staticfail = | |
| (match code with | |
| (Kquote _ | Kget_global _ | Kaccess _ | Kpushmark) :: _ -> code | |
| | _ -> Kquote cst :: code) | |
| + | Lapply(Lreset e, args) -> | |
| + let lbl = new_label() in | |
| + (* 最後を return ではなく endshiftreset にするため *) | |
| + stack__push (e, lbl, true) still_to_compile; | |
| + let code' = Kclosure lbl :: Kprim Preset :: code in | |
| + let code' = (match args with [] -> code' | _ -> Kpush :: code') in | |
| + Kpushmark :: compexplist args code' | |
| + | Lapply(Lshift e, args) -> | |
| + let lbl = new_label() in | |
| + (* 最後を return ではなく endshiftreset にするため *) | |
| + stack__push (e, lbl, true) still_to_compile; | |
| + let code' = (match args with [] -> code | _ -> Kapply :: code) in | |
| + let code' = Kclosure lbl :: Kprim Pshift :: code' in | |
| + let code' = (match args with [] -> code' | _ -> Kpush :: code') in | |
| + (match args with | |
| + [] -> code' | |
| + | _ -> Kpushmark :: compexplist args code') | |
| | Lapply(body, args) -> | |
| if is_return code then | |
| compexplist args (Kpush :: | |
| @@ -209,7 +227,7 @@ let rec compile_expr staticfail = | |
| Kgrab :: compexp body code | |
| else begin | |
| let lbl = new_label() in | |
| - stack__push (body, lbl) still_to_compile; | |
| + stack__push (body, lbl, false) still_to_compile; | |
| Kclosure lbl :: code | |
| end | |
| | Llet(args, body) -> | |
| @@ -224,7 +242,7 @@ let rec compile_expr staticfail = | |
| | Lletrec([Lfunction f, _], body) -> | |
| let code1 = if is_return code then code else Kendlet 1 :: code in | |
| let lbl = new_label() in | |
| - stack__push (f, lbl) still_to_compile; | |
| + stack__push (f, lbl, false) still_to_compile; | |
| Kletrec1 lbl :: compexp body code1 | |
| | Lletrec(args, body) -> | |
| let size = list_length args in | |
| @@ -391,6 +409,20 @@ let rec compile_expr staticfail = | |
| then compexp expr code (* don't destroy tail call opt. *) | |
| else compexp expr (Kevent event :: code) | |
| end | |
| + (* 何も考えずにやってみた *) | |
| + | Lreset expr -> | |
| + let lbl = new_label() in | |
| + (* 最後を return ではなく endshiftreset にするため *) | |
| + stack__push (expr, lbl, true) still_to_compile; | |
| + Kclosure lbl :: Kprim Preset :: code | |
| +(* compexp (Lprim (Preset, [Lfunction expr])) (Kendshiftreset :: code) *) | |
| + | Lshift expr -> | |
| + let lbl = new_label() in | |
| + stack__push (expr, lbl, true) still_to_compile; | |
| + Kclosure lbl :: Kprim Pshift :: code | |
| +(* compexp (Lprim (Pshift, [Lfunction expr])) (Kendshiftreset :: code) *) | |
| + | |
| + | |
| and compexplist = fun | |
| [] code -> code | |
| @@ -476,8 +508,15 @@ let rec compile_expr staticfail = | |
| let rec compile_rest code = | |
| try | |
| - let (exp, lbl) = stack__pop still_to_compile in | |
| - compile_rest (Klabel lbl :: compile_expr Nolabel exp (Kreturn :: code)) | |
| + let (exp, lbl, b) = stack__pop still_to_compile in | |
| +(* let code' = compile_expr Nolabel exp (Kreturn :: code) in | |
| + let code' = | |
| + if b then (rev (Kendshiftreset :: (tl (rev code')))) | |
| + else code' in | |
| + compile_rest (Klabel lbl :: code') *) | |
| + compile_rest (Klabel lbl :: compile_expr Nolabel exp | |
| + ((if b then [Kendshiftreset; Kreturn] | |
| + else [Kreturn]) @ code)) | |
| with stack__Empty -> | |
| code | |
| ;; | |
| diff --git a/src/compiler/builtins.ml b/src/compiler/builtins.ml | |
| index d54f772..1efe7c5 100644 | |
| --- a/src/compiler/builtins.ml | |
| +++ b/src/compiler/builtins.ml | |
| @@ -44,8 +44,8 @@ and constr_type_num = | |
| (* This assumes that "num" is the first type defined in "num". *) | |
| ;; | |
| -let type_arrow (t1,t2) = | |
| - {typ_desc=Tarrow(t1, t2); typ_level=notgeneric} | |
| +let type_arrow (t1,t2,t3,t4) = | |
| + {typ_desc=Tarrow(t1, t2, t3, t4); typ_level=notgeneric} | |
| and type_product tlist = | |
| {typ_desc=Tproduct(tlist); typ_level=notgeneric} | |
| and type_unit = | |
| diff --git a/src/compiler/compiler.ml b/src/compiler/compiler.ml | |
| index 4ea53ab..05f8770 100644 | |
| --- a/src/compiler/compiler.ml | |
| +++ b/src/compiler/compiler.ml | |
| @@ -77,6 +77,11 @@ let do_directive loc = function | |
| remove_infix name | |
| | Zdir("directory", dirname) -> | |
| load_path := dirname :: !load_path | |
| + | Zdir("answer", name) -> | |
| + if name = "all" || name = "none" | |
| + then types__typ_option := name | |
| + else (eprintf "This option is not supported\n"; | |
| + flush stderr) | |
| | Zdir(d, name) -> | |
| eprintf | |
| "%aWarning: unknown directive \"#%s\", ignored.\n" | |
| diff --git a/src/compiler/config.mlp b/src/compiler/config.mlp | |
| index 980dacb..d6a478f 100755 | |
| --- a/src/compiler/config.mlp | |
| +++ b/src/compiler/config.mlp | |
| @@ -41,5 +41,5 @@ let default_exec_name = "camlout.exe";; | |
| * error_prompt: Printed before compiler error and warning messages. | |
| *) | |
| -let toplevel_input_prompt = "#";; | |
| -let error_prompt = ">";; | |
| +let toplevel_input_prompt = "# ";; | |
| +let error_prompt = "> ";; | |
| diff --git a/src/compiler/emit_phr.ml b/src/compiler/emit_phr.ml | |
| index 2efdc66..de4c7cd 100644 | |
| --- a/src/compiler/emit_phr.ml | |
| +++ b/src/compiler/emit_phr.ml | |
| @@ -25,21 +25,26 @@ let start_emit_phrase outchan = | |
| ;; | |
| let emit_phrase outchan is_pure phr = | |
| +(* print_int 3; print_newline () ;*) | |
| reloc__reset(); | |
| event__reset(); | |
| init_out_code(); | |
| labels__reset_label_table(); | |
| begin match phr with | |
| { kph_fcts = [] } -> | |
| - emit phr.kph_init | |
| - | { kph_rec = false } -> | |
| +(* emit [Klabel 1; Kprim prim__Pcopyblocks]; (* added *) *) | |
| + emit phr.kph_init; | |
| + emit [Klabel 1; Kprim prim__Pcopyblocks] (* added *) | |
| + | { kph_rec = false } -> | |
| emit [Kbranch 0]; | |
| + emit [Klabel 1; Kprim prim__Pcopyblocks]; (* added *) | |
| emit phr.kph_fcts; | |
| emit [Klabel 0]; | |
| emit phr.kph_init | |
| | { kph_rec = true } -> | |
| emit phr.kph_init; | |
| emit [Kbranch 0]; | |
| + emit [Klabel 1; Kprim prim__Pcopyblocks]; (* added *) | |
| emit phr.kph_fcts; | |
| emit [Klabel 0] | |
| end; | |
| diff --git a/src/compiler/emitcode.ml b/src/compiler/emitcode.ml | |
| index 9146a80..d2a8856 100644 | |
| --- a/src/compiler/emitcode.ml | |
| +++ b/src/compiler/emitcode.ml | |
| @@ -194,6 +194,9 @@ let rec emit = function | |
| ev.ev_pos <- !out_position; | |
| event__enter ev; | |
| emit code | |
| + | Kendshiftreset :: code -> | |
| + out ENDSHIFTRESET; | |
| + emit code | |
| | instr :: code -> | |
| out(match instr with | |
| Kreturn -> RETURN | |
| diff --git a/src/compiler/error.ml b/src/compiler/error.ml | |
| index 22b4e82..f172f77 100644 | |
| --- a/src/compiler/error.ml | |
| +++ b/src/compiler/error.ml | |
| @@ -292,3 +292,27 @@ let unused_open_warning modname = | |
| output_input_name modname; | |
| flush stderr | |
| ;; | |
| + | |
| +let answer_type_err t1 t2 = | |
| + eprintf "tried to unify\n "; | |
| + output_type stderr t1; | |
| + eprintf " and "; | |
| + output_type stderr t2; | |
| + eprintf "\n(answer type cannot unify)\n"; | |
| + raise Toplevel | |
| +;; | |
| + | |
| +let impure_exp_err t1 t2 = | |
| + eprintf "This expression is not pure.\n"; | |
| + eprintf "Answer types are %a and %a.\n" | |
| + output_type t1 | |
| + output_type t2; | |
| + raise Toplevel | |
| +;; | |
| + | |
| +let impure_exp_err' () = | |
| + eprintf "This expression is not pure.\n"; | |
| + eprintf "Answer types are '_a and '_a.\n"; | |
| + raise Toplevel | |
| +;; | |
| + | |
| diff --git a/src/compiler/front.ml b/src/compiler/front.ml | |
| index 866e896..a12390b 100644 | |
| --- a/src/compiler/front.ml | |
| +++ b/src/compiler/front.ml | |
| @@ -47,6 +47,8 @@ let rec check_letrec_expr expr = | |
| do_list (fun (pat,expr) -> check_letrec_expr expr) pat_expr_list; | |
| check_letrec_expr body | |
| | Zparser _ -> () | |
| + | Zreset (_, e) -> check_letrec_expr e | |
| + | Zshift (_, _, e) -> check_letrec_expr e | |
| | _ -> | |
| illegal_letrec_expr expr.e_loc | |
| ;; | |
| @@ -74,6 +76,10 @@ let rec size_of_expr expr = | |
| size_of_expr body | |
| | Zparser _ -> | |
| 2 | |
| + | Zreset (_, e) -> | |
| + size_of_expr e | |
| + | Zshift (_, _, e) -> | |
| + size_of_expr e | |
| | _ -> | |
| illegal_letrec_expr expr.e_loc | |
| ;; | |
| @@ -291,10 +297,70 @@ let rec translate_expr env = | |
| | Zstream stream_comp_list -> | |
| translate_stream translate_expr env stream_comp_list | |
| | Zparser case_list -> | |
| - let (stream_type, _) = types__filter_arrow expr.e_typ in | |
| + let (stream_type, _, _, _) = types__filter_arrow expr.e_typ in | |
| translate_parser translate_expr expr.e_loc env case_list stream_type | |
| | Zwhen(e1,e2) -> | |
| fatal_error "front: Zwhen" | |
| +(* | |
| + | Zshift(({ p_desc = Zvarpat id } as pat1), | |
| + ({ p_desc = Zvarpat id' } as pat2), e) -> | |
| + (* 暫定 ... *) | |
| + let ty = no_type in | |
| + let lo = location__no_location in | |
| + let s = "call_shift" in | |
| + let f = | |
| + { e_desc = | |
| + Zident (ref(Zglobal{ info = { val_typ = ty; | |
| + val_prim = ValuePrim (1, Pshift) }; | |
| + qualid = { qual = s; id = s } })); | |
| + e_loc = lo; | |
| + e_typ = ty } in | |
| + let arg = { e_desc = Zident (ref(Zlocal id')); | |
| + e_loc = pat1.p_loc; | |
| + e_typ = pat1.p_typ } in | |
| + let app = { e_desc = Zapply (f, [arg]); | |
| + e_loc = pat2.p_loc; | |
| + e_typ = pat2.p_typ } in | |
| + (* k の方で env 拡張 *) | |
| + let new_env = add_for_parameter_to_env env id in | |
| + translate_expr new_env | |
| + ({ e_desc = | |
| + Zlet(false, | |
| + [({ p_desc = Zaliaspat (pat2, id); | |
| + p_loc = pat1.p_loc; p_typ = pat1.p_typ }, e)], app); | |
| + e_loc = pat2.p_loc; | |
| + e_typ = pat2.p_typ}) | |
| + | Zreset(({ p_desc = Zvarpat id } as pat), e) -> | |
| + (* 暫定 ... *) | |
| + let ty = no_type in | |
| + let lo = location__no_location in | |
| + let r = "call_reset" in | |
| + let f = | |
| + { e_desc = | |
| + Zident (ref(Zglobal{ info = { val_typ = ty; | |
| + val_prim = ValuePrim (1, Preset) }; | |
| + qualid = { qual = r; id = r } })); | |
| + e_loc = lo; | |
| + e_typ = ty } in | |
| + let arg = { e_desc = Zident (ref(Zlocal id)); | |
| + e_loc = pat.p_loc; | |
| + e_typ = pat.p_typ } in | |
| + let app = { e_desc = Zapply (f, [arg]); | |
| + e_loc = pat.p_loc; (* 胡散臭い *) | |
| + e_typ = pat.p_typ } in (* 胡散臭い *) | |
| + transl ({ e_desc = Zlet(false, [(pat, e)], app); | |
| + e_loc = pat.p_loc; | |
| + e_typ = pat.p_typ}) *) | |
| + | Zreset (_, e) -> | |
| + Lreset (transl e) | |
| +(* let new_env = Treserved env in | |
| + Lreset (translate_expr new_env e) *) | |
| + | Zshift ({ p_desc = Zvarpat id; p_typ = ty }, _, e) -> | |
| + (* 本当にこれで OK なのか、は甚だしく謎 *) | |
| + let var = var_root id ty in | |
| + let new_env = Tenv([var], env) in | |
| + Lshift (translate_expr new_env e) | |
| + | Zshift _ -> failwith "not happend" | |
| in transl | |
| and transl_action env (patlist, expr) = | |
| diff --git a/src/compiler/globals.ml b/src/compiler/globals.ml | |
| index c1e625f..d401917 100644 | |
| --- a/src/compiler/globals.ml | |
| +++ b/src/compiler/globals.ml | |
| @@ -39,7 +39,7 @@ and typ = | |
| mutable typ_level: int } (* Binding level *) | |
| and typ_desc = | |
| Tvar of mutable typ_link (* A type variable *) | |
| - | Tarrow of typ * typ (* A function type *) | |
| + | Tarrow of typ * typ * typ * typ (* A function type *) | |
| | Tproduct of typ list (* A tuple type *) | |
| | Tconstr of type_constr global * typ list (* A constructed type *) | |
| and typ_link = | |
| diff --git a/src/compiler/instruct.ml b/src/compiler/instruct.ml | |
| index 804234f..a495501 100644 | |
| --- a/src/compiler/instruct.ml | |
| +++ b/src/compiler/instruct.ml | |
| @@ -33,6 +33,7 @@ type zam_instruction = | |
| | Kbranchinterval of int * int * int * int | |
| | Kswitch of int vect | |
| | Kevent of lambda__event | |
| + | Kendshiftreset | |
| ;; | |
| type zam_phrase = | |
| @@ -43,3 +44,64 @@ type zam_phrase = | |
| let Nolabel = (-1) | |
| ;; | |
| + | |
| +let print_inst ph = | |
| + print_string "code:\n "; | |
| + let f = | |
| + list__do_list | |
| + (fun inst -> | |
| + print_string | |
| + (match inst with | |
| + | Kquote s -> | |
| + "Kquote " ^ | |
| + (match s with | |
| + | SCatom ac -> | |
| + (match ac with | |
| + | ACint i -> string_of_int i | |
| + | ACfloat f -> string_of_float f | |
| + | ACstring s -> s | |
| + | ACchar c -> char__string_of_char c) | |
| + | SCblock (tag, lst) -> | |
| + "block" ^ string_of_int (list_length lst)) | |
| + ^ "; " | |
| + | Kget_global _ -> "Kget_global; " | |
| + | Kset_global _ -> "Kset_global; " | |
| + | Kaccess n -> "Kaccess " ^ (string_of_int n) ^ "; " | |
| + | Kgrab -> "Kgrab; " | |
| + | Kpush -> "Kpush; " | |
| + | Kpushmark -> "Kpushmark; " | |
| + | Klet -> "Klet; " | |
| + | Kendlet n -> "Kendlet " ^ (string_of_int n) ^ "; " | |
| + | Kapply -> "Kapply; " | |
| + | Ktermapply -> "Ktermapply; " | |
| + | Kcheck_signals -> "Kcheck_signals; " | |
| + | Kreturn -> "Kreturn; " | |
| + | Kclosure n -> "Kclosure " ^ (string_of_int n) ^ "; " | |
| + | Kletrec1 n -> "Kletrec1 " ^ (string_of_int n) ^ "; " | |
| + | Kmakeblock (_, i) -> "Kmakeblock " ^ (string_of_int i) ^ "; " | |
| + | Kprim p -> (match p with | |
| + | Pshift -> "Shift; " | |
| + | Preset -> "Reset; " | |
| + | _ -> "Kprim; ") | |
| + | Kpushtrap n -> "Kpushtrap " ^ (string_of_int n) ^ "; " | |
| + | Kpoptrap -> "Kpoptrap; " | |
| + | Klabel n -> "Klabel " ^ (string_of_int n) ^ "; " | |
| + | Kbranch n -> "Kbranch " ^ (string_of_int n) ^ "; " | |
| + | Kbranchif n -> "Kbranchif " ^ (string_of_int n) ^ "; " | |
| + | Kbranchifnot n -> | |
| + "Kbranchifnot " ^ (string_of_int n) ^ "; " | |
| + | Kstrictbranchif n -> | |
| + "Kstrictbranchif " ^ (string_of_int n) ^ "; " | |
| + | Kstrictbranchifnot n -> | |
| + "Kstrichbranchifnot " ^ (string_of_int n) ^ "; " | |
| + | Ktest _ -> "Ktest; " | |
| + | Kbranchinterval _ -> "Kbranchinterval; " | |
| + | Kswitch _ -> "Kswitch; " | |
| + | Kevent _ -> "Kevent; " | |
| + | Kendshiftreset -> "Kendshiftreset; ")) in | |
| + print_string "init:\n"; | |
| + f ph.kph_init; | |
| + print_newline (); | |
| + print_string "fcts:\n"; | |
| + f ph.kph_fcts; | |
| + print_newline ();; | |
| diff --git a/src/compiler/lambda.ml b/src/compiler/lambda.ml | |
| index 63b51d8..1365e19 100644 | |
| --- a/src/compiler/lambda.ml | |
| +++ b/src/compiler/lambda.ml | |
| @@ -61,6 +61,8 @@ type lambda = | |
| | Lfor of lambda * lambda * bool * lambda | |
| | Lshared of lambda * int ref | |
| | Levent of event * lambda | |
| + | Lshift of lambda | |
| + | Lreset of lambda | |
| ;; | |
| let share_lambda l = | |
| diff --git a/src/compiler/lexer.mlp b/src/compiler/lexer.mlp | |
| index 15a0711..fb96b57 100644 | |
| --- a/src/compiler/lexer.mlp | |
| +++ b/src/compiler/lexer.mlp | |
| @@ -44,6 +44,9 @@ do_list (fun (str,tok) -> hashtbl__add keyword_table str tok) [ | |
| "where", WHERE; | |
| "while", WHILE; | |
| "with", WITH; | |
| + "shift", SHIFT; (* added *) | |
| + "reset", RESET; (* added *) | |
| + | |
| "quo", INFIX3("quo"); | |
| "mod", INFIX3("mod"); | |
| @@ -186,6 +189,7 @@ rule main = parse | |
| | "*" { STAR } | |
| | "," { COMMA } | |
| | "->" { MINUSGREATER } | |
| + | "/" { SLASH } | |
| | "." { DOT } | |
| | ".." { DOTDOT } | |
| | ".(" { DOTLPAREN } | |
| diff --git a/src/compiler/modules.ml b/src/compiler/modules.ml | |
| index b5e6c2b..1814952 100644 | |
| --- a/src/compiler/modules.ml | |
| +++ b/src/compiler/modules.ml | |
| @@ -130,7 +130,83 @@ let add_table t1 t2 = | |
| let open_module name = | |
| let module = find_module name in | |
| - add_table module.mod_values (!opened_modules).mod_values; | |
| + | |
| +(* | |
| + let i = ref (int_of_char `a`) in | |
| + let c () = let a = !i in i := a + 1; "'" ^ (char__string_of_char (char_of_int a)) in | |
| + let rec to_str = function | |
| + | Tvar Tnolink -> "a" (* c () *) | |
| + | Tvar (Tlinkto t) -> "b" (* to_strd t *) | |
| + | Tarrow (t1, t2, t3, t4) -> | |
| + (to_strd t1) ^ " / " ^ (to_strd t2) ^ " -> " ^ | |
| + (to_strd t3) ^ " / " ^ (to_strd t4) | |
| + | Tproduct ts -> "d" | |
| +(* it_list (fun s t -> s ^ " * " ^ (to_strd t)) "" ts *) | |
| + | Tconstr o -> "const" | |
| + and to_strd t = to_str t.typ_desc in | |
| + | |
| + print_newline(); | |
| + hashtbl__do_table (fun s t -> | |
| +(* print_string s; (* (to_strd t.info.val_typ); *) *) | |
| + print_int (t.info.val_typ.typ_level); | |
| + print_newline ()) | |
| + module.mod_values ; | |
| + | |
| + ここで書き換えてみよう ! | |
| +*) | |
| +(* | |
| + let rec cleaned t = | |
| + { typ_desc = cleaned_typ t.typ_desc; typ_level = t.typ_level } | |
| + (* Tarrow をこっそり書き換える (なにかおかしい ...) *) | |
| + and cleaned_typ t = match t with | |
| + | Tvar (Tlinkto t) -> Tvar (Tlinkto (cleaned t)) | |
| + | Tvar _ -> t | |
| + | Tarrow (t1, t2, t3, t4) -> | |
| + (* typ_level : | |
| + 0 -> 1 回だけ instantiate 出来るの | |
| + 1 -> もっと poly なの *) | |
| + let t = { typ_desc = Tvar Tnolink; typ_level = generic } in | |
| + Tarrow (cleaned t1, t, cleaned t2, t) | |
| + | Tproduct ts -> Tproduct (map cleaned ts) | |
| + | Tconstr (g, ts) -> Tconstr (g, map cleaned ts) in | |
| + let cleaned_value v = | |
| + { val_typ = cleaned v.val_typ; val_prim = v.val_prim } in | |
| + let cleaned_vglbl g = { qualid = g.qualid; info = cleaned_value g.info } in | |
| +*) | |
| + (* Tarrow で generic に書き換えたときに、それを外側に伝播させるために | |
| + こんな感じにしている *) | |
| + let rec cleaned t = match t.typ_desc with | |
| + | Tvar (Tlinkto t) -> | |
| + let (t', tl) = cleaned t in | |
| + { typ_desc = Tvar (Tlinkto t'); typ_level = tl }, tl | |
| + | Tvar _ -> t, t.typ_level | |
| + | Tarrow (t1, t2, _, _) -> | |
| + let t = { typ_desc = Tvar Tnolink; typ_level = generic } in | |
| + let (t1', _) = cleaned t1 and (t2', _) = cleaned t2 in | |
| + let t' = Tarrow (t1', t, t2', t) in | |
| + { typ_desc = t'; typ_level = generic }, generic | |
| + | Tproduct ts -> | |
| + let (ts', tl) = cleaned_list ts t.typ_level in | |
| + { typ_desc = Tproduct ts'; typ_level = tl }, tl | |
| + | Tconstr (g, ts) -> | |
| + let (ts', tl) = cleaned_list ts t.typ_level in | |
| + { typ_desc = Tconstr (g, ts'); typ_level = tl }, tl | |
| + and cleaned_list ts tl = | |
| + let rec loop ts (acc_ts, tl) = match ts with | |
| + | [] -> rev acc_ts, tl | |
| + | t :: rest -> let (t', tl') = cleaned t in | |
| + loop rest (t' :: acc_ts, if tl' < tl then tl' else tl) in | |
| + loop ts ([], tl) in | |
| + let cleaned_value v = | |
| + { val_typ = fst (cleaned v.val_typ); val_prim = v.val_prim } in | |
| + let cleaned_vglbl g = { qualid = g.qualid; info = cleaned_value g.info } in | |
| + | |
| +(* add_table module.mod_values (!opened_modules).mod_values; *) | |
| + hashtbl__do_table_rev | |
| + (fun s t -> | |
| + hashtbl__add (!opened_modules).mod_values s (cleaned_vglbl t)) | |
| + module.mod_values; | |
| + | |
| add_table module.mod_constrs (!opened_modules).mod_constrs; | |
| add_table module.mod_labels (!opened_modules).mod_labels; | |
| add_table module.mod_types (!opened_modules).mod_types; | |
| @@ -217,6 +293,12 @@ let find_desc sel_fct = function | |
| let res = hashtbl__find (sel_fct !opened_modules) s in | |
| (* Record the module as actually used *) | |
| (hashtbl__find !used_opened_modules res.qualid.qual) := true; | |
| +(* | |
| + hashtbl__do_table (fun a b -> | |
| + print_string b.qualid.id; | |
| + print_newline()) | |
| + (sel_fct !opened_modules); | |
| +*) | |
| res | |
| with Not_found -> | |
| raise Desc_not_found | |
| diff --git a/src/compiler/par_aux.ml b/src/compiler/par_aux.ml | |
| index ac3a60d..db83a90 100644 | |
| --- a/src/compiler/par_aux.ml | |
| +++ b/src/compiler/par_aux.ml | |
| @@ -133,3 +133,11 @@ let make_listpat pats = | |
| in | |
| makel (make_pat(Zconstruct0pat(constr_nil))) pats | |
| ;; | |
| + | |
| +(* gensym *) | |
| + | |
| +let counter = ref 0;; | |
| +let gensym s = counter := succ !counter; s ^ (string_of_int !counter);; | |
| + | |
| +let new_type () = Ztypevar (gensym "v");; | |
| + | |
| diff --git a/src/compiler/parser.mly b/src/compiler/parser.mly | |
| index 09cedfa..ea9c48d 100644 | |
| --- a/src/compiler/parser.mly | |
| +++ b/src/compiler/parser.mly | |
| @@ -94,6 +94,9 @@ | |
| %token WHERE /* "where" */ | |
| %token WHILE /* "while" */ | |
| %token WITH /* "with" */ | |
| +%token SHIFT /* "shift" */ // added | |
| +%token RESET /* "reset" */ // added | |
| +%token SLASH /* "/" */ // added | |
| /* Precedences and associativities. Lower precedences first. */ | |
| @@ -116,7 +119,7 @@ | |
| %right INFIX1 /* concatenations */ | |
| %right COLONCOLON /* cons */ | |
| %left INFIX2 SUBTRACTIVE /* additives, subtractives */ | |
| -%left STAR INFIX3 /* multiplicatives */ | |
| +%left STAR INFIX3 SLASH /* multiplicatives */ | |
| %right INFIX4 /* exponentiations */ | |
| %right prec_uminus | |
| %left INFIX | |
| @@ -186,6 +189,8 @@ Expr : | |
| { make_binop $2 $1 $3 } | |
| | Expr INFIX3 Expr | |
| { make_binop $2 $1 $3 } | |
| + | Expr SLASH Expr | |
| + { make_binop "quo" $1 $3 } | |
| | Expr INFIX2 Expr | |
| { make_binop $2 $1 $3 } | |
| | Expr SUBTRACTIVE Expr | |
| @@ -255,6 +260,34 @@ Expr : | |
| { make_expr(Zlet(false, $3, $1)) } | |
| | Expr WHERE REC Binding_list %prec WHERE | |
| { make_expr(Zlet(true, $4, $1)) } | |
| + | SHIFT LPAREN FUN IDENT MINUSGREATER Expr RPAREN %prec prec_app // added | |
| + { make_expr(Zshift (make_pat (Zvarpat $4), | |
| + (make_pat (Zvarpat (gensym "arg.shifh"))), $6)) } | |
| + | SHIFT LPAREN FUN UNDERSCORE MINUSGREATER Expr RPAREN | |
| + %prec prec_app // added | |
| + { make_expr(Zshift (make_pat (Zvarpat (gensym "wildcard")), | |
| + (make_pat (Zvarpat (gensym "arg.shifh"))), $6)) } | |
| + | SHIFT LPAREN FUN IDENT MINUSGREATER Expr RPAREN Simple_expr_list | |
| + %prec prec_app // added | |
| + { make_apply | |
| + (make_expr(Zshift (make_pat (Zvarpat $4), | |
| + (make_pat (Zvarpat (gensym "arg.shifh"))), $6)), $8) } | |
| + | RESET LPAREN FUN LPAREN RPAREN MINUSGREATER Expr RPAREN Simple_expr_list | |
| + %prec prec_app | |
| + { make_apply | |
| + (make_expr(Zreset (make_pat (Zvarpat (gensym "arg.reset")), $7)), | |
| + $9) } | |
| + | RESET LPAREN FUN LPAREN RPAREN MINUSGREATER Expr RPAREN %prec prec_app | |
| + { make_apply | |
| + (make_expr(Zreset (make_pat (Zvarpat (gensym "arg.reset")), $7)), | |
| + []) } | |
| +/* | |
| + | SHIFT LPAREN FUN IDENT MINUSGREATER Expr RPAREN %prec prec_app | |
| + { make_expr(Zshift (make_pat (Zvarpat $4), | |
| + (make_pat (Zvarpat (gensym "arg.shifh"))), $6)) } | |
| + | RESET LPAREN FUN LPAREN RPAREN MINUSGREATER Expr RPAREN %prec prec_app | |
| + { make_expr(Zreset (make_pat (Zvarpat (gensym "arg.reset")), $7)) } | |
| +*/ | |
| ; | |
| Simple_expr : | |
| @@ -284,6 +317,24 @@ Simple_expr : | |
| { make_binop "vect_item" $1 $3 } | |
| | Simple_expr DOTLBRACKET Expr RBRACKET | |
| { make_binop "nth_char" $1 $3 } | |
| + | SHIFT // added (shift = \x.shift k -> x k) | |
| + { let x = gensym "x" and k = gensym "cont" in | |
| + make_expr | |
| + (Zfunction [[pat_constr_or_var x], | |
| + make_expr(Zshift (make_pat (Zvarpat k), | |
| + make_pat (Zvarpat (gensym "arg.shifh")), | |
| + make_apply(make_expr(Zident(ref(Zlocal x))), | |
| + [make_expr(Zident(ref(Zlocal k)))])))]) } | |
| + | |
| + | RESET // added (reset = \x.<x ()>) | |
| + { let x = gensym "x" and u = expr_constr_or_ident (GRname "()") in | |
| + make_expr | |
| + (Zfunction [[pat_constr_or_var x], | |
| + make_apply | |
| + (make_expr(Zreset | |
| + (make_pat (Zvarpat (gensym "arg.reset")), | |
| + make_apply(make_expr(Zident(ref(Zlocal x))), | |
| + [u]))), [])]) } | |
| ; | |
| Simple_expr_list : | |
| @@ -553,6 +604,7 @@ Infx : | |
| | SUBTRACTIVE { $1 } | PREFIX { $1 } | |
| | AMPERSAND { "&" } | AMPERAMPER { "&&" } | |
| | OR { "or" } | BARBAR { "||" } | |
| + | SLASH { "/" } | |
| ; | |
| Qual_ident : | |
| @@ -575,7 +627,10 @@ Type : | |
| | Type_star_list | |
| { make_typ(Ztypetuple(rev $1)) } | |
| | Type MINUSGREATER Type | |
| - { make_typ(Ztypearrow($1, $3)) } | |
| + { let ans_type = make_typ (new_type()) in | |
| + make_typ(Ztypearrow($1, ans_type, $3, ans_type)) } | |
| + | Simple_type SLASH Simple_type MINUSGREATER Simple_type SLASH Simple_type | |
| + { make_typ(Ztypearrow($1, $3, $5, $7)) } | |
| ; | |
| Simple_type : | |
| diff --git a/src/compiler/pr_type.ml b/src/compiler/pr_type.ml | |
| index 05caccc..6a1172d 100644 | |
| --- a/src/compiler/pr_type.ml | |
| +++ b/src/compiler/pr_type.ml | |
| @@ -53,11 +53,19 @@ let rec output_typ oc sch priority ty = | |
| Tvar _ -> | |
| output_string oc "'"; | |
| output_string oc (name_of_type_var sch ty) | |
| - | Tarrow(ty1, ty2) -> | |
| + | Tarrow(ty1, ty2, ty3, ty4) -> | |
| if priority >= 1 then output_string oc "("; | |
| + print_string "("; | |
| output_typ oc sch 1 ty1; | |
| + output_string oc " / "; | |
| + output_typ oc sch 0 ty2; (* 0 ?? *) | |
| + print_string ")"; | |
| output_string oc " -> "; | |
| - output_typ oc sch 0 ty2; | |
| + print_string "("; | |
| + output_typ oc sch 0 ty3; (* 0 ?? *) | |
| + output_string oc " / "; | |
| + output_typ oc sch 0 ty4; (* 0 ?? *) | |
| + print_string ")"; | |
| if priority >= 1 then output_string oc ")" | |
| | Tproduct(ty_list) -> | |
| if priority >= 2 then output_string oc "("; | |
| @@ -86,6 +94,75 @@ and output_typ_list oc sch priority sep = function | |
| output_typ_list oc sch priority sep rest | |
| ;; | |
| +let rec compare t1 t2 = match (t1.typ_desc, t2.typ_desc) with | |
| + | Tvar Tnolink, Tvar Tnolink -> t1 == t2 | |
| + | Tvar (Tlinkto t), _ -> compare t t2 | |
| + | _, Tvar (Tlinkto t) -> compare t1 t | |
| + | _, _ -> false;; | |
| + | |
| +let rec output_typ oc sch priority ty tvars = | |
| + let ty = type_repr ty in | |
| + match ty.typ_desc with | |
| + Tvar _ -> | |
| + output_string oc "'"; | |
| + output_string oc (name_of_type_var sch ty) | |
| + | Tarrow(ty1, ty2, ty3, ty4) | |
| + when compare ty2 ty4 && false && | |
| + for_all (fun ty -> not (compare ty2 ty)) | |
| + ((free_type_vars (-1) ty1) @ | |
| + (free_type_vars (-1) ty3) @ tvars) -> | |
| + if priority >= 1 then output_string oc "("; | |
| + output_typ oc sch 1 ty1 ((free_type_vars (-1) ty3) @ tvars); | |
| + output_string oc " -> "; | |
| + output_typ oc sch 0 ty3 ((free_type_vars (-1) ty1) @ tvars); (* 0 ?? *) | |
| + if priority >= 1 then output_string oc ")" | |
| + | Tarrow(ty1, ty2, ty3, ty4) -> | |
| + let ftv1 = free_type_vars (-1) ty1 | |
| + and ftv2 = free_type_vars (-1) ty2 | |
| + and ftv3 = free_type_vars (-1) ty3 | |
| + and ftv4 = free_type_vars (-1) ty4 in | |
| + if priority >= 1 then output_string oc "("; | |
| +(* print_string "("; *) | |
| + output_typ oc sch 1 ty1 (tvars @ ftv2 @ ftv3 @ ftv4); | |
| + output_string oc " / "; | |
| + output_typ oc sch 1 ty2 (tvars @ ftv1 @ ftv3 @ ftv4); | |
| +(* print_string ")"; *) | |
| + output_string oc " -> "; | |
| +(* print_string "("; *) | |
| + output_typ oc sch 1 ty3 (tvars @ ftv2 @ ftv1 @ ftv4); | |
| + output_string oc " / "; | |
| + output_typ oc sch 1 ty4 (tvars @ ftv2 @ ftv3 @ ftv1); | |
| +(* print_string ")"; *) | |
| + if priority >= 1 then output_string oc ")" | |
| + | Tproduct(ty_list) -> | |
| + if priority >= 2 then output_string oc "("; | |
| + output_typ_list oc sch 2 " * " tvars ty_list; | |
| + if priority >= 2 then output_string oc ")" | |
| + | Tconstr(cstr, args) -> | |
| + begin match args with | |
| + [] -> () | |
| + | [ty1] -> | |
| + output_typ oc sch 2 ty1 tvars; output_string oc " " | |
| + | tyl -> | |
| + output_string oc "("; | |
| + output_typ_list oc sch 0 ", " tvars tyl; | |
| + output_string oc ") " | |
| + end; | |
| + output_global types_of_module oc cstr | |
| + | |
| +and output_typ_list oc sch priority sep tvars = function | |
| + [] -> | |
| + () | |
| + | [ty] -> | |
| + output_typ oc sch priority ty tvars | |
| + | ty::rest -> | |
| + output_typ oc sch priority ty tvars; | |
| + output_string oc sep; | |
| + output_typ_list oc sch priority sep tvars rest | |
| +;; | |
| + | |
| +let output_typ oc sch priority sep = output_typ oc sch priority sep [];; | |
| + | |
| let output_type oc ty = output_typ oc false 0 ty;; | |
| let output_one_type oc ty = reset_type_var_name(); output_typ oc false 0 ty;; | |
| diff --git a/src/compiler/prim.ml b/src/compiler/prim.ml | |
| index ab877e2..efce5dc 100644 | |
| --- a/src/compiler/prim.ml | |
| +++ b/src/compiler/prim.ml | |
| @@ -25,6 +25,7 @@ type primitive = | |
| | Pfloatprim of float_primitive | |
| | Pstringlength | Pgetstringchar | Psetstringchar | |
| | Pmakevector | Pvectlength | Pgetvectitem | Psetvectitem | |
| + | Pshift | Preset | Pcopyblocks | |
| and float_primitive = | |
| Pfloatofint | |
| diff --git a/src/compiler/prim_opc.ml b/src/compiler/prim_opc.ml | |
| index 05173cc..4416ed1 100644 | |
| --- a/src/compiler/prim_opc.ml | |
| +++ b/src/compiler/prim_opc.ml | |
| @@ -33,6 +33,9 @@ let opcode_for_primitive = function | |
| | Pvectlength -> VECTLENGTH | |
| | Pgetvectitem -> GETVECTITEM | |
| | Psetvectitem -> SETVECTITEM | |
| + | Pshift -> SHIFT | |
| + | Preset -> RESET | |
| + | Pcopyblocks -> COPYBLOCKS | |
| | _ -> fatal_error "opcode_for_primitive" | |
| ;; | |
| diff --git a/src/compiler/syntax.ml b/src/compiler/syntax.ml | |
| index 7bfa55d..35bb164 100644 | |
| --- a/src/compiler/syntax.ml | |
| +++ b/src/compiler/syntax.ml | |
| @@ -9,7 +9,11 @@ type type_expression = | |
| te_loc: location } | |
| and type_expression_desc = | |
| Ztypevar of string | |
| - | Ztypearrow of type_expression * type_expression | |
| + | Ztypearrow of (* changed *) | |
| + (* argument type / answer type (before) -> | |
| + return type / answer type (after) *) | |
| + type_expression * type_expression * type_expression * type_expression | |
| +(* type_expression * type_expression *) | |
| | Ztypetuple of type_expression list | |
| | Ztypeconstr of global_reference * type_expression list | |
| ;; | |
| @@ -58,6 +62,12 @@ and expression_desc = | |
| | Zstream of stream_component list | |
| | Zparser of (stream_pattern list * expression) list | |
| | Zwhen of expression * expression | |
| + (* k の型 * shift の引数の式の型 * 式 *) | |
| + | Zshift of pattern * pattern * expression (* added *) | |
| + (* reset の引数の式の型 * 式 *) | |
| + | Zreset of pattern * expression (* added *) | |
| +(* | Zshift of string * expression (* added *) | |
| + | Zreset of expression (* added *) *) | |
| and expr_ident = | |
| Zglobal of value_desc global | |
| diff --git a/src/compiler/tr_env.ml b/src/compiler/tr_env.ml | |
| index e4f19f8..af80e3c 100644 | |
| --- a/src/compiler/tr_env.ml | |
| +++ b/src/compiler/tr_env.ml | |
| @@ -24,7 +24,7 @@ let rec find_var name = function | |
| let rec translate_access s env = | |
| let rec transl i = function | |
| - Tnullenv -> fatal_error "translate_env" | |
| + Tnullenv -> fatal_error "translate_env " | |
| | Treserved env -> transl (i+1) env | |
| | Tenv(l, env) -> | |
| try | |
| diff --git a/src/compiler/ty_decl.ml b/src/compiler/ty_decl.ml | |
| index 17d2e48..e3a1e8e 100644 | |
| --- a/src/compiler/ty_decl.ml | |
| +++ b/src/compiler/ty_decl.ml | |
| @@ -193,6 +193,20 @@ let type_valuedecl loc decl = | |
| do_list enter_val decl | |
| ;; | |
| +(* t1 と t2 が Tvar で = であり、かつ t の ftv に含まれないことを check *) | |
| +(* (すなわち、pure/impure 判定) *) | |
| +(* typ * typ * typ -> unit *) | |
| +let check_answer_type (t1, t2, ty) = | |
| + let rec compare t1 t2 = match (t1.typ_desc, t2.typ_desc) with | |
| + | Tvar Tnolink, Tvar Tnolink -> t1 == t2 | |
| + | Tvar (Tlinkto t), _ -> compare t t2 | |
| + | _, Tvar (Tlinkto t) -> compare t1 t | |
| + | _, _ -> false in | |
| + let ftv = free_type_vars (-1) ty in | |
| + if not (compare t1 t2) || exists (fun ty -> compare t1 ty) ftv | |
| + then impure_exp_err t1 t2 | |
| +;; | |
| + | |
| let type_letdef loc rec_flag pat_expr_list = | |
| push_type_level(); | |
| let ty_list = | |
| @@ -206,9 +220,49 @@ let type_letdef loc rec_flag pat_expr_list = | |
| (fun (name,(ty,mut_flag)) -> | |
| add_value (defined_global name {val_typ=ty; val_prim=ValueNotPrim})) in | |
| if rec_flag then enter_val env; | |
| + (* 継続つなげてみたけど ... (let x = ... の形のときだけ) *) | |
| + let ty_ans1_ref = ref (new_type_var()) | |
| + and ty_ans2_ref = ref (new_type_var()) in | |
| do_list2 | |
| - (fun (pat, exp) ty -> type_expect [] exp ty) | |
| - pat_expr_list ty_list; | |
| + (if rec_flag | |
| + then (fun (pat, exp) ty -> | |
| + type_expect [] exp (new_type_var(), ty, new_type_var())) | |
| + else (fun (pat, exp) ty -> | |
| + (match exp.e_desc with | |
| + | Zfunction _ -> | |
| + type_expect [] exp (new_type_var(), ty, new_type_var()) | |
| + | _ -> | |
| + type_expect [] exp (!ty_ans1_ref, ty, !ty_ans2_ref); | |
| + check_answer_type (!ty_ans1_ref, !ty_ans2_ref, ty); | |
| + ty_ans2_ref := !ty_ans1_ref; | |
| + ty_ans1_ref := new_type_var() | |
| + (* ty_ans1_ref := !ty_ans2_ref; | |
| + ty_ans2_ref := new_type_var() *)))) pat_expr_list ty_list; | |
| +(* | |
| + if rec_flag | |
| + then | |
| + do_list2 | |
| + (fun (pat, exp) ty -> | |
| +(* let t1 = new_type_var() and t2 = new_type_var() in | |
| + (* generalize_type t1; | |
| + generalize_type t2; *) | |
| + type_expect [] exp (t1, ty, t2) *) | |
| + type_expect [] exp (new_type_var(), ty, new_type_var())) | |
| + pat_expr_list ty_list | |
| + else do_list2 | |
| + (fun (pat, exp) ty -> | |
| + (match exp.e_desc with | |
| + | Zfunction _ -> | |
| + type_expect [] exp (new_type_var(), ty, new_type_var()) | |
| + | _ -> | |
| + type_expect [] exp (!ty_ans1_ref, ty, !ty_ans2_ref); | |
| + ty_ans1_ref := !ty_ans2_ref; | |
| + ty_ans2_ref := new_type_var())) | |
| +(* | |
| + type_expect [] exp (!ty_ans1_ref, ty, !ty_ans2_ref); | |
| + ty_ans1_ref := !ty_ans2_ref; | |
| + ty_ans2_ref := new_type_var()) *) | |
| + pat_expr_list ty_list; *) | |
| pop_type_level(); | |
| let gen_type = | |
| map2 (fun (pat, expr) ty -> (is_nonexpansive expr, ty)) | |
| @@ -221,9 +275,30 @@ let type_letdef loc rec_flag pat_expr_list = | |
| let type_expression loc expr = | |
| push_type_level(); | |
| - let ty = | |
| + let (t1, ty, t2) = | |
| type_expr [] expr in | |
| pop_type_level(); | |
| if is_nonexpansive expr then generalize_type ty; | |
| +(* pr_type__output_type stdout t1; | |
| + print_newline (); | |
| + pr_type__output_type stdout t2; | |
| + print_newline (); *) | |
| + check_answer_type (t1, t2, ty); | |
| + (* 弱い多相の check | |
| + if not (t1.typ_level = generic && t2.typ_level = generic) | |
| + then impure_exp_err t1 t2; *) | |
| ty | |
| + (* pure でなければエラー | |
| + let rec compare t1 t2 = match (t1.typ_desc, t2.typ_desc) with | |
| + | Tvar Tnolink, Tvar Tnolink -> t1 == t2 | |
| + | Tvar (Tlinkto t), _ -> compare t t2 | |
| + | _, Tvar (Tlinkto t) -> compare t1 t | |
| + | _, _ -> false in | |
| + let ftv = free_type_vars (-1) ty in | |
| + (* t1 と t2 が Tvar で = であり、かつ ftv に含まれていないならば *) | |
| + if compare t1 t2 && for_all (fun ty -> not (compare t1 ty)) ftv | |
| + (* pure なので OK *) | |
| + then ty | |
| + (* でなければ error *) | |
| + else impure_exp_err () *) | |
| ;; | |
| diff --git a/src/compiler/types.ml b/src/compiler/types.ml | |
| index 265c115..3fe3144 100644 | |
| --- a/src/compiler/types.ml | |
| +++ b/src/compiler/types.ml | |
| @@ -5,6 +5,9 @@ | |
| #open "globals";; | |
| #open "modules";; | |
| +(* option *) | |
| +let typ_option = ref "none";; | |
| + | |
| (* Type constructor equality *) | |
| let same_type_constr cstr1 cstr2 = | |
| @@ -67,8 +70,8 @@ let free_type_vars level ty = | |
| match ty.typ_desc with | |
| Tvar _ -> | |
| if ty.typ_level >= level then fv := ty :: !fv | |
| - | Tarrow(t1,t2) -> | |
| - free_vars t1; free_vars t2 | |
| + | Tarrow(t1,t2,t3,t4) -> | |
| + free_vars t1; free_vars t2; free_vars t3; free_vars t4 | |
| | Tproduct(ty_list) -> | |
| do_list free_vars ty_list | |
| | Tconstr(c, ty_list) -> | |
| @@ -84,10 +87,19 @@ let rec gen_type ty = | |
| begin match ty.typ_desc with | |
| Tvar _ -> | |
| if ty.typ_level > !current_level then ty.typ_level <- generic | |
| - | Tarrow(t1,t2) -> | |
| + | Tarrow(t1,t2,t3,t4) -> | |
| let lvl1 = gen_type t1 in | |
| let lvl2 = gen_type t2 in | |
| - ty.typ_level <- if lvl1 <= lvl2 then lvl1 else lvl2 | |
| + let lvl3 = gen_type t3 in | |
| + let lvl4 = gen_type t4 in | |
| + ty.typ_level <- | |
| + if lvl1 <= lvl2 | |
| + then if lvl3 <= lvl4 | |
| + then if lvl1 <= lvl3 then lvl1 else lvl3 | |
| + else if lvl1 <= lvl4 then lvl1 else lvl4 | |
| + else if lvl3 <= lvl4 | |
| + then if lvl2 <= lvl3 then lvl2 else lvl3 | |
| + else if lvl2 <= lvl4 then lvl2 else lvl4 | |
| | Tproduct(ty_list) -> | |
| ty.typ_level <- gen_type_list ty_list | |
| | Tconstr(c, ty_list) -> | |
| @@ -116,8 +128,8 @@ let rec nongen_type ty = | |
| match ty.typ_desc with | |
| Tvar _ -> | |
| if ty.typ_level > !current_level then ty.typ_level <- !current_level | |
| - | Tarrow(t1, t2) -> | |
| - nongen_type t1; nongen_type t2 | |
| + | Tarrow(t1, t2, t3, t4) -> | |
| + nongen_type t1; nongen_type t2; nongen_type t3; nongen_type t4 | |
| | Tproduct ty_list -> | |
| do_list nongen_type ty_list | |
| | Tconstr(cstr, ty_list) -> | |
| @@ -139,9 +151,10 @@ let rec copy_type = function | |
| if level == generic | |
| then ty | |
| else copy_type ty | |
| - | {typ_desc = Tarrow(t1,t2); typ_level = level} as ty -> | |
| + | {typ_desc = Tarrow(t1,t2,t3,t4); typ_level = level} as ty -> | |
| if level == generic | |
| - then {typ_desc = Tarrow(copy_type t1, copy_type t2); | |
| + then {typ_desc = | |
| + Tarrow(copy_type t1, copy_type t2, copy_type t3, copy_type t4); | |
| typ_level = notgeneric} | |
| else ty | |
| | {typ_desc = Tproduct tlist; typ_level = level} as ty -> | |
| @@ -166,9 +179,9 @@ let rec cleanup_type = function | |
| if level == generic | |
| then begin link <- Tnolink end | |
| else cleanup_type ty | |
| - | {typ_desc = Tarrow(t1,t2); typ_level = level} as ty -> | |
| + | {typ_desc = Tarrow(t1,t2,t3,t4); typ_level = level} as ty -> | |
| if level == generic | |
| - then (cleanup_type t1; cleanup_type t2) | |
| + then (cleanup_type t1; cleanup_type t2; cleanup_type t3; cleanup_type t4) | |
| else () | |
| | {typ_desc = Tproduct(tlist); typ_level = level} as ty -> | |
| if level == generic | |
| @@ -220,8 +233,8 @@ let occur_check level0 v = | |
| {typ_desc = Tvar _; typ_level = level} as ty' -> | |
| if level > level0 then level <- level0; | |
| ty' == v | |
| - | {typ_desc = Tarrow(t1,t2)} -> | |
| - occurs_rec t1 || occurs_rec t2 | |
| + | {typ_desc = Tarrow(t1,t2,t3,t4)} -> | |
| + occurs_rec t1 || occurs_rec t2 || occurs_rec t3 || occurs_rec t4 | |
| | {typ_desc = Tproduct(ty_list)} -> | |
| exists occurs_rec ty_list | |
| | {typ_desc = Tconstr(_, ty_list)} -> | |
| @@ -247,9 +260,12 @@ let rec unify (ty1, ty2) = | |
| link1 <- Tlinkto ty2 | |
| | _, Tvar link2 when not (occur_check ty2.typ_level ty2 ty1) -> | |
| link2 <- Tlinkto ty1 | |
| - | Tarrow(t1arg, t1res), Tarrow(t2arg, t2res) -> | |
| + | Tarrow(t1arg, t1ansa, t1res, t1ansb), | |
| + Tarrow(t2arg, t2ansa, t2res, t2ansb) -> | |
| unify (t1arg, t2arg); | |
| - unify (t1res, t2res) | |
| + unify (t1ansa, t2ansa); | |
| + unify (t1res, t2res); | |
| + unify (t1ansb, t2ansb) | |
| | Tproduct tyl1, Tproduct tyl2 -> | |
| unify_list (tyl1, tyl2) | |
| | Tconstr(cstr1, []), Tconstr(cstr2, []) | |
| @@ -281,11 +297,15 @@ let rec filter_arrow ty = | |
| match type_repr ty with | |
| {typ_desc = Tvar link; typ_level = level} -> | |
| let ty1 = {typ_desc = Tvar Tnolink; typ_level = level} | |
| - and ty2 = {typ_desc = Tvar Tnolink; typ_level = level} in | |
| - link <- Tlinkto {typ_desc = Tarrow(ty1, ty2); typ_level = notgeneric}; | |
| - (ty1, ty2) | |
| - | {typ_desc = Tarrow(ty1, ty2)} -> | |
| - (ty1, ty2) | |
| + and ty2 = {typ_desc = Tvar Tnolink; typ_level = level} | |
| + and ty3 = {typ_desc = Tvar Tnolink; typ_level = level} | |
| + and ty4 = {typ_desc = Tvar Tnolink; typ_level = level} in | |
| +(* in let ty4 = ty2 in *) | |
| + link <- Tlinkto {typ_desc = Tarrow(ty1, ty2, ty3, ty4); | |
| + typ_level = notgeneric}; | |
| + (ty1, ty2, ty3, ty4) | |
| + | {typ_desc = Tarrow(ty1, ty2, ty3, ty4)} -> | |
| + (ty1, ty2, ty3, ty4) | |
| | {typ_desc = Tconstr({info = {ty_abbr = Tabbrev(params, body)}}, args)} -> | |
| filter_arrow (expand_abbrev params body args) | |
| | _ -> | |
| @@ -321,9 +341,12 @@ let rec filter (ty1, ty2) = | |
| | Tvar link1, _ when ty1.typ_level != generic | |
| && not(occur_check ty1.typ_level ty1 ty2) -> | |
| link1 <- Tlinkto ty2 | |
| - | Tarrow(t1arg, t1res), Tarrow(t2arg, t2res) -> | |
| + | Tarrow(t1arg, t1ansa, t1res, t1ansb), | |
| + Tarrow(t2arg, t2ansa, t2res, t2ansb) -> | |
| filter (t1arg, t2arg); | |
| - filter (t1res, t2res) | |
| + filter (t1ansa, t2ansa); | |
| + filter (t1res, t2res); | |
| + filter (t1ansb, t2ansb) | |
| | Tproduct(t1args), Tproduct(t2args) -> | |
| filter_list (t1args, t2args) | |
| | Tconstr(cstr1, []), Tconstr(cstr2, []) | |
| @@ -389,7 +412,9 @@ let check_recursive_abbrev cstr = | |
| let rec check_abbrev seen ty = | |
| match (type_repr ty).typ_desc with | |
| Tvar _ -> () | |
| - | Tarrow(t1, t2) -> check_abbrev seen t1; check_abbrev seen t2 | |
| + | Tarrow(t1, t2, t3, t4) -> | |
| + check_abbrev seen t1; check_abbrev seen t2; | |
| + check_abbrev seen t3; check_abbrev seen t4 | |
| | Tproduct tlist -> do_list (check_abbrev seen) tlist | |
| | Tconstr(c, tlist) -> | |
| if memq c seen then | |
| diff --git a/src/compiler/typing.ml b/src/compiler/typing.ml | |
| index ae3b249..f5322f6 100644 | |
| --- a/src/compiler/typing.ml | |
| +++ b/src/compiler/typing.ml | |
| @@ -45,8 +45,11 @@ let type_of_type_expression strict_flag typexp = | |
| type_expr_vars := (v,t) :: !type_expr_vars; t | |
| end | |
| end | |
| - | Ztypearrow(arg1, arg2) -> | |
| - type_arrow(type_of arg1, type_of arg2) | |
| + | Ztypearrow(arg1, arg2, arg3, arg4) -> | |
| + type_arrow(type_of arg1, type_of arg2, type_of arg3, type_of arg4) | |
| +(* | Ztypearrow(arg1, arg2) -> | |
| + let ty_ans = new_type_var() in | |
| + type_arrow(type_of arg1, ty_ans, type_of arg2, ty_ans) *) | |
| | Ztypetuple argl -> | |
| type_product(map type_of argl) | |
| | Ztypeconstr(cstr_name, args) -> | |
| @@ -208,10 +211,14 @@ let rec is_nonexpansive expr = | |
| (* Typing of printf formats *) | |
| +let new_type_ans() = | |
| + let t = new_type_var() in (* t.typ_level <- generic; *) t;; | |
| + | |
| let type_format loc fmt = | |
| let len = string_length fmt in | |
| let ty_input = new_type_var() | |
| - and ty_result = new_type_var() in | |
| + and ty_result = new_type_var() | |
| + and ty_ans = new_type_ans() in (* answer_type (not modified) *) | |
| let rec skip_args j = | |
| if j >= len then j else | |
| match nth_char fmt j with | |
| @@ -226,21 +233,31 @@ let type_format loc fmt = | |
| `%` -> | |
| scan_format (succ j) | |
| | `s` -> | |
| - type_arrow (type_string, scan_format (succ j)) | |
| + type_arrow (type_string, ty_ans, scan_format (succ j), ty_ans) | |
| | `c` -> | |
| - type_arrow (type_char, scan_format (succ j)) | |
| + type_arrow (type_char, ty_ans, scan_format (succ j), ty_ans) | |
| | `d` | `o` | `x` | `X` | `u` -> | |
| - type_arrow (type_int, scan_format (succ j)) | |
| + type_arrow (type_int, ty_ans, scan_format (succ j), ty_ans) | |
| | `f` | `e` | `E` | `g` | `G` -> | |
| - type_arrow (type_float, scan_format (succ j)) | |
| + type_arrow (type_float, ty_ans, scan_format (succ j), ty_ans) | |
| | `b` -> | |
| - type_arrow (type_bool, scan_format (succ j)) | |
| + type_arrow (type_bool, ty_ans, scan_format (succ j), ty_ans) | |
| | `a` -> | |
| - let ty_arg = new_type_var() in | |
| - type_arrow (type_arrow (ty_input, type_arrow (ty_arg, ty_result)), | |
| - type_arrow (ty_arg, scan_format (succ j))) | |
| + let ty_arg = new_type_var() | |
| + and ty_ans' = new_type_ans() | |
| + and ty_ans'' = new_type_ans() | |
| + and ty_ans''' = new_type_ans() in | |
| + type_arrow (type_arrow (ty_input, ty_ans', | |
| + type_arrow (ty_arg, ty_ans''', | |
| + ty_result, ty_ans'''), | |
| + ty_ans'), ty_ans, | |
| + type_arrow (ty_arg, ty_ans'', | |
| + scan_format (succ j), ty_ans'), ty_ans) | |
| | `t` -> | |
| - type_arrow (type_arrow (ty_input, ty_result), scan_format (succ j)) | |
| + let ty_ans' = new_type_ans() in | |
| + type_arrow (type_arrow (ty_input, ty_ans', | |
| + ty_result, ty_ans'), ty_ans, | |
| + scan_format (succ j), ty_ans) | |
| | c -> | |
| bad_format_letter loc c | |
| end | |
| @@ -258,17 +275,27 @@ let unify_expr expr expected_ty actual_ty = | |
| expr_wrong_type_err expr actual_ty expected_ty | |
| ;; | |
| +let unify_answer_type t1 t2 = | |
| + try | |
| + unify (t1, t2) | |
| + with Unify -> | |
| + answer_type_err t1 t2 | |
| +;; | |
| + | |
| +(* env -> exp -> typ * typ * typ *) | |
| let rec type_expr env expr = | |
| - let inferred_ty = | |
| + let (ty_a, inferred_ty, ty_b) = | |
| match expr.e_desc with | |
| Zident r -> | |
| + let ty_ans = new_type_ans() in | |
| + ty_ans, | |
| begin match !r with | |
| Zglobal glob_desc -> | |
| type_instance glob_desc.info.val_typ | |
| | Zlocal s -> | |
| try | |
| let (ty_schema, mut_flag) = assoc s env in | |
| - type_instance ty_schema | |
| + type_instance ty_schema | |
| with Not_found -> | |
| try | |
| let glob_desc = find_value_desc(GRname s) in | |
| @@ -276,58 +303,141 @@ let rec type_expr env expr = | |
| type_instance glob_desc.info.val_typ | |
| with Desc_not_found -> | |
| unbound_value_err (GRname s) expr.e_loc | |
| - end | |
| - | Zconstant cst -> | |
| - type_of_structured_constant cst | |
| + end, ty_ans | |
| + | Zconstant cst -> | |
| + let ty_ans = new_type_ans() in | |
| + ty_ans, type_of_structured_constant cst, ty_ans | |
| | Ztuple(args) -> | |
| - type_product(map (type_expr env) args) | |
| - | Zconstruct0(cstr) -> | |
| + let (ty_ans1, ts, ty_ans2) = type_expr_list env args in | |
| + ty_ans1, type_product ts, ty_ans2 | |
| + | Zconstruct0(cstr) -> | |
| + let ty_ans = new_type_ans() in | |
| + ty_ans, | |
| begin match cstr.info.cs_kind with | |
| Constr_constant -> | |
| type_instance cstr.info.cs_res | |
| | _ -> | |
| let (ty_res, ty_arg) = | |
| type_pair_instance (cstr.info.cs_res, cstr.info.cs_arg) in | |
| - type_arrow(ty_arg, ty_res) | |
| - end | |
| + let ty_ans = new_type_ans() in | |
| + type_arrow(ty_arg, ty_ans, ty_res, ty_ans) | |
| + end, ty_ans | |
| | Zconstruct1(cstr, arg) -> | |
| + let ty_ans = new_type_ans() in | |
| begin match cstr.info.cs_kind with | |
| Constr_constant -> | |
| - constant_constr_err cstr expr.e_loc | |
| - | _ -> | |
| + constant_constr_err cstr expr.e_loc | |
| + | _ -> | |
| + let ty_ans = new_type_ans() | |
| + and ty_ans' = new_type_ans() in | |
| let (ty_res, ty_arg) = | |
| type_pair_instance (cstr.info.cs_res, cstr.info.cs_arg) in | |
| - type_expect env arg ty_arg; | |
| - ty_res | |
| + type_expect env arg (ty_ans, ty_arg, ty_ans'); | |
| + (* バグりそう ... ? *) | |
| + ty_ans, ty_res, ty_ans' | |
| end | |
| | Zapply(fct, args) -> | |
| - let ty_fct = type_expr env fct in | |
| - let rec type_args ty_res = function | |
| - [] -> ty_res | |
| - | arg1 :: argl -> | |
| - let (ty1, ty2) = | |
| - try | |
| - filter_arrow ty_res | |
| - with Unify -> | |
| - application_of_non_function_err fct ty_fct in | |
| - type_expect env arg1 ty1; | |
| - type_args ty2 argl in | |
| - type_args ty_fct args | |
| +(* print_int (list_length args) ; print_newline (); *) | |
| + if (list_length args = 2 && | |
| + (match fct.e_desc with | |
| + | Zident r -> (match !r with | |
| + | Zlocal s -> | |
| + if (s = "&&" || s = "&" || | |
| + s = "or" || s = "||") | |
| + then | |
| + let glob_desc = find_value_desc(GRname s) in | |
| + r := Zglobal glob_desc; | |
| + true | |
| + else false | |
| + | Zglobal | |
| + { info = { val_prim = ValuePrim (2, p) }} -> | |
| + p = prim__Pandint || p = prim__Porint | |
| + | _ -> false) | _ -> false)) | |
| + then | |
| + (* and と or を特別扱い ... left-to-right & e2 は pure *) | |
| + begin | |
| + let e1 = hd args and e2 = hd (tl args) in | |
| + let (t1, ty1, t2) = type_expr env e1 in | |
| + let t3 = new_type_ans() in | |
| + type_expect env e2 (t3, type_bool, t1); | |
| + unify_expr e1 type_bool ty1; | |
| + unify_answer_type t1 t3; | |
| + t3, type_bool, t2 | |
| + end | |
| + else | |
| + begin | |
| + (* バグるかも ... *) | |
| + let (t1, ty_fct, t2) = type_expr env fct in | |
| + let rec type_args (t1, ty_res, t2) = function | |
| + [] -> | |
| + (t1, ty_res, t2) | |
| + | arg1 :: argl -> | |
| + let (ty1, ty2, ty3, ty4) = | |
| + try | |
| + filter_arrow ty_res | |
| + with Unify -> | |
| + application_of_non_function_err fct ty_fct in | |
| + let ty_ans = new_type_ans() in | |
| + (try (unify_answer_type t1 ty4) with | |
| + | e -> | |
| + pr_type__output_type stdout ty1; print_newline (); | |
| + pr_type__output_type stdout ty2; print_newline (); | |
| + pr_type__output_type stdout ty3; print_newline (); | |
| + pr_type__output_type stdout ty4; print_newline (); | |
| + pr_type__output_type stdout t1; print_newline (); | |
| + pr_type__output_type stdout t2; print_newline (); | |
| + pr_type__output_type stdout ty_res; print_newline (); | |
| + raise e); | |
| + type_expect env arg1 (t2, ty1, ty_ans); | |
| + type_args (ty2, ty3, ty_ans) argl in | |
| + type_args (t1, ty_fct, t2) args | |
| + end | |
| | Zlet(rec_flag, pat_expr_list, body) -> | |
| - type_expr (type_let_decl env rec_flag pat_expr_list) body | |
| +(* | |
| + print_int 3; print_newline (); | |
| + (match pat_expr_list with | |
| + | [] -> () | |
| + | (a, e) :: _ -> (match a.p_desc with | |
| + | Zvarpat _ -> | |
| + (match e.e_desc with | |
| + | Zfunction _ -> print_int 5; print_newline () | |
| + | _ -> print_int 6; print_newline ()) | |
| + | _ -> print_int 4; print_newline ())); | |
| +*) | |
| + (* あ、let = pure の条件、抜けているな ... | |
| + CamlLight の制約だけで十分か ?? *) | |
| +(* print_string (string_of_bool rec_flag); | |
| + print_newline (); *) | |
| + let (env, ty_ans3, ty_ans2) = type_let_decl env rec_flag pat_expr_list in | |
| + let (ty_ans1, ty, ty_ans3') = type_expr env body in | |
| + unify_answer_type ty_ans3 ty_ans3'; | |
| + ty_ans1, ty, ty_ans2 | |
| | Zfunction [] -> | |
| fatal_error "type_expr: empty matching" | |
| | Zfunction ((patl1,expr1)::_ as matching) -> | |
| + (* pure *) | |
| let ty_args = map (fun pat -> new_type_var()) patl1 in | |
| - let ty_res = new_type_var() in | |
| + let ty_res = new_type_var() | |
| + and ty_ans = new_type_ans() | |
| + and ty_ans' = new_type_ans() | |
| + and ty_ans'' = new_type_ans() in | |
| let tcase (patl, action) = | |
| if list_length patl != list_length ty_args then | |
| ill_shaped_match_err expr; | |
| - type_expect (type_pattern_list patl ty_args @ env) action ty_res in | |
| + type_expect (type_pattern_list patl ty_args @ env) action | |
| + (ty_ans, ty_res, ty_ans') in | |
| do_list tcase matching; | |
| - list_it (fun ty_arg ty_res -> type_arrow(ty_arg, ty_res)) | |
| - ty_args ty_res | |
| - | Ztrywith (body, matching) -> | |
| + (if list_length ty_args = 0 then failwith "empty function"); | |
| + let (ty_arg, ty_args') = | |
| + let rev_args = rev ty_args in hd rev_args, rev (tl rev_args) in | |
| + ty_ans'', | |
| + list_it (fun ty_arg ty_res -> | |
| + let ty_ans = new_type_ans() in | |
| + type_arrow(ty_arg, ty_ans, ty_res, ty_ans)) | |
| + ty_args' (type_arrow (ty_arg, ty_ans, ty_res, ty_ans')), | |
| + ty_ans'' | |
| + | Ztrywith (body, matching) -> | |
| + (* わかんないから放置 ... まずそう ... *) | |
| let ty = type_expr env body in | |
| do_list | |
| (fun (pat, expr) -> | |
| @@ -335,61 +445,85 @@ let rec type_expr env expr = | |
| matching; | |
| ty | |
| | Zsequence (e1, e2) -> | |
| - type_statement env e1; type_expr env e2 | |
| + let (ty_ans1, ty_ans2) = type_statement env e1 in | |
| + let (ty_ans2', ty, ty_ans3) = type_expr env e2 in | |
| + unify_answer_type ty_ans2 ty_ans2'; | |
| + ty_ans1, ty, ty_ans3 | |
| | Zcondition (cond, ifso, ifnot) -> | |
| - type_expect env cond type_bool; | |
| + let ty_ans1 = new_type_ans() | |
| + and ty_ans2 = new_type_ans() in | |
| + type_expect env cond (ty_ans1, type_bool, ty_ans2); | |
| if match ifnot.e_desc | |
| with Zconstruct0 cstr -> cstr == constr_void | _ -> false | |
| then begin | |
| - type_expect env ifso type_unit; | |
| - type_unit | |
| + let ty_ans3 = new_type_ans() in | |
| + type_expect env ifso (ty_ans3, type_unit, ty_ans1); | |
| + ty_ans3, type_unit, ty_ans2 | |
| end else begin | |
| - let ty = type_expr env ifso in | |
| - type_expect env ifnot ty; | |
| - ty | |
| + let (ty_ans3, ty, ty_ans1') = type_expr env ifso in | |
| + type_expect env ifnot (ty_ans3, ty, ty_ans1'); | |
| + unify_answer_type ty_ans1 ty_ans1'; | |
| + ty_ans3, ty, ty_ans2 | |
| end | |
| | Zwhen (cond, act) -> | |
| - type_expect env cond type_bool; | |
| - type_expr env act | |
| + let ty_ans1 = new_type_ans() in | |
| + let (ty_ans2, ty, ty_ans3) = type_expr env act in | |
| + type_expect env cond (ty_ans3, type_bool, ty_ans1); | |
| + ty_ans2, ty, ty_ans1 | |
| | Zwhile (cond, body) -> | |
| - type_expect env cond type_bool; | |
| - type_statement env body; | |
| - type_unit | |
| + let (ty_ans1, ty_ans1') = type_statement env body in | |
| + unify_answer_type ty_ans1 ty_ans1'; | |
| + type_expect env cond (ty_ans1, type_bool, ty_ans1); | |
| + ty_ans1, type_unit, ty_ans1 | |
| | Zfor (id, start, stop, up_flag, body) -> | |
| - type_expect env start type_int; | |
| - type_expect env stop type_int; | |
| - type_statement ((id,(type_int,Notmutable)) :: env) body; | |
| - type_unit | |
| + let ty_ans1 = new_type_ans() | |
| + and ty_ans2 = new_type_ans() | |
| + and ty_ans3 = new_type_ans() in | |
| + type_expect env start (ty_ans3, type_int, ty_ans2); | |
| + type_expect env stop (ty_ans1, type_int, ty_ans3); | |
| + let (ty_ans1', ty_ans1'') = | |
| + type_statement ((id,(type_int,Notmutable)) :: env) body in | |
| + unify_answer_type ty_ans1 ty_ans1'; | |
| + unify_answer_type ty_ans1 ty_ans1''; | |
| + ty_ans1, type_unit, ty_ans2 | |
| | Zconstraint (e, ty_expr) -> | |
| + let ty_ans = new_type_ans() in | |
| let ty' = type_of_type_expression false ty_expr in | |
| - type_expect env e ty'; | |
| - ty' | |
| + type_expect env e (ty_ans, ty', ty_ans); | |
| + ty_ans, ty', ty_ans | |
| | Zvector elist -> | |
| let ty_arg = new_type_var() in | |
| - do_list (fun e -> type_expect env e ty_arg) elist; | |
| - type_vect ty_arg | |
| + let (ty_ans1, tlist, ty_ans2) = type_expr_list env elist in | |
| + do_list2 (fun t e -> unify_expr e ty_arg t) tlist elist; | |
| + ty_ans1, (type_vect ty_arg), ty_ans2 | |
| | Zassign(id, e) -> | |
| begin try | |
| match assoc id env with | |
| (ty_schema, Notmutable) -> | |
| not_mutable_err id expr.e_loc | |
| | (ty_schema, Mutable) -> | |
| - type_expect env e (type_instance ty_schema); | |
| - type_unit | |
| + let ty_ans1 = new_type_ans() | |
| + and ty_ans2 = new_type_ans() in | |
| + type_expect env e (ty_ans1, (type_instance ty_schema), ty_ans2); | |
| + ty_ans1, type_unit, ty_ans2 | |
| with Not_found -> | |
| unbound_value_err (GRname id) expr.e_loc | |
| end | |
| | Zrecord lbl_expr_list -> | |
| let ty = new_type_var() in | |
| - do_list | |
| - (fun (lbl, exp) -> | |
| - let (ty_res, ty_arg) = | |
| - type_pair_instance (lbl.info.lbl_res, lbl.info.lbl_arg) in | |
| - begin try unify (ty, ty_res) | |
| - with Unify -> label_not_belong_err expr lbl ty | |
| - end; | |
| - type_expect env exp ty_arg) | |
| - lbl_expr_list; | |
| + let rec loop = function | |
| + | [] -> let ty_ans = new_type_ans() in ty_ans, ty_ans | |
| + | (lbl, exp) :: rest -> | |
| + let (ty_ans1, ty_ans2) = loop rest in | |
| + let ty_ans3 = new_type_ans() in | |
| + let (ty_res, ty_arg) = | |
| + type_pair_instance (lbl.info.lbl_res, lbl.info.lbl_arg) in | |
| + begin try unify (ty, ty_res) | |
| + with Unify -> label_not_belong_err expr lbl ty | |
| + end; | |
| + type_expect env exp (ty_ans3, ty_arg, ty_ans1); | |
| + ty_ans3, ty_ans2 in | |
| + let (ty_ans1, ty_ans2) = loop lbl_expr_list in | |
| let label = vect_of_list (labels_of_type ty) in | |
| let defined = make_vect (vect_length label) false in | |
| do_list (fun (lbl, exp) -> | |
| @@ -401,55 +535,138 @@ let rec type_expr env expr = | |
| for i = 0 to vect_length label - 1 do | |
| if not defined.(i) then label_undefined_err expr label.(i) | |
| done; | |
| - ty | |
| + ty_ans1, ty, ty_ans2 | |
| | Zrecord_access (e, lbl) -> | |
| + let ty_ans1 = new_type_ans() | |
| + and ty_ans2 = new_type_ans() in | |
| let (ty_res, ty_arg) = | |
| type_pair_instance (lbl.info.lbl_res, lbl.info.lbl_arg) in | |
| - type_expect env e ty_res; | |
| - ty_arg | |
| + type_expect env e (ty_ans1, ty_res, ty_ans2); | |
| + ty_ans1, ty_arg, ty_ans2 | |
| | Zrecord_update (e1, lbl, e2) -> | |
| + let ty_ans1 = new_type_ans() | |
| + and ty_ans2 = new_type_ans() | |
| + and ty_ans3 = new_type_ans() in | |
| let (ty_res, ty_arg) = | |
| type_pair_instance (lbl.info.lbl_res, lbl.info.lbl_arg) in | |
| if lbl.info.lbl_mut == Notmutable then label_not_mutable_err expr lbl; | |
| - type_expect env e1 ty_res; | |
| - type_expect env e2 ty_arg; | |
| - type_unit | |
| + type_expect env e1 (ty_ans1, ty_res, ty_ans2); | |
| + type_expect env e2 (ty_ans2, ty_arg, ty_ans3); | |
| + ty_ans1, type_unit, ty_ans3 | |
| | Zstream complist -> | |
| + (* on demand で実行するから、answer type は関係ない ?? *) | |
| let ty_comp = new_type_var() in | |
| let ty_res = type_stream ty_comp in | |
| + let ty_ans1 = new_type_ans() | |
| + and ty_ans2 = new_type_ans() in | |
| do_list | |
| - (function Zterm e -> type_expect env e ty_comp | |
| - | Znonterm e -> type_expect env e ty_res) | |
| + (function Zterm e -> | |
| + type_expect env e (ty_ans1, ty_comp, ty_ans2) | |
| + | Znonterm e -> | |
| + type_expect env e (ty_ans1, ty_res, ty_ans2)) | |
| complist; | |
| - ty_res | |
| + ty_ans1, ty_res, ty_ans2 | |
| | Zparser casel -> | |
| + (* よくわからん ... stream が ... *) | |
| let ty_comp = new_type_var() in | |
| let ty_stream = type_stream ty_comp in | |
| let ty_res = new_type_var() in | |
| + let ty_ans1 = new_type_ans() | |
| + and ty_ans2 = new_type_ans() | |
| +(* and ty_ans1' = new_type_var() | |
| + and ty_ans2' = new_type_var() *) in | |
| let rec type_stream_pat new_env = function | |
| ([], act) -> | |
| - type_expect (new_env @ env) act ty_res | |
| + type_expect (new_env @ env) act (ty_ans1, ty_res, ty_ans2) | |
| | (Ztermpat p :: rest, act) -> | |
| type_stream_pat (tpat new_env (p, ty_comp, Notmutable)) (rest,act) | |
| | (Znontermpat(parsexpr, p) :: rest, act) -> | |
| let ty_parser_result = new_type_var() in | |
| type_expect (new_env @ env) parsexpr | |
| - (type_arrow(ty_stream, ty_parser_result)); | |
| + (ty_ans1, | |
| + type_arrow(ty_stream, ty_ans1, | |
| + ty_parser_result, ty_ans2), | |
| + ty_ans2); | |
| type_stream_pat (tpat new_env (p, ty_parser_result, Notmutable)) | |
| (rest,act) | |
| | (Zstreampat s :: rest, act) -> | |
| type_stream_pat ((s, (ty_stream, Notmutable)) :: new_env) (rest,act) | |
| in | |
| do_list (type_stream_pat []) casel; | |
| - type_arrow(ty_stream, ty_res) | |
| + ty_ans1, type_arrow(ty_stream, ty_ans1, ty_res, ty_ans2), ty_ans2 | |
| + | |
| + | Zshift ({ p_desc = Zvarpat id } as pat1, pat2, exp) -> | |
| + (* ∀t.('t/t ->'a/t) の表現がこれでいいのか疑問 ... *) | |
| + let ty_ans = new_type_ans() | |
| + and ty_arg = new_type_var() | |
| + and ty_res = new_type_var() in | |
| + ty_ans.typ_level <- generic; | |
| + let ty_arr = type_arrow (ty_arg, ty_ans, ty_res, ty_ans) in | |
| +(* generalize_type ty_ans; *) | |
| + ty_arr.typ_level <- generic; | |
| + (* answer type polymorphic *) | |
| + ty_ans.typ_level <- generic; | |
| + pat1.p_typ <- ty_arr; | |
| + let (ty_ans1, ty', ty_ans2) = | |
| + type_expr ((id, (pat1.p_typ, Notmutable)) :: env) exp in | |
| + unify_answer_type ty_ans1 ty'; | |
| + pat2.p_typ <- type_arrow (ty_arr, ty', ty', ty_ans2); | |
| + ty_res, ty_arg, ty_ans2 | |
| + | |
| + | Zshift _ -> failwith "not happend" | |
| + | Zreset (pat, exp) -> | |
| + (* これでいいのかなぁ ... ?? *) | |
| + let (ty_ans1, ty, ty_ans2) = type_expr env exp in | |
| + let ty_ans = new_type_ans() in | |
| +(* ty_ans.typ_level <- generic; *) | |
| + (* 型エラーメッセージ変更のため *) | |
| + unify_expr exp ty ty_ans1; | |
| + ty_ans, ty_ans2, ty_ans | |
| +(* pat.p_typ <- type_arrow (type_unit, ty_ans2, ty, ty_ans2);*) | |
| +(* unify_pat pat (type_arrow (type_unit, ty_ans2, ty, ty_ans2)) pat.p_typ; *) | |
| +(* | |
| +env; 's |- e : 's; 't | |
| +--------------------- | |
| +env |-p reset e : 't | |
| + | |
| + | |
| +env; 's |- e : unit -> 's; 't | |
| +----------------------------- | |
| +env |- reset e : 't | |
| +*) | |
| +(* | |
| + | Zshift (id, exp) -> | |
| + (* ∀t.('t/t ->'a/t) の表現がこれでいいのか疑問 ... *) | |
| + let ty_ans = new_type_var() | |
| + and ty_arg = new_type_var() | |
| + and ty_res = new_type_var() in | |
| + generalize_type ty_ans; | |
| + let ty_arr = type_arrow (ty_arg, ty_ans, ty_res, ty_ans) in | |
| + let (ty_ans1, ty, ty_ans2) = | |
| + type_expr ((id, (ty_arr, Notmutable)) :: env) exp in | |
| + unify_answer_type ty_ans1 ty; | |
| + ty_res, ty_arg, ty_ans2 | |
| + | Zreset exp -> | |
| + let (ty_ans1, ty, ty_ans2) = type_expr env exp in | |
| + let ty_ans = new_type_var() in | |
| + unify_expr expr ty ty_ans1; | |
| + ty_ans, ty_ans2, ty_ans *) | |
| in | |
| expr.e_typ <- inferred_ty; | |
| - inferred_ty | |
| + ty_a, inferred_ty, ty_b | |
| +(* typing for list (right-to-left) *) | |
| +and type_expr_list env = function | |
| + | [] -> let ty_ans = new_type_ans() in ty_ans, [], ty_ans | |
| + | e :: es -> | |
| + let (t1, t, t2) = type_expr env e in | |
| + let (t2', ts, t3) = type_expr_list env es in | |
| + unify_answer_type t2 t2'; | |
| + t1, (t :: ts), t3 | |
| (* Typing of an expression with an expected type. | |
| Some constructs are treated specially to provide better error messages. *) | |
| -and type_expect env exp expected_ty = | |
| +and type_expect env exp (ty_ans1, expected_ty, ty_ans2) = | |
| match exp.e_desc with | |
| Zconstant(SCatom(ACstring s)) -> | |
| let actual_ty = | |
| @@ -461,25 +678,44 @@ and type_expect env exp expected_ty = | |
| else type_string | |
| | _ -> | |
| type_string in | |
| + unify_answer_type ty_ans1 ty_ans2; | |
| unify_expr exp expected_ty actual_ty | |
| | Zlet(rec_flag, pat_expr_list, body) -> | |
| - type_expect (type_let_decl env rec_flag pat_expr_list) body expected_ty | |
| + let (env, ty_ans3, ty_ans2') = | |
| + type_let_decl env rec_flag pat_expr_list in | |
| + unify_answer_type ty_ans2 ty_ans2'; | |
| + type_expect env body (ty_ans1, expected_ty, ty_ans3) | |
| | Zsequence (e1, e2) -> | |
| - type_statement env e1; type_expect env e2 expected_ty | |
| + let (ty_ans3, ty_ans2') = type_statement env e1 in | |
| + unify_answer_type ty_ans2 ty_ans2'; | |
| + type_expect env e2 (ty_ans1, expected_ty, ty_ans3) | |
| | Zcondition (cond, ifso, ifnot) -> | |
| - type_expect env cond type_bool; | |
| - type_expect env ifso expected_ty; | |
| - type_expect env ifnot expected_ty | |
| + let ty_ans3 = new_type_ans() in | |
| + type_expect env cond (ty_ans3, type_bool, ty_ans2); | |
| + type_expect env ifso (ty_ans1, expected_ty, ty_ans3); | |
| + type_expect env ifnot (ty_ans1, expected_ty, ty_ans3) | |
| | Ztuple el -> | |
| + let ty_ans1_ref = ref ty_ans1 | |
| + and ty_ans2_ref = ref (new_type_ans()) in | |
| begin try | |
| - do_list2 (type_expect env) | |
| - el (filter_product (list_length el) expected_ty) | |
| + do_list2 (fun e ty -> | |
| + type_expect env e (!ty_ans1_ref, ty, !ty_ans2_ref); | |
| + ty_ans1_ref := !ty_ans2_ref; | |
| + ty_ans2_ref := new_type_ans()) | |
| + el (filter_product (list_length el) expected_ty); | |
| + unify_answer_type !ty_ans1_ref ty_ans2 | |
| with Unify -> | |
| - unify_expr exp expected_ty (type_expr env exp) | |
| + let (ty_ans1', ty, ty_ans2') = type_expr env exp in | |
| + unify_expr exp expected_ty ty; | |
| + unify_answer_type ty_ans1 ty_ans1'; | |
| + unify_answer_type ty_ans2 ty_ans2' | |
| end | |
| (* To do: try...with, match...with ? *) | |
| | _ -> | |
| - unify_expr exp expected_ty (type_expr env exp) | |
| + let (ty_ans1', ty, ty_ans2') = type_expr env exp in | |
| + unify_answer_type ty_ans1' ty_ans1; | |
| + unify_answer_type ty_ans2' ty_ans2; | |
| + unify_expr exp expected_ty ty | |
| (* Typing of "let" definitions *) | |
| @@ -493,25 +729,113 @@ and type_let_decl env rec_flag pat_expr_list = | |
| typing_let := false; | |
| let new_env = | |
| add_env @ env in | |
| + let env' = if rec_flag then new_env else env in | |
| + (* 継続つなげてみたけど ... (let x = ... の形のときだけ) *) | |
| + let ty_ans2 = new_type_ans() in | |
| + let ty_ans1_ref = ref (new_type_ans()) | |
| + and ty_ans2_ref = ref ty_ans2 in | |
| do_list2 | |
| + (if rec_flag | |
| + then (fun (pat, exp) ty -> | |
| + type_expect env' exp (new_type_ans(), ty, new_type_ans())) | |
| + else (fun (pat, exp) ty -> | |
| + (match exp.e_desc with | |
| + | Zfunction _ -> | |
| + type_expect env' exp (new_type_ans(), ty, new_type_ans()) | |
| + | _ -> | |
| + type_expect env' exp (!ty_ans1_ref, ty, !ty_ans2_ref); | |
| + ty_ans2_ref := !ty_ans1_ref; | |
| + ty_ans1_ref := new_type_ans()))) pat_expr_list ty_list; | |
| +(* | |
| + let ty_ans1 = new_type_var() in | |
| + let ty_ans1_ref = ref ty_ans1 | |
| + and ty_ans2_ref = ref (new_type_var()) in | |
| + do_list2 | |
| + (if rec_flag | |
| + then (fun (pat, exp) ty -> | |
| + type_expect env' exp (new_type_var (), ty, new_type_var ())) | |
| + else (fun (pat, exp) ty -> | |
| + (match exp.e_desc with | |
| + | Zfunction _ -> | |
| + type_expect env' exp (new_type_var(), ty, new_type_var()) | |
| + | _ -> | |
| + type_expect env' exp (!ty_ans1_ref, ty, !ty_ans2_ref); | |
| + ty_ans1_ref := !ty_ans2_ref; | |
| + ty_ans2_ref := new_type_var()))) pat_expr_list ty_list; | |
| +*) | |
| +(* | |
| + if rec_flag | |
| + then (do_list2 (fun (pat, exp) ty -> type_expect env' exp (new_type_var (), ty, new_type_var ())) pat_expr_list ty_list) | |
| + else do_list2 | |
| (fun (pat, exp) ty -> | |
| - type_expect (if rec_flag then new_env else env) exp ty) | |
| - pat_expr_list ty_list; | |
| + (match exp.e_desc with | |
| + | Zfunction _ -> | |
| + type_expect env' exp (new_type_var(), ty, new_type_var()) | |
| + | _ -> | |
| + type_expect env' exp (!ty_ans1_ref, ty, !ty_ans2_ref); | |
| + ty_ans1_ref := !ty_ans2_ref; | |
| + ty_ans2_ref := new_type_var())) | |
| + pat_expr_list ty_list; *) | |
| pop_type_level(); | |
| let gen_type = | |
| map2 (fun (pat, expr) ty -> (is_nonexpansive expr, ty)) | |
| pat_expr_list ty_list in | |
| do_list (fun (gen, ty) -> if not gen then nongen_type ty) gen_type; | |
| do_list (fun (gen, ty) -> if gen then generalize_type ty) gen_type; | |
| - new_env | |
| + new_env, !ty_ans2_ref, ty_ans2 (* ty_ans1, !ty_ans1_ref *) | |
| (* Typing of statements (expressions whose values are ignored) *) | |
| and type_statement env expr = | |
| - let ty = type_expr env expr in | |
| - match (type_repr ty).typ_desc with | |
| - | Tarrow(_,_) -> partial_apply_warning expr.e_loc | |
| - | Tvar _ -> () | |
| - | _ -> | |
| - if not (same_base_type ty type_unit) then not_unit_type_warning expr ty | |
| + let (ty_ans1, ty, ty_ans2) = type_expr env expr in | |
| + (match (type_repr ty).typ_desc with | |
| + | Tarrow(_,_,_,_) -> partial_apply_warning expr.e_loc | |
| + | Tvar t -> () (* t <- Tlinkto type_unit *) | |
| + | _ -> | |
| + if not (same_base_type ty type_unit) | |
| + then not_unit_type_warning expr ty); | |
| + ty_ans1, ty_ans2 | |
| ;; | |
| + | |
| + | |
| + | |
| +(* | |
| + print_string (match exp.e_desc with | |
| + | Zident _ -> "ident" | |
| + | Zconstant _ -> "const" | |
| + | Ztuple _ -> "tuple" | |
| + | Zconstruct0 _ -> "construct0" | |
| + | Zconstruct1 _ -> "construct1" | |
| + | Zapply _ -> "app" | |
| + | Zlet _ -> "let" | |
| + | Zfunction _ -> "fun" | |
| + | Ztrywith _ -> "try with" | |
| + | Zsequence _ -> "seq" | |
| + | Zcondition _ -> "cond" | |
| + | Zwhile _ -> "while" | |
| + | Zfor _ -> "for" | |
| + | Zconstraint _ -> "constraint" | |
| + | Zvector _ -> "vect (array)" | |
| + | Zassign _ -> "assign" | |
| + | Zrecord _ -> "record" | |
| + | Zrecord_access _ -> "reco_access" | |
| + | Zrecord_update _ -> "reco_update" | |
| + | Zstream _ -> "stream" | |
| + | Zparser _ -> "parser" | |
| + | Zwhen _ -> "when" | |
| + | Zshift _ -> "shift" | |
| + | Zreset _ -> "reset"); | |
| + print_newline (); | |
| + print_string (match pat.p_desc with | |
| + | Zwildpat -> "wiled pat" | |
| + | Zvarpat _ -> "vars" | |
| + | Zaliaspat _ -> "alias" | |
| + | Zconstantpat _ -> "const" | |
| + | Ztuplepat _ -> "tuple" | |
| + | Zconstruct0pat _ -> "construct0" | |
| + | Zconstruct1pat _ -> "construct1" | |
| + | Zorpat _ -> "or" | |
| + | Zconstraintpat _ -> "constraint" | |
| + | Zrecordpat _ -> "record"); | |
| + print_newline (); | |
| +*) | |
| diff --git a/src/lib/int.ml b/src/lib/int.ml | |
| index 41a154d..638db85 100644 | |
| --- a/src/lib/int.ml | |
| +++ b/src/lib/int.ml | |
| @@ -10,7 +10,7 @@ let lnot n = | |
| n lxor (-1) | |
| ;; | |
| -let string_of_int = format_int "%ld";; | |
| +let string_of_int n = format_int "%ld" n;; | |
| let min_int = 1 lsl (if 1 lsl 31 = 0 then 30 else 62);; | |
| let max_int = min_int - 1;; | |
| diff --git a/src/lib/printexc.ml b/src/lib/printexc.ml | |
| index 1cadb07..9c5aaaf 100644 | |
| --- a/src/lib/printexc.ml | |
| +++ b/src/lib/printexc.ml | |
| @@ -40,7 +40,7 @@ let f fct arg = | |
| input_value ic; | |
| input_value ic; | |
| let tag_exn_table = (input_value ic : (qualid * int) vect) in | |
| - close_in ic; | |
| + close_in ic; | |
| if tag >= vect_length tag_exn_table then raise Exit; | |
| let (q,s) = tag_exn_table.(tag) in | |
| prerr_string q.qual; | |
| diff --git a/src/runtime/compare.c b/src/runtime/compare.c | |
| index 7137e64..e4c3633 100644 | |
| --- a/src/runtime/compare.c | |
| +++ b/src/runtime/compare.c | |
| @@ -46,6 +46,7 @@ static long compare_val(v1, v2) | |
| case Final_tag: | |
| invalid_argument("equal: abstract value"); | |
| case Closure_tag: | |
| + case Cont_tag: | |
| invalid_argument("equal: functional value"); | |
| default: { | |
| mlsize_t sz1 = Wosize_val(v1); | |
| diff --git a/src/runtime/debugcom.c b/src/runtime/debugcom.c | |
| index 0512b23..cb938f2 100644 | |
| --- a/src/runtime/debugcom.c | |
| +++ b/src/runtime/debugcom.c | |
| @@ -182,7 +182,7 @@ int debugger(event) | |
| value val; | |
| value * p; | |
| - if (dbg_socket == -1) return; /* Not connected to a debugger. */ | |
| + if (dbg_socket == -1) return 0; /* Not connected to a debugger. */ | |
| /* Report the event to the debugger */ | |
| switch(event) { | |
| diff --git a/src/runtime/fail.c b/src/runtime/fail.c | |
| index d2224c3..dee72de 100644 | |
| --- a/src/runtime/fail.c | |
| +++ b/src/runtime/fail.c | |
| @@ -54,3 +54,8 @@ void raise_out_of_memory() | |
| { | |
| mlraise(Atom(OUT_OF_MEMORY_EXN)); | |
| } | |
| + | |
| +void raise_without_reset() | |
| +{ | |
| + failwith ("shift is executed without enclosing reset"); | |
| +} | |
| diff --git a/src/runtime/fail.h b/src/runtime/fail.h | |
| index 9f51e40..a4aaec3 100644 | |
| --- a/src/runtime/fail.h | |
| +++ b/src/runtime/fail.h | |
| @@ -32,5 +32,6 @@ void raise_with_string P((tag_t tag, char * msg)); | |
| void failwith P((char *)); | |
| void invalid_argument P((char *)); | |
| void raise_out_of_memory P((void)); | |
| +void raise_without_reset P((void)); | |
| #endif /* _fail_ */ | |
| diff --git a/src/runtime/instruct.h b/src/runtime/instruct.h | |
| index 2807c3e..fbb8d07 100644 | |
| --- a/src/runtime/instruct.h | |
| +++ b/src/runtime/instruct.h | |
| @@ -125,7 +125,11 @@ enum instructions { | |
| VECTLENGTH, | |
| GETVECTITEM, | |
| SETVECTITEM, | |
| - BREAK | |
| + BREAK, | |
| + SHIFT, | |
| + RESET, | |
| + ENDSHIFTRESET, | |
| + COPYBLOCKS | |
| }; | |
| enum float_instructions { | |
| diff --git a/src/runtime/interp.c b/src/runtime/interp.c | |
| index a5eeb34..ce54bd8 100755 | |
| --- a/src/runtime/interp.c | |
| +++ b/src/runtime/interp.c | |
| @@ -86,6 +86,8 @@ unsigned char return_from_interrupt[] = { POP, RETURN }; | |
| retsp->cache_size = cache_size; \ | |
| *--asp = accu; \ | |
| extern_asp = asp; extern_rsp = rsp; \ | |
| + extern_rp = rp; \ | |
| + extern_rp_a = rp_a; \ | |
| } | |
| #define Restore_after_gc \ | |
| @@ -102,6 +104,7 @@ unsigned char return_from_interrupt[] = { POP, RETURN }; | |
| retsp->cache_size = cache_size; \ | |
| extern_asp = asp; \ | |
| extern_rsp = rsp; \ | |
| + extern_rp = rp; \ | |
| } | |
| #define Restore_after_c_call \ | |
| { asp = extern_asp; \ | |
| @@ -190,19 +193,34 @@ value interprete(prog) | |
| int cache_size; | |
| value env; | |
| value tmp; | |
| + value rp; | |
| + value rp_a; | |
| struct longjmp_buffer * initial_external_raise; | |
| int initial_rsp_offset; | |
| value * initial_c_roots_head; | |
| struct longjmp_buffer raise_buf; | |
| + int flg = 0; | |
| + | |
| #ifdef DIRECT_JUMP | |
| static void * jumptable[] = { | |
| # include "jumptbl.h" | |
| }; | |
| #endif | |
| +#ifdef CAML_SIXTYFOUR | |
| + static word_size = 8; | |
| +#else | |
| + static word_size = 4; | |
| +#endif | |
| + | |
| asp = extern_asp; | |
| rsp = extern_rsp; | |
| + // とりあえず、始めは rsp の bottom かな ? と思ったものの、;; のあとに rsp に | |
| + // されるとまずいので、0 にしておく。 | |
| + // # そもそも reset が抜けたら実行出来ない、という仕様。 | |
| + rp = (value) 0; | |
| + rp_a = (value) 0; | |
| pc = prog; | |
| env = null_env; | |
| cache_size = 0; | |
| @@ -268,6 +286,14 @@ value interprete(prog) | |
| Instruct(APPLY): | |
| apply: | |
| + { int i; | |
| + if (flg == -2) { | |
| + for (i = -10; i < 11; i++) | |
| + printf ("apc%3d(%d): %d\n", i, rsp+i, *(rsp+i)); | |
| + } | |
| + if (flg == -1) | |
| + printf ("tpa (%d): %d, %d, %d, %d, %d\n", | |
| + tp, tp->pc, tp->env, tp->cache_size, tp->asp, tp->tp); | |
| push_ret_frame(); | |
| retsp->pc = pc; | |
| retsp->env = env; | |
| @@ -276,9 +302,23 @@ value interprete(prog) | |
| cache_size = 1; | |
| pc = Code_val(accu); | |
| env = Env_val(accu); | |
| + if (flg == -1) | |
| + printf ("tp (%d): %d, %d, %d, %d, %d\n", | |
| + tp, tp->pc, tp->env, tp->cache_size, tp->asp, tp->tp); | |
| + if (flg == 2) { printf ("%d, %d\n", pc, env); } | |
| goto check_stacks; | |
| - | |
| + } | |
| Instruct(RETURN): | |
| + if (flg == 2) { | |
| + printf ("now return! (cache size: %d)\n", cache_size); | |
| + int i; | |
| + for (i = -20; i < 21; i++) printf ("ret(%3d): %d\n", i, *(rsp + i)); | |
| + printf ("%d\n", *asp); | |
| + } | |
| + ret: | |
| + if (flg == -101) { | |
| + if (*asp == MARK) printf ("MARK!\n"); | |
| + else printf ("not MARK!\n"); } | |
| if (*asp == MARK) { | |
| rsp += cache_size; | |
| asp++; | |
| @@ -286,6 +326,12 @@ value interprete(prog) | |
| env = retsp->env; | |
| cache_size = retsp->cache_size; | |
| pop_ret_frame(); | |
| + if (flg == 2) { | |
| + printf ("accu: %d\n", (accu - 1) / 2); | |
| + printf ("pc: %d, cache: %d\n", pc, cache_size); | |
| + int i; | |
| + for (i = -10; i < 11; i++) printf ("ret(%3d): %d\n", i, *(rsp+i)); | |
| + } | |
| if (something_to_do) goto process_signal; | |
| Next; | |
| } | |
| @@ -305,6 +351,8 @@ value interprete(prog) | |
| realloc_stacks(); | |
| rsp = extern_rsp; | |
| asp = extern_asp; | |
| + rp = extern_rp; | |
| + rp_a = extern_rp_a; | |
| Restore_after_gc; | |
| } | |
| /* fall through CHECK_SIGNALS */ | |
| @@ -396,8 +444,8 @@ value interprete(prog) | |
| Instruct(ACC5): | |
| accu = access(5); Next; | |
| Instruct(ACCESS): | |
| - { int n = *pc++; | |
| - accu = access(n); | |
| + { int n = *pc++; | |
| + accu = access(n); | |
| Next; | |
| } | |
| @@ -473,7 +521,8 @@ value interprete(prog) | |
| Instruct(PUSHTRAP): | |
| { value * src = rsp + cache_size; | |
| int i = cache_size; | |
| - | |
| + int j = pc + s16pc; | |
| + | |
| push_trap_frame(); | |
| trapsp->pc = pc + s16pc; | |
| pc += SHORT; | |
| @@ -481,6 +530,12 @@ value interprete(prog) | |
| trapsp->cache_size = cache_size + 2; | |
| trapsp->asp = asp; | |
| trapsp->tp = tp; | |
| + if (flg == -1) { | |
| + printf ("... %d, %d, %d, %d, %d\n", | |
| + j, env, cache_size + 2, asp, tp); | |
| + for (j = -10; j < 11; j++) | |
| + printf ("pushtrap%3d(%d): %d\n", j, j + asp, *(j + asp)); | |
| + } | |
| tp = trapsp; | |
| while(i--) *--rsp = *--src; | |
| *--asp = MARK; | |
| @@ -490,6 +545,14 @@ value interprete(prog) | |
| raise: /* An external raise jumps here */ | |
| Instruct(RAISE): | |
| + if (flg == -101) printf ("raise!\n"); | |
| + if (flg == -1) { | |
| + int i; | |
| + printf ("tp (%d): %d, %d, %d, %d, %d\n", | |
| + tp, tp->pc, tp->env, tp->cache_size, tp->asp, tp->tp); | |
| + for (i = -10; i < 11; i++) | |
| + printf ("%3d(%d): %d\n", i, i + tp->asp, *(i + tp->asp)); | |
| + } | |
| if ((value *) tp >= trap_barrier) debugger(TRAP_BARRIER); | |
| rsp = (value *) tp; | |
| if (rsp >= (value *)((char *) ret_stack_high - initial_rsp_offset)) { | |
| @@ -497,6 +560,16 @@ value interprete(prog) | |
| external_raise = initial_external_raise; | |
| longjmp(external_raise->buf, 1); | |
| } | |
| + // reset pointers を巻き戻す | |
| + // value * tmp; | |
| + if (rp < rsp && rp != 0) { | |
| + value * tmp = rp; | |
| + rp = *(tmp - 1); | |
| + tmp = rp_a; rp_a = *(tmp - 1); | |
| + // rp = *(rp - 1); | |
| + /* tmp = rp; rp = *(tmp - 1); | |
| + tmp = rp_a; rp_a = *(tmp - 1); */ | |
| + } | |
| pc = trapsp->pc; | |
| env = trapsp->env; | |
| cache_size = trapsp->cache_size - 2; | |
| @@ -505,9 +578,12 @@ value interprete(prog) | |
| pop_trap_frame(); | |
| *--rsp = accu; | |
| cache_size++; | |
| + if (flg == -1) printf ("%d, %d, %d, %d, %d\n", | |
| + pc, env, cache_size, asp, tp); | |
| Next; | |
| Instruct(POPTRAP): | |
| + if (flg == -101) printf ("poptrap!\n"); | |
| if (something_to_do) { | |
| /* We must check here so that if a signal is pending and its | |
| handler triggers an exception, the exception is trapped | |
| @@ -756,13 +832,17 @@ value interprete(prog) | |
| accu = Val_long((accu - 1) / tmp); | |
| Next; | |
| Instruct(MODINT): | |
| + { | |
| + /* if (flg == 1) | |
| + for (i = -20; i < 21; i++) | |
| + printf ("??%d(%3d): %3d\n", pc+i, i, *(pc+i)); */ | |
| tmp = *asp++ - 1; | |
| if (tmp == 0) { | |
| accu = Atom(ZERO_DIVIDE_EXN); | |
| goto raise; | |
| } | |
| accu = 1 + (accu - 1) % tmp; | |
| - Next; | |
| + Next; } | |
| Instruct(ANDINT): | |
| accu &= *asp++; Next; | |
| Instruct(ORINT): | |
| @@ -908,6 +988,313 @@ value interprete(prog) | |
| tmp = Long_val(*asp++); | |
| goto setfield; | |
| + Instruct(RESET): | |
| + { int i; | |
| + // for (i = -10; i < 21; i++) printf("%3d: %d\n", i, *(rsp + i)); | |
| + flg = 1; | |
| + flg = -102; | |
| + // flg = -1; | |
| + // *--asp = MARK; | |
| + *--asp = rp_a; | |
| + rp_a = asp + 1; | |
| + push_ret_frame(); | |
| + retsp->pc = pc; | |
| + retsp->env = env; | |
| + retsp->cache_size = cache_size; | |
| + // printf ("rsp (reset): %d\n", rsp); | |
| + *--rsp = rp; // rp 保存 | |
| + if (flg == 3) | |
| + printf ("\t\t*** reset mark !! *** %d ***\n", rp); | |
| + // printf ("rp: %d, ", rp); | |
| + rp = rsp + 1; // 現在の rsp で rp 更新 | |
| + // extern_rp = rp; | |
| + // printf ("rsp?: %d\n", rp); | |
| + // rp = rsp + 1; | |
| + // *rp = *rsp; | |
| + //printf ("rsp?: %d\n", *rp); | |
| + // for (i = -10; i < 21; i++) printf ("%3d?: %d\n", i, *(rsp + i)); | |
| + cache_size = 0; // 1 | |
| + pc = Code_val(accu); | |
| + env = Env_val(accu); | |
| + if (flg == 3) { | |
| + for (i = -10; i < 11; i++) printf("1rr%3d: %d\n", i, *(rsp + i)); } | |
| + goto check_stacks; } | |
| + Instruct(ENDSHIFTRESET): | |
| + { int i = 0; | |
| + // printf ("tp: %d, %d\n", tp, rsp); | |
| + if (flg == -101) printf ("end shift/reset1!!\n"); | |
| + if (flg == 3) | |
| + for (i = -10; i < 11; i++) printf("%3dc: %d\n", i, *(rsp + i)); | |
| + i = 0; | |
| + if (flg >= 3) { printf("end of shift or reset !\n"); } | |
| + // while (*asp != RESETMARK) { asp++; i++; } | |
| + if (flg >= 3) { printf ("accu: %d\n", (accu - 1) / 2); } | |
| + asp = rp_a; | |
| + rp_a = *(asp - 1); | |
| + // asp++; | |
| + // printf ("*** rp ... %d, ", rp); | |
| + rsp = rp; | |
| + // printf ("*** rsp!: %d, ", rsp); | |
| + rp = *(rsp - 1); | |
| + // extern_rp = rp; | |
| + //rsp++; | |
| + // printf ("*** rp! %d\n", rp); | |
| + if (flg >= 3) { printf ("cache_size: %d\n", cache_size); } | |
| + //rsp++; | |
| + cache_size = 0; | |
| + //for (i = -5; i < 6; i++) printf ("cc%3dcc: %d\n", i, *(i + rsp)); | |
| + if (flg == -101) { | |
| + printf ("end shift/reset2!!\n"); | |
| + printf ("pc: %d, env: %d, asp: %d, rsp: %d\n", pc, env, asp, rsp); | |
| + printf ("tp (%d): %d, %d, %d, %d, %d\n", | |
| + tp, tp->pc, tp->env, tp->cache_size, tp->asp, tp->tp); } | |
| + Next; | |
| + } | |
| + Instruct(SHIFT): | |
| + { int i, j, tmp1, tmp2, size; | |
| + value cls = 10; | |
| + value * to; | |
| + int b = 0; | |
| + // heap の tp | |
| + value tp_heap = (value) 0; | |
| + | |
| + // shift (fun k -> k 3) のような実行に対する error | |
| + if (rp == (value) 0 || rp_a == (value) 0) raise_without_reset(); | |
| + | |
| + // printf ("%d, %d\n", rsp, tp); | |
| + // | |
| + // コピーするフレームの内部に tp がある場合 | |
| + if (rp >= tp && rsp <= tp) { | |
| + if (flg == -1) printf ("** tp is in the frame !! (Bug)\n"); | |
| + // flg を立てる | |
| + b = 1; } | |
| + if (cache_size) heapify_env(); | |
| + // flg = 2; | |
| + // printf ("shift\n"); | |
| + if (flg >= 3) | |
| + { for (tmp1 = -10; tmp1 < 11; tmp1++) | |
| + printf ("%3d: %d\n", tmp1, *(rsp + tmp1)); } | |
| + //for (i = -1; i < 21; i++) printf ("s%3d: %d\n", i, *(rsp+i)); | |
| + // i = 0; while (*asp != RESETMARK) { ++asp; ++i; } | |
| + i = ((int)rp_a - (int)asp) / word_size; | |
| + asp = rp_a - word_size; | |
| + if (i != 0) i--; | |
| + /* たまに *(rsp - 1) のところに RESETMARK があるので、 | |
| + こういう妙なコードにしてある; */ | |
| + //j = 0; while (*(rsp - 1) != rp) { ++rsp; ++j; } | |
| + if (flg >= 3) printf ("%d, ", rsp); | |
| + j = ((int)rp - (int)rsp) / word_size; | |
| + rsp = rp - word_size; | |
| + if (j != 0) j--; | |
| + // printf ("\na: %d, r: %d\n", i, j); | |
| + if (flg >= 3) printf ("%d; %d\n", rsp, j); | |
| + if (flg == 3) | |
| + { for (tmp1 = -5; tmp1 < 6; tmp1++) | |
| + printf ("%3d: %d\n", tmp1, *(rsp + tmp1)); } | |
| + // if (j != 0) { j--; } | |
| + /* (i + 1) + (j + 1) + frame size 2 つ + | |
| + pc + env + pc->copyblocks + cache_size + tp + asp */ | |
| + // printf ("size: %d, %d\n", i, j); | |
| + size = i + j + 10; | |
| + if (size < Max_young_wosize) { | |
| + asp -= i; rsp -= j; // Alloc_small may call minor_gc. | |
| + Alloc_small (cls, size, Cont_tag); | |
| + asp += i; rsp += j; | |
| + Field (cls, 5) = cache_size; | |
| + Field (cls, 4) = j; | |
| + Field (cls, 3) = pc; | |
| + Field (cls, 2) = i; | |
| + /* | |
| + for (tmp1 = -10; tmp1 < 11; tmp1++) | |
| + printf ("%3d(%d): %d\n", tmp1, tmp1 + rsp, *(tmp1 + rsp)); */ | |
| + tmp1 = i; tmp2 = j; | |
| + while (i >= 0) { Field(cls, i + 8) = *(asp - i - 1); i--; } | |
| + while (j >= 0) { | |
| + // tp に来たら | |
| + // printf ("%d, %d\n", (int) tp + 16, rsp - j - 1); | |
| + if (b && (int)(rsp - j - 1) == (int) tp + word_size * 4) { | |
| + // printf ("%d!!!!\n", Field(cls, j + tmp1 + 8)); | |
| + // tp を 1 つ巻き戻して | |
| + tp = tp->tp; | |
| + // heap のほうには heap の tp を保存 | |
| + Field(cls, j + tmp1 + 9) = tp_heap; | |
| + // heap の tp も更新 | |
| + // printf ("%d' %d\n", cls, cls + j + tmp1 + 8); | |
| + tp_heap = j + tmp1 + 9; // cls + j + tmp1 + 9; | |
| + // printf ("%d, %d\n", tp_heap, cls); | |
| + } else { Field(cls, j + tmp1 + 9) = *(rsp - j - 1); } | |
| + j--; } | |
| + Field (cls, 6) = tp_heap; | |
| + Field (cls, 7) = asp; | |
| + i = 0; while (*(pc + i) != COPYBLOCKS) i++; | |
| + Env_val(cls) = env; | |
| + Code_val(cls) = pc + i; } | |
| + else { | |
| + // printf ("big! %d, %d\n", i, j); | |
| + // printf ("pc: %d, cache size: %d\n", pc, cache_size); | |
| + // "Setup_for_gc" madifies a top value of asp. => -i (& -j) | |
| + asp -= i; rsp -= j; | |
| + Setup_for_gc; | |
| + cls = alloc_shr (size, Cont_tag); | |
| + Restore_after_gc; | |
| + // +i (& +j) | |
| + asp += i; rsp += j; | |
| + to = &Field(cls, 0); | |
| + initialize (to + 5, cache_size); | |
| + initialize (to + 4, j); | |
| + initialize (to + 3, pc); | |
| + initialize (to + 2, i); | |
| + tmp1 = i; tmp2 = j; | |
| + while(i >= 0) { initialize (to + i + 8, *(asp - i - 1)); i--; } | |
| + // printf ("* * * %d * * *\n", *(asp)); | |
| + while(j >= 0) { | |
| + // tp に来たら | |
| + if (b && (int)(rsp - j - 1) == (int) tp + word_size * 4) { | |
| + // tp を 1 つ巻き戻して | |
| + tp = tp->tp; | |
| + // heap のほうには heap の tp を保存 | |
| + Field(cls, j + tmp1 + 9) = tp_heap; | |
| + // heap の tp も更新 | |
| + tp_heap = j + tmp1 + 9; // cls + j + tmp1 + 9; | |
| + } else { Field(cls, j + tmp1 + 9) = *(rsp - j - 1); } | |
| + j--; } | |
| + initialize (to + 6, tp_heap); | |
| + initialize (to + 7, asp); | |
| + i = 0; while (*(pc + i) != COPYBLOCKS) i++; | |
| + initialize (to + 1, env); | |
| + initialize (to, pc + i); | |
| + // printf ("env: %d, copy's pc: %d, ", env, pc + i); | |
| + } | |
| + *--rsp = cls; | |
| + cache_size = 1; // OK ?? | |
| + pc = Code_val(accu); | |
| + env = Env_val(accu); | |
| + // printf ("accu: %d\n", cls); | |
| + // printf ("** %d **\n", tp_heap); | |
| + goto check_stacks; } | |
| + Instruct(COPYBLOCKS): | |
| + { int i, j, tmp1, tmp2; | |
| + // printf ("COPY!\n"); | |
| + value arg; | |
| + value tp_heap; | |
| + value tp_heap_back = (value) 0; | |
| + value tp_asp; | |
| + arg = *rsp++; // get an arg | |
| + if (flg >= 3) | |
| + for (i = -10; i < 11; i++) printf ("cc%3d: %d\n", i, *(rsp + i)); | |
| + // *--asp = RESETMARK; | |
| + *--asp = rp_a; | |
| + rp_a = asp + 1; | |
| + *--rsp = rp; | |
| + if (flg == 3) printf ("\t\t*** reset mark !! *** %d ***\t", rp); | |
| + rp = rsp + 1; | |
| + if (flg == 3) printf ("%d\n", rp); | |
| + tp_asp = Field (accu, 7); | |
| + tp_heap = Field (accu, 6); | |
| + cache_size = Field (accu, 5); | |
| + j = Field (accu, 4); | |
| + pc = Field (accu, 3); | |
| + i = Field (accu, 2); | |
| + // printf ("accu: %d\n", accu); | |
| + //printf ("%d, %d, %d\n", j, pc, i); | |
| + if (flg == 3) | |
| + printf("asp: %d, rsp: %d, pc: %d, pc*: %d\n", i, j, pc, *pc); | |
| + tmp1 = i; tmp2 = j; | |
| + | |
| + /********************/ | |
| + /* copy する分の stack があるか check する */ | |
| + while ((asp - tmp1) < arg_stack_threshold) { | |
| + /* printf ("after_copy : (asp < arg_stack_threshold) = (%d < %d)\n", | |
| + asp - tmp1, arg_stack_threshold); */ | |
| + Setup_for_gc; | |
| + realloc_arg_stack0 (); // 強制 realloc (stack.c 追加) | |
| + rsp = extern_rsp; asp = extern_asp; | |
| + rp = extern_rp; rp_a = extern_rp_a; | |
| + Restore_after_gc; | |
| + } | |
| + while ((rsp - tmp2) < ret_stack_threshold) { | |
| + /* printf ("after_copy : (rsp < threshold) = (%d < %d)\n", | |
| + rsp - tmp2, ret_stack_threshold); */ | |
| + Setup_for_gc; | |
| + realloc_ret_stack0 (); // 強制 realloc (stack.c 追加) | |
| + rsp = extern_rsp; asp = extern_asp; | |
| + rp = extern_rp; rp_a = extern_rp_a; | |
| + Restore_after_gc; | |
| + } | |
| + /********************/ | |
| + | |
| + /* arg stack にコピー */ | |
| + while (i >= 0) { *(asp - i - 1) = Field (accu, i + 8); i--; } | |
| + /* return stack にコピー */ | |
| + while (j >= 0) { | |
| + // trap frame の trap pointer の場合 | |
| + // if (tp_heap == accu + tmp1 + tmp2 - j + 9) { | |
| + if ((int)tp_heap == tmp1 + tmp2 - j + 9) { // CHECK | |
| + if (flg == -1) | |
| + printf ("%d, %d, %d, %d, %d??\n", | |
| + Field (accu, tmp1 + tmp2 - j + 8), | |
| + Field (accu, tmp1 + tmp2 - j + 9), | |
| + Field (accu, tmp1 + tmp2 - j + 10), | |
| + Field (accu, tmp1 + tmp2 - j + 11), | |
| + Field (accu, tmp1 + tmp2 - j + 12)); | |
| + // tp を保存 | |
| + *(rsp - tmp2 + j - 1) = tp; | |
| + // その trap frame を指すように tp を更新 | |
| + tp = (struct trap_frame *) (rsp - tmp2 + j - 1 - 4); | |
| + tp_heap_back = tp_heap; | |
| + tp_heap = Field(accu, tmp1 + tmp2 - j + 9); | |
| + // } else if (tp_heap_back + 1 == accu + tmp1 + tmp2 - j + 9) { | |
| + } else if ((int)tp_heap_back + 1 == tmp1 + tmp2 - j + 9) { // CHECK | |
| + if (flg == -1) | |
| + printf ("%d, %d, %d, %d, %d??\n", | |
| + Field (accu, tmp1 + tmp2 - j + 8), | |
| + Field (accu, tmp1 + tmp2 - j + 9), | |
| + Field (accu, tmp1 + tmp2 - j + 10), | |
| + Field (accu, tmp1 + tmp2 - j + 11), | |
| + Field (accu, tmp1 + tmp2 - j + 12)); | |
| + if (flg == -1) | |
| + printf ("!!!%d, %d, %d -> %d !!!\n", | |
| + (int)asp, tp_asp, Field (accu, tmp1 + tmp2 - j + 9), | |
| + (Field (accu, tmp1 + tmp2 - j + 9) + (int)asp - tp_asp)); | |
| + /* printf ("%d, %d\n", | |
| + asp - tp_asp + Field (accu, tmp1 + tmp2 - j + 9), | |
| + Field (accu, tmp1 + tmp2 - j + 9)) ; */ | |
| + // asp が意図していたところを指すように変更して保存 | |
| + // int に cast しないとコケる | |
| + *(rsp - tmp2 + j - 1) = | |
| + (value)((int)asp - | |
| + (int)tp_asp + Field (accu, tmp1 + tmp2 - j + 9)); | |
| + } else { *(rsp - tmp2 + j - 1) = Field (accu, tmp1 + tmp2 - j + 9); } | |
| + j--; | |
| + } | |
| + if (flg == -1) { | |
| + printf ("tp (%d): %d, %d, %d, %d(%d), %d\n", | |
| + tp, tp->pc, tp->env, tp->cache_size, | |
| + tp->asp, *tp->asp, tp->tp); } | |
| + // while (j >= 0) { *(rsp - j - 1) = Field (accu, j + tmp1 + 8); j--; } | |
| + /* | |
| + while (j >= 0) { | |
| + if (tp_heap == accu + j + tmp1 + 8) { | |
| + *(rsp - j - 1) = tp; | |
| + tp_heap = Field (accu, j + tmp1 + 8); | |
| + tp = 4; | |
| + } else { | |
| + *(rsp - j - 1) = Field (accu, j + tmp1 + 8); j--; }} */ | |
| + asp -= tmp1; | |
| + rsp -= tmp2; | |
| + if (flg == 3) | |
| + for (i = -10; i < 11; i++) printf ("c%3d: %d\n", i, *(rsp + i)); | |
| + accu = arg; | |
| + //for (i = -1; i < 21; i++) printf ("c%3d: %d\n", i, *(rsp + i)); | |
| + // printf ("argument of a captured cont: %d\n", (accu - 1) / 2); | |
| + if (flg >= 3) | |
| + printf("*** *** argument of k: %d *** ***\n", (arg - 1) / 2); | |
| + // for (i = -10; i < 11; i++) printf ("pc%3d: %d\n", i, *(pc + i)); | |
| + // printf ("%d??\n", rp); | |
| + // extern_rp = rp; | |
| + | |
| + Next; } | |
| + | |
| Instruct(BREAK): | |
| Setup_for_gc; | |
| retsp->pc = pc - 1; | |
| diff --git a/src/runtime/io.c b/src/runtime/io.c | |
| index bd68920..f68a767 100755 | |
| --- a/src/runtime/io.c | |
| +++ b/src/runtime/io.c | |
| @@ -1,5 +1,9 @@ | |
| /* Buffered input/output. */ | |
| +#include "../../config/s.h" | |
| +#ifdef HAS_UNISTD | |
| +#include <unistd.h> | |
| +#endif | |
| #include <errno.h> | |
| #ifdef __MWERKS__ | |
| #include "myfcntl.h" | |
| diff --git a/src/runtime/main.c b/src/runtime/main.c | |
| index dd8e53f..82b87fd 100755 | |
| --- a/src/runtime/main.c | |
| +++ b/src/runtime/main.c | |
| @@ -1,5 +1,9 @@ | |
| /* Start-up code */ | |
| +#include "../../config/s.h" | |
| +#ifdef HAS_UNISTD | |
| +#include <unistd.h> | |
| +#endif | |
| #include <stdio.h> | |
| #ifdef __MWERKS__ | |
| #include "myfcntl.h" | |
| diff --git a/src/runtime/major_gc.c b/src/runtime/major_gc.c | |
| index 5909250..c231922 100755 | |
| --- a/src/runtime/major_gc.c | |
| +++ b/src/runtime/major_gc.c | |
| @@ -72,6 +72,7 @@ void darken (v) | |
| value v; | |
| { | |
| if (Is_block (v) && Is_in_heap (v) && Is_white_val (v)){ | |
| + // printf ("darken!\n"); | |
| Hd_val (v) = Grayhd_hd (Hd_val (v)); | |
| *gray_vals_cur++ = v; | |
| if (gray_vals_cur >= gray_vals_end) realloc_gray_vals (); | |
| @@ -107,6 +108,8 @@ static void mark_slice (work) | |
| Assert (Is_gray_val (v)); | |
| Hd_val (v) = Blackhd_hd (Hd_val (v)); | |
| if (Tag_val (v) < No_scan_tag){ | |
| + // if (Tag_val (v) == Cont_tag) printf ("mark_slice is called!\n"); | |
| + // printf ("mark_slice: %d\n", Wosize_val(v)); | |
| for (i = Wosize_val (v); i != 0;){ | |
| --i; | |
| child = Field (v, i); | |
| @@ -223,12 +226,14 @@ void major_collection_slice () | |
| #define Margin 100 /* Make it a little faster to be on the safe side. */ | |
| if (gc_phase == Phase_mark){ | |
| + //printf ("mark\n"); | |
| mark_slice (2 * (100 - percent_free) | |
| * (allocated_words * 3 / percent_free / 2 | |
| + 100 * extra_heap_memory) | |
| + Margin); | |
| gc_message ("!", 0); | |
| }else{ | |
| + //printf ("sweep\n"); | |
| Assert (gc_phase == Phase_sweep); | |
| sweep_slice (200 * (allocated_words * 3 / percent_free / 2 | |
| + 100 * extra_heap_memory) | |
| diff --git a/src/runtime/minor_gc.c b/src/runtime/minor_gc.c | |
| index 9fa152c..1da0670 100755 | |
| --- a/src/runtime/minor_gc.c | |
| +++ b/src/runtime/minor_gc.c | |
| @@ -72,6 +72,9 @@ static void oldify (p, v) | |
| value field0 = Field (v, 0); | |
| mlsize_t sz = Wosize_val (v); | |
| + //printf ("%d\n", sz); | |
| + // if (Tag_val(v) == Cont_tag) { printf ("gc! %d\n", sz); } | |
| + | |
| result = alloc_shr (sz, Tag_val (v)); | |
| *p = result; | |
| Hd_val (v) = Bluehd_hd (Hd_val (v)); /* Put the forward flag. */ | |
| @@ -81,6 +84,7 @@ static void oldify (p, v) | |
| v = field0; | |
| goto tail_call; | |
| }else{ | |
| + // printf ("?%d\n", sz); | |
| oldify (&Field (result, 0), field0); | |
| for (i = 1; i < sz - 1; i++){ | |
| oldify (&Field (result, i), Field (v, i)); | |
| @@ -108,7 +112,7 @@ void minor_collection () | |
| old_external_raise = external_raise; | |
| external_raise = &raise_buf; | |
| - gc_message ("<", 0); | |
| + gc_message ("<", 0); | |
| local_roots (oldify); | |
| for (r = ref_table; r < ref_table_ptr; r++) oldify (*r, **r); | |
| stat_minor_words += Wsize_bsize (young_ptr - young_start); | |
| diff --git a/src/runtime/mlvalues.h b/src/runtime/mlvalues.h | |
| index 6655b4f..bfb93bc 100755 | |
| --- a/src/runtime/mlvalues.h | |
| +++ b/src/runtime/mlvalues.h | |
| @@ -165,6 +165,7 @@ typedef unsigned char *code_t; | |
| #define Code_val(val) (((code_t *) (val)) [0]) /* Also an l-value. */ | |
| #define Env_val(val) (Field(val, 1)) /* Also an l-value. */ | |
| +#define Cont_tag (No_scan_tag - 2) | |
| /* 2- If tag >= No_scan_tag : a sequence of bytes. */ | |
| diff --git a/src/runtime/roots.c b/src/runtime/roots.c | |
| index 1950c25..6d0620d 100755 | |
| --- a/src/runtime/roots.c | |
| +++ b/src/runtime/roots.c | |
| @@ -11,26 +11,67 @@ void local_roots (copy_fn) | |
| { | |
| register value *sp; | |
| register int i; | |
| + register value *rp; | |
| + value *tmp; | |
| + // printf ("??\n"); | |
| /* argument stack */ | |
| - for (sp = extern_asp; sp < arg_stack_high; sp++) { | |
| - if (*sp != MARK) copy_fn (sp, *sp); | |
| + for (sp = extern_asp, rp = extern_rp_a; sp < arg_stack_high; sp++) { | |
| + if (*sp != MARK) { | |
| + if (sp + 1 != rp ) copy_fn (sp, *sp); | |
| + else rp = *(rp - 1); | |
| + } | |
| } | |
| + | |
| + // printf ("??? %d\n", extern_rp); | |
| + | |
| + int j; | |
| + int flg = 0; | |
| + //for (j = -5; j <= 30; j++) printf ("%3d: %d\n", j, *(extern_rsp + j)); | |
| + //printf ("\n"); | |
| /* return stack */ | |
| - for (sp = extern_rsp; sp < ret_stack_high; ) { | |
| - copy_fn (&((struct return_frame *) sp)->env, | |
| - ((struct return_frame *) sp)->env); | |
| - i = ((struct return_frame *) sp)->cache_size; | |
| - sp = (value *) ((char *) sp + sizeof(struct return_frame)); | |
| - while (i > 0) { | |
| - Assert (sp < ret_stack_high); | |
| - copy_fn (sp, *sp); | |
| - sp++; | |
| - i--; | |
| - } | |
| + // printf ("%d\n", ret_stack_high); | |
| + | |
| + sp = 551860; // ret_stack_high; | |
| + /* | |
| + for (j = -10; j < 11; j++) | |
| + printf ("%3d(%d): %d; %d\n", j, sp + j, *(sp + j), extern_rp); | |
| + printf ("%d\n", extern_rp); */ | |
| + for (sp = extern_rsp, rp = extern_rp; sp < ret_stack_high; ) { | |
| + // for (sp = extern_rsp; sp < ret_stack_high; ) { | |
| + // if (*sp != RESETMARK) { | |
| + if (sp + 1 != rp) { | |
| + //for (j = -5; j <= 30; j++) printf ("%3d: %d\n", j, *(sp + j)) ; | |
| + // printf ("\n"); | |
| + // printf ("%d\n", *(sp - 1)); | |
| + if (flg) printf ("%d, %d, ", sp, rp); | |
| + | |
| + copy_fn (&((struct return_frame *) sp)->env, | |
| + ((struct return_frame *) sp)->env); | |
| + i = ((struct return_frame *) sp)->cache_size; | |
| + if (flg) printf ("%d\n", i); | |
| + if (i > 20 && flg) | |
| + for (j = -10; j < 11; j++) | |
| + printf ("%d(%3d): %d\n", sp + j, j, *(sp + j)); | |
| + if (i > 20) printf ("%d\n", sp); | |
| + sp = (value *) ((char *) sp + sizeof(struct return_frame)); | |
| + while (i > 0) { | |
| + Assert (sp < ret_stack_high); | |
| + copy_fn (sp, *sp); | |
| + sp++; | |
| + i--; | |
| + } | |
| + } else { if (flg) { | |
| + printf ("reset mark %d, %d\n", rp, sp + 1); | |
| + for (j = -10; j < 11; j++) { | |
| + printf ("%d(%3d): %d\n", sp + j, j, *(sp + j)); }} | |
| + // copy_fn (sp, *sp); | |
| + rp = *(rp - 1); | |
| + if (flg) printf ("** %d\n", rp); sp++; } | |
| } | |
| - | |
| + | |
| + // printf ("????\n"); | |
| /* C roots */ | |
| { | |
| value *block; | |
| diff --git a/src/runtime/stacks.c b/src/runtime/stacks.c | |
| index 20c46c0..07635ad 100755 | |
| --- a/src/runtime/stacks.c | |
| +++ b/src/runtime/stacks.c | |
| @@ -16,6 +16,8 @@ value * ret_stack_high; | |
| value * ret_stack_threshold; | |
| value * extern_asp; | |
| value * extern_rsp; | |
| +value extern_rp; | |
| +value extern_rp_a; | |
| struct trap_frame * tp; | |
| value global_data; | |
| @@ -38,7 +40,8 @@ static void realloc_arg_stack() | |
| asize_t size; | |
| value * new_low, * new_high, * new_asp; | |
| struct trap_frame * p; | |
| - | |
| + value * rp_a; | |
| + | |
| Assert(extern_asp >= arg_stack_low); | |
| size = arg_stack_high - arg_stack_low; | |
| if (size >= Max_arg_stack_size) | |
| @@ -59,6 +62,15 @@ static void realloc_arg_stack() | |
| stat_free((char *) arg_stack_low); | |
| for (p = tp; p < (struct trap_frame *) ret_stack_high; p = p->tp) | |
| p->asp = (value *) shift(p->asp); | |
| + | |
| + /* shift rp_a */ | |
| + if (extern_rp_a > 0) { | |
| + extern_rp_a = (value *) shift (extern_rp_a); | |
| + for (rp_a = extern_rp_a; *(rp_a - 1) > 0; rp_a = *(rp_a - 1)) { | |
| + *(rp_a - 1) = (value *) shift (*(rp_a - 1)); | |
| + } | |
| + } | |
| + | |
| arg_stack_low = new_low; | |
| arg_stack_high = new_high; | |
| arg_stack_threshold = arg_stack_low + Arg_stack_threshold / sizeof (value); | |
| @@ -72,7 +84,8 @@ static void realloc_ret_stack() | |
| asize_t size; | |
| value * new_low, * new_high, * new_rsp; | |
| struct trap_frame * p; | |
| - | |
| + value * rp; | |
| + | |
| Assert(extern_rsp >= ret_stack_low); | |
| size = ret_stack_high - ret_stack_low; | |
| if (size >= Max_ret_stack_size) | |
| @@ -96,6 +109,15 @@ static void realloc_ret_stack() | |
| p->tp = (struct trap_frame *) shift(p->tp); | |
| } | |
| trap_barrier = (value *) shift(trap_barrier); | |
| + | |
| + /* shift rp */ | |
| + if (extern_rp > 0) { | |
| + extern_rp = (value *) shift (extern_rp); | |
| + for (rp = extern_rp; *(rp - 1) > 0; rp = *(rp - 1)) { | |
| + *(rp - 1) = (value *) shift (*(rp - 1)); | |
| + } | |
| + } | |
| + | |
| ret_stack_low = new_low; | |
| ret_stack_high = new_high; | |
| ret_stack_threshold = ret_stack_low + Ret_stack_threshold / sizeof (value); | |
| @@ -111,3 +133,13 @@ void realloc_stacks() | |
| if (extern_asp < arg_stack_threshold) | |
| realloc_arg_stack(); | |
| } | |
| + | |
| +void realloc_ret_stack0() | |
| +{ | |
| + realloc_ret_stack(); | |
| +} | |
| + | |
| +void realloc_arg_stack0() | |
| +{ | |
| + realloc_arg_stack(); | |
| +} | |
| diff --git a/src/runtime/stacks.h b/src/runtime/stacks.h | |
| index 6416bb4..d41b8f0 100644 | |
| --- a/src/runtime/stacks.h | |
| +++ b/src/runtime/stacks.h | |
| @@ -8,7 +8,7 @@ | |
| #include "mlvalues.h" | |
| #include "memory.h" | |
| -/* 1- Argument stack : (value | mark)* */ | |
| +/* 1- Argument stack : (value | mark | resetmark)* */ | |
| #define MARK ((value) 0) | |
| @@ -21,6 +21,8 @@ | |
| return_frame with cache_size = N trap_frame with cache_size=N+2 | |
| ... | |
| Low addresses | |
| + | |
| + OR reset pointer | |
| */ | |
| struct return_frame { | |
| @@ -47,6 +49,8 @@ extern value * ret_stack_high; | |
| extern value * ret_stack_threshold; | |
| extern value * extern_asp; | |
| extern value * extern_rsp; | |
| +extern value extern_rp; | |
| +extern value extern_rp_a; | |
| extern struct trap_frame * tp; | |
| extern value global_data; | |
| diff --git a/src/toplevel/do_phr.ml b/src/toplevel/do_phr.ml | |
| index 479f555..5655adf 100644 | |
| --- a/src/toplevel/do_phr.ml | |
| +++ b/src/toplevel/do_phr.ml | |
| @@ -26,14 +26,16 @@ let do_toplevel_phrase phr = | |
| Zexpr expr -> | |
| let ty = | |
| type_expression phr.im_loc expr in | |
| + let insts = (compile_lambda false (translate_expression expr)) in | |
| +(* instruct__print_inst insts; *) | |
| let res = | |
| - load_phrase(compile_lambda false (translate_expression expr)) in | |
| + load_phrase insts in | |
| flush std_err; | |
| open_box 1; | |
| print_string "- :"; print_space(); | |
| - print_one_type ty; | |
| + print_one_type ty; | |
| print_string " ="; print_space(); | |
| - print_value res ty; | |
| + print_value res ty; | |
| print_newline() | |
| | Zletdef(rec_flag, pat_expr_list) -> | |
| let env = type_letdef phr.im_loc rec_flag pat_expr_list in | |
| diff --git a/src/toplevel/fmt_type.ml b/src/toplevel/fmt_type.ml | |
| index 1d2d045..6a2cb4c 100644 | |
| --- a/src/toplevel/fmt_type.ml | |
| +++ b/src/toplevel/fmt_type.ml | |
| @@ -49,24 +49,122 @@ let name_of_type_var var = | |
| var_name | |
| ;; | |
| -let rec print_typ priority ty = | |
| +let rec print_typ' priority ty = | |
| let ty = type_repr ty in | |
| match ty.typ_desc with | |
| Tvar _ -> | |
| print_string "'"; | |
| print_string (name_of_type_var ty) | |
| - | Tarrow(ty1, ty2) -> | |
| + | Tarrow(ty1, ty2, ty3, ty4) -> | |
| if priority >= 1 then begin open_box 1; print_string "(" end | |
| + else open_box 0; | |
| + print_string "("; | |
| + print_typ' 1 ty1; | |
| + print_string " / "; | |
| + print_typ' 0 ty2; (* 0 ?? *) | |
| + print_string ")"; | |
| + print_string " ->"; print_space(); | |
| + print_string "("; | |
| + print_typ' 0 ty3; (* 0 ?? *) | |
| + print_string " / "; | |
| + print_typ' 0 ty4; | |
| + print_string ")"; | |
| + if priority >= 1 then print_string ")"; | |
| + close_box() | |
| + | Tproduct(ty_list) -> | |
| + if priority >= 2 then begin open_box 1; print_string "(" end | |
| else open_box 0; | |
| - print_typ 1 ty1; | |
| + print_typ'_list 2 " *" ty_list; | |
| + if priority >= 2 then print_string ")"; | |
| + close_box() | |
| + | Tconstr(cstr, args) -> | |
| + open_box 0; | |
| + begin match args with | |
| + [] -> () | |
| + | [ty1] -> | |
| + print_typ' 2 ty1; print_space () | |
| + | tyl -> | |
| + open_box 1; | |
| + print_string "("; | |
| + print_typ'_list 0 "," tyl; | |
| + print_string ")"; | |
| + close_box(); | |
| + print_space() | |
| + end; | |
| + print_global types_of_module cstr; | |
| + close_box() | |
| + | |
| +and print_typ'_list priority sep = function | |
| + [] -> | |
| + () | |
| + | [ty] -> | |
| + print_typ' priority ty | |
| + | ty::rest -> | |
| + print_typ' priority ty; | |
| + print_string sep; print_space(); | |
| + print_typ'_list priority sep rest | |
| +;; | |
| + | |
| +let rec compare t1 t2 = match (t1.typ_desc, t2.typ_desc) with | |
| + | Tvar Tnolink, Tvar Tnolink -> t1 == t2 | |
| + | Tvar (Tlinkto t), _ -> compare t t2 | |
| + | _, Tvar (Tlinkto t) -> compare t1 t | |
| + | _, _ -> false;; | |
| + | |
| +let rec get_tlevel t = match t.typ_desc with | |
| + | Tvar Tnolink -> t.typ_level | |
| + | Tvar (Tlinkto t) -> get_tlevel t | |
| + | _ -> generic + 1;; | |
| + | |
| +let rec print_typ priority ty tvars = | |
| + let ty = type_repr ty in | |
| + match ty.typ_desc with | |
| + Tvar _ -> | |
| + print_string "'"; | |
| + print_string (name_of_type_var ty) | |
| + | Tarrow(ty1, ({ typ_desc = (Tvar _) } as ty2), ty3, ty4) | |
| + when compare ty2 ty4 && | |
| + for_all (fun ty -> not (compare ty2 ty)) | |
| + ((free_type_vars (-1) ty1) @ | |
| + (free_type_vars (-1) ty3) @ tvars) && | |
| + get_tlevel ty2 = generic -> | |
| + if priority >= 1 then begin open_box 1; print_string "(" end | |
| + else open_box 0; | |
| + print_typ 1 ty1 ((free_type_vars (-1) ty3) @ tvars); | |
| print_string " ->"; print_space(); | |
| - print_typ 0 ty2; | |
| + print_typ 0 ty3 ((free_type_vars (-1) ty1) @ tvars); | |
| + if priority >= 1 then print_string ")"; | |
| + close_box() | |
| + | Tarrow(ty1, ty2, ty3, ty4) -> | |
| + let ftv1 = free_type_vars (-1) ty1 | |
| + and ftv2 = free_type_vars (-1) ty2 | |
| + and ftv3 = free_type_vars (-1) ty3 | |
| + and ftv4 = free_type_vars (-1) ty4 in | |
| + if priority >= 1 then begin open_box 1; print_string "(" end | |
| + else open_box 0; | |
| + if (ty2 = ty4 && !typ_option <> "all") || !typ_option = "none" | |
| + then | |
| + begin | |
| + print_typ 1 ty1 (tvars @ ftv2 @ ftv3 @ ftv4); | |
| + print_string " => "; | |
| + print_typ 0 ty3 (tvars @ ftv2 @ ftv1 @ ftv4); | |
| + end | |
| + else | |
| + begin | |
| + print_typ 1 ty1 (tvars @ ftv2 @ ftv3 @ ftv4); | |
| + print_string " / "; | |
| + print_typ 1 ty2 (tvars @ ftv1 @ ftv3 @ ftv4); | |
| + print_string " ->"; print_space(); | |
| + print_typ 1 ty3 (tvars @ ftv2 @ ftv1 @ ftv4); | |
| + print_string " / "; | |
| + print_typ 1 ty4 (tvars @ ftv2 @ ftv3 @ ftv1); | |
| + end; | |
| if priority >= 1 then print_string ")"; | |
| close_box() | |
| | Tproduct(ty_list) -> | |
| if priority >= 2 then begin open_box 1; print_string "(" end | |
| else open_box 0; | |
| - print_typ_list 2 " *" ty_list; | |
| + print_typ_list 2 " *" tvars ty_list; | |
| if priority >= 2 then print_string ")"; | |
| close_box() | |
| | Tconstr(cstr, args) -> | |
| @@ -74,11 +172,11 @@ let rec print_typ priority ty = | |
| begin match args with | |
| [] -> () | |
| | [ty1] -> | |
| - print_typ 2 ty1; print_space () | |
| + print_typ 2 ty1 tvars; print_space () | |
| | tyl -> | |
| open_box 1; | |
| print_string "("; | |
| - print_typ_list 0 "," tyl; | |
| + print_typ_list 0 "," tvars tyl; | |
| print_string ")"; | |
| close_box(); | |
| print_space() | |
| @@ -86,15 +184,20 @@ let rec print_typ priority ty = | |
| print_global types_of_module cstr; | |
| close_box() | |
| -and print_typ_list priority sep = function | |
| +and print_typ_list priority sep tvars = function | |
| [] -> | |
| () | |
| | [ty] -> | |
| - print_typ priority ty | |
| + print_typ priority ty tvars | |
| | ty::rest -> | |
| - print_typ priority ty; | |
| + print_typ priority ty tvars; | |
| print_string sep; print_space(); | |
| - print_typ_list priority sep rest | |
| + print_typ_list priority sep tvars rest | |
| ;; | |
| -let print_one_type ty = reset_type_var_name(); print_typ 0 ty;; | |
| +let print_typ tl t = print_typ tl t [];; | |
| + | |
| +let print_one_type ty = reset_type_var_name(); | |
| +(* print_newline (); print_string "* dubug * : "; | |
| + print_typ' 0 ty; print_newline (); *) | |
| + print_typ 0 ty;; | |
| diff --git a/src/toplevel/load_phr.ml b/src/toplevel/load_phr.ml | |
| index 41260b3..86f2154 100644 | |
| --- a/src/toplevel/load_phr.ml | |
| +++ b/src/toplevel/load_phr.ml | |
| @@ -56,13 +56,17 @@ let load_phrase phr = | |
| if phr.kph_rec then begin | |
| emit phr.kph_init; | |
| out STOP; | |
| +(* emit [Klabel 1; Kprim prim__Pcopyblocks]; (* added *)*) | |
| emit phr.kph_fcts; | |
| + emit [Klabel 1; Kprim prim__Pcopyblocks]; | |
| 0 | |
| end else begin | |
| +(* emit [Klabel 1; Kprim prim__Pcopyblocks]; (* added *)*) | |
| emit phr.kph_fcts; | |
| let p = !out_position in | |
| emit phr.kph_init; | |
| out STOP; | |
| + emit [Klabel 1; Kprim prim__Pcopyblocks]; | |
| p | |
| end in | |
| let len = !out_position in | |
| diff --git a/src/toplevel/pr_value.mlp b/src/toplevel/pr_value.mlp | |
| index f2b8498..ac58a89 100644 | |
| --- a/src/toplevel/pr_value.mlp | |
| +++ b/src/toplevel/pr_value.mlp | |
| @@ -89,7 +89,7 @@ let rec print_val prio depth obj ty = | |
| match (type_repr ty).typ_desc with | |
| Tvar _ -> | |
| print_string "<poly>" | |
| - | Tarrow(ty1, ty2) -> | |
| + | Tarrow(ty1, ty2, ty3, ty4) -> | |
| print_string "<fun>" | |
| | Tproduct(ty_list) -> | |
| if prio > 0 then begin open_box 1; print_string "(" end | |
| @@ -178,9 +178,9 @@ and print_concrete_type prio depth obj cstr ty ty_list = | |
| loop depth false label_list | |
| in | |
| open_box 1; | |
| - print_string "{"; | |
| + print_string "{ "; | |
| cautious (print_fields depth) label_list; | |
| - print_string "}"; | |
| + print_string " }"; | |
| close_box() | |
| | Abbrev_type(params, body) -> | |
| print_val prio depth obj (expand_abbrev params body ty_list) | |
| diff --git a/src/toplevel/toplevel.ml b/src/toplevel/toplevel.ml | |
| index 8770b23..ce2e9f2 100755 | |
| --- a/src/toplevel/toplevel.ml | |
| +++ b/src/toplevel/toplevel.ml | |
| @@ -150,7 +150,8 @@ let trace_env = ref ([] : (int * obj) list);; | |
| let rec trace_instr name val ty = | |
| match (type_repr ty).typ_desc with | |
| - Tarrow(t1,t2) -> | |
| + Tarrow(t1,t2,t3,t4) -> | |
| + (* とりあえず、t1 & t3 しか出力しない格好;; *) | |
| let namestar = name ^ "*" in | |
| repr(fun arg -> | |
| print_string name; print_string " <-- "; | |
| @@ -158,8 +159,8 @@ let rec trace_instr name val ty = | |
| try | |
| let res = (magic_obj val : obj -> obj) arg in | |
| print_string name; print_string " --> "; | |
| - print_value res t2; print_newline (); | |
| - trace_instr namestar res t2 | |
| + print_value res t3; print_newline (); | |
| + trace_instr namestar res t3 | |
| with exc -> | |
| print_string name; | |
| print_string " raises "; | |
| @@ -221,8 +222,10 @@ let install_printer name = | |
| let val_desc = find_value_desc (parse_global name) in | |
| begin try | |
| push_type_level(); | |
| - let ty_arg = new_type_var() in | |
| - let ty_printer = type_arrow(ty_arg, type_unit) in | |
| + let ty_arg = new_type_var() | |
| + and ty_ansa = new_type_var() | |
| + and ty_ansb = new_type_var() in | |
| + let ty_printer = type_arrow(ty_arg, ty_ansa, type_unit, ty_ansb) in | |
| unify (type_instance val_desc.info.val_typ, ty_printer); | |
| pop_type_level(); | |
| generalize_type ty_arg; | |
| diff --git a/src/toplevel/version.mlp b/src/toplevel/version.mlp | |
| index 04754b9..de16e65 100644 | |
| --- a/src/toplevel/version.mlp | |
| +++ b/src/toplevel/version.mlp | |
| @@ -5,4 +5,4 @@ | |
| #endif | |
| let print_banner() = | |
| - interntl__printf "> Caml Light version %s\n" VERSION; ();; | |
| + interntl__printf "> Caml Light version %s + shift/reset\n" VERSION; ();; | |
| diff --git a/src/yacc/error.c b/src/yacc/error.c | |
| index 8dd095a..a17daa0 100644 | |
| --- a/src/yacc/error.c | |
| +++ b/src/yacc/error.c | |
| @@ -40,7 +40,7 @@ char *st_cptr; | |
| { | |
| register char *s; | |
| - if (st_line == 0) return; | |
| + if (st_line == 0) return 0; | |
| for (s = st_line; *s != '\n'; ++s) | |
| { | |
| if (isprint(*s) || *s == '\t') | |
| diff --git a/src/yacc/main.c b/src/yacc/main.c | |
| index c509386..a0fe8c0 100644 | |
| --- a/src/yacc/main.c | |
| +++ b/src/yacc/main.c | |
| @@ -138,7 +138,7 @@ char *argv[]; | |
| case '\0': | |
| input_file = stdin; | |
| if (i + 1 < argc) usage(); | |
| - return; | |
| + return 0; | |
| case '-': | |
| ++i; | |
| diff --git a/src/yacc/output.c b/src/yacc/output.c | |
| index 878fee2..eefa2cc 100644 | |
| --- a/src/yacc/output.c | |
| +++ b/src/yacc/output.c | |
| @@ -345,7 +345,7 @@ int default_state; | |
| if (to_state[i] != default_state) | |
| ++count; | |
| } | |
| - if (count == 0) return; | |
| + if (count == 0) return 0; | |
| symno = symbol_value[symbol] + 2*nstates; | |
| @@ -737,7 +737,7 @@ output_stored_text() | |
| open_error(text_file_name); | |
| in = text_file; | |
| if ((c = getc(in)) == EOF) | |
| - return; | |
| + return 0; | |
| out = code_file; | |
| if (c == '\n') | |
| ++outline; | |
| @@ -763,7 +763,7 @@ output_trailing_text() | |
| register FILE *in, *out; | |
| if (line == 0) | |
| - return; | |
| + return 0; | |
| in = input_file; | |
| out = code_file; | |
| @@ -772,7 +772,7 @@ output_trailing_text() | |
| { | |
| ++lineno; | |
| if ((c = getc(in)) == EOF) | |
| - return; | |
| + return 0; | |
| if (!lflag) | |
| { | |
| ++outline; | |
| @@ -827,7 +827,7 @@ copy_file(file, file_name) | |
| open_error(file_name); | |
| if ((c = getc(*file)) == EOF) | |
| - return; | |
| + return 0; | |
| out = code_file; | |
| last = c; | |
| diff --git a/src/yacc/reader.c b/src/yacc/reader.c | |
| index 2a5fb10..3b078aa 100644 | |
| --- a/src/yacc/reader.c | |
| +++ b/src/yacc/reader.c | |
| @@ -60,7 +60,7 @@ get_line() | |
| if (line) { FREE(line); line = 0; } | |
| cptr = 0; | |
| saw_eof = 1; | |
| - return; | |
| + return 0; | |
| } | |
| if (line == 0 || linesize != (LINESIZE + 1)) | |
| @@ -76,7 +76,7 @@ get_line() | |
| for (;;) | |
| { | |
| line[i] = c; | |
| - if (c == '\n') { cptr = line; return; } | |
| + if (c == '\n') { cptr = line; return 0; } | |
| if (++i >= linesize) | |
| { | |
| linesize += LINESIZE; | |
| @@ -89,7 +89,7 @@ get_line() | |
| line[i] = '\n'; | |
| saw_eof = 1; | |
| cptr = line; | |
| - return; | |
| + return 0; | |
| } | |
| } | |
| } | |
| @@ -128,7 +128,7 @@ skip_comment() | |
| { | |
| cptr = s + 2; | |
| FREE(st_line); | |
| - return; | |
| + return 0; | |
| } | |
| if (*s == '\n') | |
| { | |
| @@ -284,14 +284,14 @@ copy_ident() | |
| if (c == '\n') | |
| { | |
| fprintf(f, "\"\n"); | |
| - return; | |
| + return 0; | |
| } | |
| putc(c, f); | |
| if (c == '"') | |
| { | |
| putc('\n', f); | |
| ++cptr; | |
| - return; | |
| + return 0; | |
| } | |
| } | |
| } | |
| @@ -402,7 +402,7 @@ loop: | |
| if (need_newline) putc('\n', f); | |
| ++cptr; | |
| FREE(t_line); | |
| - return; | |
| + return 0; | |
| } | |
| /* fall through */ | |
| @@ -456,7 +456,7 @@ loop: | |
| if (c == '}' && depth == 0) { | |
| fprintf(text_file, " YYSTYPE;\n"); | |
| FREE(u_line); | |
| - return; | |
| + return 0; | |
| } | |
| goto loop; | |
| @@ -811,7 +811,7 @@ int assoc; | |
| else if (c == '\'' || c == '"') | |
| bp = get_literal(); | |
| else | |
| - return; | |
| + return 0; | |
| if (bp == goal) tokenized_start(bp->name); | |
| bp->class = TERM; | |
| @@ -871,7 +871,7 @@ declare_types() | |
| else if (c == '\'' || c == '"') | |
| bp = get_literal(); | |
| else | |
| - return; | |
| + return 0; | |
| if (bp->tag && tag != bp->tag) | |
| retyped_warning(bp->name); | |
| @@ -888,7 +888,7 @@ declare_start() | |
| for (;;) { | |
| c = nextc(); | |
| - if (!isalpha(c) && c != '_' && c != '.' && c != '$') return; | |
| + if (!isalpha(c) && c != '_' && c != '.' && c != '$') return 0; | |
| bp = get_name(); | |
| if (bp->class == TERM) | |
| @@ -916,7 +916,7 @@ read_declarations() | |
| switch (k = keyword()) | |
| { | |
| case MARK: | |
| - return; | |
| + return 0; | |
| case IDENT: | |
| copy_ident(); | |
| @@ -1142,7 +1142,7 @@ add_symbol() | |
| end_rule(); | |
| start_rule(bp, s_lineno); | |
| ++cptr; | |
| - return; | |
| + return 0; | |
| } | |
| if (last_was_action) | |
| @@ -1230,7 +1230,7 @@ loop: | |
| fprintf(f, ") : '%s))\n", plhs[nrules]->name); | |
| if (sflag) | |
| fprintf(f, ";;\n"); | |
| - return; | |
| + return 0; | |
| } | |
| putc(c, f); | |
| ++cptr; | |
| @@ -1401,7 +1401,7 @@ free_tags() | |
| { | |
| register int i; | |
| - if (tag_table == 0) return; | |
| + if (tag_table == 0) return 0; | |
| for (i = 0; i < ntags; ++i) | |
| { | |
| @@ -1702,7 +1702,7 @@ print_grammar() | |
| int spacing; | |
| register FILE *f = verbose_file; | |
| - if (!vflag) return; | |
| + if (!vflag) return 0; | |
| k = 1; | |
| for (i = 2; i < nrules; ++i) | |
| diff --git a/src/yacc/verbose.c b/src/yacc/verbose.c | |
| index 2c7cc52..a9b1a8b 100644 | |
| --- a/src/yacc/verbose.c | |
| +++ b/src/yacc/verbose.c | |
| @@ -8,7 +8,7 @@ verbose() | |
| { | |
| register int i; | |
| - if (!vflag) return; | |
| + if (!vflag) return 0; | |
| null_rules = (short *) MALLOC(nrules*sizeof(short)); | |
| if (null_rules == 0) no_space(); |