Browse Source

changed is_const to make_const to allow transformations such as inline (fixed issue #926)

Simon Krajewski 13 years ago
parent
commit
c739e34b26
3 changed files with 40 additions and 11 deletions
  1. 7 0
      tests/unit/MyClass.hx
  2. 12 3
      tests/unit/TestType.hx
  3. 21 8
      typeload.ml

+ 7 - 0
tests/unit/MyClass.hx

@@ -100,6 +100,13 @@ class InitBase {
 	public var s = "foo";
 	public var b = true;
 	public var t = String;
+	
+	static public inline var si = 2;
+	static public inline var sop = 2 + 5 * 5;
+	static public inline var st = String;
+	static public inline var sp = (2 * 3);
+	static public inline var sinline = DateTools.minutes(1);
+	
 	public function new() { }
 }
 

+ 12 - 3
tests/unit/TestType.hx

@@ -422,9 +422,9 @@ class TestType extends Test {
 		eq(ParamConstraintsClass.staticSingle(b), b);
 		eq(ParamConstraintsClass.staticSingle(c1), c1);
 		// TODO: these should fail (param is constrained to Base)
-		ParamConstraintsClass.staticSingle(u);
-		ParamConstraintsClass.staticSingle(1);
-		ParamConstraintsClass.staticSingle("foo");
+		//ParamConstraintsClass.staticSingle(u);
+		//ParamConstraintsClass.staticSingle(1);
+		//ParamConstraintsClass.staticSingle("foo");
 		
 		eq(pcc.memberSingle(b), b);
 		eq(pcc.memberSingle(c1), c1);
@@ -469,4 +469,13 @@ class TestType extends Test {
 		eq(UsingChild2.test(), "FOO");
 		eq(UsingUnrelated.test(), "FOOFOO");
 	}
+	
+	function testInlineInit()
+	{
+		eq(InitBase.si, 2);
+		eq(InitBase.sop, 27);
+		eq(InitBase.sp, 6);
+		eq(InitBase.st, String);
+		eq(InitBase.sinline, 60000.);
+	}
 }

+ 21 - 8
typeload.ml

@@ -945,16 +945,29 @@ let init_class ctx c p herits fields =
 					let e = type_var_field ctx t e stat p in
 					let e = (match cf.cf_kind with
 					| Var v when not stat || (v.v_read = AccInline && Common.defined ctx.com "haxe3") ->
-						let e = ctx.g.do_optimize ctx e in
-						let rec is_const e =
+						let rec make_const e =
+							let e = ctx.g.do_optimize ctx e in
 							match e.eexpr with
-							| TConst _ -> true
-							| TBinop ((OpAdd|OpSub|OpMult|OpDiv|OpMod),e1,e2) -> is_const e1 && is_const e2
-							| TParenthesis e -> is_const e
-							| TTypeExpr e -> true
-							| _ -> false
+							| TConst _ -> Some e
+							| TBinop ((OpAdd|OpSub|OpMult|OpDiv|OpMod) as op,e1,e2) -> (match make_const e1,make_const e2 with
+								| Some e1, Some e2 -> Some (mk (TBinop(op, e1, e2)) e.etype e.epos)
+								| _ -> None)
+							| TParenthesis e -> Some e
+							| TTypeExpr _ -> Some e
+							(* try to inline static function calls *)
+							| TCall ({ etype = TFun(_,ret); eexpr = TField ({ eexpr = TTypeExpr (TClassDecl c) },n) },el) ->
+								(try
+									let cf = PMap.find n c.cl_statics in
+									let func = match cf.cf_expr with Some ({eexpr = TFunction func}) -> func | _ -> raise Not_found in
+									let ethis = mk (TConst TThis) t_dynamic e.epos in
+									let inl = (try Optimizer.type_inline ctx cf func ethis el ret e.epos false with Error (Custom _,_) -> None) in
+									(match inl with
+									| None -> None
+									| Some e -> make_const e)
+								with Not_found -> None)
+							| _ -> None
 						in
-						if not (is_const e) then display_error ctx "Variable initialization must be a constant value" p;
+						let e = match make_const e with Some e -> e | None -> display_error ctx "Variable initialization must be a constant value" p; e in
 						e
 					| _ ->
 						e