浏览代码

@:generic abstract is now @:multiType abstract, also improved error messages on invalid type parameters

Simon Krajewski 12 年之前
父节点
当前提交
aa841a131e
共有 5 个文件被更改,包括 28 次插入21 次删除
  1. 2 0
      ast.ml
  2. 9 4
      codegen.ml
  3. 11 11
      std/Map.hx
  4. 5 5
      typeload.ml
  5. 1 1
      typer.ml

+ 2 - 0
ast.ml

@@ -83,6 +83,7 @@ module Meta = struct
 		| Meta
 		| Macro
 		| MaybeUsed
+		| MultiType
 		| Native
 		| NativeGen
 		| NativeGeneric
@@ -189,6 +190,7 @@ module Meta = struct
 		| Meta -> ":meta"
 		| Macro -> ":macro"
 		| MaybeUsed -> ":maybeUsed"
+		| MultiType -> ":multiType"
 		| Native -> ":native"
 		| NativeGen -> ":nativeGen"
 		| NativeGeneric -> ":nativeGeneric"

+ 9 - 4
codegen.ml

@@ -1366,13 +1366,13 @@ let handle_abstract_casts ctx e =
 		| TBinop(OpAssign,e1,e2) ->
 			let e2 = check_cast e1.etype e2 e.epos in
 			{ e with eexpr = TBinop(OpAssign,loop e1,e2) }
-		| TLocal v when (match follow v.v_type with TAbstract(a,_) -> Meta.has Meta.Generic a.a_meta | _ -> false) ->
+		| TLocal v when (match follow v.v_type with TAbstract(a,_) -> Meta.has Meta.MultiType a.a_meta | _ -> false) ->
 			{e with etype = v.v_type}
 		| TVars vl ->
 			let vl = List.map (fun (v,eo) -> match eo with
 				| None -> (v,eo)
 				| Some e ->
-					let is_generic_abstract = match e.etype with TAbstract ({a_impl = Some _} as a,_) -> Meta.has Meta.Generic a.a_meta | _ -> false in
+					let is_generic_abstract = match e.etype with TAbstract ({a_impl = Some _} as a,_) -> Meta.has Meta.MultiType a.a_meta | _ -> false in
 					let e = check_cast v.v_type e e.epos in
 					(* we can rewrite this for better field inference *)
 					if is_generic_abstract then v.v_type <- e.etype;
@@ -1385,7 +1385,12 @@ let handle_abstract_casts ctx e =
 			let m = mk_mono() in
 			let _,cfo =
 				try find_to a pl at m
-				with Not_found -> error ("Could not determine type for " ^ (s_type (print_context()) at)) e.epos
+				with Not_found ->
+					let st = s_type (print_context()) at in
+					if has_mono at then
+						error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") e.epos
+					else
+						error ("Abstract " ^ (s_type_path a.a_path) ^ " has no @:to function that accepts " ^ st) e.epos;
 			in
 			begin match cfo with
 			| None -> assert false
@@ -1400,7 +1405,7 @@ let handle_abstract_casts ctx e =
 				begin match e1.eexpr with
 					| TField(e2,fa) ->
 						begin match follow e2.etype with
-							| TAbstract(a,pl) when Meta.has Meta.Generic a.a_meta ->
+							| TAbstract(a,pl) when Meta.has Meta.MultiType a.a_meta ->
 								let at = apply_params a.a_types pl a.a_this in
 								let m = mk_mono() in
 								let _ = find_to a pl at m in

+ 11 - 11
std/Map.hx

@@ -1,13 +1,4 @@
-typedef IMap < K, V > = {
-	public function get(k:K):V;
-	public function set(k:K, v:V):Void;
-	public function exists(k:K):Null<V>;
-	public function remove(k:K):Bool;
-	public function keys():Iterator<K>;
-	public function iterator():Iterator<V>;
-}
-
-@:generic
+@:multiType
 abstract Map(IMap < K, V > )<K,V> {
 	public function new();
 
@@ -29,4 +20,13 @@ abstract Map(IMap < K, V > )<K,V> {
 	public inline function remove(k:K) return this.remove(k)
 	public inline function keys() return this.keys()
 	public inline function iterator() return this.iterator()
-}
+}
+
+private typedef IMap < K, V > = {
+	public function get(k:K):V;
+	public function set(k:K, v:V):Void;
+	public function exists(k:K):Null<V>;
+	public function remove(k:K):Bool;
+	public function keys():Iterator<K>;
+	public function iterator():Iterator<V>;
+}

+ 5 - 5
typeload.ml

@@ -131,14 +131,14 @@ let make_module ctx mpath file tdecls loadp =
 					| FFun fu when f.cff_name = "new" && not stat ->
 						let init p = (EVars ["this",Some this_t,None],p) in
 						let ret p = (EReturn (Some (EConst (Ident "this"),p)),p) in
-						if Meta.has Meta.Generic a.a_meta then begin
-							if List.mem AInline f.cff_access then error "Generic constructors cannot be inline" f.cff_pos;
-							if fu.f_expr <> None then error "Generic constructors cannot have a body" f.cff_pos;
+						if Meta.has Meta.MultiType a.a_meta then begin
+							if List.mem AInline f.cff_access then error "MultiType constructors cannot be inline" f.cff_pos;
+							if fu.f_expr <> None then error "MultiType constructors cannot have a body" f.cff_pos;
 						end;
 						let fu = {
 							fu with
 							f_expr = (match fu.f_expr with
-							| None -> if Meta.has Meta.Generic a.a_meta then Some (EConst (Ident "null"),p) else None
+							| None -> if Meta.has Meta.MultiType a.a_meta then Some (EConst (Ident "null"),p) else None
 							| Some (EBlock [EBinop (OpAssign,(EConst (Ident "this"),_),e),_],_ | EBinop (OpAssign,(EConst (Ident "this"),_),e),_) ->
 								Some (EReturn (Some e), pos e)
 							| Some (EBlock el,p) -> Some (EBlock (init p :: el @ [ret p]),p)
@@ -1371,7 +1371,7 @@ let init_class ctx c p context_init herits fields =
 						unify ctx t (tfun [ta] m) f.cff_pos;
 						if not (Meta.has Meta.Impl cf.cf_meta) then cf.cf_meta <- (Meta.Impl,[],cf.cf_pos) :: cf.cf_meta;
 						a.a_to <- (follow m, Some cf) :: a.a_to
-					end else if f.cff_name = "_new" && Meta.has Meta.Generic a.a_meta then
+					end else if f.cff_name = "_new" && Meta.has Meta.MultiType a.a_meta then
 						do_bind := false
 					else (try match Meta.get Meta.Op cf.cf_meta with
 						| _,[EBinop(op,_,_),_],_ ->

+ 1 - 1
typer.ml

@@ -2421,7 +2421,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 				error "Constructor is not a function" p
 			) in
 			(match c.cl_kind with
-			| KAbstractImpl a when not (Meta.has Meta.Generic a.a_meta) ->
+			| KAbstractImpl a when not (Meta.has Meta.MultiType a.a_meta) ->
 				let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
 				let e = mk (TTypeExpr (TClassDecl c)) ta p in
 				let e = mk (TField (e,(FStatic (c,f)))) ct p in