diff options
Diffstat (limited to 'bytecomp')
-rw-r--r-- | bytecomp/bytegen.ml | 4 | ||||
-rw-r--r-- | bytecomp/dllpath.ml | 59 | ||||
-rw-r--r-- | bytecomp/dllpath.mli | 25 | ||||
-rw-r--r-- | bytecomp/instruct.ml | 2 | ||||
-rw-r--r-- | bytecomp/instruct.mli | 4 | ||||
-rw-r--r-- | bytecomp/lambda.ml | 116 | ||||
-rw-r--r-- | bytecomp/lambda.mli | 12 | ||||
-rw-r--r-- | bytecomp/matching.ml | 64 | ||||
-rw-r--r-- | bytecomp/printinstr.ml | 8 | ||||
-rw-r--r-- | bytecomp/printlambda.ml | 20 | ||||
-rw-r--r-- | bytecomp/simplif.ml | 2 | ||||
-rw-r--r-- | bytecomp/switch.ml | 3 | ||||
-rw-r--r-- | bytecomp/symtable.ml | 1 | ||||
-rw-r--r-- | bytecomp/translclass.ml | 198 | ||||
-rw-r--r-- | bytecomp/translclass.mli | 1 | ||||
-rw-r--r-- | bytecomp/translcore.ml | 145 | ||||
-rw-r--r-- | bytecomp/transljoin.ml | 4 | ||||
-rw-r--r-- | bytecomp/translmod.ml | 89 |
18 files changed, 368 insertions, 389 deletions
diff --git a/bytecomp/bytegen.ml b/bytecomp/bytegen.ml index 01156f4384..65e51dcbcf 100644 --- a/bytecomp/bytegen.ml +++ b/bytecomp/bytegen.ml @@ -146,7 +146,7 @@ let rec size_of_lambda = function let copy_event ev kind info repr = { ev_pos = 0; (* patched in emitcode *) ev_module = ev.ev_module; - ev_char = ev.ev_char; + ev_loc = ev.ev_loc; ev_kind = kind; ev_info = info; ev_typenv = ev.ev_typenv; @@ -686,7 +686,7 @@ let rec comp_expr env exp sz cont = let event kind info = { ev_pos = 0; (* patched in emitcode *) ev_module = !compunit_name; - ev_char = lev.lev_pos; + ev_loc = lev.lev_loc; ev_kind = kind; ev_info = info; ev_typenv = lev.lev_env; diff --git a/bytecomp/dllpath.ml b/bytecomp/dllpath.ml deleted file mode 100644 index f0626a871b..0000000000 --- a/bytecomp/dllpath.ml +++ /dev/null @@ -1,59 +0,0 @@ -(***********************************************************************) -(* *) -(* Objective Caml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the Q Public License version 1.0. *) -(* *) -(***********************************************************************) - -(* $Id$ *) - -(* Handling of load path for dynamically-linked libraries *) - -(* Read the [ld.conf] file and return the corresponding list of directories *) - -let ld_conf_contents () = - let path = ref [] in - begin try - let ic = open_in (Filename.concat Config.standard_library "ld.conf") in - begin try - while true do - path := input_line ic :: !path - done - with End_of_file -> () - end; - close_in ic - with Sys_error _ -> () - end; - List.rev !path - -(* Split the CAML_LD_LIBRARY_PATH environment variable and return - the corresponding list of directories. *) - -let split str sep = - let rec split_rec pos = - if pos >= String.length str then [] else begin - try - let newpos = String.index_from str pos sep in - String.sub str pos (newpos - pos) :: - split_rec (newpos + 1) - with Not_found -> - [String.sub str pos (String.length str - pos)] - end in - split_rec 0 - -let ld_library_path_contents () = - let path_separator = - match Sys.os_type with - "Unix" | "Cygwin" -> ':' | "Win32" -> ';' | _ -> assert false in - try - split (Sys.getenv "CAML_LD_LIBRARY_PATH") path_separator - with Not_found -> - [] - -let split_dll_path path = - split path '\000' diff --git a/bytecomp/dllpath.mli b/bytecomp/dllpath.mli deleted file mode 100644 index 496fbf4974..0000000000 --- a/bytecomp/dllpath.mli +++ /dev/null @@ -1,25 +0,0 @@ -(***********************************************************************) -(* *) -(* Objective Caml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the Q Public License version 1.0. *) -(* *) -(***********************************************************************) - -(* $Id$ *) - -(* Handling of load path for dynamically-linked libraries *) - -(* Read the [ld.conf] file and return the corresponding list of directories *) -val ld_conf_contents: unit -> string list - -(* Split the CAML_LD_LIBRARY_PATH environment variable and return - the corresponding list of directories *) -val ld_library_path_contents: unit -> string list - -(* Split the given 0-separated path *) -val split_dll_path: string -> string list diff --git a/bytecomp/instruct.ml b/bytecomp/instruct.ml index fd13db5d7a..9fd2cb9409 100644 --- a/bytecomp/instruct.ml +++ b/bytecomp/instruct.ml @@ -22,7 +22,7 @@ type compilation_env = type debug_event = { mutable ev_pos: int; (* Position in bytecode *) ev_module: string; (* Name of defining module *) - ev_char: Lexing.position; (* Position in source file *) + ev_loc: Location.t; (* Location in source file *) ev_kind: debug_event_kind; (* Before/after event *) ev_info: debug_event_info; (* Extra information *) ev_typenv: Env.summary; (* Typing environment *) diff --git a/bytecomp/instruct.mli b/bytecomp/instruct.mli index fdedd8fd47..b7dbd7e3ba 100644 --- a/bytecomp/instruct.mli +++ b/bytecomp/instruct.mli @@ -23,7 +23,7 @@ type compilation_env = ce_heap: int Ident.tbl; (* Structure of the heap-allocated env *) ce_rec: int Ident.tbl } (* Functions bound by the same let rec *) -(* The ce_stack component gives locations of variables residing +(* The ce_stack component gives locations of variables residing in the stack. The locations are offsets w.r.t. the origin of the stack frame. The ce_heap component gives the positions of variables residing in the @@ -39,7 +39,7 @@ type compilation_env = type debug_event = { mutable ev_pos: int; (* Position in bytecode *) ev_module: string; (* Name of defining module *) - ev_char: Lexing.position; (* Position in source file *) + ev_loc: Location.t; (* Location in source file *) ev_kind: debug_event_kind; (* Before/after event *) ev_info: debug_event_info; (* Extra information *) ev_typenv: Env.summary; (* Typing environment *) diff --git a/bytecomp/lambda.ml b/bytecomp/lambda.ml index dfc26721e0..3a2fe60c18 100644 --- a/bytecomp/lambda.ml +++ b/bytecomp/lambda.ml @@ -96,7 +96,7 @@ and bigarray_kind = | Pbigarray_float32 | Pbigarray_float64 | Pbigarray_sint8 | Pbigarray_uint8 | Pbigarray_sint16 | Pbigarray_uint16 - | Pbigarray_int32 | Pbigarray_int64 + | Pbigarray_int32 | Pbigarray_int64 | Pbigarray_caml_int | Pbigarray_native_int | Pbigarray_complex32 | Pbigarray_complex64 @@ -110,6 +110,7 @@ type structured_constant = | Const_pointer of int | Const_block of int * structured_constant list | Const_float_array of string list + | Const_immstring of string type function_kind = Curried | Tupled @@ -148,7 +149,7 @@ and lambda_switch = sw_failaction : lambda option} and lambda_event = - { lev_pos: Lexing.position; + { lev_loc: Location.t; lev_kind: lambda_event_kind; lev_repr: int ref option; lev_env: Env.summary } @@ -163,10 +164,6 @@ let const_unit = Const_pointer 0 let lambda_unit = Lconst const_unit -let lambda_int i = Lconst (Const_base (Const_int i)) - -let lambda_string s = Lconst (Const_base (Const_string s)) - let rec same l1 l2 = match (l1, l2) with | Lvar v1, Lvar v2 -> @@ -205,7 +202,7 @@ let rec same l1 l2 = | Lsend(k1, a1, b1, cl1), Lsend(k2, a2, b2, cl2) -> k1 = k2 && same a1 a2 && same b1 b2 && samelist same cl1 cl2 | Levent(a1, ev1), Levent(a2, ev2) -> - same a1 a2 && ev1.lev_pos = ev2.lev_pos + same a1 a2 && ev1.lev_loc = ev2.lev_loc | Lifused(id1, a1), Lifused(id2, a2) -> Ident.same id1 id2 && same a1 a2 | _, _ -> @@ -240,63 +237,88 @@ let name_lambda_list args fn = Llet(Strict, id, arg, name_list (Lvar id :: names) rem) in name_list [] args -module IdentSet = - Set.Make(struct - type t = Ident.t - let compare = compare - end) - -let free_variables l = - let fv = ref IdentSet.empty in - let rec freevars = function - Lvar id -> - fv := IdentSet.add id !fv - | Lconst sc -> () +let rec iter f = function + Lvar _ + | Lconst _ -> () | Lapply(fn, args) -> - freevars fn; List.iter freevars args + f fn; List.iter f args | Lfunction(kind, params, body) -> - freevars body; - List.iter (fun param -> fv := IdentSet.remove param !fv) params + f body | Llet(str, id, arg, body) -> - freevars arg; freevars body; fv := IdentSet.remove id !fv + f arg; f body | Lletrec(decl, body) -> - freevars body; - List.iter (fun (id, exp) -> freevars exp) decl; - List.iter (fun (id, exp) -> fv := IdentSet.remove id !fv) decl + f body; + List.iter (fun (id, exp) -> f exp) decl | Lprim(p, args) -> - List.iter freevars args + List.iter f args | Lswitch(arg, sw) -> - freevars arg; - List.iter (fun (key, case) -> freevars case) sw.sw_consts; - List.iter (fun (key, case) -> freevars case) sw.sw_blocks; + f arg; + List.iter (fun (key, case) -> f case) sw.sw_consts; + List.iter (fun (key, case) -> f case) sw.sw_blocks; begin match sw.sw_failaction with | None -> () - | Some l -> freevars l + | Some l -> f l end | Lstaticraise (_,args) -> - List.iter freevars args + List.iter f args | Lstaticcatch(e1, (_,vars), e2) -> - freevars e1; freevars e2 ; - List.iter (fun id -> fv := IdentSet.remove id !fv) vars + f e1; f e2 | Ltrywith(e1, exn, e2) -> - freevars e1; freevars e2; fv := IdentSet.remove exn !fv + f e1; f e2 | Lifthenelse(e1, e2, e3) -> - freevars e1; freevars e2; freevars e3 + f e1; f e2; f e3 | Lsequence(e1, e2) -> - freevars e1; freevars e2 + f e1; f e2 | Lwhile(e1, e2) -> - freevars e1; freevars e2 - | Lfor(v, e1, e2, dir, e3) -> - freevars e1; freevars e2; freevars e3; fv := IdentSet.remove v !fv + f e1; f e2 + | Lfor(v, e1, e2, dir, e3) -> + f e1; f e2; f e3 | Lassign(id, e) -> - fv := IdentSet.add id !fv; freevars e + f e | Lsend (k, met, obj, args) -> - List.iter freevars (met::obj::args) + List.iter f (met::obj::args) | Levent (lam, evt) -> - freevars lam + f lam | Lifused (v, e) -> - freevars e - in freevars l; !fv + f e + +module IdentSet = + Set.Make(struct + type t = Ident.t + let compare = compare + end) + +let free_ids get l = + let fv = ref IdentSet.empty in + let rec free l = + iter free l; + fv := List.fold_right IdentSet.add (get l) !fv; + match l with + Lfunction(kind, params, body) -> + List.iter (fun param -> fv := IdentSet.remove param !fv) params + | Llet(str, id, arg, body) -> + fv := IdentSet.remove id !fv + | Lletrec(decl, body) -> + List.iter (fun (id, exp) -> fv := IdentSet.remove id !fv) decl + | Lstaticcatch(e1, (_,vars), e2) -> + List.iter (fun id -> fv := IdentSet.remove id !fv) vars + | Ltrywith(e1, exn, e2) -> + fv := IdentSet.remove exn !fv + | Lfor(v, e1, e2, dir, e3) -> + fv := IdentSet.remove v !fv + | Lassign(id, e) -> + fv := IdentSet.add id !fv + | Lvar _ | Lconst _ | Lapply _ + | Lprim _ | Lswitch _ | Lstaticraise _ + | Lifthenelse _ | Lsequence _ | Lwhile _ + | Lsend _ | Levent _ | Lifused _ -> () + in free l; !fv + +let free_variables l = + free_ids (function Lvar id -> [id] | _ -> []) l + +let free_methods l = + free_ids (function Lsend(Self, Lvar meth, obj, _) -> [meth] | _ -> []) l (* Check if an action has a "when" guard *) let raise_count = ref 0 @@ -365,14 +387,14 @@ let subst_lambda s lam = match sw.sw_failaction with | None -> None | Some l -> Some (subst l)}) - + | Lstaticraise (i,args) -> Lstaticraise (i, List.map subst args) | Lstaticcatch(e1, io, e2) -> Lstaticcatch(subst e1, io, subst e2) | Ltrywith(e1, exn, e2) -> Ltrywith(subst e1, exn, subst e2) | Lifthenelse(e1, e2, e3) -> Lifthenelse(subst e1, subst e2, subst e3) | Lsequence(e1, e2) -> Lsequence(subst e1, subst e2) | Lwhile(e1, e2) -> Lwhile(subst e1, subst e2) - | Lfor(v, e1, e2, dir, e3) -> Lfor(v, subst e1, subst e2, dir, subst e3) + | Lfor(v, e1, e2, dir, e3) -> Lfor(v, subst e1, subst e2, dir, subst e3) | Lassign(id, e) -> Lassign(id, subst e) | Lsend (k, met, obj, args) -> Lsend (k, subst met, subst obj, List.map subst args) diff --git a/bytecomp/lambda.mli b/bytecomp/lambda.mli index 6709c87d9f..0aa6412fb0 100644 --- a/bytecomp/lambda.mli +++ b/bytecomp/lambda.mli @@ -110,6 +110,7 @@ type structured_constant = | Const_pointer of int | Const_block of int * structured_constant list | Const_float_array of string list + | Const_immstring of string type function_kind = Curried | Tupled @@ -156,7 +157,7 @@ and lambda_switch = sw_blocks: (int * lambda) list; (* Tag block cases *) sw_failaction : lambda option} (* Action to take if failure *) and lambda_event = - { lev_pos: Lexing.position; + { lev_loc: Location.t; lev_kind: lambda_event_kind; lev_repr: int ref option; lev_env: Env.summary } @@ -169,16 +170,15 @@ and lambda_event_kind = val same: lambda -> lambda -> bool val const_unit: structured_constant val lambda_unit: lambda -val lambda_int : int -> lambda -val lambda_string : string -> lambda - val name_lambda: lambda -> (Ident.t -> lambda) -> lambda val name_lambda_list: lambda list -> (lambda list -> lambda) -> lambda val is_guarded: lambda -> bool val patch_guarded : lambda -> lambda -> lambda +val iter: (lambda -> unit) -> lambda -> unit module IdentSet: Set.S with type elt = Ident.t val free_variables: lambda -> IdentSet.t +val free_methods: lambda -> IdentSet.t val transl_path: Path.t -> lambda val make_sequence: ('a -> lambda) -> 'a list -> lambda @@ -200,8 +200,8 @@ val next_raise_count : unit -> int val staticfail : lambda (* Anticipated static failure *) (* Check anticipated failure, substitute its final value *) -val is_guarded: lambda -> bool -val patch_guarded : lambda -> lambda -> lambda +val is_guarded: lambda -> bool +val patch_guarded : lambda -> lambda -> lambda (*>JOCAML*) (* Get a runtime location, ie a tuple (filename, line, pos) *) diff --git a/bytecomp/matching.ml b/bytecomp/matching.ml index 64d0b9e75f..330e91f867 100644 --- a/bytecomp/matching.ml +++ b/bytecomp/matching.ml @@ -101,8 +101,12 @@ let rshift_num n {left=left ; right=right} = let ctx_rshift_num n ctx = List.map (rshift_num n) ctx +(* Recombination of contexts (eg: (_,_)::p1::p2::rem -> (p1,p2)::rem) + All mutable fields are replaced by '_', since side-effects in + guards can alter these fields *) + let combine {left=left ; right=right} = match left with -| p::ps -> {left=ps ; right=set_args p right} +| p::ps -> {left=ps ; right=set_args_erase_mutable p right} | _ -> assert false let ctx_combine ctx = List.map combine ctx @@ -376,11 +380,11 @@ let pretty_cases cases = prerr_string " " ; prerr_string (Format.flush_str_formatter ())) ps ; - +(* prerr_string " -> " ; Printlambda.lambda Format.str_formatter l ; prerr_string (Format.flush_str_formatter ()) ; - +*) prerr_endline "") cases @@ -1075,7 +1079,7 @@ let rec matcher_const cst p rem = match p.pat_desc with | _ -> raise NoMatch let get_key_constant caller = function - | {pat_desc= Tpat_constant cst} as p -> cst + | {pat_desc= Tpat_constant cst} -> cst | p -> prerr_endline ("BAD: "^caller) ; pretty_pat p ; @@ -1241,7 +1245,7 @@ let get_key_variant p = match p.pat_desc with | Tpat_variant(lab, None , _) -> Cstr_constant (Btype.hash_variant lab) | _ -> assert false -let divide_variant row ctx ({cases = cl; args = al; default=def} as pm) = +let divide_variant row ctx {cases = cl; args = al; default=def} = let row = Btype.row_repr row in let rec divide = function ({pat_desc = Tpat_variant(lab, pato, _)} as p:: patl, action) :: rem -> @@ -1486,7 +1490,7 @@ let as_int_list cases acts = let default = max_vals cases acts in let min_key,_,_ = cases.(0) and _,max_key,_ = cases.(Array.length cases-1) in - let offset = max_key-min_key in + let rec do_rec i k = if i >= 0 then let low, high, act = cases.(i) in @@ -1636,7 +1640,7 @@ let as_interval_canfail fail low high l = let rec init_rec = function | [] -> [] - | (i,act_i)::rem as all -> + | (i,act_i)::rem -> let index = store.act_store act_i in if index=0 then fail_rec low i rem @@ -1795,6 +1799,7 @@ let mk_failaction_neg partial ctx def = match partial with end | Total -> None, [], jumps_empty + (* Conforme a l'article et plus simple qu'avant *) @@ -1894,7 +1899,6 @@ let combine_constructor arg ex_pat cstr partial ctx def (tag_lambda_list, total1, pats) = if cstr.cstr_consts < 0 then begin (* Special cases for exceptions *) - let cstrs = List.map fst tag_lambda_list in let fail, to_add, local_jumps = mk_failaction_neg partial ctx def in let tag_lambda_list = to_add@tag_lambda_list in @@ -1921,8 +1925,7 @@ let combine_constructor arg ex_pat cstr partial ctx def (* Regular concrete type *) let ncases = List.length tag_lambda_list and nconstrs = cstr.cstr_consts + cstr.cstr_nonconsts in - let sig_complete = ncases = nconstrs - and cstrs = List.map fst tag_lambda_list in + let sig_complete = ncases = nconstrs in let fails,local_jumps = if sig_complete then [],jumps_empty else @@ -1998,7 +2001,9 @@ let combine_variant row arg partial ctx def (tag_lambda_list, total1, pats) = let sig_complete = List.length tag_lambda_list = !num_constr and one_action = same_actions tag_lambda_list in let fail, to_add, local_jumps = - if sig_complete || (match partial with Total -> true | _ -> false) then + if + sig_complete || (match partial with Total -> true | _ -> false) + then None, [], jumps_empty else mk_failaction_neg partial ctx def in @@ -2055,7 +2060,7 @@ let rec event_branch repr lam = lam | (Levent(lam', ev), Some r) -> incr r; - Levent(lam', {lev_pos = ev.lev_pos; + Levent(lam', {lev_loc = ev.lev_loc; lev_kind = ev.lev_kind; lev_repr = repr; lev_env = ev.lev_env}) @@ -2299,7 +2304,6 @@ and do_compile_matching_pr repr partial ctx arg x = pretty_jumps jumps ; r *) - and do_compile_matching repr partial ctx arg pmh = match pmh with | Pm pm -> let pat = what_is_cases pm.cases in @@ -2356,8 +2360,23 @@ and compile_no_test divide up_ctx repr partial ctx to_match = (* The entry points *) +(* + If there is a guard in a matching, then + set exhaustiveness info to Partial. + (because of side effects in guards, assume the worst) +*) + +let check_partial pat_act_list partial = + if + List.exists + (fun (_,lam) -> is_guarded lam) + pat_act_list + then begin + Partial + end else + partial -(* had toplevel handler when appropriate *) +(* have toplevel handler when appropriate *) let start_ctx n = [{left=[] ; right = omegas n}] @@ -2369,6 +2388,7 @@ let check_total total lambda i handler_fun = end let compile_matching loc repr handler_fun arg pat_act_list partial = + let partial = check_partial pat_act_list partial in match partial with | Partial -> let raise_num = next_raise_count () in @@ -2380,7 +2400,7 @@ let compile_matching loc repr handler_fun arg pat_act_list partial = let (lambda, total) = compile_match repr partial (start_ctx 1) pm in check_total total lambda raise_num handler_fun with - | Unused -> assert false ; handler_fun() + | Unused -> assert false (* ; handler_fun() *) end | Total -> let pm = @@ -2391,6 +2411,7 @@ let compile_matching loc repr handler_fun arg pat_act_list partial = assert (jumps_is_empty total) ; lambda + let partial_function loc () = (* [Location.get_pos_info] is too expensive *) let fname = match loc.Location.loc_start.Lexing.pos_fname with @@ -2426,6 +2447,7 @@ let for_let (handler,loc) param pat body = (* Easy case since variables are available *) let for_tupled_function loc paraml pats_act_list partial = + let partial = check_partial pats_act_list partial in let raise_num = next_raise_count () in let omegas = [List.map (fun _ -> omega) paraml] in let pm = @@ -2443,7 +2465,7 @@ let for_tupled_function loc paraml pats_act_list partial = let flatten_pattern size p = match p.pat_desc with -| Tpat_tuple args -> args +| Tpat_tuple args -> args | Tpat_any -> omegas size | _ -> raise Cannot_flatten @@ -2451,6 +2473,9 @@ let rec flatten_pat_line size p k = match p.pat_desc with | Tpat_any -> omegas size::k | Tpat_tuple args -> args::k | Tpat_or (p1,p2,_) -> flatten_pat_line size p1 (flatten_pat_line size p2 k) +| Tpat_alias (p,_) -> (* Note: if this 'as' pat is here, then this is a useless + binding, solves PR #3780 *) + flatten_pat_line size p k | _ -> fatal_error "Matching.flatten_pat_line" let flatten_cases size cases = @@ -2461,7 +2486,7 @@ let flatten_cases size cases = cases let flatten_matrix size pss = - List.fold_right + List.fold_right (fun ps r -> match ps with | [p] -> flatten_pat_line size p r | _ -> fatal_error "Matching.flatten_matrix") @@ -2503,6 +2528,7 @@ let compile_flattened repr partial ctx _ pmh = match pmh with let for_multiple_match (handler, loc) paraml pat_act_list partial = let repr = None in + let partial = check_partial pat_act_list partial in let raise_num,pm1 = match partial with | Partial -> @@ -2544,8 +2570,6 @@ let for_multiple_match (handler, loc) paraml pat_act_list partial = | Total -> assert (jumps_is_empty total) ; lam) - - with Cannot_flatten -> let (lambda, total) = compile_match None partial (start_ctx 1) pm1 in begin match partial with @@ -2557,5 +2581,5 @@ let for_multiple_match (handler, loc) paraml pat_act_list partial = lambda end with Unused -> - assert false ; partial_function loc () + assert false (* ; partial_function loc () *) diff --git a/bytecomp/printinstr.ml b/bytecomp/printinstr.ml index a7c859d847..2f0508b299 100644 --- a/bytecomp/printinstr.ml +++ b/bytecomp/printinstr.ml @@ -99,8 +99,10 @@ let instruction ppf = function | Kgetpubmet n -> fprintf ppf "\tgetpubmet %i" n | Kgetdynmet -> fprintf ppf "\tgetdynmet" | Kstop -> fprintf ppf "\tstop" - | Kevent ev -> fprintf ppf "\tevent \"%s\" %i" ev.ev_char.Lexing.pos_fname - ev.ev_char.Lexing.pos_cnum + | Kevent ev -> fprintf ppf "\tevent \"%s\" %i-%i" + ev.ev_loc.Location.loc_start.Lexing.pos_fname + ev.ev_loc.Location.loc_start.Lexing.pos_cnum + ev.ev_loc.Location.loc_end.Lexing.pos_cnum let rec instruction_list ppf = function [] -> () @@ -108,6 +110,6 @@ let rec instruction_list ppf = function fprintf ppf "L%i:%a" lbl instruction_list il | instr :: il -> fprintf ppf "%a@ %a" instruction instr instruction_list il - + let instrlist ppf il = fprintf ppf "@[<v 0>%a@]" instruction_list il diff --git a/bytecomp/printlambda.ml b/bytecomp/printlambda.ml index fb129ffb75..27c0ff3d55 100644 --- a/bytecomp/printlambda.ml +++ b/bytecomp/printlambda.ml @@ -23,6 +23,7 @@ let rec struct_const ppf = function | Const_base(Const_int n) -> fprintf ppf "%i" n | Const_base(Const_char c) -> fprintf ppf "%C" c | Const_base(Const_string s) -> fprintf ppf "%S" s + | Const_immstring s -> fprintf ppf "#%S" s | Const_base(Const_float f) -> fprintf ppf "%s" f | Const_base(Const_int32 n) -> fprintf ppf "%lil" n | Const_base(Const_int64 n) -> fprintf ppf "%LiL" n @@ -172,12 +173,6 @@ let primitive ppf = function | Pbigarrayref(n, kind, layout) -> print_bigarray "get" kind ppf layout | Pbigarrayset(n, kind, layout) -> print_bigarray "set" kind ppf layout -let pstr = function - | Strict -> "S" - | StrictOpt -> "SO" - | Alias -> "A" - | Variable -> "V" - let rec lam ppf = function | Lvar id -> Ident.print ppf id @@ -205,12 +200,10 @@ let rec lam ppf = function | Llet(str, id, arg, body) -> let rec letbody = function | Llet(str, id, arg, body) -> - fprintf ppf "@ @[<2>%a(%s)@ %a@]" - Ident.print id (pstr str) lam arg; + fprintf ppf "@ @[<2>%a@ %a@]" Ident.print id lam arg; letbody body | expr -> expr in - fprintf ppf "@[<2>(let@ @[<hv 1>(@[<2>%a(%s)@ %a@]" - Ident.print id (pstr str) lam arg; + fprintf ppf "@[<2>(let@ @[<hv 1>(@[<2>%a@ %a@]" Ident.print id lam arg; let expr = letbody body in fprintf ppf ")@]@ %a)@]" lam expr | Lletrec(id_arg_list, body) -> @@ -289,12 +282,15 @@ let rec lam ppf = function if k = Self then "self" else if k = Cached then "cache" else "" in fprintf ppf "@[<2>(send%s@ %a@ %a%a)@]" kind lam obj lam met args largs | Levent(expr, ev) -> - let kind = + let kind = match ev.lev_kind with | Lev_before -> "before" | Lev_after _ -> "after" | Lev_function -> "funct-body" in - fprintf ppf "@[<2>(%s %i@ %a)@]" kind ev.lev_pos.Lexing.pos_cnum lam expr + fprintf ppf "@[<2>(%s %i-%i@ %a)@]" kind + ev.lev_loc.Location.loc_start.Lexing.pos_cnum + ev.lev_loc.Location.loc_end.Lexing.pos_cnum + lam expr | Lifused(id, expr) -> fprintf ppf "@[<2>(ifused@ %a@ %a)@]" Ident.print id lam expr diff --git a/bytecomp/simplif.ml b/bytecomp/simplif.ml index 126aa7772a..ee59cab742 100644 --- a/bytecomp/simplif.ml +++ b/bytecomp/simplif.ml @@ -370,7 +370,7 @@ let simplify_lets lam = | Llet(StrictOpt, v, l1, l2) -> begin match count_var v with 0 -> simplif l2 - | n -> Llet(StrictOpt, v, simplif l1, simplif l2) + | n -> Llet(Alias, v, simplif l1, simplif l2) end | Llet(kind, v, l1, l2) -> Llet(kind, v, simplif l1, simplif l2) | Lletrec(bindings, body) -> diff --git a/bytecomp/switch.ml b/bytecomp/switch.ml index 38db1d5502..ff58af72e6 100644 --- a/bytecomp/switch.ml +++ b/bytecomp/switch.ml @@ -653,7 +653,7 @@ let approx_count cases i j n_actions = (* Sends back a boolean that says whether is switch is worth or not *) -let dense ({cases=cases ; actions=actions} as s) i j = +let dense {cases=cases ; actions=actions} i j = if i=j then true else let l,_,_ = cases.(i) @@ -775,7 +775,6 @@ let make_clusters ({cases=cases ; actions=actions} as s) n_clusters k = let zyva (low,high) konst arg cases actions = - let lcases = Array.length cases in let old_ok = !ok_inter in ok_inter := (abs low <= inter_limit && abs high <= inter_limit) ; if !ok_inter <> old_ok then Hashtbl.clear t ; diff --git a/bytecomp/symtable.ml b/bytecomp/symtable.ml index 4d22e092ab..6a55cabf28 100644 --- a/bytecomp/symtable.ml +++ b/bytecomp/symtable.ml @@ -212,6 +212,7 @@ let rec transl_const = function | Const_base(Const_int64 i) -> Obj.repr i | Const_base(Const_nativeint i) -> Obj.repr i | Const_pointer i -> Obj.repr i + | Const_immstring s -> Obj.repr s | Const_block(tag, fields) -> let block = Obj.new_block tag (List.length fields) in let pos = ref 0 in diff --git a/bytecomp/translclass.ml b/bytecomp/translclass.ml index e635134cfd..b0eeeacfc2 100644 --- a/bytecomp/translclass.ml +++ b/bytecomp/translclass.ml @@ -46,12 +46,12 @@ let lsequence l1 l2 = let lfield v i = Lprim(Pfield i, [Lvar v]) -let transl_label l = share (Const_base (Const_string l)) +let transl_label l = share (Const_immstring l) let rec transl_meth_list lst = if lst = [] then Lconst (Const_pointer 0) else share (Const_block - (0, List.map (fun lab -> Const_base (Const_string lab)) lst)) + (0, List.map (fun lab -> Const_immstring lab) lst)) let set_inst_var obj id expr = let kind = if Typeopt.maybe_pointer expr then Paddrarray else Pintarray in @@ -71,35 +71,26 @@ let transl_val tbl create name = Lapply (oo_prim (if create then "new_variable" else "get_variable"), [Lvar tbl; transl_label name]) -let transl_vals tbl create sure vals rem = - if create && sure && List.length vals > 1 then - let (_,id0) = List.hd vals in - let call = - Lapply(oo_prim "new_variables", - [Lvar tbl; transl_meth_list (List.map fst vals)]) in - let i = ref (List.length vals) in - Llet(Strict, id0, call, - List.fold_right - (fun (name,id) rem -> - decr i; Llet(Alias, id, Lprim(Poffsetint !i, [Lvar id0]), rem)) - (List.tl vals) rem) - else +let transl_vals tbl create vals rem = List.fold_right (fun (name, id) rem -> Llet(StrictOpt, id, transl_val tbl create name, rem)) vals rem -let transl_super tbl meths inh_methods rem = +let meths_super tbl meths inh_meths = List.fold_right (fun (nm, id) rem -> - begin try - Llet(StrictOpt, id, Lapply (oo_prim "get_method", - [Lvar tbl; Lvar (Meths.find nm meths)]), - rem) - with Not_found -> - rem - end) - inh_methods rem + try + (nm, id, + Lapply(oo_prim "get_method", [Lvar tbl; Lvar (Meths.find nm meths)])) + :: rem + with Not_found -> rem) + inh_meths [] + +let bind_super tbl (vals, meths) cl_init = + transl_vals tbl false vals + (List.fold_right (fun (nm, id, def) rem -> Llet(StrictOpt, id, def, rem)) + meths cl_init) let create_object cl obj init = let obj' = Ident.create "self" in @@ -217,32 +208,43 @@ let bind_method tbl lab id cl_init = [Lvar tbl; transl_label lab]), cl_init) -let bind_methods tbl meths cl_init = +let bind_methods tbl meths vals cl_init = let methl = Meths.fold (fun lab id tl -> (lab,id) :: tl) meths [] in - let len = List.length methl in - if len < 2 then Meths.fold (bind_method tbl) meths cl_init else + let len = List.length methl and nvals = List.length vals in + if len < 2 && nvals = 0 then Meths.fold (bind_method tbl) meths cl_init else + if len = 0 && nvals < 2 then transl_vals tbl true vals cl_init else let ids = Ident.create "ids" in let i = ref len in + let getter, names, cl_init = + match vals with [] -> "get_method_labels", [], cl_init + | (_,id0)::vals' -> + incr i; + let i = ref (List.length vals) in + "new_methods_variables", + [transl_meth_list (List.map fst vals)], + Llet(Strict, id0, lfield ids 0, + List.fold_right + (fun (name,id) rem -> + decr i; + Llet(Alias, id, Lprim(Poffsetint !i, [Lvar id0]), rem)) + vals' cl_init) + in Llet(StrictOpt, ids, - Lapply (oo_prim "get_method_labels", - [Lvar tbl; transl_meth_list (List.map fst methl)]), + Lapply (oo_prim getter, + [Lvar tbl; transl_meth_list (List.map fst methl)] @ names), List.fold_right - (fun (lab,id) lam -> - decr i; Llet(StrictOpt, id, Lprim(Pfield !i, [Lvar ids]), lam)) + (fun (lab,id) lam -> decr i; Llet(StrictOpt, id, lfield ids !i, lam)) methl cl_init) -let output_methods tbl vals methods lam = - let lam = - match methods with - [] -> lam - | [lab; code] -> - lsequence (Lapply(oo_prim "set_method", [Lvar tbl; lab; code])) lam - | _ -> - lsequence (Lapply(oo_prim "set_methods", - [Lvar tbl; Lprim(Pmakeblock(0,Immutable), methods)])) - lam - in - transl_vals tbl true true vals lam +let output_methods tbl methods lam = + match methods with + [] -> lam + | [lab; code] -> + lsequence (Lapply(oo_prim "set_method", [Lvar tbl; lab; code])) lam + | _ -> + lsequence (Lapply(oo_prim "set_methods", + [Lvar tbl; Lprim(Pmakeblock(0,Immutable), methods)])) + lam let rec ignore_cstrs cl = match cl.cl_desc with @@ -250,7 +252,12 @@ let rec ignore_cstrs cl = | Tclass_apply (cl, _) -> ignore_cstrs cl | _ -> cl -let rec build_class_init cla cstr inh_init cl_init msubst top cl = +let rec index a = function + [] -> raise Not_found + | b :: l -> + if b = a then 0 else 1 + index a l + +let rec build_class_init cla cstr super inh_init cl_init msubst top cl = match cl.cl_desc with Tclass_ident path -> begin match inh_init with @@ -260,23 +267,23 @@ let rec build_class_init cla cstr inh_init cl_init msubst top cl = Llet (Strict, obj_init, Lapply(Lprim(Pfield 1, [lpath]), Lvar cla :: if top then [Lprim(Pfield 3, [lpath])] else []), - cl_init)) + bind_super cla super cl_init)) | _ -> assert false end | Tclass_structure str -> + let cl_init = bind_super cla super cl_init in let (inh_init, cl_init, methods, values) = List.fold_right (fun field (inh_init, cl_init, methods, values) -> match field with Cf_inher (cl, vals, meths) -> - let cl_init = output_methods cla values methods cl_init in + let cl_init = output_methods cla methods cl_init in let inh_init, cl_init = - build_class_init cla false inh_init - (transl_vals cla false false vals - (transl_super cla str.cl_meths meths cl_init)) - msubst top cl in - (inh_init, cl_init, [], []) + build_class_init cla false + (vals, meths_super cla str.cl_meths meths) + inh_init cl_init msubst top cl in + (inh_init, cl_init, [], values) | Cf_val (name, id, exp) -> (inh_init, cl_init, methods, (name, id)::values) | Cf_meth (name, exp) -> @@ -291,13 +298,6 @@ let rec build_class_init cla cstr inh_init cl_init msubst top cl = (inh_init, cl_init, Lvar (Meths.find name str.cl_meths) :: met_code @ methods, values) - (* - Lsequence(Lapply (oo_prim ("set_method" ^ builtin), - Lvar cla :: - Lvar (Meths.find name str.cl_meths) :: - met_code), - cl_init)) - *) | Cf_let (rec_flag, defs, vals) -> let vals = List.map (function (id, _) -> (Ident.name id, id)) vals @@ -312,43 +312,61 @@ let rec build_class_init cla cstr inh_init cl_init msubst top cl = str.cl_field (inh_init, cl_init, [], []) in - let cl_init = output_methods cla values methods cl_init in - (inh_init, bind_methods cla str.cl_meths cl_init) + let cl_init = output_methods cla methods cl_init in + (inh_init, bind_methods cla str.cl_meths values cl_init) | Tclass_fun (pat, vals, cl, _) -> let (inh_init, cl_init) = - build_class_init cla cstr inh_init cl_init msubst top cl + build_class_init cla cstr super inh_init cl_init msubst top cl in let vals = List.map (function (id, _) -> (Ident.name id, id)) vals in - (inh_init, transl_vals cla true false vals cl_init) + (inh_init, transl_vals cla true vals cl_init) | Tclass_apply (cl, exprs) -> - build_class_init cla cstr inh_init cl_init msubst top cl + build_class_init cla cstr super inh_init cl_init msubst top cl | Tclass_let (rec_flag, defs, vals, cl) -> let (inh_init, cl_init) = - build_class_init cla cstr inh_init cl_init msubst top cl + build_class_init cla cstr super inh_init cl_init msubst top cl in let vals = List.map (function (id, _) -> (Ident.name id, id)) vals in - (inh_init, transl_vals cla true false vals cl_init) + (inh_init, transl_vals cla true vals cl_init) | Tclass_constraint (cl, vals, meths, concr_meths) -> let virt_meths = List.filter (fun lab -> not (Concr.mem lab concr_meths)) meths in + let concr_meths = Concr.elements concr_meths in let narrow_args = [Lvar cla; transl_meth_list vals; transl_meth_list virt_meths; - transl_meth_list (Concr.elements concr_meths)] in + transl_meth_list concr_meths] in let cl = ignore_cstrs cl in begin match cl.cl_desc, inh_init with Tclass_ident path, (obj_init, path')::inh_init -> assert (Path.same path path'); let lpath = transl_path path in + let inh = Ident.create "inh" + and inh_vals = Ident.create "vals" + and inh_meths = Ident.create "meths" + and valids, methids = super in + let cl_init = + List.fold_left + (fun init (nm, id, _) -> + Llet(StrictOpt, id, lfield inh_meths (index nm concr_meths), + init)) + cl_init methids in + let cl_init = + List.fold_left + (fun init (nm, id) -> + Llet(StrictOpt, id, lfield inh_vals (index nm vals), init)) + cl_init valids in (inh_init, - Llet (Strict, obj_init, + Llet (Strict, inh, Lapply(oo_prim "inherits", narrow_args @ [lpath; Lconst(Const_pointer(if top then 1 else 0))]), - cl_init)) + Llet(StrictOpt, obj_init, lfield inh 0, + Llet(Alias, inh_vals, lfield inh 1, + Llet(Alias, inh_meths, lfield inh 2, cl_init))))) | _ -> let core cl_init = - build_class_init cla true inh_init cl_init msubst top cl + build_class_init cla true super inh_init cl_init msubst top cl in if cstr then core cl_init else let (inh_init, cl_init) = @@ -366,6 +384,16 @@ let rec build_class_lets cl = | _ -> (cl.cl_env, fun x -> x) +let rec get_class_meths cl = + match cl.cl_desc with + Tclass_structure cl -> + Meths.fold (fun _ -> IdentSet.add) cl.cl_meths IdentSet.empty + | Tclass_ident _ -> IdentSet.empty + | Tclass_fun (_, _, cl, _) + | Tclass_let (_, _, _, cl) + | Tclass_apply (cl, _) + | Tclass_constraint (cl, _, _, _) -> get_class_meths cl + (* XXX Il devrait etre peu couteux d'ecrire des classes : class c x y = d e f @@ -426,7 +454,6 @@ let transl_class_rebind ids cl = let cla = Ident.create "class" and new_init = Ident.create "new_init" - and arg = Ident.create "arg" and env_init = Ident.create "env_init" and table = Ident.create "table" and envs = Ident.create "envs" in @@ -478,8 +505,8 @@ let rec builtin_meths self env env2 body = | _ -> raise Not_found in match body with - | Llet(Alias, s', Lvar s, body) when List.mem s self -> - builtin_meths self env env2 body + | Llet(_, s', Lvar s, body) when List.mem s self -> + builtin_meths (s'::self) env env2 body | Lapply(f, [arg]) when const_path f -> let s, args = conv arg in ("app_"^s, f :: args) | Lapply(f, [arg; p]) when const_path f && const_path p -> @@ -504,7 +531,7 @@ let rec builtin_meths self env env2 body = | Lprim(Parraysetu _, [Lvar s; Lvar n; Lvar x']) when Ident.same x x' && List.mem s self -> ("set_var", [Lvar n]) - | Llet(Alias, s', Lvar s, body) when List.mem s self -> + | Llet(_, s', Lvar s, body) when List.mem s self -> enter (s'::self) body | _ -> raise Not_found in enter self body @@ -579,11 +606,18 @@ let transl_class ids cl_id arity pub_meths cl = let cl_env, llets = build_class_lets cl in let new_ids = if top then [] else Env.diff top_env cl_env in let env2 = Ident.create "env" in + let meth_ids = get_class_meths cl in let subst env lam i0 new_ids' = let fv = free_variables lam in let fv = List.fold_right IdentSet.remove !new_ids' fv in - let fv = - IdentSet.filter (fun id -> List.mem id new_ids) fv in + (* IdentSet.iter + (fun id -> + if not (List.mem id new_ids) then prerr_endline (Ident.name id)) + fv; *) + let fv = IdentSet.filter (fun id -> List.mem id new_ids) fv in + (* need to handle methods specially (PR#3576) *) + let fm = IdentSet.diff (free_methods lam) meth_ids in + let fv = IdentSet.union fv fm in new_ids' := !new_ids' @ IdentSet.elements fv; let i = ref (i0-1) in List.fold_left @@ -633,8 +667,9 @@ let transl_class ids cl_id arity pub_meths cl = build_object_init_0 cla [] cl copy_env subst_env top ids in if not (Translcore.check_recursive_lambda ids obj_init) then raise(Error(cl.cl_loc, Illegal_class_expr)); + let inh_init' = List.rev inh_init in let (inh_init', cl_init) = - build_class_init cla true (List.rev inh_init) obj_init msubst top cl + build_class_init cla true ([],[]) inh_init' obj_init msubst top cl in assert (inh_init' = []); let table = Ident.create "table" @@ -691,8 +726,8 @@ let transl_class ids cl_id arity pub_meths cl = if top then llets (lbody_virt lambda_unit) else (* Now for the hard stuff: prepare for table cacheing *) - let env_index = Ident.create "env_index" - and envs = Ident.create "envs" in + let envs = Ident.create "envs" + and cached = Ident.create "cached" in let lenvs = if !new_ids_meths = [] && !new_ids_init = [] && inh_init = [] then lambda_unit @@ -719,8 +754,6 @@ let transl_class ids cl_id arity pub_meths cl = Lapply (oo_prim "new_variable", [Lvar cla; transl_label ""]), lam) in - let obj_init2 = Ident.create "obj_init" - and cached = Ident.create "cached" in let inh_paths = List.filter (fun (_,path) -> List.mem (Path.head path) new_ids) inh_init in @@ -767,11 +800,6 @@ let transl_class ids cl_id arity pub_meths cl = else [lambda_unit; lfield cached 0; lambda_unit; lenvs] ))))) -(* Dummy for recursive modules *) - -let dummy_class undef_fn = - Lprim(Pmakeblock(0, Mutable), [undef_fn; undef_fn; undef_fn; lambda_unit]) - (* Wrapper for class compilation *) let transl_class ids cl_id arity pub_meths cl = diff --git a/bytecomp/translclass.mli b/bytecomp/translclass.mli index 85d5f74bcd..8b74d29811 100644 --- a/bytecomp/translclass.mli +++ b/bytecomp/translclass.mli @@ -15,7 +15,6 @@ open Typedtree open Lambda -val dummy_class : lambda -> lambda val transl_class : Ident.t list -> Ident.t -> int -> string list -> class_expr -> lambda;; diff --git a/bytecomp/translcore.ml b/bytecomp/translcore.ml index ccd5d202e4..21e4f887ea 100644 --- a/bytecomp/translcore.ml +++ b/bytecomp/translcore.ml @@ -53,7 +53,8 @@ let comparisons_table = create_hashtable 11 [ prim_native_name = ""; prim_native_float = false}, Pbintcomp(Pnativeint, Ceq), Pbintcomp(Pint32, Ceq), - Pbintcomp(Pint64, Ceq)); + Pbintcomp(Pint64, Ceq), + true); "%notequal", (Pccall{prim_name = "caml_notequal"; prim_arity = 2; prim_alloc = true; prim_native_name = ""; prim_native_float = false}, @@ -64,7 +65,8 @@ let comparisons_table = create_hashtable 11 [ prim_native_float = false}, Pbintcomp(Pnativeint, Cneq), Pbintcomp(Pint32, Cneq), - Pbintcomp(Pint64, Cneq)); + Pbintcomp(Pint64, Cneq), + true); "%lessthan", (Pccall{prim_name = "caml_lessthan"; prim_arity = 2; prim_alloc = true; prim_native_name = ""; prim_native_float = false}, @@ -75,7 +77,8 @@ let comparisons_table = create_hashtable 11 [ prim_native_float = false}, Pbintcomp(Pnativeint, Clt), Pbintcomp(Pint32, Clt), - Pbintcomp(Pint64, Clt)); + Pbintcomp(Pint64, Clt), + false); "%greaterthan", (Pccall{prim_name = "caml_greaterthan"; prim_arity = 2; prim_alloc = true; prim_native_name = ""; prim_native_float = false}, @@ -86,7 +89,8 @@ let comparisons_table = create_hashtable 11 [ prim_native_float = false}, Pbintcomp(Pnativeint, Cgt), Pbintcomp(Pint32, Cgt), - Pbintcomp(Pint64, Cgt)); + Pbintcomp(Pint64, Cgt), + false); "%lessequal", (Pccall{prim_name = "caml_lessequal"; prim_arity = 2; prim_alloc = true; prim_native_name = ""; prim_native_float = false}, @@ -97,7 +101,8 @@ let comparisons_table = create_hashtable 11 [ prim_native_float = false}, Pbintcomp(Pnativeint, Cle), Pbintcomp(Pint32, Cle), - Pbintcomp(Pint64, Cle)); + Pbintcomp(Pint64, Cle), + false); "%greaterequal", (Pccall{prim_name = "caml_greaterequal"; prim_arity = 2; prim_alloc = true; @@ -109,7 +114,8 @@ let comparisons_table = create_hashtable 11 [ prim_native_float = false}, Pbintcomp(Pnativeint, Cge), Pbintcomp(Pint32, Cge), - Pbintcomp(Pint64, Cge)); + Pbintcomp(Pint64, Cge), + false); "%compare", (Pccall{prim_name = "caml_compare"; prim_arity = 2; prim_alloc = true; prim_native_name = ""; prim_native_float = false}, @@ -130,7 +136,8 @@ let comparisons_table = create_hashtable 11 [ prim_native_float = false}, Pccall{prim_name = "caml_int64_compare"; prim_arity = 2; prim_alloc = false; prim_native_name = ""; - prim_native_float = false}) + prim_native_float = false}, + false) ] let primitives_table = create_hashtable 57 [ @@ -262,12 +269,15 @@ let prim_obj_dup = let transl_prim prim args = try let (gencomp, intcomp, floatcomp, stringcomp, - nativeintcomp, int32comp, int64comp) = + nativeintcomp, int32comp, int64comp, + simplify_constant_constructor) = Hashtbl.find comparisons_table prim.prim_name in begin match args with - [arg1; {exp_desc = Texp_construct({cstr_tag = Cstr_constant _}, _)}] -> + [arg1; {exp_desc = Texp_construct({cstr_tag = Cstr_constant _}, _)}] + when simplify_constant_constructor -> intcomp - | [{exp_desc = Texp_construct({cstr_tag = Cstr_constant _}, _)}; arg2] -> + | [{exp_desc = Texp_construct({cstr_tag = Cstr_constant _}, _)}; arg2] + when simplify_constant_constructor -> intcomp | [arg1; arg2] when has_base_type arg1 Predef.path_int || has_base_type arg1 Predef.path_char -> @@ -325,7 +335,7 @@ let make_sequence lam1 lam2 = let simple_prim p = let prim = try - let (gencomp, _, _, _, _, _, _) = + let (gencomp, _, _, _, _, _, _, _) = Hashtbl.find comparisons_table p.prim_name in gencomp with Not_found -> @@ -344,7 +354,7 @@ let () = Transljoin.simple_prim := simple_prim let transl_primitive p = let prim = try - let (gencomp, _, _, _, _, _, _) = + let (gencomp, _, _, _, _, _, _, _) = Hashtbl.find comparisons_table p.prim_name in gencomp with Not_found -> @@ -456,8 +466,8 @@ let rec push_defaults loc bindings pat_expr_list partial = [pat, ({exp_desc = Texp_function(pl,partial)} as exp)] -> let pl = push_defaults exp.exp_loc bindings pl partial in [pat, {exp with exp_desc = Texp_function(pl, partial)}] - | [pat, ({exp_desc = Texp_let - (Default, cases, ({exp_desc = Texp_function _} as e2))} as e1)] -> + | [pat, {exp_desc = Texp_let + (Default, cases, ({exp_desc = Texp_function _} as e2))}] -> push_defaults loc (cases :: bindings) [pat, e2] partial | [pat, exp] -> let exp = @@ -488,7 +498,7 @@ let event_before exp lam = match lam with | Lstaticraise (_,_) -> lam | _ -> if !Clflags.debug - then Levent(lam, {lev_pos = exp.exp_loc.Location.loc_start; + then Levent(lam, {lev_loc = exp.exp_loc; lev_kind = Lev_before; lev_repr = None; lev_env = Env.summary exp.exp_env}) @@ -496,20 +506,18 @@ let event_before exp lam = match lam with let event_after exp lam = if !Clflags.debug - then Levent(lam, {lev_pos = exp.exp_loc.Location.loc_end; + then Levent(lam, {lev_loc = exp.exp_loc; lev_kind = Lev_after exp.exp_type; lev_repr = None; lev_env = Env.summary exp.exp_env}) else lam -let no_event exp lam = lam - let event_function exp lam = if !Clflags.debug then let repr = Some (ref 0) in let (info, body) = lam repr in (info, - Levent(body, {lev_pos = exp.exp_loc.Location.loc_start; + Levent(body, {lev_loc = exp.exp_loc; lev_kind = Lev_function; lev_repr = repr; lev_env = Env.summary exp.exp_env})) @@ -528,13 +536,6 @@ let primitive_is_ccall = function let assert_failed loc = (* [Location.get_pos_info] is too expensive *) - let fname = match loc.Location.loc_start.Lexing.pos_fname with - | "" -> !Location.input_name - | x -> x - in - let pos = loc.Location.loc_start in - let line = pos.Lexing.pos_lnum in - let char = pos.Lexing.pos_cnum - pos.Lexing.pos_bol in Lprim(Praise, [Lprim(Pmakeblock(0, Immutable), [transl_path Predef.path_assert_failure; transl_location loc])]) @@ -545,6 +546,11 @@ let assert_failed loc = let id_lam lam = lam ;; +let rec cut n l = + if n = 0 then ([],l) else + match l with [] -> failwith "Translcore.cut" + | a::l -> let (l1,l2) = cut (n-1) l in (a::l1,l2) + (* Translation of expressions *) let rec transl_exp e = @@ -588,7 +594,6 @@ and transl_exp0 e = | Texp_def (d,body) -> do_transl_def d (transl_exp body) | Texp_loc (d,body) -> assert false -(*< JOCAML *) | Texp_function (pat_expr_list, partial) -> let ((kind, params), body) = event_function e @@ -611,8 +616,13 @@ and transl_exp0 e = Transljoin.local_send_sync auto idx (transl_exp arg) (*<JOCAML*) | Texp_apply({exp_desc = Texp_ident(path, {val_kind = Val_prim p})}, args) - when List.length args = p.prim_arity + when List.length args >= p.prim_arity && List.for_all (fun (arg,_) -> arg <> None) args -> + let args, args' = cut p.prim_arity args in + let wrap f = + event_after e (if args' = [] then f else transl_apply f args') in + let wrap0 f = + if args' = [] then f else wrap f in let args = List.map (function Some x, _ -> x | _ -> assert false) args in let argl = transl_list transl_exp args in let public_send = p.prim_name = "%send" @@ -620,39 +630,38 @@ and transl_exp0 e = if public_send || p.prim_name = "%sendself" then let kind = if public_send then Public else Self in let obj = List.hd argl in - event_after e (Lsend (kind, List.nth argl 1, obj, [])) + wrap (Lsend (kind, List.nth argl 1, obj, [])) else if p.prim_name = "%sendcache" then match argl with [obj; meth; cache; pos] -> - event_after e (Lsend(Cached, meth, obj, [cache; pos])) + wrap (Lsend(Cached, meth, obj, [cache; pos])) | _ -> assert false else begin let prim = transl_prim p args in match (prim, args) with (Praise, [arg1]) -> - Lprim(Praise, [event_after arg1 (List.hd argl)]) + wrap0 (Lprim(Praise, [event_after arg1 (List.hd argl)])) | (_, _) -> - if primitive_is_ccall prim - then event_after e (Lprim(prim, argl)) - else Lprim(prim, argl) + let p = Lprim(prim, argl) in + if primitive_is_ccall prim then wrap p else wrap0 p end | Texp_apply(funct, oargs) -> event_after e (transl_apply (transl_exp funct) oargs) - | Texp_match({exp_desc = Texp_tuple argl} as arg, pat_expr_list, partial) -> + | Texp_match({exp_desc = Texp_tuple argl}, pat_expr_list, partial) -> Matching.for_multiple_match (id_lam,e.exp_loc) (transl_list transl_exp argl) - (transl_cases event_before transl_exp pat_expr_list) partial + (transl_cases transl_exp pat_expr_list) partial | Texp_match(arg, pat_expr_list, partial) -> Matching.for_function (id_lam,e.exp_loc) None (transl_exp arg) - (transl_cases event_before transl_exp pat_expr_list) partial + (transl_cases transl_exp pat_expr_list) partial | Texp_try(body, pat_expr_list) -> let id = name_pattern "exn" pat_expr_list in Ltrywith (transl_exp body, id, Matching.for_trywith (Lvar id) - (transl_cases event_before transl_exp pat_expr_list)) + (transl_cases transl_exp pat_expr_list)) | Texp_tuple el -> let ll = transl_list transl_exp el in begin try @@ -731,11 +740,7 @@ and transl_exp0 e = event_before ifso (transl_exp ifso), lambda_unit) | Texp_sequence(expr1, expr2) -> - let lam1 = transl_exp expr1 in - if lam1 = lambda_unit then - transl_exp expr2 - else - Lsequence(lam1, event_before expr2 (transl_exp expr2)) + Lsequence(transl_exp expr1, event_before expr2 (transl_exp expr2)) | Texp_while(cond, body) -> Lwhile(transl_exp cond, event_before body (transl_exp body)) | Texp_for(param, low, high, dir, body) -> @@ -779,15 +784,15 @@ and transl_exp0 e = else Lifthenelse (transl_exp cond, lambda_unit, assert_failed e.exp_loc) | Texp_assertfalse -> assert_failed e.exp_loc | Texp_lazy e -> - let fn = Lfunction (Curried, [Ident.create "param"], transl_exp e) in - Lprim(Pmakeblock(Config.lazy_tag, Immutable), [fn]) + let fn = Lfunction (Curried, [Ident.create "param"], transl_exp e) in + Lprim(Pmakeblock(Config.lazy_tag, Immutable), [fn]) | Texp_object (cs, cty, meths) -> let cl = Ident.create "class" in !transl_object cl meths - { cl_desc = Tclass_structure cs; - cl_loc = e.exp_loc; - cl_type = Tcty_signature cty; - cl_env = e.exp_env } + { cl_desc = Tclass_structure cs; + cl_loc = e.exp_loc; + cl_type = Tcty_signature cty; + cl_env = e.exp_env } (*> JOCAML *) | Texp_spawn (e) -> transl_spawn e (*< JOCAML *) @@ -832,17 +837,17 @@ and transl_proc die sync p = match p.exp_desc with Lifthenelse (Transljoin.reply_handler sync p transl_exp cond, transl_proc die sync body, staticfail) -| Texp_match({exp_desc = Texp_tuple argl} as arg, pat_expr_list, partial) -> +| Texp_match({exp_desc = Texp_tuple argl}, pat_expr_list, partial) -> Matching.for_multiple_match (Transljoin.lambda_reply_handler sync p, p.exp_loc) (transl_list (Transljoin.reply_handler sync p transl_exp) argl) - (transl_cases no_event (transl_proc die sync) pat_expr_list) partial + (transl_cases (transl_proc die sync) pat_expr_list) partial | Texp_match(arg, pat_expr_list, partial) -> Matching.for_function (Transljoin.lambda_reply_handler sync p, p.exp_loc) None (Transljoin.reply_handler sync p transl_exp arg) - (transl_cases no_event (transl_proc die sync) pat_expr_list) partial + (transl_cases (transl_proc die sync) pat_expr_list) partial | Texp_for(param, low, high, dir, body) -> assert (sync = None) ; let lam_low = transl_exp low @@ -913,15 +918,14 @@ and transl_simple_proc die sync p = match p.exp_desc with | Texp_when(cond, body) -> (Lifthenelse (transl_exp cond, transl_simple_proc die sync body, staticfail)) -| Texp_match({exp_desc = Texp_tuple argl} as arg, pat_expr_list, partial) -> +| Texp_match({exp_desc = Texp_tuple argl}, pat_expr_list, partial) -> Matching.for_multiple_match (id_lam, p.exp_loc) (transl_list transl_exp argl) - (transl_cases no_event - (transl_simple_proc die sync) pat_expr_list) partial + (transl_cases (transl_simple_proc die sync) pat_expr_list) partial | Texp_match(arg, pat_expr_list, partial) -> Matching.for_function (id_lam, p.exp_loc) None (transl_exp arg) - (transl_cases no_event + (transl_cases (transl_simple_proc die sync) pat_expr_list) partial | Texp_for(param, low, high, dir, body) -> assert (sync=None) ; @@ -969,11 +973,6 @@ and transl_simple_proc die sync p = match p.exp_desc with and transl_reaction (name,_) (Reac reac) = let (x, _ , actuals, idpats, p) = reac in -(* - let dump_oid fp = function - | Some id -> Printf.fprintf fp "+%s" (Ident.unique_name id) - | None -> Printf.fprintf fp "-" in -*) (* Principal continuation, as computed by typing *) let sync = Transljoin.principal p in (* Important: argument order comes from actual pattern order, @@ -984,12 +983,6 @@ and transl_reaction (name,_) (Reac reac) = | p::_ -> p | [] -> assert false) actuals in let konts = List.map (fun jp -> !(jp.jpat_kont)) jpats in -(* - - Printf.eprintf "Principal: %a\n" dump_oid sync ; - List.iter (fun k -> dump_oid stderr k) konts ; - prerr_endline "" ; -*) let body = List.fold_right (fun (param, pat) lam -> @@ -1043,7 +1036,10 @@ and transl_dispatcher disp = | [] -> assert false | (auto,_)::_ -> let cls = - List.map (fun (_,(p,i)) -> p,lambda_int i) allchans in + List.map + (fun (_,(p,i)) -> + p,Lconst (Const_base (Const_int i))) + allchans in (if chan.jchannel_sync then Transljoin.local_send_sync2 else @@ -1100,13 +1096,15 @@ and transl_as_seq die es k = match es with make_sequence (transl_simple_proc false None e) (transl_as_seq die rem k) -(*< JOCAML *) -and transl_list comp_fun expr_list = List.map comp_fun expr_list -and transl_cases event_before transl_exp pat_expr_list = +and transl_list transl_exp expr_list = + List.map transl_exp expr_list + +and transl_cases transl_exp pat_expr_list = List.map (fun (pat, expr) -> (pat, event_before expr (transl_exp expr))) pat_expr_list +(*< JOCAML *) and transl_tupled_cases patl_expr_list = List.map (fun (patl, expr) -> (patl, transl_exp expr)) patl_expr_list @@ -1185,13 +1183,13 @@ and transl_function loc untuplify_fn repr partial pat_expr_list = let param = name_pattern "param" pat_expr_list in ((Curried, [param]), Matching.for_function (id_lam,loc) repr (Lvar param) - (transl_cases event_before transl_exp pat_expr_list) partial) + (transl_cases transl_exp pat_expr_list) partial) end | _ -> let param = name_pattern "param" pat_expr_list in ((Curried, [param]), Matching.for_function (id_lam,loc) repr (Lvar param) - (transl_cases event_before transl_exp pat_expr_list) partial) + (transl_cases transl_exp pat_expr_list) partial) and transl_let reply_handler transl_exp rec_flag pat_expr_list body = match rec_flag with @@ -1275,7 +1273,6 @@ and do_transl_def autos body = List.fold_right Transljoin.create_auto autos r in r -(*< JOCAML *) and transl_setinstvar self var expr = Lprim(Parraysetu (if maybe_pointer expr then Paddrarray else Pintarray), diff --git a/bytecomp/transljoin.ml b/bytecomp/transljoin.ml index 23ca1ae455..806db53c43 100644 --- a/bytecomp/transljoin.ml +++ b/bytecomp/transljoin.ml @@ -99,6 +99,9 @@ let mk_apply f args = match Lazy.force f with | path,_ -> Lapply (transl_path path, args) +let lambda_int i = Lconst (Const_base (Const_int i)) +and lambda_string s = Lconst (Const_immstring s) + let init_unit_queue auto idx = mk_apply lambda_init_unit_queue [Lvar auto ; lambda_int idx] @@ -717,7 +720,6 @@ let create_table auto gs r = (fun bd jpat r -> match bd with | None,lam -> lam::r | Some y,_ -> - let k = jpat.jpat_kont in if !(jpat.jpat_kont) = sync then Lprim (Pfield 1, [Lvar y])::r else diff --git a/bytecomp/translmod.ml b/bytecomp/translmod.ml index 1a3113d39c..bc74712f8c 100644 --- a/bytecomp/translmod.ml +++ b/bytecomp/translmod.ml @@ -17,6 +17,7 @@ open Misc open Asttypes +open Longident open Path open Types open Typedtree @@ -95,7 +96,15 @@ let field_path path field = (* Utilities for compiling "module rec" definitions *) -let undefined_exception loc = +let mod_prim name = + try + transl_path + (fst (Env.lookup_value (Ldot (Lident "CamlinternalMod", name)) + Env.empty)) + with Not_found -> + fatal_error ("Primitive " ^ name ^ " not found.") + +let undefined_location loc = (* Confer Translcore.assert_failed *) let fname = match loc.Location.loc_start.Lexing.pos_fname with | "" -> !Location.input_name @@ -103,61 +112,50 @@ let undefined_exception loc = let pos = loc.Location.loc_start in let line = pos.Lexing.pos_lnum in let char = pos.Lexing.pos_cnum - pos.Lexing.pos_bol in - Lprim(Pmakeblock(0, Immutable), - [transl_path Predef.path_undefined_recursive_module; - Lconst(Const_block(0, - [Const_base(Const_string fname); - Const_base(Const_int line); - Const_base(Const_int char)]))]) - -let undefined_function loc = - Lfunction(Curried, [Ident.create "undef"], - Lprim(Praise, [undefined_exception loc])) - -let init_value modl = - let undef_exn_id = Ident.create "undef_exception" in - let undef_function_id = Ident.create "undef_function" in - let rec init_value_mod env mty = + Lconst(Const_block(0, + [Const_base(Const_string fname); + Const_base(Const_int line); + Const_base(Const_int char)])) + +let init_shape modl = + let rec init_shape_mod env mty = match Mtype.scrape env mty with Tmty_ident _ -> raise Not_found | Tmty_signature sg -> - Lprim(Pmakeblock(0, Mutable), init_value_struct env sg) + Const_block(0, [Const_block(0, init_shape_struct env sg)]) | Tmty_functor(id, arg, res) -> - raise Not_found (* to be fixed? *) - and init_value_struct env sg = + raise Not_found (* can we do better? *) + and init_shape_struct env sg = match sg with [] -> [] | Tsig_value(id, vdesc) :: rem -> let init_v = match Ctype.expand_head env vdesc.val_type with {desc = Tarrow(_,_,_,_)} -> - Lvar undef_function_id + Const_pointer 0 (* camlinternalMod.Function *) | {desc = Tconstr(p, _, _)} when Path.same p Predef.path_lazy_t -> - Lprim(Pmakeblock(Config.lazy_tag, Immutable), - [Lvar undef_function_id]) + Const_pointer 1 (* camlinternalMod.Lazy *) | _ -> raise Not_found in - init_v :: init_value_struct env rem + init_v :: init_shape_struct env rem | Tsig_type(id, tdecl, _) :: rem -> - init_value_struct (Env.add_type id tdecl env) rem + init_shape_struct (Env.add_type id tdecl env) rem | Tsig_exception(id, edecl) :: rem -> - transl_exception - id (Some Predef.path_undefined_recursive_module) edecl :: - init_value_struct env rem + raise Not_found | Tsig_module(id, mty, _) :: rem -> - init_value_mod env mty :: - init_value_struct (Env.add_module id mty env) rem + init_shape_mod env mty :: + init_shape_struct (Env.add_module id mty env) rem | Tsig_modtype(id, minfo) :: rem -> - init_value_struct (Env.add_modtype id minfo env) rem + init_shape_struct (Env.add_modtype id minfo env) rem | Tsig_class(id, cdecl, _) :: rem -> - Translclass.dummy_class (Lvar undef_function_id) :: - init_value_struct env rem + Const_pointer 2 (* camlinternalMod.Class *) + :: init_shape_struct env rem | Tsig_cltype(id, ctyp, _) :: rem -> - init_value_struct env rem + init_shape_struct env rem in try - Some(Llet(Alias, undef_function_id, undefined_function modl.mod_loc, - init_value_mod modl.mod_env modl.mod_type)) + Some(undefined_location modl.mod_loc, + Lconst(init_shape_mod modl.mod_env modl.mod_type)) with Not_found -> None @@ -197,35 +195,30 @@ let reorder_rec_bindings bindings = (* Generate lambda-code for a reordered list of bindings *) -let prim_update = - { prim_name = "caml_update_dummy"; - prim_arity = 2; - prim_alloc = true; - prim_native_name = ""; - prim_native_float = false } - let eval_rec_bindings bindings cont = let rec bind_inits = function [] -> bind_strict bindings | (id, None, rhs) :: rem -> bind_inits rem - | (id, Some init, rhs) :: rem -> - Llet(Strict, id, init, bind_inits rem) + | (id, Some(loc, shape), rhs) :: rem -> + Llet(Strict, id, Lapply(mod_prim "init_mod", [loc; shape]), + bind_inits rem) and bind_strict = function [] -> patch_forwards bindings | (id, None, rhs) :: rem -> Llet(Strict, id, rhs, bind_strict rem) - | (id, Some init, rhs) :: rem -> + | (id, Some(loc, shape), rhs) :: rem -> bind_strict rem and patch_forwards = function [] -> cont | (id, None, rhs) :: rem -> patch_forwards rem - | (id, Some init, rhs) :: rem -> - Lsequence(Lprim(Pccall prim_update, [Lvar id; rhs]), patch_forwards rem) + | (id, Some(loc, shape), rhs) :: rem -> + Lsequence(Lapply(mod_prim "update_mod", [shape; Lvar id; rhs]), + patch_forwards rem) in bind_inits bindings @@ -234,7 +227,7 @@ let compile_recmodule compile_rhs bindings cont = (reorder_rec_bindings (List.map (fun (id, modl) -> - (id, modl.mod_loc, init_value modl, compile_rhs id modl)) + (id, modl.mod_loc, init_shape modl, compile_rhs id modl)) bindings)) cont |