2
0
Эх сурвалжийг харах

pattern match support for untyped code

Simon Krajewski 12 жил өмнө
parent
commit
96bf01fa5f

+ 8 - 4
matcher.ml

@@ -325,12 +325,15 @@ let to_pattern ctx e t =
 			| _ -> error "Constant expression expected" p)
 		| ((EConst(Ident s),p) as ec) -> (try
 				(* HACK so type_ident via type_field does not cause display errors *)
+				let old = ctx.untyped in
 				ctx.untyped <- true;
 				let tc = monomorphs ctx.type_params t in
 				let ec = try type_expr_with_type ctx ec (Some tc) true with _ -> raise Not_found in
-				ctx.untyped <- false;
+				ctx.untyped <- old;
 				(* we might have found the wrong thing entirely *)
-				(try unify_raise ctx tc ec.etype ec.epos with Error (Unify _,_) -> raise Not_found);
+				(match tc with
+					| TMono _ -> ()
+					| _ -> try unify_raise ctx ec.etype tc ec.epos with Error (Unify _,_) -> raise Not_found);
 				(match ec.eexpr with
 					| TEnumField(en,s)
 					| TField ({ eexpr = TTypeExpr (TEnumDecl en) },s) ->
@@ -338,7 +341,9 @@ let to_pattern ctx e t =
 						unify_enum_field en (List.map (fun _ -> mk_mono()) en.e_types) ef tc;
 						mk_con_pat (CEnum(en,ef)) [] t p
 					| TTypeExpr mt ->
-						mk_con_pat (CType mt) [] t p
+						let tcl = Typeload.load_instance ctx {tname="Class";tpackage=[];tsub=None;tparams=[]} p true in
+						let t2 = match tcl with TAbstract(a,_) -> TAbstract(a,[mk_mono()]) | _ -> assert false in
+						mk_con_pat (CType mt) [] t2 p
 					| _ ->
 						raise Not_found);
 			with Not_found ->
@@ -817,7 +822,6 @@ and to_typed_ast ctx need_val (dt : decision_tree) : texpr =
 
 (* Main match function *)
 let match_expr ctx e cases def need_val with_type p =
-	if ctx.untyped then raise Exit;
 	let cases = match cases,def with
 		| [],None -> error "Empty switch" p
 		| cases,Some def -> cases @ [[(EConst(Ident "_")),pos def],def]

+ 1 - 1
std/haxe/xml/Check.hx

@@ -111,7 +111,7 @@ class Check {
 				var found = false;
 				for( att in attribs )
 					switch( att ) {
-					case Att(name,filter,defvalue):
+					case Att(name,filter,_):
 						if( xatt != name )
 							continue;
 						if( filter != null && !filterMatch(x.get(xatt),filter) )

+ 5 - 5
std/neko/Boot.hx

@@ -70,11 +70,11 @@ class Boot {
 		untyped {
 			if( cl == Dynamic )
 				return true;
-			switch __dollar__typeof(o) {
-			case __dollar__tint: return (cl == Int || cl == Float);
-			case __dollar__tfloat: return cl == Float || (cl == Int && __dollar__int(o) == o);
-			case __dollar__tbool: return cl == Bool;
-			case __dollar__tobject:
+			switch( __dollar__typeof(o) ) {
+			case 1: return (cl == Int || cl == Float);
+			case 2: return cl == Float || (cl == Int && __dollar__int(o) == o);
+			case 3: return cl == Bool;
+			case 5:
 				if( cl == null )
 					return false;
 				return __interfLoop(o.__class__,cl) || ( o.__enum__ == cl ) || (cl == Class && o.__name__ != null) || (cl == Enum && o.__ename__ != null );

+ 12 - 12
std/neko/Lib.hx

@@ -94,17 +94,17 @@ class Lib {
 	**/
 	public static function nekoToHaxe( v : Dynamic ) : Dynamic untyped {
 		switch( __dollar__typeof(v) ) {
-		case __dollar__tnull: return v;
-		case __dollar__tint: return v;
-		case __dollar__tfloat: return v;
-		case __dollar__tbool: return v;
-		case __dollar__tstring: return new String(v);
-		case __dollar__tarray:
+		case 0: return v;
+		case 1: return v;
+		case 2: return v;
+		case 3: return v;
+		case 4: return new String(v);
+		case 6:
 			var a = Array.new1(v,__dollar__asize(v));
 			for( i in 0...a.length )
 				a[i] = nekoToHaxe(a[i]);
 			return a;
-		case __dollar__tobject:
+		case 5:
 			var f = __dollar__objfields(v);
 			var i = 0;
 			var l = __dollar__asize(f);
@@ -126,11 +126,11 @@ class Lib {
 	**/
 	public static function haxeToNeko( v : Dynamic ) : Dynamic untyped {
 		switch( __dollar__typeof(v) ) {
-		case __dollar__tnull: return v;
-		case __dollar__tint: return v;
-		case __dollar__tfloat: return v;
-		case __dollar__tbool: return v;
-		case __dollar__tobject:
+		case 0: return v;
+		case 1: return v;
+		case 2: return v;
+		case 3: return v;
+		case 5:
 			var cl = v.__class__;
 			if( cl == String )
 				return v.__s;

+ 6 - 6
std/neko/_std/Type.hx

@@ -163,12 +163,12 @@ enum ValueType {
 
 	public static function typeof( v : Dynamic ) : ValueType untyped {
 		return switch( __dollar__typeof(v) ) {
-		case __dollar__tnull: TNull;
-		case __dollar__tint: TInt;
-		case __dollar__tfloat: TFloat;
-		case __dollar__tbool: TBool;
-		case __dollar__tfunction: TFunction;
-		case __dollar__tobject:
+		case 0: TNull;
+		case 1: TInt;
+		case 2: TFloat;
+		case 3: TBool;
+		case 7: TFunction;
+		case 5:
 			var c = v.__class__;
 			if( c != null )
 				TClass(c);

+ 17 - 3
tests/unit/TestMatch.hx

@@ -109,7 +109,15 @@ class TestMatch extends Test {
 			case _:
 				"5";
 		}
-	}	
+	}
+	
+	static function switchClass<T>(cl:Class<T>) {
+		return switch(cl) {
+			case String: "String";
+			case haxe.Template: "haxe.Template";
+			case a: "other: " +Type.getClassName(a);
+		}
+	}
 	
 	function testBasic() {
 		eq("bar", switchNormal(macro "bar"));
@@ -202,11 +210,17 @@ class TestMatch extends Test {
 		}
 	}
 	
-	function testGadt () {
+	function testGadt() {
 		eq("<=1", toStringX(U1(1)));
 		eq(">1", toStringX(U1(2)));
 		eq("U2", toStringX(U2));
-	}	
+	}
+	
+	function testClassSwitch() {
+		eq("String", switchClass(String));
+		eq("haxe.Template", switchClass(haxe.Template));
+		eq("other: unit.TestMatch", switchClass(TestMatch));
+	}
 		
 	function testNonExhaustiveness() {
 		eq("This match is not exhaustive, these patterns are not matched: false", getErrorMessage(switch(true) {