Explorar o código

start working on local type parameters

Simon Krajewski %!s(int64=2) %!d(string=hai) anos
pai
achega
13a3c027f2

+ 35 - 8
src/compiler/hxb/hxbReader.ml

@@ -33,6 +33,7 @@ class hxb_reader
 	val vars = Hashtbl.create 0
 	val mutable type_type_parameters = Array.make 0 (mk_type_param "" t_dynamic None)
 	val mutable field_type_parameters = Array.make 0 (mk_type_param "" t_dynamic None)
+	val mutable local_type_parameters = []
 
 	val mutable tvoid = None
 	method get_tvoid =
@@ -594,6 +595,18 @@ class hxb_reader
 			let i = self#read_uleb128 in
 			(* Printf.eprintf "     Get type type param %d\n" i; *)
 			(type_type_parameters.(i)).ttp_type
+		| 7 ->
+			let k = self#read_uleb128 in
+			let i = self#read_uleb128 in
+			let rec loop left params = match params with
+				| _ :: params when left > 0 ->
+					loop (left - 1) params
+				| params :: _ ->
+					params.(i).ttp_type
+				| _ ->
+					error (Printf.sprintf "Bad index into local params: %i" k)
+			in
+			loop k local_type_parameters
 		| 10 ->
 			TInst(self#read_class_ref,[])
 		| 11 ->
@@ -735,6 +748,7 @@ class hxb_reader
 		let args = self#read_list (fun () -> self#read_tfunction_arg) in
 		let r = self#read_type_instance in
 		let e = self#read_texpr in
+		let args = List.map (fun ((v,close),cto) -> close(); (v,cto)) args in
 		{
 			tf_args = args;
 			tf_type = r;
@@ -757,17 +771,24 @@ class hxb_reader
 			| _ -> assert false
 
 	method read_var =
+		let close = ref (fun () -> ()) in (* TODO: awkward *)
 		let id = IO.read_i32 ch in
 		let name = self#read_string in
-		let t = self#read_type_instance in
-		let kind = self#read_var_kind in
 		let extra = self#read_option (fun () ->
+			let params = ref [] in
+			self#read_type_parameters null_module ([],name) (fun a ->
+				local_type_parameters <- a :: local_type_parameters;
+				params := Array.to_list a;
+				close := (fun () -> local_type_parameters <- List.tl local_type_parameters)
+			);
 			let vexpr = self#read_option (fun () -> self#read_texpr) in
 			{
-				v_params = []; (* TODO *)
+				v_params = !params;
 				v_expr = vexpr;
 			};
 		) in
+		let t = self#read_type_instance in
+		let kind = self#read_var_kind in
 		let flags = IO.read_i32 ch in
 		let meta = self#read_metadata in
 		let pos = self#read_pos in
@@ -782,7 +803,7 @@ class hxb_reader
 			v_flags = flags;
 		} in
 		Hashtbl.add vars id v;
-		v
+		v,!close
 
 	method read_texpr =
 		let t = self#read_type_instance in
@@ -803,10 +824,14 @@ class hxb_reader
 
 			(* vars 20-29 *)
 			| 20 -> TLocal (Hashtbl.find vars (IO.read_i32 ch))
-			| 21 -> TVar (self#read_var,None)
+			| 21 ->
+				let v,close = self#read_var in
+				close();
+				TVar (v,None)
 			| 22 ->
-					let v = self#read_var in
+					let v,close = self#read_var in
 					let e = self#read_texpr in
+					close();
 					TVar (v, Some e)
 
 			(* blocks 30-49 *)
@@ -887,8 +912,9 @@ class hxb_reader
 			| 83 ->
 				let e1 = self#read_texpr in
 				let catches = self#read_list (fun () ->
-					let v = self#read_var in
+					let v,close = self#read_var in
 					let e = self#read_texpr in
+					close();
 					(v,e)
 				) in
 				TTry(e1,catches)
