Pārlūkot izejas kodu

group Array cases

Simon Krajewski 12 gadi atpakaļ
vecāks
revīzija
d2c24321e5
1 mainītis faili ar 42 papildinājumiem un 38 dzēšanām
  1. 42 38
      matcher.ml

+ 42 - 38
matcher.ml

@@ -840,6 +840,40 @@ let rec to_typed_ast mctx dt =
 		| TInst({cl_path = [],"Array"},[t]) -> to_array_switch mctx t st cases
 		| t -> to_value_switch mctx t st cases
 
+and group_cases mctx cases to_case =
+	let def = ref None in
+	let is_compatible out1 out2 =
+		out1.o_id = out2.o_id
+		&& out1.o_guard = None
+		&& (out1.o_bindings = []
+			|| (List.length out1.o_bindings) = (List.length out2.o_bindings)
+			&& (ExtList.List.for_all2 (fun ((v1,_),st1) ((v2,_),st2) -> v1.v_name = v2.v_name && (s_st st1) = (s_st st2)) out1.o_bindings out2.o_bindings))
+	in
+	let group,cases,dto = List.fold_left (fun (group,cases,dto) (con,dt) -> match con.c_def with
+		| CConst TNull ->
+			let e = to_typed_ast mctx dt in
+			def := Some e;
+			(group,cases,dto)
+		| _ -> match dto with
+			| None -> ([to_case con],cases,Some dt)
+			| Some dt2 -> match dt,dt2 with
+				| Bind(out1,_),Bind(out2,_) when is_compatible out1 out2 ->
+					((to_case con) :: group,cases,dto)
+				| _ ->
+					let e = to_typed_ast mctx dt2 in
+					([to_case con],(List.rev group,e) :: cases, Some dt)
+	) ([],[],None) cases in
+	let cases = List.rev (match group,dto with
+		| [],None ->
+			cases
+		| group,Some dt ->
+			let e = to_typed_ast mctx dt in
+			(List.rev group,e) :: cases
+		| _ ->
+			assert false
+	) in
+	cases,def
+
 and to_enum_switch mctx en pl st cases =
 	let eval = st_to_texpr mctx st in
 	let et = monomorphs mctx.ctx.type_params (TEnum(en,pl)) in
@@ -875,7 +909,6 @@ and to_enum_switch mctx en pl st cases =
 
 and to_value_switch mctx t st cases =
 	let eval = st_to_texpr mctx st in
-	let def = ref None in
 	let to_case con = match con.c_def with
 		| CConst c ->
 			mk_const mctx.ctx con.c_pos c
@@ -886,48 +919,19 @@ and to_value_switch mctx t st cases =
 		| _ ->
 			error ("Unexpected "  ^ (s_con con)) con.c_pos
 	in
-	let group,cases,dto = List.fold_left (fun (group,cases,dto) (con,dt) -> match con.c_def with
-		| CConst TNull ->
-			let e = to_typed_ast mctx dt in
-			def := Some e;
-			(group,cases,dto)
-		| _ -> match dto with
-			| None -> ([to_case con],cases,Some dt)
-			| Some dt2 -> match dt,dt2 with
-				| Bind(out1,_),Bind(out2,_) when out1.o_id = out2.o_id && out1.o_guard = None ->
-					((to_case con) :: group,cases,dto)
-				| _ ->
-					let e = to_typed_ast mctx dt2 in
-					([to_case con],(List.rev group,e) :: cases, Some dt)
-	) ([],[],None) cases in
-	let cases = List.rev (match group,dto with
-		| [],None ->
-			cases
-		| group,Some dt ->
-			let e = to_typed_ast mctx dt in
-			(List.rev group,e) :: cases
-		| _ ->
-			assert false
-	) in
+	let cases,def = group_cases mctx cases to_case in
 	mk (TSwitch(eval,cases,!def)) mctx.out_type eval.epos
 
 and to_array_switch mctx t st cases =
-	let def = ref None in
-	let rec loop cases = match cases with
-		| [] ->
-			[]
-		| ({c_def = CArray i} as con,dt) :: cases ->
-			let e = to_typed_ast mctx dt in
-			([mk_const mctx.ctx con.c_pos (TInt (Int32.of_int i))],e) :: loop cases
-		| ({c_def = CConst TNull},dt) :: cases ->
-			let e = to_typed_ast mctx dt in
-			def := Some e;
-			loop cases
-		| (con,_) :: _ ->
+	let to_case con = match con.c_def with
+		| CArray i ->
+			mk_const mctx.ctx con.c_pos (TInt (Int32.of_int i))
+		| _ ->
 			error ("Unexpected "  ^ (s_con con)) con.c_pos
 	in
-	let cases = loop cases in
-	let eval = mk (TField(st_to_texpr mctx st,FDynamic "length")) mctx.ctx.com.basic.tint st.st_pos in
+	let cases,def = group_cases mctx cases to_case in
+	let eval = st_to_texpr mctx st in
+	let eval = mk (TField(eval,quick_field eval.etype "length")) mctx.ctx.com.basic.tint st.st_pos in
 	mk (TSwitch(eval,cases,!def)) mctx.out_type eval.epos
 
 (* Main *)