summaryrefslogtreecommitdiff
path: root/bytecomp/matching.ml
diff options
context:
space:
mode:
Diffstat (limited to 'bytecomp/matching.ml')
-rw-r--r--bytecomp/matching.ml262
1 files changed, 0 insertions, 262 deletions
diff --git a/bytecomp/matching.ml b/bytecomp/matching.ml
deleted file mode 100644
index d2367cf139..0000000000
--- a/bytecomp/matching.ml
+++ /dev/null
@@ -1,262 +0,0 @@
-(* Compilation of pattern matching *)
-
-open Location
-open Asttypes
-open Typedtree
-open Lambda
-
-
-(* See Peyton-Jones, "The Implementation of functional programming
- languages", chapter 5. *)
-
-type pattern_matching =
- { mutable cases : (pattern list * lambda) list;
- args : lambda list }
-
-(* To group lines of patterns with identical keys *)
-
-let add_line patl_action pm =
- pm.cases <- patl_action :: pm.cases; pm
-
-let add make_matching_fun division key patl_action args =
- try
- let pm = List.assoc key division in
- pm.cases <- patl_action :: pm.cases;
- division
- with Not_found ->
- let pm = make_matching_fun args in
- pm.cases <- patl_action :: pm.cases;
- (key, pm) :: division
-
-(* To expand "or" patterns and remove aliases *)
-
-let rec simplify = function
- ({pat_desc = Tpat_alias(p, id)} :: patl, action) :: rem ->
- simplify((p :: patl, action) :: rem)
- | ({pat_desc = Tpat_or(p1, p2)} :: patl, action) :: rem ->
- let shared_action = share_lambda action in
- simplify((p1 :: patl, shared_action) ::
- (p2 :: patl, shared_action) :: rem)
- | cases ->
- cases
-
-(* Matching against a constant *)
-
-let make_constant_matching (arg :: argl) =
- {cases = []; args = argl}
-
-let divide_constant {cases = cl; args = al} =
- let rec divide cl =
- match simplify cl with
- ({pat_desc = Tpat_constant cst} :: patl, action) :: rem ->
- let (constants, others) = divide rem in
- (add make_constant_matching constants cst (patl, action) al, others)
- | cl ->
- ([], {cases = cl; args = al})
- in divide cl
-
-(* Matching against a constructor *)
-
-let make_constr_matching cstr (arg :: argl) =
- let (first_pos, last_pos) =
- match cstr.cstr_tag with
- Cstr_tag _ -> (0, cstr.cstr_arity - 1)
- | Cstr_exception _ -> (1, cstr.cstr_arity) in
- let rec make_args pos =
- if pos > last_pos
- then argl
- else Lprim(Pfield pos, [arg]) :: make_args (pos + 1) in
- {cases = []; args = make_args first_pos}
-
-let divide_constructor {cases = cl; args = al} =
- let rec divide cl =
- match simplify cl with
- ({pat_desc = Tpat_construct(cstr, args)} :: patl, action) :: rem ->
- let (constructs, others) = divide rem in
- (add (make_constr_matching cstr) constructs
- cstr.cstr_tag (args @ patl, action) al,
- others)
- | cl ->
- ([], {cases = cl; args = al})
- in divide cl
-
-(* Matching against a variable *)
-
-let divide_var {cases = cl; args = al} =
- let rec divide cl =
- match simplify cl with
- ({pat_desc = (Tpat_any | Tpat_var _)} :: patl, action) :: rem ->
- let (vars, others) = divide rem in
- (add_line (patl, action) vars, others)
- | cl ->
- (make_constant_matching al, {cases = cl; args = al})
- in divide cl
-
-(* Matching against a tuple pattern *)
-
-let make_tuple_matching num_comps (arg :: argl) =
- let rec make_args pos =
- if pos >= num_comps
- then argl
- else Lprim(Pfield pos, [arg]) :: make_args (pos + 1) in
- {cases = []; args = make_args 0}
-
-let any_pat =
- {pat_desc = Tpat_any; pat_loc = Location.none; pat_type = Ctype.none}
-
-let divide_tuple arity {cases = cl; args = al} =
- let rec divide cl =
- match simplify cl with
- ({pat_desc = Tpat_tuple args} :: patl, action) :: rem ->
- add_line (args @ patl, action) (divide rem)
- | ({pat_desc = (Tpat_any | Tpat_var _)} :: patl, action) :: rem ->
- let rec make_args n =
- if n >= arity then patl else any_pat :: make_args (n+1) in
- add_line (make_args 0, action) (divide rem)
- | [] ->
- make_tuple_matching arity al
- in divide cl
-
-(* Matching against a record pattern *)
-
-let divide_record num_fields {cases = cl; args = al} =
- let record_matching_line lbl_pat_list =
- let patv = Array.new num_fields any_pat in
- List.iter (fun (lbl, pat) -> patv.(lbl.lbl_pos) <- pat) lbl_pat_list;
- Array.to_list patv in
- let rec divide cl =
- match simplify cl with
- ({pat_desc = Tpat_record lbl_pat_list} :: patl, action) :: rem ->
- add_line (record_matching_line lbl_pat_list @ patl, action)
- (divide rem)
- | ({pat_desc = (Tpat_any | Tpat_var _)} :: patl, action) :: rem ->
- add_line (record_matching_line [] @ patl, action) (divide rem)
- | [] ->
- make_tuple_matching num_fields al
- in divide cl
-
-(* To List.combine sub-matchings together *)
-
-let combine_var (lambda1, total1) (lambda2, total2) =
- if total1 then (lambda1, true) else (Lcatch(lambda1, lambda2), total2)
-
-let combine_constant arg cst (const_lambda_list, total1) (lambda2, total2) =
- let lambda1 =
- match cst with
- Const_int _ ->
- List.fold_right
- (fun (c, act) rem ->
- Lifthenelse(
- Lprim(Pcomp Ceq, [arg; Lconst(Const_base c)]), act, rem))
- const_lambda_list Lstaticfail
- | Const_char _ ->
- Lswitch(arg, 0, 256,
- List.map (fun (Const_char c, l) -> (Char.code c, l))
- const_lambda_list)
- | Const_string _ | Const_float _ ->
- List.fold_right
- (fun (c, act) rem ->
- Lifthenelse(
- Lprim(Pccall("equal", 2), [arg; Lconst(Const_base c)]),
- act, rem))
- const_lambda_list Lstaticfail
- in (Lcatch(lambda1, lambda2), total2)
-
-let combine_constructor arg cstr (tag_lambda_list, total1) (lambda2, total2) =
- if cstr.cstr_span < 0 then begin
- (* Special cases for exceptions *)
- let lambda1 =
- List.fold_right
- (fun (Cstr_exception path, act) rem ->
- Lifthenelse(Lprim(Pcomp Ceq, [Lprim(Pfield 0, [arg]);
- transl_path path]), act, rem))
- tag_lambda_list Lstaticfail
- in (Lcatch(lambda1, lambda2), total2)
- end else begin
- (* Regular concrete type *)
- let caselist =
- List.map (function (Cstr_tag n, act) -> (n, act)) tag_lambda_list in
- let lambda1 =
- match (caselist, cstr.cstr_span) with
- ([0, act], 1) -> act
- | ([0, act], 2) -> Lifthenelse(arg, Lstaticfail, act)
- | ([1, act], 2) -> Lifthenelse(arg, act, Lstaticfail)
- | ([0, act0; 1, act1], 2) -> Lifthenelse(arg, act1, act0)
- | ([1, act1; 0, act0], 2) -> Lifthenelse(arg, act1, act0)
- | _ ->
- if cstr.cstr_span < Config.max_tag
- then Lswitch(Lprim(Ptagof, [arg]), 0, cstr.cstr_span, caselist)
- else Lswitch(Lprim(Pfield 0, [arg]), 0, cstr.cstr_span, caselist) in
- if total1 & List.length tag_lambda_list = cstr.cstr_span
- then (lambda1, true)
- else (Lcatch(lambda1, lambda2), total2)
- end
-
-(* The main compilation function.
- Input: a pattern matching.
- Output: a lambda term, a "total" flag (true if we're sure that the
- matching covers all cases; this is an approximation). *)
-
-let rec compile_match m =
-
- let rec compile_list = function
- [] -> ([], true)
- | (key, pm) :: rem ->
- let (lambda1, total1) = compile_match pm in
- let (list2, total2) = compile_list rem in
- ((key, lambda1) :: list2, total1 & total2) in
-
- match { cases = simplify m.cases; args = m.args } with
- { cases = [] } ->
- (Lstaticfail, false)
- | { cases = ([], action) :: rem; args = argl } ->
- if is_guarded action then begin
- let (lambda, total) = compile_match { cases = rem; args = argl } in
- (Lcatch(action, lambda), total)
- end else
- (action, true)
- | { cases = (pat :: patl, action) :: _; args = arg :: _ } as pm ->
- match pat.pat_desc with
- Tpat_any | Tpat_var _ ->
- let (vars, others) = divide_var pm in
- combine_var (compile_match vars) (compile_match others)
- | Tpat_constant cst ->
- let (constants, others) = divide_constant pm in
- combine_constant arg cst
- (compile_list constants) (compile_match others)
- | Tpat_tuple patl ->
- compile_match (divide_tuple (List.length patl) pm)
- | Tpat_construct(cstr, patl) ->
- let (constrs, others) = divide_constructor pm in
- combine_constructor arg cstr
- (compile_list constrs) (compile_match others)
- | Tpat_record((lbl, _) :: _) ->
- compile_match (divide_record (Array.length lbl.lbl_all) pm)
-
-(* The entry points *)
-
-let compile_matching handler_fun arg pat_act_list =
- let pm =
- { cases = List.map (fun (pat, act) -> ([pat], act)) pat_act_list;
- args = [arg] } in
- let (lambda, total) = compile_match pm in
- if total then lambda else Lcatch(lambda, handler_fun())
-
-let partial_function loc () =
- Lprim(Praise, [Lprim(Pmakeblock 0,
- [transl_path Predef.path_match_failure;
- Lconst(Const_block(0,
- [Const_base(Const_string !Location.input_name);
- Const_base(Const_int loc.loc_start);
- Const_base(Const_int loc.loc_end)]))])])
-
-let for_function loc param pat_act_list =
- compile_matching (partial_function loc) (Lvar param) pat_act_list
-
-let for_trywith param pat_act_list =
- compile_matching (fun () -> Lprim(Praise, [Lvar param]))
- (Lvar param) pat_act_list
-
-let for_let loc param pat body =
- compile_matching (partial_function loc) (Lvar param) [pat, body]
-