Parcourir la source

added abstract types basic support (still keep old StdTypes until we fix bugs and test completely)

Nicolas Cannasse il y a 13 ans
Parent
commit
d6fb3fa088
21 fichiers modifiés avec 272 ajouts et 64 suppressions
  1. 8 0
      ast.ml
  2. 11 0
      codegen.ml
  3. 13 1
      genas3.ml
  4. 4 2
      gencpp.ml
  5. 2 1
      genjs.ml
  6. 4 4
      genneko.ml
  7. 21 9
      genphp.ml
  8. 4 0
      genswf.ml
  9. 3 1
      genswf8.ml
  10. 12 8
      genswf9.ml
  11. 23 11
      genxml.ml
  12. 12 3
      interp.ml
  13. 1 1
      lexer.mll
  14. 6 3
      optimizer.ml
  15. 16 1
      parser.ml
  16. 4 0
      std/haxe/macro/Type.hx
  17. 0 2
      std/neko/_std/Std.hx
  18. 3 8
      tests/unit/TestReflect.hx
  19. 51 1
      type.ml
  20. 34 2
      typeload.ml
  21. 40 6
      typer.ml

+ 8 - 0
ast.ml

@@ -65,6 +65,7 @@ type keyword =
 	| Null
 	| True
 	| False
+	| Abstract
 
 type binop =
 	| OpAdd
@@ -239,6 +240,11 @@ type class_flag =
 	| HExtends of type_path
 	| HImplements of type_path
 
+type abstract_flag =
+	| APrivAbstract
+	| ASubType of complex_type
+	| ASuperType of complex_type
+
 type enum_constructor = string * documentation * metadata * (string * bool * complex_type) list * pos
 
 type ('a,'b) definition = {
@@ -254,6 +260,7 @@ type type_def =
 	| EClass of (class_flag, class_field list) definition
 	| EEnum of (enum_flag, enum_constructor list) definition
 	| ETypedef of (enum_flag, complex_type) definition
+	| EAbstract of (abstract_flag, unit) definition
 	| EImport of type_path
 	| EUsing of type_path
 
@@ -368,6 +375,7 @@ let s_keyword = function
 	| Null -> "null"
 	| True -> "true"
 	| False -> "false"
+	| Abstract -> "abstract"
 
 let rec s_binop = function
 	| OpAdd -> "+"

+ 11 - 0
codegen.ml

@@ -221,6 +221,7 @@ let make_generic ctx ps pt p =
 			let path = (match follow t with		
 				| TInst (ct,_) -> ct.cl_path
 				| TEnum (e,_) -> e.e_path
+				| TAbstract (a,_) when has_meta ":runtime_value" a.a_meta -> a.a_path
 				| TMono _ -> raise (Generic_Exception (("Could not determine type for parameter " ^ s), p))
 				| t -> raise (Generic_Exception (("Type parameter must be a class or enum instance (found " ^ (s_type (print_context()) t) ^ ")"), p))
 			) in
@@ -300,6 +301,7 @@ let rec build_generic ctx c p tl =
 			| TInst (c,tl) -> add_dep c.cl_module tl
 			| TEnum (e,tl) -> add_dep e.e_module tl
 			| TType (t,tl) -> add_dep t.t_module tl
+			| TAbstract (a,tl) -> add_dep a.a_module tl
 			| TMono r ->
 				(match !r with
 				| None -> ()
@@ -418,6 +420,8 @@ let build_metadata com t =
 			(e.e_pos, ["",e.e_meta],List.map (fun n -> n, (PMap.find n e.e_constrs).ef_meta) e.e_names, [])
 		| TTypeDecl t ->
 			(t.t_pos, ["",t.t_meta],(match follow t.t_type with TAnon a -> PMap.fold (fun f acc -> (f.cf_name,f.cf_meta) :: acc) a.a_fields [] | _ -> []),[])
+		| TAbstractDecl a ->
+			(a.a_pos, ["",a.a_meta],[],[])
 	) in
 	let filter l =
 		let l = List.map (fun (n,ml) -> n, List.filter (fun (m,_,_) -> m.[0] <> ':') ml) l in
@@ -505,6 +509,8 @@ let build_instance ctx mtype p =
 		e.e_types , e.e_path , (fun t -> TEnum (e,t))
 	| TTypeDecl t ->
 		t.t_types , t.t_path , (fun tl -> TType(t,tl))
+	| TAbstractDecl a ->
+		a.a_types, a.a_path, (fun tl -> TAbstract(a,tl))
 
 let on_inherit ctx c p h =
 	match h with
@@ -1075,6 +1081,7 @@ let rename_local_vars com e =
 		| TInst (c,_) -> check (TClassDecl c)
 		| TEnum (e,_) -> check (TEnumDecl e)
 		| TType (t,_) -> check (TTypeDecl t)
+		| TAbstract (a,_) -> check (TAbstractDecl a)
 		| TMono _ | TLazy _ | TAnon _ | TDynamic _ | TFun _ -> ()
 	in
 	let rec loop e =
@@ -1276,6 +1283,7 @@ let post_process filters t =
 			c.cl_init <- Some (List.fold_left (fun e f -> f e) e filters));
 	| TEnumDecl _ -> ()
 	| TTypeDecl _ -> ()
+	| TAbstractDecl _ -> ()
 
 let post_process_end() =
 	incr pp_counter
@@ -1602,6 +1610,8 @@ let dump_types com =
 			print "}"
 		| Type.TTypeDecl t ->
 			print "%stype %s%s = %s" (if t.t_private then "private " else "") (s_type_path path) (params t.t_types) (s_type t.t_type);
+		| Type.TAbstractDecl a ->
+			print "%sabstract %s%s {}" (if a.a_private then "private " else "") (s_type_path path) (params a.a_types);
 		);
 		close();
 	) com.types
@@ -1638,6 +1648,7 @@ let default_cast ?(vtmp="$t") com e texpr t p =
 	let mk_texpr = function
 		| TClassDecl c -> TAnon { a_fields = PMap.empty; a_status = ref (Statics c) }
 		| TEnumDecl e -> TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) }
+		| TAbstractDecl a -> TAnon { a_fields = PMap.empty; a_status = ref (AbstractStatics a) }
 		| TTypeDecl _ -> assert false
 	in
 	let vtmp = alloc_var vtmp e.etype in

+ 13 - 1
genas3.ml

@@ -207,6 +207,14 @@ let rec type_str ctx t p =
 	match t with
 	| TEnum _ | TInst _ when List.memq t ctx.local_types ->
 		"*"
