浏览代码

handle OpAssignOp for abstract getter + setter combination (fixed issue #1754)

Simon Krajewski 12 年之前
父节点
当前提交
18cbf74fd4
共有 2 个文件被更改,包括 31 次插入1 次删除
  1. 11 0
      tests/unit/MyAbstract.hx
  2. 20 1
      typer.ml

+ 11 - 0
tests/unit/MyAbstract.hx

@@ -128,6 +128,17 @@ class MyPoint3 {
 }
 
 abstract MyVector(MyPoint3) from MyPoint3 to MyPoint3 {
+	var x(get, set):Float;
+	var y(get, set):Float;
+	var z(get, set):Float;
+
+	public function get_x() return this.x;
+	public function get_y() return this.y;
+	public function get_z() return this.z;
+	public function set_x(x) return this.x = x;
+	public function set_y(y) return this.y = y;
+	public function set_z(z) return this.z = z;
+	
 	@:op(A + B) static public inline function add(lhs:MyVector, rhs:MyVector):MyVector {
 		return new MyPoint3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z);
 	}

+ 20 - 1
typer.ml

@@ -1446,6 +1446,25 @@ let rec type_binop ctx op e1 e2 is_assign_op p =
 				mk (TVars [v,Some e]) ctx.t.tvoid p;
 				make_call ctx (mk (TField (ev,FDynamic m)) (tfun [t] t) p) [get] t p
 			]) t p
+ 		| AKUsing(ef,c,cf,et) ->
+ 			(* abstract setter + getter *)
+ 			let ta = match c.cl_kind with KAbstractImpl a -> TAbstract(a, List.map (fun _ -> mk_mono()) a.a_types) | _ -> assert false in
+			let ret = match ef.etype with
+				| TFun([_;_],ret) -> ret
+				| _ ->  error "Invalid field type for abstract setter" p
+			in
+			let l = save_locals ctx in
+			let v = gen_local ctx ta in
+			let ev = mk (TLocal v) ta p in
+			(* this relies on the fact that cf_name is set_name *)
+			let getter_name = String.sub cf.cf_name 4 (String.length cf.cf_name - 4) in
+			let get = type_binop ctx op (EField ((EConst (Ident v.v_name),p),getter_name),p) e2 true p in
+			unify ctx get.etype ret p;
+			l();
+			mk (TBlock [
+				mk (TVars [v,Some et]) ctx.t.tvoid p;
+				make_call ctx ef [ev;get] ret p
+			]) ret p
 		| AKAccess(ebase,ekey) ->
 			let a,pl,c = match follow ebase.etype with TAbstract({a_impl = Some c} as a,pl) -> a,pl,c | _ -> error "Invalid operation" p in
 			let et = type_module_type ctx (TClassDecl c) None p in
@@ -1477,7 +1496,7 @@ let rec type_binop ctx op e1 e2 is_assign_op p =
 					e;
 					make_call ctx ef_set [ebase;ekey;eget] r_set p
 				]) r_set p)
-		| AKInline _ | AKUsing _ | AKMacro _ ->
+		| AKInline _ | AKMacro _ ->
 			assert false)
 	| _ ->
 	let e1 = type_expr ctx e1 Value in