|
@@ -23,6 +23,7 @@ type pat_def =
|
|
| PCon of con * pat list
|
|
| PCon of con * pat list
|
|
| POr of pat * pat
|
|
| POr of pat * pat
|
|
| PBind of tvar * pat
|
|
| PBind of tvar * pat
|
|
|
|
+ | PTuple of pat array
|
|
|
|
|
|
and pat = {
|
|
and pat = {
|
|
p_def : pat_def;
|
|
p_def : pat_def;
|
|
@@ -142,6 +143,8 @@ let mk_any t p = {
|
|
|
|
|
|
let any = mk_any t_dynamic Ast.null_pos
|
|
let any = mk_any t_dynamic Ast.null_pos
|
|
|
|
|
|
|
|
+let fake_tuple_type = TInst(mk_class null_module ([],"-Tuple") null_pos, [])
|
|
|
|
+
|
|
let mk_subs st con = match con.c_def with
|
|
let mk_subs st con = match con.c_def with
|
|
| CFields (_,fl) -> List.map (fun (s,cf) -> mk_st (SField(st,s)) cf.cf_type st.st_pos) fl
|
|
| CFields (_,fl) -> List.map (fun (s,cf) -> mk_st (SField(st,s)) cf.cf_type st.st_pos) fl
|
|
| CEnum (en,({ef_type = TFun _} as ef)) ->
|
|
| CEnum (en,({ef_type = TFun _} as ef)) ->
|
|
@@ -161,6 +164,10 @@ let mk_subs st con = match con.c_def with
|
|
| CEnum _ | CConst _ | CType _ | CExpr _ ->
|
|
| CEnum _ | CConst _ | CType _ | CExpr _ ->
|
|
[]
|
|
[]
|
|
|
|
|
|
|
|
+let get_tuple_types t = match t with
|
|
|
|
+ | TFun(tl,tr) when tr == fake_tuple_type -> Some tl
|
|
|
|
+ | _ -> None
|
|
|
|
+
|
|
(* Printing *)
|
|
(* Printing *)
|
|
|
|
|
|
let s_type = s_type (print_context())
|
|
let s_type = s_type (print_context())
|
|
@@ -187,6 +194,7 @@ let rec s_pat pat = match pat.p_def with
|
|
| POr (pat1,pat2) -> s_pat pat1 ^ " | " ^ s_pat pat2
|
|
| POr (pat1,pat2) -> s_pat pat1 ^ " | " ^ s_pat pat2
|
|
| PAny -> "_"
|
|
| PAny -> "_"
|
|
| PBind(v,pat) -> v.v_name ^ "=" ^ s_pat pat
|
|
| PBind(v,pat) -> v.v_name ^ "=" ^ s_pat pat
|
|
|
|
+ | PTuple pl -> String.concat " " (Array.to_list (Array.map s_pat pl))
|
|
|
|
|
|
let st_args l r v =
|
|
let st_args l r v =
|
|
(if l > 0 then (String.concat "," (ExtList.List.make l "_")) ^ "," else "")
|
|
(if l > 0 then (String.concat "," (ExtList.List.make l "_")) ^ "," else "")
|
|
@@ -336,7 +344,17 @@ let to_pattern ctx e t =
|
|
mk_con_pat (CEnum(en,ef)) (loop2 0 el tl) t p
|
|
mk_con_pat (CEnum(en,ef)) (loop2 0 el tl) t p
|
|
| _ -> perror p)
|
|
| _ -> perror p)
|
|
| EConst(Ident "_") ->
|
|
| EConst(Ident "_") ->
|
|
- mk_any t p
|
|
|
|
|
|
+ begin match get_tuple_types t with
|
|
|
|
+ | Some tl ->
|
|
|
|
+ let pl = List.map (fun (_,_,t) -> mk_any t p) tl in
|
|
|
|
+ {
|
|
|
|
+ p_def = PTuple (Array.of_list pl);
|
|
|
|
+ p_pos = p;
|
|
|
|
+ p_type = t_dynamic;
|
|
|
|
+ }
|
|
|
|
+ | None ->
|
|
|
|
+ mk_any t p
|
|
|
|
+ end
|
|
| EConst(Ident s) ->
|
|
| EConst(Ident s) ->
|
|
begin try
|
|
begin try
|
|
let tc = monomorphs ctx.type_params (t) in
|
|
let tc = monomorphs ctx.type_params (t) in
|
|
@@ -374,8 +392,13 @@ let to_pattern ctx e t =
|
|
raise Not_found);
|
|
raise Not_found);
|
|
with Not_found ->
|
|
with Not_found ->
|
|
if not (is_lower_ident s) then error "Capture variables must be lower-case" p;
|
|
if not (is_lower_ident s) then error "Capture variables must be lower-case" p;
|
|
- let v = mk_var pctx s t p in
|
|
|
|
- mk_pat (PVar v) v.v_type p
|
|
|
|
|
|
+ begin match get_tuple_types t with
|
|
|
|
+ | Some _ ->
|
|
|
|
+ error "Cannot bind tuple" p
|
|
|
|
+ | None ->
|
|
|
|
+ let v = mk_var pctx s t p in
|
|
|
|
+ mk_pat (PVar v) v.v_type p
|
|
|
|
+ end
|
|
end
|
|
end
|
|
| (EObjectDecl fl) ->
|
|
| (EObjectDecl fl) ->
|
|
begin match follow t with
|
|
begin match follow t with
|
|
@@ -404,6 +427,17 @@ let to_pattern ctx e t =
|
|
loop pctx e t2
|
|
loop pctx e t2
|
|
) el in
|
|
) el in
|
|
mk_con_pat (CArray (List.length el)) pl t p
|
|
mk_con_pat (CArray (List.length el)) pl t p
|
|
|
|
+ | TFun(tl,tr) when tr == fake_tuple_type ->
|
|
|
|
+ let pl = try
|
|
|
|
+ List.map2 (fun e (_,_,t) -> loop pctx e t) el tl
|
|
|
|
+ with Invalid_argument _ ->
|
|
|
|
+ error ("Invalid number of arguments: expected " ^ (string_of_int (List.length tl)) ^ ", found " ^ (string_of_int (List.length el))) p
|
|
|
|
+ in
|
|
|
|
+ {
|
|
|
|
+ p_def = PTuple (Array.of_list pl);
|
|
|
|
+ p_pos = p;
|
|
|
|
+ p_type = t_dynamic;
|
|
|
|
+ }
|
|
| _ ->
|
|
| _ ->
|
|
error ((s_type t) ^ " should be Array") p
|
|
error ((s_type t) ^ " should be Array") p
|
|
end
|
|
end
|
|
@@ -421,14 +455,14 @@ let to_pattern ctx e t =
|
|
ctx.com.warning "This pattern is unused" (pos e2);
|
|
ctx.com.warning "This pattern is unused" (pos e2);
|
|
pat1
|
|
pat1
|
|
| _ ->
|
|
| _ ->
|
|
- let pctx2 = {
|
|
|
|
- pc_sub_vars = Some pctx.pc_locals;
|
|
|
|
- pc_locals = old;
|
|
|
|
- } in
|
|
|
|
- let pat2 = loop pctx2 e2 t in
|
|
|
|
- PMap.iter (fun s (_,p) -> if not (PMap.mem s pctx2.pc_locals) then verror s p) pctx.pc_locals;
|
|
|
|
- unify ctx pat1.p_type pat2.p_type pat1.p_pos;
|
|
|
|
- mk_pat (POr(pat1,pat2)) pat2.p_type (punion pat1.p_pos pat2.p_pos);
|
|
|
|
|
|
+ let pctx2 = {
|
|
|
|
+ pc_sub_vars = Some pctx.pc_locals;
|
|
|
|
+ pc_locals = old;
|
|
|
|
+ } in
|
|
|
|
+ let pat2 = loop pctx2 e2 t in
|
|
|
|
+ PMap.iter (fun s (_,p) -> if not (PMap.mem s pctx2.pc_locals) then verror s p) pctx.pc_locals;
|
|
|
|
+ unify ctx pat1.p_type pat2.p_type pat1.p_pos;
|
|
|
|
+ mk_pat (POr(pat1,pat2)) pat2.p_type (punion pat1.p_pos pat2.p_pos);
|
|
end
|
|
end
|
|
| _ ->
|
|
| _ ->
|
|
error "Unrecognized pattern" p;
|
|
error "Unrecognized pattern" p;
|
|
@@ -487,6 +521,8 @@ let spec mctx con pmat =
|
|
loop2 (Array.append [|pat2|] tl) out2;
|
|
loop2 (Array.append [|pat2|] tl) out2;
|
|
| PBind(_,pat) ->
|
|
| PBind(_,pat) ->
|
|
loop2 (Array.append [|pat|] (array_tl pv)) out
|
|
loop2 (Array.append [|pat|] (array_tl pv)) out
|
|
|
|
+ | PTuple tl ->
|
|
|
|
+ loop2 tl out
|
|
in
|
|
in
|
|
let rec loop pmat = match pmat with
|
|
let rec loop pmat = match pmat with
|
|
| (pv,out) :: pl ->
|
|
| (pv,out) :: pl ->
|
|
@@ -514,6 +550,8 @@ let default mctx pmat =
|
|
loop2 (Array.append [|pat2|] tl) out;
|
|
loop2 (Array.append [|pat2|] tl) out;
|
|
| PBind(_,pat) ->
|
|
| PBind(_,pat) ->
|
|
loop2 (Array.append [|pat|] (array_tl pv)) out
|
|
loop2 (Array.append [|pat|] (array_tl pv)) out
|
|
|
|
+ | PTuple tl ->
|
|
|
|
+ loop2 tl out
|
|
in
|
|
in
|
|
let rec loop pmat = match pmat with
|
|
let rec loop pmat = match pmat with
|
|
| (pv,out) :: pl ->
|
|
| (pv,out) :: pl ->
|
|
@@ -581,6 +619,8 @@ let column_sigma mctx st pmat =
|
|
loop2 pat.p_def
|
|
loop2 pat.p_def
|
|
| PAny ->
|
|
| PAny ->
|
|
()
|
|
()
|
|
|
|
+ | PTuple tl ->
|
|
|
|
+ loop ((tl,out) :: pr)
|
|
in
|
|
in
|
|
loop2 pv.(0).p_def;
|
|
loop2 pv.(0).p_def;
|
|
loop pr
|
|
loop pr
|
|
@@ -671,6 +711,8 @@ let rec compile mctx stl pmat = match pmat with
|
|
end
|
|
end
|
|
| _ ->
|
|
| _ ->
|
|
assert false)
|
|
assert false)
|
|
|
|
+ | ([|{p_def = PTuple pt}|],out) :: pl ->
|
|
|
|
+ compile mctx stl ((pt,out) :: pl)
|
|
| (pv,out) :: pl ->
|
|
| (pv,out) :: pl ->
|
|
let i = pick_column pmat in
|
|
let i = pick_column pmat in
|
|
if i = -1 then begin
|
|
if i = -1 then begin
|
|
@@ -918,6 +960,7 @@ let match_expr ctx e cases def with_type p =
|
|
let st = loop e in
|
|
let st = loop e in
|
|
if a = 1 then st else mk_st (STuple(st,i,a)) st.st_type st.st_pos
|
|
if a = 1 then st else mk_st (STuple(st,i,a)) st.st_type st.st_pos
|
|
) evals in
|
|
) evals in
|
|
|
|
+ let tl = List.map (fun st -> st.st_type) stl in
|
|
let mctx = {
|
|
let mctx = {
|
|
ctx = ctx;
|
|
ctx = ctx;
|
|
stl = stl;
|
|
stl = stl;
|
|
@@ -936,21 +979,9 @@ let match_expr ctx e cases def with_type p =
|
|
let pl = List.map (fun (el,eg,e) ->
|
|
let pl = List.map (fun (el,eg,e) ->
|
|
let ep = collapse_case el in
|
|
let ep = collapse_case el in
|
|
let save = save_locals ctx in
|
|
let save = save_locals ctx in
|
|
- let pl = match fst ep,stl with
|
|
|
|
- | (EArrayDecl el | (EParenthesis(EArrayDecl el,_))),[st] when (match follow st.st_type with TInst({cl_path=[],"Array"},[_]) -> true | _ -> false) ->
|
|
|
|
- [add_pattern_locals (to_pattern ctx ep st.st_type)]
|
|
|
|
- | (EArrayDecl el | (EParenthesis(EArrayDecl el,_))),stl ->
|
|
|
|
- begin try
|
|
|
|
- List.map2 (fun e st -> add_pattern_locals (to_pattern ctx e st.st_type)) el stl
|
|
|
|
- with Invalid_argument _ ->
|
|
|
|
- error ("Invalid number of arguments: expected " ^ (string_of_int (List.length stl)) ^ ", found " ^ (string_of_int (List.length el))) (pos ep)
|
|
|
|
- end
|
|
|
|
- | _,[st] ->
|
|
|
|
- [add_pattern_locals (to_pattern ctx ep st.st_type)]
|
|
|
|
- | EConst(Ident "_"),stl ->
|
|
|
|
- List.map (fun st -> mk_any st.st_type st.st_pos) stl
|
|
|
|
- | _,_ ->
|
|
|
|
- error "Unrecognized pattern" (pos ep);
|
|
|
|
|
|
+ let pl = match tl with
|
|
|
|
+ | [t] -> [add_pattern_locals (to_pattern ctx ep t)]
|
|
|
|
+ | tl -> [add_pattern_locals (to_pattern ctx ep (tfun tl fake_tuple_type))]
|
|
in
|
|
in
|
|
let e = match e with
|
|
let e = match e with
|
|
| None -> mk (TBlock []) ctx.com.basic.tvoid (punion_el el)
|
|
| None -> mk (TBlock []) ctx.com.basic.tvoid (punion_el el)
|