+	| TAbstract (a,_) ->
+		(match a.a_path with
+		| [], "Void" -> "void"
+		| [], "UInt" -> "uint"
+		| [], "Int" -> "int"
+		| [], "Float" -> "Number"
+		| [], "Bool" -> "Boolean"
+		| _ -> s_path ctx true a.a_path p)
 	| TEnum (e,_) ->
 		if e.e_extern then (match e.e_path with
 			| [], "Void" -> "void"
@@ -243,6 +251,10 @@ let rec type_str ctx t p =
 			(match args with
 			| [t] ->
 				(match follow t with
+				| TAbstract ({ a_path = [],"UInt" },_)
+				| TAbstract ({ a_path = [],"Int" },_)
+				| TAbstract ({ a_path = [],"Float" },_)
+				| TAbstract ({ a_path = [],"Bool" },_)
 				| TInst ({ cl_path = [],"Int" },_)
 				| TInst ({ cl_path = [],"Float" },_)
 				| TEnum ({ e_path = [],"Bool" },_) -> "*"
@@ -1204,7 +1216,7 @@ let generate com =
 				let ctx = init infos e.e_path in
 				generate_enum ctx e;
 				close ctx
-		| TTypeDecl t ->
+		| TTypeDecl _ | TAbstractDecl _ ->
 			()
 	) com.types;
 	(match com.main with

+ 4 - 2
gencpp.ml

@@ -403,6 +403,8 @@ and type_string_suff suffix haxe_type =
       *)
 	| TDynamic haxe_type -> "Dynamic" ^ suffix
 	| TLazy func -> type_string_suff suffix ((!func)())
+	| TAbstract (abs,pl) ->
+		"::" ^ (join_class_path abs.a_path "::") ^ suffix
 	)
 and type_string haxe_type =
 	type_string_suff "" haxe_type
@@ -2119,7 +2121,7 @@ let find_referenced_types ctx obj super_deps constructor_deps header_only =
 	| TClassDecl class_def -> visit_class class_def;
 		(match class_def.cl_init with Some expression -> visit_types expression | _ -> ())
 	| TEnumDecl enum_def -> visit_enum enum_def
-	| TTypeDecl _ -> (* These are expanded *) ());
+	| TTypeDecl _ | TAbstractDecl _ -> (* These are expanded *) ());
 
 	List.sort inc_cmp (List.filter (fun path -> (include_class_header path) ) (pmap_keys !types))
 	;;
@@ -3146,7 +3148,7 @@ let generate common_ctx =
 				let deps = generate_enum_files common_ctx enum_def super_deps meta file_info in
 				exe_classes := (enum_def.e_path, deps) :: !exe_classes;
 			end
-		| TTypeDecl _ -> (* already done *) ()
+		| TTypeDecl _ | TAbstractDecl _ -> (* already done *) ()
 		);
 	) common_ctx.types;
 

+ 2 - 1
genjs.ml