@@ -901,9 +927,10 @@ class hxb_reader
 				let e2 = self#read_texpr in
 				TWhile(e1,e2,DoWhile)
 			| 86 ->
-				let v = self#read_var in
+				let v,close = self#read_var in
 				let e1 = self#read_texpr in
 				let e2 = self#read_texpr in
+				close();
 				TFor(v,e1,e2)
 
 			(* control flow 90-99 *)

+ 40 - 11
src/compiler/hxb/hxbWriter.ml

@@ -229,6 +229,7 @@ class ['a] hxb_writer
 	val mutable ttp_key = None
 	val mutable type_type_parameters = new pool
 	val mutable field_type_parameters = new pool
+	val mutable local_type_parameters = []
 
 	(* Chunks *)
 
@@ -330,10 +331,25 @@ class ['a] hxb_writer
 				let i = type_type_parameters#get (snd c.cl_path) in
 				chunk#write_byte 6;
 				chunk#write_uleb128 i
+			with Not_found -> try
+				let rec loop k l = match l with
+					| [] ->
+						raise Not_found
+					| pool :: l ->
+						begin try
+							let i = pool#get (snd c.cl_path) in
+							chunk#write_byte 7;
+							chunk#write_uleb128 k;
+							chunk#write_uleb128 i
+						with Not_found ->
+							loop (k + 1) l
+						end
+				in
+				loop 0 local_type_parameters
 			with Not_found ->
 				(* error ("Unbound type parameter " ^ (s_type_path c.cl_path)) *)
 				Printf.eprintf "%s Unbound type parameter %s\n" todo_error (s_type_path c.cl_path);
-				chunk#write_byte 0
+				chunk#write_byte 40
 			end
 		| TInst(c,[]) ->
 			chunk#write_byte 10;
@@ -738,19 +754,30 @@ class ['a] hxb_writer
 		in
 		chunk#write_byte b
 
+	method set_local_type_parameters (params : typed_type_param list) =
+		let pool = new pool in
+		local_type_parameters <- pool :: local_type_parameters;
+		List.iter (fun ttp ->
+			ignore(pool#add ttp.ttp_name ttp);
+		) params
+
 	method write_var v =
+		let close = ref (fun () -> ()) in (* TODO: awkward *)
 		chunk#write_i32 v.v_id;
 		chunk#write_string v.v_name;
-		self#write_type_instance v.v_type;
-		self#write_var_kind v.v_kind;
 		chunk#write_option v.v_extra (fun ve ->
-			(* TODO *)
-			(* chunk#write_list ve.v_params self#write_typed_type_param; *)
+			self#set_local_type_parameters ve.v_params;
+			chunk#write_list ve.v_params self#write_type_parameter_forward;
+			chunk#write_list ve.v_params self#write_type_parameter_data;
 			chunk#write_option ve.v_expr self#write_texpr;
+			close := (fun () -> local_type_parameters <- List.tl local_type_parameters)
 		);
+		self#write_type_instance v.v_type;
+		self#write_var_kind v.v_kind;
 		chunk#write_i32 v.v_flags;
 		self#write_metadata v.v_meta;
 		self#write_pos v.v_pos;
+		!close
 
 	method write_texpr (e : texpr) =
 		let rec loop e =
@@ -787,11 +814,12 @@ class ['a] hxb_writer
 				chunk#write_i32 v.v_id;
 			| TVar(v,None) ->
 				chunk#write_byte 21;
-				self#write_var v;
+				self#write_var v ()
 			| TVar(v,Some e1) ->
 				chunk#write_byte 22;
-				self#write_var v;
+				let close = self#write_var v in
 				loop e1;
+				close()
 			(* blocks 30-49 *)
 			| TBlock [] ->
 				chunk#write_byte 30;
@@ -820,8 +848,9 @@ class ['a] hxb_writer
 			| TFunction tf ->
 				chunk#write_byte 50;
 				chunk#write_list tf.tf_args (fun (v,eo) ->
-					self#write_var v;
-					chunk#write_option eo loop
+					let close = self#write_var v in
+					chunk#write_option eo loop;
+					close();
 				);
 				self#write_type_instance tf.tf_type;
 				loop tf.tf_expr;
@@ -877,7 +906,7 @@ class ['a] hxb_writer
 				chunk#write_byte 83;
 				loop e1;
 				chunk#write_list catches  (fun (v,e) ->
-					self#write_var v;
+					self#write_var v ();
 					loop e
 				);
 			| TWhile(e1,e2,flag) ->
@@ -886,7 +915,7 @@ class ['a] hxb_writer
 				loop e2;
 			| TFor(v,e1,e2) ->
 				chunk#write_byte 86;
-				self#write_var v;
+				self#write_var v ();
 				loop e1;
 				loop e2;
 			(* control flow 90-99 *)

+ 6 - 7
tests/unit/src/unit/issues/Issue10124.hx

@@ -30,12 +30,11 @@ class Issue10124 extends Test {
 	}
 
 	function test3() {
-		// function rest<T>(...values:T):Array<T> {
-		// 	return values.toArray();
-		// }
-		// var a = rest(5, 6.2, 7);
-		// aeq([5, 6.2, 7], a);
-		// eq('Array<Float>', HelperMacros.typeString(a));
-		Assert.pass();
+		function rest<T>(...values:T):Array<T> {
+			return values.toArray();
+		}
+		var a = rest(5, 6.2, 7);
+		aeq([5, 6.2, 7], a);
+		eq('Array<Float>', HelperMacros.typeString(a));
 	}
 }

+ 11 - 14
tests/unit/src/unit/issues/Issue2889.hx

@@ -1,16 +1,14 @@
 package unit.issues;
 
 class Issue2889 extends Test {
-	public function test()
-	{
-		// function mapMappable <A,B>(m:Mappable<A>, f:A->B):Mappable<B> {
-		// 	return m.map(f);
-		// }
-		// var r = mapMappable([1], function (y) return y+1);
-		// var r:Array<Int> = cast r;
-		// eq(r.length,1);
-		// eq(2,r[0]);
-		utest.Assert.pass();
+	public function test() {
+		function mapMappable<A, B>(m:Mappable<A>, f:A->B):Mappable<B> {
+			return m.map(f);
+		}
+		var r = mapMappable([1], function(y) return y + 1);
+		var r:Array<Int> = cast r;
+		eq(r.length, 1);
+		eq(2, r[0]);
 	}
 
 	function testDynamic() {
@@ -25,14 +23,14 @@ class Issue2889 extends Test {
 	}
 
 	function testFilterStructure() {
-		var a:{ function filter(f:Int->Bool):Array<Int>; } = [1, 2];
+		var a:{function filter(f:Int->Bool):Array<Int>;} = [1, 2];
 		var b = a.filter(function(x) return x % 2 == 0);
 		eq(1, b.length);
 		eq(2, b[0]);
 	}
 
 	function testMapStructure() {
-		var a:{ function map(f:Int->Int):Array<Int>; } = [1, 2];
+		var a:{function map(f:Int->Int):Array<Int>;} = [1, 2];
 		var b = a.map(function(x) return x * 2);
 		eq(2, b.length);
 		eq(2, b[0]);
@@ -41,6 +39,5 @@ class Issue2889 extends Test {
 }
 
 private typedef Mappable<Y> = {
-	public function map <X>(f:Y->X):Array<X>;
+	public function map<X>(f:Y->X):Array<X>;
 }
-

+ 19 - 20
tests/unit/src/unit/issues/Issue5793.hx

@@ -1,25 +1,24 @@
 package unit.issues;
 
 class Issue5793 extends Test {
-  public function test() {
-    // function run1() {
-    //   function foo <T> (expected:Array<T>, a:T) {
-    //     eq(expected[0], a);
-    //   }
-    //   foo([2], 2);
-    // }
-    // run1();
+	public function test() {
+		function run1() {
+			function foo<T>(expected:Array<T>, a:T) {
+				eq(expected[0], a);
+			}
+			foo([2], 2);
+		}
+		run1();
 
-    // function run2() {
-    //   function bar<A>(expected:Array<A>, a:A) {
-    //     function baz<B>(expected:Array<B>, b:B) {
-    //       eq(expected[0], b);
-    //     }
-    //     baz(expected,a);
-    //   }
-    //   bar([42],42);
-    // }
-    // run2();
-    utest.Assert.pass();
-  }
+		function run2() {
+			function bar<A>(expected:Array<A>, a:A) {
+				function baz<B>(expected:Array<B>, b:B) {
+					eq(expected[0], b);
+				}
+				baz(expected, a);
+			}
+			bar([42], 42);
+		}
+		run2();
+	}
 }

+ 6 - 5
tests/unit/src/unit/issues/Issue6106.hx

@@ -3,12 +3,13 @@ package unit.issues;
 class Issue6106 extends unit.Test {
 	function test() {
 		var code = 0;
-		// function assertEquals<T>(expected:T, actual:T) {
-		// 	if(expected != actual) code++;
-		// }
+		function assertEquals<T>(expected:T, actual:T) {
+			if (expected != actual)
+				code++;
+		}
 
-		// var f = function() assertEquals(1, 1);
-		// f();
+		var f = function() assertEquals(1, 1);
+		f();
 		noAssert();
 	}
 }

+ 8 - 9
tests/unit/src/unit/issues/Issue6304.hx

@@ -2,16 +2,15 @@ package unit.issues;
 
 class Issue6304 extends unit.Test {
 	function test() {
-		// eq(2, main1([], 1));
-		utest.Assert.pass();
+		eq(2, main1([], 1));
 	}
 
-	static function main1 (arr:Array<{}>, multiplier:Int) {
-		// function doSomething <T>() {
-		// 	var mul:Int =  multiplier;
-		// 	arr.push({});
-		// 	return arr.length + mul;
-		// };
-		// return doSomething();
+	static function main1(arr:Array<{}>, multiplier:Int) {
+		function doSomething<T>() {
+			var mul:Int = multiplier;
+			arr.push({});
+			return arr.length + mul;
+		};
+		return doSomething();
 	}
 }

+ 9 - 11
tests/unit/src/unit/issues/Issue6560.hx

@@ -1,15 +1,13 @@
 package unit.issues;
 
 class Issue6560 extends unit.Test {
-
-    function test() {
-        // function foo<F>(a:F):Array<F> {
-        //     if (false) foo(1);
-        //     return if (a == null) [] else foo(null);
-        // }
-        // var bar:Array<Int> = foo(1);
-        // eq(0, bar.length);
-        utest.Assert.pass();
-    }
-
+	function test() {
+		function foo<F>(a:F):Array<F> {
+			if (false)
+				foo(1);
+			return if (a == null) [] else foo(null);
+		}
+		var bar:Array<Int> = foo(1);
+		eq(0, bar.length);
+	}
 }

+ 11 - 8
tests/unit/src/unit/issues/Issue6751.hx

@@ -3,20 +3,23 @@ package unit.issues;
 import unit.HelperMacros.typedAs;
 
 private abstract O(String) {
-	public function new(s) this = s;
-	@:to function toInt() return 42;
+	public function new(s)
+		this = s;
+
+	@:to function toInt()
+		return 42;
 }
 
 private abstract A<T>(T) from T {}
 
 class Issue6751 extends Test {
 	function test() {
-		// function make<T>(o:A<T>) return o;
+		function make<T>(o:A<T>)
+			return o;
 
-		// var o = new O("hello");
-		// var a = make(o);
-		// typedAs(a, (null : A<O>));
-		// eq(Std.string(a), "hello");
-		utest.Assert.pass();
+		var o = new O("hello");
+		var a = make(o);
+		typedAs(a, (null : A<O>));
+		eq(Std.string(a), "hello");
 	}
 }