@@ -586,6 +586,7 @@ and gen_expr ctx e =
 			let t = (match follow v.v_type with
 			| TEnum (e,_) -> Some (TEnumDecl e)
 			| TInst (c,_) -> Some (TClassDecl c)
+			| TAbstract (a,_) -> Some (TAbstractDecl a)
 			| TFun _
 			| TLazy _
 			| TType _
@@ -1071,7 +1072,7 @@ let generate_type ctx = function
 	| TEnumDecl e when e.e_extern ->
 		()
 	| TEnumDecl e -> generate_enum ctx e
-	| TTypeDecl _ -> ()
+	| TTypeDecl _ | TAbstractDecl _ -> ()
 
 let set_current_class ctx c =
 	ctx.current <- c

+ 4 - 4
genneko.ml

@@ -610,12 +610,12 @@ let gen_type ctx t acc =
 			acc
 		else
 			gen_enum ctx e :: acc
-	| TTypeDecl t ->
+	| TTypeDecl _ | TAbstractDecl _ ->
 		acc
 
 let gen_static_vars ctx t =
 	match t with
-	| TEnumDecl _ | TTypeDecl _ -> []
+	| TEnumDecl _ | TTypeDecl _ | TAbstractDecl _ -> []
 	| TClassDecl c ->
 		if c.cl_extern then
 			[]
@@ -643,7 +643,7 @@ let gen_package ctx t =
 		| x :: l ->
 			let path = acc @ [x] in
 			if not (Hashtbl.mem ctx.packages path) then begin
-				let p = pos ctx (match t with TClassDecl c -> c.cl_pos | TEnumDecl e -> e.e_pos | TTypeDecl t -> t.t_pos) in
+				let p = pos ctx (t_infos t).mt_pos in
 				let e = (EBinop ("=",gen_type_path p (acc,x),call p (builtin p "new") [null p]),p) in
 				Hashtbl.add ctx.packages path ();
 				(match acc with
@@ -698,7 +698,7 @@ let gen_name ctx acc t =
 			| l ->
 				let interf = field p (gen_type_path p c.cl_path) "__interfaces__" in
 				(EBinop ("=",interf, call p (field p (ident p "Array") "new1") [interf; int p (List.length l)]),p) :: acc)
-	| TTypeDecl _ ->
+	| TTypeDecl _ | TAbstractDecl _ ->
 		acc
 
 let generate_libs_init = function

+ 21 - 9
genphp.ml

@@ -104,12 +104,17 @@ let rec class_string klass suffix params =
 and type_string_suff suffix haxe_type =
 	(match haxe_type with
 	| TMono r -> (match !r with None -> "Dynamic" | Some t -> type_string_suff suffix t)
+	| TAbstract ({ a_path = [],"Int" },[]) -> "int"
+	| TAbstract ({ a_path = [],"Float" },[]) -> "double"
+	| TAbstract ({ a_path = [],"Bool" },[]) -> "bool"
+	| TAbstract ({ a_path = [],"Void" },[]) -> "Void"
 	| TEnum ({ e_path = ([],"Void") },[]) -> "Void"
 	| TEnum ({ e_path = ([],"Bool") },[]) -> "bool"
 	| TInst ({ cl_path = ([],"Float") },[]) -> "double"
 	| TInst ({ cl_path = ([],"Int") },[]) -> "int"
 	| TEnum (enum,params) ->  (join_class_path enum.e_path "::") ^ suffix
 	| TInst (klass,params) ->  (class_string klass suffix params)
+	| TAbstract (abs,params) ->  (join_class_path abs.a_path "::") ^ suffix
 	| TType (type_def,params) ->
 		(match type_def.t_path with
 		| [] , "Null" ->
@@ -1497,20 +1502,26 @@ and gen_expr ctx e =
 			let b = save_locals ctx in
 			if not !first then spr ctx "else ";
 			(match follow v.v_type with
-			| TEnum (te,_) -> (match snd te.e_path with
-				| "Bool"   -> print ctx "if(is_bool($%s = $%s))" ev evar
+			| TEnum (te,_) -> (match te.e_path with
+				| [], "Bool"   -> print ctx "if(is_bool($%s = $%s))" ev evar
 				| _ -> print ctx "if(($%s = $%s) instanceof %s)" ev evar (s_path ctx te.e_path te.e_extern e.epos));
 				restore_in_block ctx in_block;
 				gen_expr ctx (mk_block e);
-			| TInst (tc,_) -> (match snd tc.cl_path with
-				| "Int"	-> print ctx "if(is_int($%s = $%s))"		ev evar
-				| "Float"  -> print ctx "if(is_numeric($%s = $%s))"	ev evar
-				| "String" -> print ctx "if(is_string($%s = $%s))"	ev evar
-				| "Array"  -> print ctx "if(($%s = $%s) instanceof _hx_array)"	ev evar
+			| TInst (tc,_) -> (match tc.cl_path with
+				| [], "Int"	-> print ctx "if(is_int($%s = $%s))"		ev evar
+				| [], "Float"  -> print ctx "if(is_numeric($%s = $%s))"	ev evar
+				| [], "String" -> print ctx "if(is_string($%s = $%s))"	ev evar
+				| [], "Array"  -> print ctx "if(($%s = $%s) instanceof _hx_array)"	ev evar
 				| _ -> print ctx "if(($%s = $%s) instanceof %s)"    ev evar (s_path ctx tc.cl_path tc.cl_extern e.epos));
 				restore_in_block ctx in_block;
 				gen_expr ctx (mk_block e);
-
+			| TAbstract (ta,_) -> (match ta.a_path with
+				| [], "Int"	-> print ctx "if(is_int($%s = $%s))"		ev evar
+				| [], "Float"  -> print ctx "if(is_numeric($%s = $%s))"	ev evar
+				| [], "Bool"   -> print ctx "if(is_bool($%s = $%s))" ev evar
+				| _ -> print ctx "if(($%s = $%s) instanceof %s)"    ev evar (s_path ctx ta.a_path false e.epos));
+				restore_in_block ctx in_block;
+				gen_expr ctx (mk_block e);
 			| TFun _
 			| TLazy _
 			| TType _
@@ -1622,6 +1633,7 @@ and gen_expr ctx e =
 		let mk_texpr = function
 			| TClassDecl c -> TAnon { a_fields = PMap.empty; a_status = ref (Statics c) }
 			| TEnumDecl e -> TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) }
+			| TAbstractDecl a -> TAnon { a_fields = PMap.empty; a_status = ref (AbstractStatics a) }
 			| TTypeDecl _ -> assert false
 		in
 		spr ctx "_hx_cast(";
@@ -2324,7 +2336,7 @@ let generate com =
 				let ctx = init com php_lib_path e.e_path 1 in
 			generate_enum ctx e;
 			close ctx
-		| TTypeDecl t ->
+		| TTypeDecl _ | TAbstractDecl _ ->
 			());
 	) com.types;
 	(match com.main with

+ 4 - 0
genswf.ml

@@ -647,6 +647,9 @@ let build_dependencies t =
 		| TInst (c,pl) ->
 			add_path c.cl_path DKType;
 			List.iter (add_type_rec (t::l)) pl;
+		| TAbstract (a,pl) ->
+			add_path a.a_path DKType;
+			List.iter (add_type_rec (t::l)) pl;
 		| TFun (pl,t2) ->
 			List.iter (fun (_,_,t2) -> add_type_rec (t::l) t2) pl;
 			add_type_rec (t::l) t2;
@@ -1101,6 +1104,7 @@ let generate com swf_header =
 						let extern = (match t with
 							| TClassDecl c -> c.cl_extern
 							| TEnumDecl e -> e.e_extern
+							| TAbstractDecl a -> false
 							| TTypeDecl t -> false
 						) in
 						if not extern && s_type_path (t_path t) = e.f9_classname then

+ 3 - 1
genswf8.ml

@@ -629,6 +629,7 @@ let rec gen_access ?(read_write=false) ctx forcall e =
 		(match t with
 		| TClassDecl c -> gen_path ctx c.cl_path c.cl_extern
 		| TEnumDecl e -> gen_path ctx e.e_path false
+		| TAbstractDecl a -> gen_path ctx a.a_path false
 		| TTypeDecl _ -> assert false)
 	| _ ->
 		if not forcall then invalid_expr e.epos;
@@ -658,6 +659,7 @@ and gen_try_catch ctx retval e catchs =
 		else let t = (match follow v.v_type with
 			| TEnum (e,_) -> Some (TEnumDecl e)
 			| TInst (c,_) -> Some (TClassDecl c)
+			| TAbstract (a,_) -> Some (TAbstractDecl a)
 			| TFun _
 			| TLazy _
 			| TType _
@@ -1438,7 +1440,7 @@ let gen_type_def ctx t =
 			write ctx AObjSet;
 		);
 		PMap.iter (fun _ f -> gen_enum_field ctx e f) e.e_constrs
-	| TTypeDecl _ ->
+	| TTypeDecl _ | TAbstractDecl _ ->
 		()
 
 let gen_boot ctx =

+ 12 - 8
genswf9.ml

@@ -183,6 +183,10 @@ let rec follow_basic t =
 		(match follow_basic tp with
 		| TMono _
 		| TFun _
+		| TAbstract ({ a_path = ([],"Int") },[])
+		| TAbstract ({ a_path = ([],"Float") },[])
+		| TAbstract ({ a_path = [],"UInt" },[])
+		| TAbstract ({ a_path = ([],"Bool") },[])
 		| TInst ({ cl_path = (["haxe"],"Int32") },[])
 		| TInst ({ cl_path = ([],"Int") },[])
 		| TInst ({ cl_path = ([],"Float") },[])
@@ -241,13 +245,13 @@ let type_void ctx t =
 
 let classify ctx t =
 	match follow_basic t with
-	| TInst ({ cl_path = [],"Int" },_) | TInst ({ cl_path = ["haxe"],"Int32" },_) ->
+	| TAbstract ({ a_path = [],"Int" },_) | TInst ({ cl_path = [],"Int" },_) | TInst ({ cl_path = ["haxe"],"Int32" },_) ->
 		KInt
-	| TInst ({ cl_path = [],"Float" },_) ->
+	| TAbstract ({ a_path = [],"Float" },_) | TInst ({ cl_path = [],"Float" },_) ->
 		KFloat
-	| TEnum ({ e_path = [],"Bool" },_) ->
+	| TAbstract ({ a_path = [],"Bool" },_) | TEnum ({ e_path = [],"Bool" },_) ->
 		KBool
-	| TEnum ({ e_path = [],"Void" },_) ->
+	| TAbstract ({ a_path = [],"Void" },_) | TEnum ({ e_path = [],"Void" },_) ->
 		KDynamic
 	| TEnum ({ e_path = [],"XmlType"; e_extern = true },_) ->
 		KType (HMPath ([],"String"))
@@ -263,9 +267,7 @@ let classify ctx t =
 			| _ :: l -> loop l
 		in
 		loop e.e_meta
-	| TInst _ ->
-		KType (type_id ctx t)
-	| TType ({ t_path = [],"UInt" },_) ->
+	| TAbstract ({ a_path = [],"UInt" },_) | TType ({ t_path = [],"UInt" },_) ->
 		KUInt
 	| TFun _ | TType ({ t_path = ["flash";"utils"],"Function" },[]) ->
 		KType (HMPath ([],"Function"))
@@ -275,6 +277,8 @@ let classify ctx t =
 		| _ -> KDynamic)
 	| TType ({ t_path = ["flash";"utils"],"Object" },[]) ->
 		KType (HMPath ([],"Object"))
+	| TInst _ | TAbstract _ ->
+		KType (type_id ctx t)
 	| TMono _
 	| TType _
 	| TDynamic _ ->
@@ -2307,7 +2311,7 @@ let generate_type ctx t =
 				hlf_kind = HFClass hlc;
 				hlf_metas = extract_meta e.e_meta;
 			})
-	| TTypeDecl _ ->
+	| TTypeDecl _ | TAbstractDecl _ ->
 		None
 
 let resource_path name =

+ 23 - 11
genxml.ml

@@ -62,11 +62,9 @@ let real_path path meta =
 	in
 	loop meta
 
-let cpath c =
-	real_path c.cl_path c.cl_meta
-
-let epath e =
-	real_path e.e_path e.e_meta
+let tpath t =
+	let i = t_infos t in
+	real_path i.mt_path i.mt_meta
 
 let rec follow_param t =
 	match t with
@@ -100,14 +98,19 @@ let gen_meta meta =
 let rec gen_type t =
 	match t with
 	| TMono m -> (match !m with None -> tag "unknown" | Some t -> gen_type t)
-	| TEnum (e,params) -> node "e" [gen_path (epath e) e.e_private] (List.map gen_type params)
-	| TInst (c,params) -> node "c" [gen_path (cpath c) c.cl_private] (List.map gen_type params)
-	| TType (t,params) -> node "t" [gen_path t.t_path t.t_private] (List.map gen_type params)
+	| TEnum (e,params) -> gen_type_decl "e" (TEnumDecl e) params
+	| TInst (c,params) -> gen_type_decl "c" (TClassDecl c) params
+	| TAbstract (a,params) -> gen_type_decl "x" (TAbstractDecl a) params
+	| TType (t,params) -> gen_type_decl "t" (TTypeDecl t) params
 	| TFun (args,r) -> node "f" ["a",String.concat ":" (List.map gen_arg_name args)] (List.map gen_type (List.map (fun (_,opt,t) -> if opt then follow_param t else t) args @ [r]))
 	| TAnon a -> node "a" [] (pmap (fun f -> gen_field [] { f with cf_public = false }) a.a_fields)
 	| TDynamic t2 -> node "d" [] (if t == t2 then [] else [gen_type t2])
 	| TLazy f -> gen_type (!f())
 
+and gen_type_decl n t pl =
+	let i = t_infos t in
+	node n [gen_path (tpath t) i.mt_private] (List.map gen_type pl)
+
 and gen_field att f =
 	let add_get_set acc name att =
 		match acc with
@@ -146,7 +149,7 @@ let gen_type_params ipos priv path params pos m =
 	gen_path path priv :: ("params", String.concat ":" (List.map fst params)) :: (file @ mpriv @ mpath)
 
 let gen_class_path name (c,pl) =
-	node name [("path",s_type_path (cpath c))] (List.map gen_type pl)
+	node name [("path",s_type_path (tpath (TClassDecl c)))] (List.map gen_type pl)
 
 let rec exists f c =
 	PMap.exists f.cf_name c.cl_fields ||
@@ -178,16 +181,20 @@ let gen_type_decl com pos t =
 			| None -> []
 			| Some t -> [node "haxe_dynamic" [] [gen_type t]]
 		) in
-		node "class" (gen_type_params pos c.cl_private (cpath c) c.cl_types c.cl_pos m @ ext @ interf) (tree @ stats @ fields @ constr @ doc @ meta @ dynamic)
+		node "class" (gen_type_params pos c.cl_private (tpath t) c.cl_types c.cl_pos m @ ext @ interf) (tree @ stats @ fields @ constr @ doc @ meta @ dynamic)
 	| TEnumDecl e ->
 		let doc = gen_doc_opt e.e_doc in
 		let meta = gen_meta e.e_meta in
-		node "enum" (gen_type_params pos e.e_private (epath e) e.e_types e.e_pos m) (pmap gen_constr e.e_constrs @ doc @ meta)
+		node "enum" (gen_type_params pos e.e_private (tpath t) e.e_types e.e_pos m) (pmap gen_constr e.e_constrs @ doc @ meta)
 	| TTypeDecl t ->
 		let doc = gen_doc_opt t.t_doc in
 		let meta = gen_meta t.t_meta in
 		let tt = gen_type t.t_type in
 		node "typedef" (gen_type_params pos t.t_private t.t_path t.t_types t.t_pos m) (tt :: doc @ meta)
+	| TAbstractDecl a ->
+		let doc = gen_doc_opt a.a_doc in
+		let meta = gen_meta a.a_meta in
+		node "abstract" (gen_type_params pos a.a_private (tpath t) a.a_types a.a_pos m) ([] @ doc @ meta)
 
 let att_str att =
 	String.concat "" (List.map (fun (a,v) -> Printf.sprintf " %s=\"%s\"" a v) att)
@@ -287,6 +294,8 @@ let generate_type com t =
 			path e.e_path tl
 		| TType (t,tl) ->
 			path t.t_path tl
+		| TAbstract (a,tl) ->
+			path a.a_path tl
 		| TAnon a ->
 			let fields = PMap.fold (fun f acc -> (f.cf_name ^ " : " ^ stype f.cf_type) :: acc) a.a_fields [] in
 			"{" ^ String.concat ", " fields ^ "}"
@@ -439,6 +448,9 @@ let generate_type com t =
 		p "typedef %s = " (stype (TType (t,List.map snd t.t_types)));
 		p "%s" (stype t.t_type);
 		p "\n";
+	| TAbstractDecl a ->
+		print_meta a.a_meta;
+		p "abstract %s {}" (stype (TAbstract (a,List.map snd a.a_types)));
 	);
 	IO.close_out ch
 

+ 12 - 3
interp.ml

@@ -2260,7 +2260,7 @@ let macro_lib =
 					(match !r with
 					| None -> t
 					| Some t -> t)
-				| TEnum _ | TInst _ | TFun _ | TAnon _ | TDynamic _ ->
+				| TAbstract _ | TEnum _ | TInst _ | TFun _ | TAnon _ | TDynamic _ ->
 					t
 				| TType (t,tl) ->
 					apply_params t.t_types tl t.t_type
@@ -3897,6 +3897,7 @@ let rec encode_mtype t fields =
 		"module", enc_string (s_type_path i.mt_module.m_path);
 		"isPrivate", VBool i.mt_private;
 		"meta", encode_meta i.mt_meta (fun m -> i.mt_meta <- m);
+		"doc", null enc_string i.mt_doc;
 	] @ fields)
 
 and encode_tenum e =
@@ -3906,7 +3907,11 @@ and encode_tenum e =
 		"params", enc_array (List.map (fun (n,t) -> enc_obj ["name",enc_string n;"t",encode_type t]) e.e_types);
 		"constructs", encode_pmap encode_efield e.e_constrs;
 		"names", enc_array (List.map enc_string e.e_names);
-		"doc", null enc_string e.e_doc;
+	]
+
+and encode_tabstract a =
+	encode_mtype (TAbstractDecl a) [
+		"params", enc_array (List.map (fun (n,t) -> enc_obj ["name",enc_string n;"t",encode_type t]) a.a_types);
 	]
 
 and encode_efield f =
@@ -4039,6 +4044,8 @@ and encode_type t =
 				6, [encode_type tsub]
 		| TLazy f ->
 			loop (!f())
+		| TAbstract (a, pl) ->
+			7, [encode_ref a encode_tabstract (fun() -> s_type_path a.a_path); encode_tparams pl]
 	in
 	let tag, pl = loop t in
 	enc_enum IType tag pl
@@ -4170,6 +4177,8 @@ let rec make_type = function
 		tpath c.cl_path (List.map make_type pl)
 	| TType (t,pl) ->
 		tpath t.t_path (List.map make_type pl)
+	| TAbstract (a,pl) ->
+		tpath a.a_path (List.map make_type pl)
 	| TFun (args,ret) ->
 		CTFunction (List.map (fun (_,_,t) -> make_type t) args, make_type ret)
 	| TAnon a ->
@@ -4274,7 +4283,7 @@ let rec make_ast e =
 		let t = (match t with
 			| None -> None
 			| Some t ->
-				let t = (match t with TClassDecl c -> TInst (c,[]) | TEnumDecl e -> TEnum (e,[]) | TTypeDecl t -> TType (t,[])) in
+				let t = (match t with TClassDecl c -> TInst (c,[]) | TEnumDecl e -> TEnum (e,[]) | TTypeDecl t -> TType (t,[]) | TAbstractDecl a -> TAbstract (a,[])) in
 				Some (try make_type t with Exit -> assert false)
 		) in
 		ECast (make_ast e,t))

+ 1 - 1
lexer.mll

@@ -75,7 +75,7 @@ let keywords =
 		Switch;Case;Default;Public;Private;Try;Untyped;
 		Catch;New;This;Throw;Extern;Enum;In;Interface;
 		Cast;Override;Dynamic;Typedef;Package;Callback;
-		Inline;Using;Null;True;False];
+		Inline;Using;Null;True;False;Abstract];
 	h
 
 let init file =

+ 6 - 3
optimizer.ml

@@ -180,7 +180,7 @@ let rec type_inline ctx cf f ethis params tret p force =
 	let in_local_fun = ref false in
 	let cancel_inlining = ref false in
 	let has_return_value = ref false in
-	let ret_val = (match follow f.tf_type with TEnum ({ e_path = ([],"Void") },[]) -> false | _ -> true) in
+	let ret_val = (match follow f.tf_type with TEnum ({ e_path = ([],"Void") },[]) | TAbstract ({ a_path = ([],"Void") },[]) -> false | _ -> true) in
 	let rec map term e =
 		let po = e.epos in
 		let e = { e with epos = p } in
@@ -349,7 +349,7 @@ let rec type_inline ctx cf f ethis params tret p force =
 				(match follow e.etype with 
 				| TMono _ -> 
 					(match follow tret with
-					| TEnum ({ e_path = [],"Void" },_) -> e
+					| TEnum ({ e_path = [],"Void" },_) | TAbstract ({ a_path = [],"Void" },_) -> e
 					| _ -> raise (Unify_error []))
 				| _ -> 
 					type_eq EqStrict (if has_params then map_type e.etype else e.etype) tret;
@@ -541,6 +541,9 @@ let rec add_final_return e t =
 			| TInst ({ cl_path = [],"Int" },_) -> TInt 0l
 			| TInst ({ cl_path = [],"Float" },_) -> TFloat "0."
 			| TEnum ({ e_path = [],"Bool" },_) -> TBool false
+			| TAbstract ({ a_path = [],"Int" },_) -> TInt 0l
+			| TAbstract ({ a_path = [],"Float" },_) -> TFloat "0."
+			| TAbstract ({ a_path = [],"Bool" },_) -> TBool false
 			| _ -> TNull
 		) in
 		{ eexpr = TReturn (Some { eexpr = TConst c; epos = p; etype = t }); etype = t; epos = p }
@@ -633,7 +636,7 @@ let sanitize_expr com e =
 		{ e with eexpr = TFor (v,e1,e2) }
 	| TFunction f ->
 		let f = (match follow f.tf_type with
-			| TEnum ({ e_path = [],"Void" },[]) -> f
+			| TEnum ({ e_path = [],"Void" },[]) | TAbstract ({ a_path = [],"Void" },[]) -> f
 			| t ->
 				if com.config.pf_add_final_return then { f with tf_expr = add_final_return f.tf_expr t } else f
 		) in

+ 16 - 1
parser.ml

@@ -232,6 +232,21 @@ and parse_type_decl s =
 				d_flags = List.map snd c;
 				d_data = t;
 			}, punion p1 p2)
+		| [< '(Kwd Abstract,p1); doc = get_doc; name = type_name; tl = parse_constraint_params; sl = psep Comma parse_abstract_relations; '(BrOpen,_); '(BrClose,p2) >] ->
+			let flags = List.map (fun (_,c) -> match c with EPrivate -> APrivAbstract | EExtern -> error (Custom "extern abstract not allowed") p1) c in
+			(EAbstract {
+				d_name = name;
+				d_doc = doc;
+				d_meta = meta;
+				d_params = tl;
+				d_flags = flags @ sl;
+				d_data = ();
+			},punion p1 p2)
+
+and parse_abstract_relations s =
+	match s with parser
+	| [< '(Binop OpLte,_); t = parse_complex_type >] -> ASuperType t
+	| [< '(Binop OpAssign,p1); '(Binop OpGt,p2) when p1.pmax = p2.pmin; t = parse_complex_type >] -> ASubType t
 
 and parse_package s = psep Dot lower_ident s
 
@@ -298,7 +313,7 @@ and parse_class_field_resume tdecl s =
 				junk_tokens (k - 1);
 				[]
 			(* type declaration *)
-			| Eof :: _ | Kwd Import :: _ | Kwd Using :: _ | Kwd Extern :: _ | Kwd Class :: _ | Kwd Interface :: _ | Kwd Enum :: _ | Kwd Typedef :: _ ->
+			| Eof :: _ | Kwd Import :: _ | Kwd Using :: _ | Kwd Extern :: _ | Kwd Class :: _ | Kwd Interface :: _ | Kwd Enum :: _ | Kwd Typedef :: _ | Kwd Abstract :: _->
 				junk_tokens (k - 1);
 				[]
 			| [] ->

+ 4 - 0
std/haxe/macro/Type.hx

@@ -38,6 +38,7 @@ enum Type {
 	TAnonymous( a : Ref<AnonType> );
 	TDynamic( t : Null<Type> );
 	TLazy( f : Void -> Type );
+	TAbstract( t : Ref<AbstractType>, params : Array<Type> );
 }
 
 typedef AnonType = {
@@ -111,6 +112,9 @@ typedef DefType = {> BaseType,
 	var type : Type;
 }
 
+
+typedef AbstractType = BaseType;
+
 typedef MetaAccess = {
 	function get() : Expr.Metadata;
 	function add( name : String, params : Array<Expr>, pos : Expr.Position ) : Void;

+ 0 - 2
std/neko/_std/Std.hx

@@ -72,7 +72,6 @@
 		Dynamic = { __name__ : ["Dynamic"] };
 		Class = { __name__ : ["Class"] };
 		Enum = {};
-		Void = { __ename__ : ["Void"] };
 		var cl = neko.Boot.__classes;
 		cl.Int = Int;
 		cl.Float = Float;
@@ -80,7 +79,6 @@
 		cl.Dynamic = Dynamic;
 		cl.Class = Class;
 		cl.Enum = Enum;
-		cl.Void = Void;
 	}
 
 }

+ 3 - 8
tests/unit/TestReflect.hx

@@ -63,7 +63,7 @@ class TestReflect extends Test {
 		null,Int,String,Bool,Float,
 		Array,Hash,List,Date,Xml,Math,
 		unit.MyEnum,unit.MyClass,unit.MySubClass,
-		Class,Enum,#if !(java || cs)Void,#end Dynamic,unit.MyInterface
+		Class,Enum,Dynamic,unit.MyInterface
 	];
 
 	static inline function u( s : String ) : String {
@@ -87,7 +87,7 @@ class TestReflect extends Test {
 		"null","Int","String","Bool","Float",
 		"Array",u("Hash"),u("List"),"Date","Xml","Math",
 		u2("unit","MyEnum"),u2("unit","MyClass"),u2("unit","MySubClass"),
-		#if !flash9 u #end("Class"), u("Enum"), #if !(java || cs) u("Void"), #end u("Dynamic"),
+		#if !flash9 u #end("Class"), u("Enum"), u("Dynamic"),
 		u2("unit","MyInterface")
 	];
 
@@ -99,7 +99,7 @@ class TestReflect extends Test {
 			f( t == null );
 			if( name == u("Enum") ) {
 				// neither an enum or a class
-			} else if( t == MyEnum || #if !(java || cs) t == Void || #end t == Bool ) {
+			} else if( t == MyEnum || t == Bool ) {
 				eq( Type.getEnumName(t), name );
 				eq( Type.resolveEnum(name), t );
 			} else {
@@ -108,9 +108,6 @@ class TestReflect extends Test {
 			}
 		}
 		infos(null);
-		// these are very specific cases since we can't allow reflection on core type
-		unspec( function() Type.getEnumConstructs(Void) );
-		unspec( function() Type.getEnumConstructs(Bool) );
 	}
 
 	public function testIs() {
@@ -143,7 +140,6 @@ class TestReflect extends Test {
 		is(function() { },null);
 		is(MyClass,Class);
 		is(MyEnum,Enum);
-		is(Void,Enum);
 		is(Class,Class);
 	}
 
@@ -184,7 +180,6 @@ class TestReflect extends Test {
 		typeof(function() {},TFunction);
 		typeof(MyClass,TObject);
 		typeof(MyEnum,TObject);
-		typeof(Void,TObject);
 		#if !flash9
 		// on flash9, Type.typeof(Class) is crashing the player
 		typeof(Class,TObject);

+ 51 - 1
type.ml

@@ -53,6 +53,7 @@ type t =
 	| TAnon of tanon
 	| TDynamic of t
 	| TLazy of (unit -> t) ref
+	| TAbstract of tabstract * tparams
 
 and tparams = t list
 
@@ -87,6 +88,7 @@ and anon_status =
 	| Const
 	| Statics of tclass
 	| EnumStatics of tenum
+	| AbstractStatics of tabstract
 
 and tanon = {
 	mutable a_fields : (string, tclass_field) PMap.t;
@@ -223,10 +225,23 @@ and tdef = {
 	mutable t_type : t;
 }
 
+and tabstract = {
+	a_path : path;
+	a_module : module_def;
+	a_pos : Ast.pos;
+	a_private : bool;
+	a_doc : Ast.documentation;
+	mutable a_meta : metadata;
+	mutable a_types : type_params;
+	mutable a_sub : t list;
+	mutable a_super : t list;
+}
+
 and module_type =
 	| TClassDecl of tclass
 	| TEnumDecl of tenum
 	| TTypeDecl of tdef
+	| TAbstractDecl of tabstract
 
 and module_def = {
 	m_id : int;
@@ -342,6 +357,7 @@ let t_infos t : tinfos =
 	| TClassDecl c -> Obj.magic c
 	| TEnumDecl e -> Obj.magic e
 	| TTypeDecl t -> Obj.magic t
+	| TAbstractDecl a -> Obj.magic a
 
 let t_path t = (t_infos t).mt_path
 
@@ -361,6 +377,8 @@ let rec s_type ctx t =
 		Ast.s_type_path c.cl_path ^ s_type_params ctx tl
 	| TType (t,tl) ->
 		Ast.s_type_path t.t_path ^ s_type_params ctx tl
+	| TAbstract (a,tl) ->
+		Ast.s_type_path a.a_path ^ s_type_params ctx tl
 	| TFun ([],t) ->
 		"Void -> " ^ s_fun ctx t false
 	| TFun (l,t) ->
@@ -381,6 +399,8 @@ and s_fun ctx t void =
 		"(" ^ s_type ctx t ^ ")"
 	| TEnum ({ e_path = ([],"Void") },[]) when void ->
 		"(" ^ s_type ctx t ^ ")"
+	| TAbstract ({ a_path = ([],"Void") },[]) when void ->
+		"(" ^ s_type ctx t ^ ")"
 	| TMono r ->
 		(match !r with
 		| None -> s_type ctx t
@@ -434,6 +454,8 @@ let map loop t =
 		TInst (c, List.map loop tl)
 	| TType (t2,tl) ->
 		TType (t2,List.map loop tl)
+	| TAbstract (a,tl) ->
+		TAbstract (a,List.map loop tl)
 	| TFun (tl,r) ->
 		TFun (List.map (fun (s,o,t) -> s, o, loop t) tl,loop r)
 	| TAnon a ->
@@ -478,6 +500,10 @@ let apply_params cparams params t =
 			(match tl with
 			| [] -> t
 			| _ -> TType (t2,List.map loop tl))
+		| TAbstract (a,tl) ->
+			(match tl with
+			| [] -> t
+			| _ -> TAbstract (a,List.map loop tl))
 		| TInst (c,tl) ->
 			(match tl with
 			| [] ->
@@ -551,6 +577,7 @@ let rec is_nullable ?(no_lazy=false) = function
 	| TInst ({ cl_path = ([],"Int") },[])
 	| TInst ({ cl_path = ([],"Float") },[])
 	| TEnum ({ e_path = ([],"Bool") },[]) -> false
+	| TAbstract (a,_) -> not (List.exists (fun (m2,_,_) -> m2 = ":notNull") a.a_meta)
 	| _ ->
 		true
 
@@ -574,7 +601,7 @@ let rec link e a b =
 		else match t with
 		| TMono t -> (match !t with None -> false | Some t -> loop t)
 		| TEnum (_,tl) -> List.exists loop tl
-		| TInst (_,tl) | TType (_,tl) -> List.exists loop tl
+		| TInst (_,tl) | TType (_,tl) | TAbstract (_,tl) -> List.exists loop tl
 		| TFun (tl,t) -> List.exists (fun (_,_,t) -> loop t) tl || loop t
 		| TDynamic t2 ->
 			if t == t2 then
@@ -740,6 +767,9 @@ let rec type_eq param a b =
 			Unify_error l -> error (cannot_unify a b :: l))
 	| TDynamic a , TDynamic b ->
 		type_eq param a b
+	| TAbstract (a1,tl1) , TAbstract (a2,tl2) ->
+		if a1 != a2 && not (param = EqCoreType && a1.a_path = a2.a_path) then error [cannot_unify a b];
+		List.iter2 (type_eq param) tl1 tl2
 	| TAnon a1, TAnon a2 ->
 		(try
 			PMap.iter (fun n f1 ->
@@ -892,6 +922,16 @@ let rec unify a b =
 	| TEnum (ea,tl1) , TEnum (eb,tl2) ->
 		if ea != eb then error [cannot_unify a b];
 		unify_types a b tl1 tl2
+	| TAbstract (a1,tl1) , TAbstract (a2,tl2) when a1 == a2 ->
+		unify_types a b tl1 tl2
+	| TAbstract (a1,tl1) , TAbstract (a2,tl2) ->		
+		if not (List.exists (fun t ->
+			let t = apply_params a1.a_types tl1 t in
+			try unify t b; true with Unify_error _ -> false
+		) a1.a_super) && not (List.exists (fun t ->
+			let t = apply_params a2.a_types tl2 t in
+			try unify a t; true with Unify_error _ -> false
+		) a2.a_sub) then error [cannot_unify a b]		
 	| TInst (c1,tl1) , TInst (c2,tl2) ->
 		let rec loop c tl =
 			if c == c2 then begin
@@ -1032,6 +1072,16 @@ let rec unify a b =
 				error (cannot_unify a b :: l))
 		| _ ->
 			error [cannot_unify a b])
+	| TAbstract (aa,tl), _  ->
+		if not (List.exists (fun t ->
+			let t = apply_params aa.a_types tl t in
+			try unify t b; true with Unify_error _ -> false
+		) aa.a_super) then error [cannot_unify a b];
+	| _, TAbstract (bb,tl) ->
+		if not (List.exists (fun t ->
+			let t = apply_params bb.a_types tl t in
+			try unify a t; true with Unify_error _ -> false
+		) bb.a_sub) then error [cannot_unify a b];
 	| _ , _ ->
 		error [cannot_unify a b]
 

+ 34 - 2
typeload.ml

@@ -918,7 +918,7 @@ let init_class ctx c p herits fields =
 		match t with
 		| TFun (args,ret) -> is_full_type ret && List.for_all (fun (_,_,t) -> is_full_type t) args
 		| TMono r -> (match !r with None -> false | Some t -> is_full_type t)
-		| TInst _ | TEnum _ | TLazy _ | TDynamic _ | TAnon _ | TType _ -> true
+		| TAbstract _ | TInst _ | TEnum _ | TLazy _ | TDynamic _ | TAnon _ | TType _ -> true
 	in
 	let bind_type cf r p macro =
 		if ctx.com.display then begin
@@ -1286,11 +1286,12 @@ let init_class ctx c p herits fields =
 
 let resolve_typedef t =
 	match t with
-	| TClassDecl _ | TEnumDecl _ -> t
+	| TClassDecl _ | TEnumDecl _ | TAbstractDecl _ -> t
 	| TTypeDecl td ->
 		match follow td.t_type with
 		| TEnum (e,_) -> TEnumDecl e
 		| TInst (c,_) -> TClassDecl c
+		| TAbstract (a,_) -> TAbstractDecl a
 		| _ -> t
 
 let add_module ctx m p =
@@ -1362,6 +1363,21 @@ let type_module ctx m file tdecls loadp =
 				t_meta = d.d_meta;
 			} in
 			decls := TTypeDecl t :: !decls
+	   | EAbstract d ->
+			let priv = List.mem APrivAbstract d.d_flags in
+			let path = make_path d.d_name priv in
+			let a = {
+				a_path = path;
+				a_private = priv;
+				a_module = m;
+				a_pos = p;
+				a_doc = d.d_doc;
+				a_types = [];
+				a_meta = d.d_meta;
+				a_sub = [];
+				a_super = [];
+			} in
+			decls := TAbstractDecl a :: !decls
 	) tdecls;
 	m.m_types <- List.rev !decls;
 	add_module ctx m loadp;
@@ -1403,6 +1419,10 @@ let type_module ctx m file tdecls loadp =
 		let s = List.find (fun d -> match d with TTypeDecl { t_path = _ , n } -> n = name | _ -> false) m.m_types in
 		match s with TTypeDecl s -> s | _ -> assert false
 	in
+	let get_abstract name =
+		let s = List.find (fun d -> match d with TAbstractDecl { a_path = _ , n } -> n = name | _ -> false) m.m_types in
+		match s with TAbstractDecl a -> a | _ -> assert false
+	in
 	let filter_classes types =
 		let rec loop acc types = match List.rev types with
 			| t :: l ->
@@ -1425,6 +1445,9 @@ let type_module ctx m file tdecls loadp =
 		| ETypedef d ->
 			let t = get_tdef d.d_name in
 			t.t_types <- List.map (type_type_params ctx t.t_path (fun() -> t.t_types) p) d.d_params;
+		| EAbstract d ->
+			let a = get_abstract d.d_name in
+			a.a_types <- List.map (type_type_params ctx a.a_path (fun() -> a.a_types) p) d.d_params;
 	) tdecls;
 	(* back to PASS2 *)
 	List.iter (fun (d,p) ->
@@ -1530,6 +1553,14 @@ let type_module ctx m file tdecls loadp =
 				| None -> r := Some tt;
 				| Some _ -> assert false);
 			| _ -> assert false);
+		| EAbstract d ->
+			let a = get_abstract d.d_name in
+			let ctx = { ctx with type_params = a.a_types } in
+			List.iter (function
+				| APrivAbstract -> ()
+				| ASubType t -> a.a_sub <- load_complex_type ctx p t :: a.a_sub
+				| ASuperType t -> a.a_super <- load_complex_type ctx p t :: a.a_super
+			) d.d_flags
 	) tdecls;
 	(* PASS 3 : type checking, delayed until all modules and types are built *)
 	List.iter (delay ctx) (List.rev (!delays));
@@ -1592,6 +1623,7 @@ let parse_module ctx m p =
 			| EClass d -> build HPrivate d
 			| EEnum d -> build EPrivate d
 			| ETypedef d -> build EPrivate d
+			| EAbstract d -> build APrivAbstract d
 			| EImport _ | EUsing _ -> acc
 		) [(EImport { tpackage = !remap; tname = snd m; tparams = []; tsub = None; },null_pos)] decls)
 	else

+ 40 - 6
typer.ml

@@ -80,6 +80,8 @@ let rec classify t =
 	| TInst ({ cl_path = ([],"Int") },[]) -> KInt
 	| TInst ({ cl_path = ([],"Float") },[]) -> KFloat
 	| TInst ({ cl_path = ([],"String") },[]) -> KString
+	| TAbstract ({ a_path = [],"Int" },[]) -> KInt
+	| TAbstract ({ a_path = [],"Float" },[]) -> KFloat	
 	| TInst ({ cl_kind = KTypeParameter ctl },_) when List.exists (fun t -> match classify t with KInt | KFloat -> true | _ -> false) ctl -> KParam t
 	| TMono r when !r = None -> KUnk
 	| TDynamic _ -> KDyn
@@ -412,13 +414,31 @@ let rec type_module_type ctx t tparams p =
 		mk (TTypeExpr (TEnumDecl e)) (TType (t_tmp,types)) p
 	| TTypeDecl s ->
 		let t = apply_params s.t_types (List.map (fun _ -> mk_mono()) s.t_types) s.t_type in
-		match follow t with
+		(match follow t with
 		| TEnum (e,params) ->
 			type_module_type ctx (TEnumDecl e) (Some params) p
 		| TInst (c,params) ->
 			type_module_type ctx (TClassDecl c) (Some params) p
+		| TAbstract (a,params) ->
+			type_module_type ctx (TAbstractDecl a) (Some params) p
 		| _ ->
-			error (s_type_path s.t_path ^ " is not a value") p
+			error (s_type_path s.t_path ^ " is not a value") p)
+	| TAbstractDecl a ->
+		if not (has_meta ":runtime_value" a.a_meta) then error (s_type_path a.a_path ^ " is not a value") p;
+		let t_tmp = {
+			t_path = fst a.a_path, "#" ^ snd a.a_path;
+			t_module = a.a_module;
+			t_doc = None;
+			t_pos = a.a_pos;
+			t_type = TAnon {
+				a_fields = PMap.empty;
+				a_status = ref (AbstractStatics a);
+			};
+			t_private = true;
+			t_types = [];
+			t_meta = no_meta;
+		} in
+		mk (TTypeExpr (TAbstractDecl a)) (TType (t_tmp,[])) p		
 
 let type_type ctx tpath p =
 	type_module_type ctx (Typeload.load_type_def ctx p { tpackage = fst tpath; tname = snd tpath; tparams = []; tsub = None }) None p
@@ -714,7 +734,7 @@ let type_ident_raise ?(imported_enums=true) ctx i p mode =
 			| [] -> raise Not_found
 			| t :: l ->
 				match t with
-				| TClassDecl _ ->
+				| TClassDecl _ | TAbstractDecl _ ->
 					loop l
 				| TTypeDecl t ->
 					(match follow t.t_type with
@@ -2421,7 +2441,7 @@ let get_main ctx =
 	| Some cl ->
 		let t = Typeload.load_type_def ctx null_pos { tpackage = fst cl; tname = snd cl; tparams = []; tsub = None } in
 		let ft, r = (match t with
-		| TEnumDecl _ | TTypeDecl _ ->
+		| TEnumDecl _ | TTypeDecl _ | TAbstractDecl _ ->
 			error ("Invalid -main : " ^ s_type_path cl ^ " is not a class") null_pos
 		| TClassDecl c ->
 			try
@@ -2474,7 +2494,7 @@ let generate ctx =
 			| TClassDecl c ->
 				walk_class p c;
 				t
-			| TEnumDecl _ | TTypeDecl _ ->
+			| TEnumDecl _ | TTypeDecl _ | TAbstractDecl _ ->
 				t
 			) in
 			Hashtbl.replace states p Done;
@@ -2486,6 +2506,9 @@ let generate ctx =
 	and loop_enum p e =
 		if e.e_path <> p then loop (TEnumDecl e)
 
+	and loop_abstract p a =
+		if a.a_path <> p then loop (TAbstractDecl a)
+
 	and walk_static_call p c name =
 		try
 			let f = PMap.find name c.cl_statics in
@@ -2507,6 +2530,7 @@ let generate ctx =
 			(match t with
 			| TClassDecl c -> loop_class p c
 			| TEnumDecl e -> loop_enum p e
+			| TAbstractDecl a -> loop_abstract p a
 			| TTypeDecl _ -> assert false)
 		| TEnumField (e,_) ->
 			loop_enum p e
@@ -2538,6 +2562,7 @@ let generate ctx =
 				| TField ({ eexpr = TTypeExpr t },name) ->
 					(match t with
 					| TEnumDecl _ -> ()
+					| TAbstractDecl _ -> assert false
 					| TTypeDecl _ -> assert false
 					| TClassDecl c -> walk_static_call p c name)
 				| _ -> ()
@@ -2650,6 +2675,7 @@ let make_macro_api ctx p =
 		| TClassDecl c -> TInst (c,List.map snd c.cl_types)
 		| TEnumDecl e -> TEnum (e,List.map snd e.e_types)
 		| TTypeDecl t -> TType (t,List.map snd t.t_types)
+		| TAbstractDecl a -> TAbstract (a,List.map snd a.a_types)
 	in
 	{
 		Interp.pos = p;
@@ -2768,7 +2794,8 @@ let make_macro_api ctx p =
 				Some (match mt with
 					| TClassDecl c -> TInst (c,[])
 					| TEnumDecl e -> TEnum (e,[])
-					| TTypeDecl t -> TType (t,[]))
+					| TTypeDecl t -> TType (t,[])
+					| TAbstractDecl a -> TAbstract(a,[]))
 			| None ->
 				if ctx.curclass == null_class then
 					None
@@ -3103,6 +3130,13 @@ let rec create com =
 	);
 	List.iter (fun t ->
 		match t with
+		| TAbstractDecl a ->
+			(match snd a.a_path with
+			| "Void" -> ctx.t.tvoid <- TAbstract (a,[]);
+			| "Float" -> ctx.t.tfloat <- TAbstract (a,[]);
+			| "Int" -> ctx.t.tint <- TAbstract (a,[])
+			| "Bool" -> ctx.t.tbool <- TAbstract (a,[])
+			| _ -> ());
 		| TEnumDecl e ->
 			(match snd e.e_path with
 			| "Void" -> ctx.t.tvoid <- TEnum (e,[])