Browse Source

rearchitecture

Nicolas Cannasse 17 năm trước cách đây
mục cha
commit
2c73faf587
18 tập tin đã thay đổi với 1968 bổ sung1285 xóa
  1. 28 17
      Makefile.win
  2. 561 0
      codegen.ml
  3. 46 1
      common.ml
  4. 25 10
      doc/install.ml
  5. 11 13
      genas3.ml
  6. 15 17
      genjs.ml
  7. 1 4
      genneko.ml
  8. 22 19
      genswf8.ml
  9. 14 14
      genswf9.ml
  10. 4 6
      genxml.ml
  11. 8 2
      haxe.vcproj
  12. 19 17
      main.ml
  13. 1 1
      std/haxe/io/Bytes.hx
  14. 0 331
      transform.ml
  15. 69 5
      type.ml
  16. 184 0
      typecore.ml
  17. 925 0
      typeload.ml
  18. 35 828
      typer.ml

+ 28 - 17
Makefile.win

@@ -1,4 +1,4 @@
-# Makefile generated by OCamake 
+# Makefile generated by OCamake
 # http://tech.motion-twin.com
 .SUFFIXES : .ml .mli .cmo .cmi .cmx .mll .mly
 
@@ -7,47 +7,58 @@ LIBS=extLib.cmxa extc.cmxa swfLib.cmxa unix.cmxa xml-light.cmxa
 LFLAGS=-g -o haxe.exe -I ../neko/libs/include/ocaml
 OUTPUT=sed 's/File "\([^"]\+\)", line \([0-9]\+\), \(.*\)/\1(\2): \3/' tmp.cmi
 
-FILES = ../neko/libs/include/ocaml/nast.cmx ast.cmx common.cmx ../neko/libs/include/ocaml/nxml.cmx ../neko/libs/include/ocaml/binast.cmx lexer.cmx type.cmx parser.cmx transform.cmx typer.cmx genswf9.cmx genswf8.cmx genneko.cmx genjs.cmx genswf.cmx genxml.cmx genas3.cmx main.cmx
-
+FILES = ast.cmx lexer.cmx type.cmx common.cmx parser.cmx typecore.cmx \
+	genxml.cmx typeload.cmx codegen.cmx typer.cmx \
+	../neko/libs/include/ocaml/nast.cmx ../neko/libs/include/ocaml/binast.cmx ../neko/libs/include/ocaml/nxml.cmx \
+	genneko.cmx genas3.cmx genjs.cmx genswf8.cmx genswf9.cmx genswf.cmx \
+	main.cmx
+	
 all: haxe.exe
 
 haxe.exe: $(FILES)
 	ocamlopt $(LFLAGS) $(LIBS) $(FILES)
 
-genneko.cmx: typer.cmx type.cmx common.cmx ../neko/libs/include/ocaml/binast.cmx ../neko/libs/include/ocaml/nast.cmx lexer.cmx ast.cmx
-
 ../neko/libs/include/ocaml/binast.cmx: ../neko/libs/include/ocaml/nast.cmx
 
+genneko.cmx: type.cmx ../neko/libs/include/ocaml/nxml.cmx ../neko/libs/include/ocaml/nast.cmx lexer.cmx common.cmx ../neko/libs/include/ocaml/binast.cmx ast.cmx
+
 ../neko/libs/include/ocaml/nxml.cmx: ../neko/libs/include/ocaml/nast.cmx
 
-genjs.cmx: typer.cmx type.cmx transform.cmx ast.cmx
+../../mtcvs/swflib/as3hl.cmi: ../../mtcvs/swflib/as3.cmi
+
+codegen.cmx: typeload.cmx typecore.cmx type.cmx genxml.cmx common.cmx ast.cmx
+
+common.cmx: type.cmx ast.cmx
 
-genas3.cmx: typer.cmx type.cmx transform.cmx ast.cmx
+genas3.cmx: type.cmx codegen.cmx ../../mtcvs/swflib/swfParser.cmx ../../mtcvs/swflib/swf.cmx common.cmx ast.cmx ../../mtcvs/swflib/as3parse.cmx ../../mtcvs/swflib/as3code.cmx ../../mtcvs/swflib/as3.cmi
 
-genswf.cmx: typer.cmx type.cmx common.cmx genswf8.cmx genswf9.cmx
+genjs.cmx: type.cmx codegen.cmx lexer.cmx common.cmx ast.cmx
 
-genswf8.cmx: typer.cmx type.cmx transform.cmx common.cmx ast.cmx
+genswf.cmx: type.cmx ../../mtcvs/swflib/swfZip.cmx ../../mtcvs/swflib/swfParser.cmx ../../mtcvs/swflib/swf.cmx genswf9.cmx genswf8.cmx common.cmx ast.cmx ../../mtcvs/swflib/as3hlparse.cmx ../../mtcvs/swflib/as3hl.cmi ../../mtcvs/swflib/as3.cmi
 
-genswf9.cmx: type.cmx ast.cmx typer.cmx transform.cmx common.cmx
+genswf8.cmx: type.cmx codegen.cmx ../../mtcvs/swflib/swf.cmx lexer.cmx common.cmx ast.cmx ../../mtcvs/swflib/actionScript.cmx
 
-genxml.cmx: typer.cmx type.cmx lexer.cmx ast.cmx
+genswf9.cmx: type.cmx codegen.cmx lexer.cmx common.cmx ast.cmx ../../mtcvs/swflib/as3hlparse.cmx ../../mtcvs/swflib/as3hl.cmi ../../mtcvs/swflib/as3.cmi
+
+genxml.cmx: type.cmx lexer.cmx common.cmx ast.cmx
 
 lexer.cmx: lexer.ml
 
 lexer.cmx: ast.cmx
 
-main.cmx: typer.cmx common.cmx parser.cmx lexer.cmx genxml.cmx genswf.cmx genneko.cmx genjs.cmx genas3.cmx ast.cmx
+main.cmx: typer.cmx typeload.cmx typecore.cmx type.cmx parser.cmx lexer.cmx genxml.cmx genswf.cmx genneko.cmx genjs.cmx genas3.cmx common.cmx ast.cmx
 
-parser.cmx: parser.ml common.cmx lexer.cmx ast.cmx
+parser.cmx: lexer.cmx common.cmx ast.cmx
 	(ocamlopt -pp camlp4o $(CFLAGS) -c parser.ml 2>tmp.cmi && $(OUTPUT)) || ($(OUTPUT) && exit 1)
 
-transform.cmx: type.cmx
-
 type.cmx: ast.cmx
 
-typer.cmx: type.cmx common.cmx parser.cmx lexer.cmx ast.cmx transform.cmx
+typecore.cmx: type.cmx common.cmx ast.cmx
+
+typeload.cmx: typecore.cmx type.cmx parser.cmx common.cmx ast.cmx
+
+typer.cmx: typeload.cmx typecore.cmx type.cmx parser.cmx lexer.cmx common.cmx ast.cmx codegen.cmx
 
-common.cmx: type.cmx
 
 clean:
 	rm -f haxe.exe

+ 561 - 0
codegen.ml

@@ -0,0 +1,561 @@
+(*
+ *  Haxe Compiler
+ *  Copyright (c)2005-2008 Nicolas Cannasse
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *)
+ 
+open Ast
+open Type
+open Common
+open Typecore
+
+(* -------------------------------------------------------------------------- *)
+(* REMOTING PROXYS *)
+
+let rec reverse_type t =
+	match t with
+	| TEnum (e,params) ->
+		TPNormal { tpackage = fst e.e_path; tname = snd e.e_path; tparams = List.map reverse_param params }
+	| TInst (c,params) ->
+		TPNormal { tpackage = fst c.cl_path; tname = snd c.cl_path; tparams = List.map reverse_param params }
+	| TType (t,params) ->
+		TPNormal { tpackage = fst t.t_path; tname = snd t.t_path; tparams = List.map reverse_param params }
+	| TFun (params,ret) ->
+		TPFunction (List.map (fun (_,_,t) -> reverse_type t) params,reverse_type ret)
+	| TAnon a ->
+		TPAnonymous (PMap.fold (fun f acc ->
+			(f.cf_name , Some f.cf_public, AFVar (reverse_type f.cf_type), null_pos) :: acc
+		) a.a_fields [])
+	| TDynamic t2 ->
+		TPNormal { tpackage = []; tname = "Dynamic"; tparams = if t == t2 then [] else [TPType (reverse_type t2)] }
+	| _ ->
+		raise Exit
+
+and reverse_param t =
+	TPType (reverse_type t)
+
+(*/*
+let extend_remoting ctx c t p async prot =
+	if c.cl_super <> None then error "Cannot extend several classes" p;
+	if ctx.isproxy then
+		() (* skip this proxy generation, we shouldn't need it anyway *)
+	else
+	let ctx2 = context ctx.com in
+	(* remove forbidden packages *)
+	let rules = ctx.com.package_rules in
+	ctx.com.package_rules <- PMap.foldi (fun key r acc -> match r with Forbidden -> acc | _ -> PMap.add key r acc) rules PMap.empty;
+	ctx2.isproxy <- true;
+	let ct = (try load_normal_type ctx2 t p false with e -> ctx.com.package_rules <- rules; raise e) in
+	ctx.com.package_rules <- rules;
+	let tvoid = TPNormal { tpackage = []; tname = "Void"; tparams = [] } in
+	let make_field name args ret =
+		try
+			let targs = List.map (fun (a,o,t) -> a, o, Some (reverse_type t)) args in
+			let tret = reverse_type ret in
+			let eargs = [EArrayDecl (List.map (fun (a,_,_) -> (EConst (Ident a),p)) args),p] in
+			let targs , tret , eargs = if async then
+				match tret with
+				| TPNormal { tpackage = []; tname = "Void" } -> targs , tvoid , eargs @ [EConst (Ident "null"),p]
+				| _ -> targs @ ["__callb",true,Some (TPFunction ([tret],tvoid))] , tvoid , eargs @ [EUntyped (EConst (Ident "__callb"),p),p]
+			else
+				targs, tret , eargs
+			in
+			let idname = EConst (String name) , p in
+			(FFun (name,None,[APublic],[], {
+				f_args = targs;
+				f_type = Some tret;
+				f_expr = (EBlock [
+					(EReturn (Some (EUntyped (ECall (
+						(EField (
+							(ECall (
+								(EField ((EConst (Ident "__cnx"),p),"resolve"),p),
+								[if prot then idname else ECall ((EConst (Ident "__unprotect__"),p),[idname]),p]
+							),p)
+						,"call"),p),eargs
+					),p),p)),p)
+				],p);
+			}),p)
+		with
+			Exit -> error ("Field " ^ name ^ " type is not complete and cannot be used by RemotingProxy") p
+	in
+	let class_fields = (match ct with
+		| TInst (c,params) ->
+			(FVar ("__cnx",None,[],Some (TPNormal { tpackage = ["haxe";"remoting"]; tname = if async then "AsyncConnection" else "Connection"; tparams = [] }),None),p) ::
+			(FFun ("new",None,[APublic],[],{ f_args = ["c",false,None]; f_type = None; f_expr = (EBinop (OpAssign,(EConst (Ident "__cnx"),p),(EConst (Ident "c"),p)),p) }),p) ::
+			PMap.fold (fun f acc ->
+				if not f.cf_public then
+					acc
+				else match follow f.cf_type with
+				| TFun (args,ret) when f.cf_get = NormalAccess && (f.cf_set = NormalAccess || f.cf_set = MethodCantAccess) && f.cf_params = [] ->
+					make_field f.cf_name args ret :: acc
+				| _ -> acc
+			) c.cl_fields []
+		| _ ->
+			error "Remoting type parameter should be a class" p
+	) in
+	let class_decl = (EClass {
+		d_name = t.tname;
+		d_doc = None;
+		d_params = [];
+		d_flags = [];
+		d_data = class_fields;
+	},p) in
+	let m = (try Hashtbl.find ctx2.modules (t.tpackage,t.tname) with Not_found -> assert false) in
+	let mdecl = (List.map (fun (m,t) -> (EImport (fst m.mpath, snd m.mpath, t),p)) m.mimports) @ [class_decl] in
+	let m = (!type_module_ref) ctx ("Remoting" :: t.tpackage,t.tname) mdecl p in
+	c.cl_super <- Some (match m.mtypes with
+		| [TClassDecl c] -> (c,[])
+		| _ -> assert false
+	)
+*/*)
+
+(* -------------------------------------------------------------------------- *)
+(* HAXE.RTTI.GENERIC *)
+
+let build_generic ctx c p tl =
+	let pack = fst c.cl_path in
+	let recurse = ref false in
+	let rec check_recursive t =
+		match follow t with
+		| TInst (c,tl) ->
+			if c.cl_kind = KTypeParameter then recurse := true;
+			List.iter check_recursive tl;
+		| _ ->
+			()
+	in
+	let name = String.concat "_" (snd c.cl_path :: (List.map (fun t ->
+		check_recursive t;
+		let path = (match follow t with
+			| TInst (c,_) -> c.cl_path
+			| TEnum (e,_) -> e.e_path
+			| _ -> error "Type parameter must be a class or enum instance" p
+		) in
+		match path with
+		| [] , name -> name
+		| l , name -> String.concat "_" l ^ "_" ^ name
+	) tl)) in
+	if !recurse then begin
+		TInst (c,tl)
+	end else try
+		Typeload.load_normal_type ctx { tpackage = pack; tname = name; tparams = [] } p false
+	with Error(Module_not_found path,_) when path = (pack,name) ->
+		(* try to find the module in which the generic class was originally defined *)
+		let mpath = (if c.cl_private then match List.rev (fst c.cl_path) with [] -> assert false | x :: l -> List.rev l, String.sub x 1 (String.length x - 1) else c.cl_path) in
+		let mtypes = try (Hashtbl.find ctx.modules mpath).mtypes with Not_found -> [] in
+		let ctx = { ctx with local_types = mtypes @ ctx.local_types } in
+		let cg = mk_class (pack,name) c.cl_pos None false in
+		let mg = {
+			mpath = cg.cl_path;
+			mtypes = [TClassDecl cg];
+			mimports = [];
+		} in
+		Hashtbl.add ctx.modules mg.mpath mg;
+		let rec loop l1 l2 =
+			match l1, l2 with
+			| [] , [] -> []
+			| (x,TLazy f) :: l1, _ -> loop ((x,(!f)()) :: l1) l2
+			| (_,t1) :: l1 , t2 :: l2 -> (t1,t2) :: loop l1 l2
+			| _ -> assert false
+		in
+		let subst = loop c.cl_types tl in
+		let rec build_type t =
+			match t with
+			| TInst ({ cl_kind = KGeneric } as c,tl) ->
+				(* maybe loop, or generate cascading generics *)
+				Typeload.load_type ctx p (reverse_type (TInst (c,List.map build_type tl)))
+			| _ ->
+				try List.assq t subst with Not_found -> Type.map build_type t
+		in
+		let rec build_expr e =
+			let t = build_type e.etype in
+			match e.eexpr with
+			| TFunction f ->
+				{
+					eexpr = TFunction {
+						tf_args = List.map (fun (n,o,t) -> n, o, build_type t) f.tf_args;
+						tf_type = build_type f.tf_type;
+						tf_expr = build_expr f.tf_expr;
+					};
+					etype = t;
+					epos = e.epos;
+				}
+			| TNew (c,tl,el) ->
+				let c, tl = (match follow t with TInst (c,tl) -> c, tl | _ -> assert false) in
+				{
+					eexpr = TNew (c,tl,List.map build_expr el);
+					etype = t;
+					epos = e.epos;
+				};
+			| TVars vl ->
+				{
+					eexpr = TVars (List.map (fun (v,t,eo) ->
+						v, build_type t, (match eo with None -> None | Some e -> Some (build_expr e))
+					) vl);
+					etype = t;
+					epos = e.epos;
+				}
+			(* there's still some 't' lefts in TFor, TMatch and TTry *)
+			| _ ->
+				Type.map_expr build_expr { e with etype = t }
+		in
+		let build_field f =
+			let t = build_type f.cf_type in
+			{ f with cf_type = t; cf_expr = (match f.cf_expr with None -> None | Some e -> Some (build_expr e)) }
+		in
+		if c.cl_super <> None || c.cl_init <> None || c.cl_dynamic <> None then error "This class can't be generic" p;
+		if c.cl_ordered_statics <> [] then error "A generic class can't have static fields" p;
+		cg.cl_kind <- KGenericInstance (c,tl);
+		cg.cl_constructor <- (match c.cl_constructor with None -> None | Some c -> Some (build_field c));
+		cg.cl_implements <- List.map (fun (i,tl) -> i, List.map build_type tl) c.cl_implements;
+		cg.cl_ordered_fields <- List.map (fun f ->
+			let f = build_field f in
+			cg.cl_fields <- PMap.add f.cf_name f cg.cl_fields;
+			f
+		) c.cl_ordered_fields;
+		TInst (cg,[])
+
+(* -------------------------------------------------------------------------- *)
+(* HAXE.XML.PROXY *)
+
+let extend_xml_proxy ctx c t file p =
+	let t = Typeload.load_type ctx p t in
+	let file = (try Common.find_file ctx.com file with Not_found -> file) in
+	try
+		let rec loop = function
+			| Xml.Element (_,attrs,childs) ->
+				(try
+					let id = List.assoc "id" attrs in
+					if PMap.mem id c.cl_fields then error ("Duplicate id " ^ id) p;
+					let f = {
+						cf_name = id;
+						cf_type = t;
+						cf_public = true;
+						cf_doc = None;
+						cf_get = ResolveAccess;
+						cf_set = NoAccess;
+						cf_params = [];
+						cf_expr = None;
+					} in
+					c.cl_fields <- PMap.add id f c.cl_fields;
+				with
+					Not_found -> ());
+				List.iter loop childs;
+			| Xml.PCData _ -> ()
+		in
+		loop (Xml.parse_file file)
+	with
+		| Xml.Error e -> error ("XML error " ^ Xml.error e) p
+		| Xml.File_not_found f -> error ("XML File not found : " ^ f) p
+
+(* -------------------------------------------------------------------------- *)
+(* API EVENTS *)
+
+let build_instance ctx mtype p =
+	match mtype with
+	| TClassDecl c ->
+		c.cl_types , c.cl_path , (match c.cl_kind with KGeneric -> build_generic ctx c p | _ -> (fun t -> TInst (c,t)))
+	| TEnumDecl e ->
+		e.e_types , e.e_path , (fun t -> TEnum (e,t))
+	| TTypeDecl t ->
+		t.t_types , t.t_path , (fun tl -> TType(t,tl))
+
+let on_inherit ctx c p h =
+	match h with
+(*/*
+	| HExtends { tpackage = ["haxe";"remoting"]; tname = "Proxy"; tparams = [TPType(TPNormal t)] } ->
+		extend_remoting ctx c t p false true;
+		false
+	| HExtends { tpackage = ["haxe";"remoting"]; tname = "AsyncProxy"; tparams = [TPType(TPNormal t)] } ->
+		extend_remoting ctx c t p true true;
+		false
+	| HExtends { tpackage = ["mt"]; tname = "AsyncProxy"; tparams = [TPType(TPNormal t)] } ->
+		extend_remoting ctx c t p true false;
+		false
+*/*)
+	| HImplements { tpackage = ["haxe";"rtti"]; tname = "Generic"; tparams = [] } ->
+		c.cl_kind <- KGeneric;
+		false
+	| HExtends { tpackage = ["haxe";"xml"]; tname = "Proxy"; tparams = [TPConst(String file);TPType t] } ->
+		extend_xml_proxy ctx c t file p;
+		true
+	| _ ->
+		true
+
+let rec has_rtti c =
+	List.exists (function (t,pl) ->
+		match t, pl with
+		| { cl_path = ["haxe";"rtti"],"Infos" },[] -> true
+		| _ -> false
+	) c.cl_implements || (match c.cl_super with None -> false | Some (c,_) -> has_rtti c)
+
+let on_generate ctx t =
+	match t with
+	| TClassDecl c when has_rtti c ->
+		let f = mk_field "__rtti" ctx.api.tstring in
+		let str = Genxml.gen_type_string ctx.com t in
+		f.cf_expr <- Some (mk (TConst (TString str)) f.cf_type c.cl_pos);
+		c.cl_ordered_statics <- f :: c.cl_ordered_statics;
+		c.cl_statics <- PMap.add f.cf_name f c.cl_statics;
+	| _ ->
+		()
+
+(* -------------------------------------------------------------------------- *)
+(* PER-BLOCK VARIABLES *)
+
+(*
+	This algorithm ensure that variables used in loop sub-functions are captured
+	by value. It transforms the following expression :
+
+	for( x in array )
+		funs.push(function() return x);
+
+	Into the following :
+
+	for( x in array )
+		funs.push(function(x) { function() return x; }(x));
+
+	This way, each value is captured independantly.	
+*)
+
+let block_vars e =
+	let add_var map v d = map := PMap.add v d (!map) in
+	let wrap e used =
+		match PMap.foldi (fun v _ acc -> v :: acc) used [] with
+		| [] -> e
+		| vars ->
+			mk (TCall (
+				(mk (TFunction {
+					tf_args = List.map (fun v -> v , false, t_dynamic) vars;
+					tf_type = t_dynamic;
+					tf_expr = mk (TReturn (Some e)) t_dynamic e.epos;
+				}) t_dynamic e.epos),
+				List.map (fun v -> mk (TLocal v) t_dynamic e.epos) vars)
+			) t_dynamic e.epos
+	in
+	let rec in_fun vars depth used_locals e =
+		match e.eexpr with
+		| TLocal v ->
+			(try
+				if PMap.find v vars = depth then add_var used_locals v depth;				
+			with
+				Not_found -> ())
+		| _ ->
+			iter (in_fun vars depth used_locals) e
+
+	and in_loop vars depth e =
+		match e.eexpr with
+		| TVars l ->
+			{ e with eexpr = TVars (List.map (fun (v,t,e) ->
+				let e = (match e with None -> None | Some e -> Some (in_loop vars depth e)) in
+				add_var vars v depth;
+				v, t, e
+			) l) }
+		| TFor (v,t,i,e1) ->
+			let new_vars = PMap.add v depth (!vars) in
+			{ e with eexpr = TFor (v,t,in_loop vars depth i,in_loop (ref new_vars) depth e1) }
+		| TTry (e1,cases) ->
+			let e1 = in_loop vars depth e1 in
+			let cases = List.map (fun (v,t,e) ->
+				let new_vars = PMap.add v depth (!vars) in
+				v , t, in_loop (ref new_vars) depth e
+			) cases in
+			{ e with eexpr = TTry (e1,cases) }
+		| TMatch (e1,t,cases,def) ->
+			let e1 = in_loop vars depth e1 in
+			let cases = List.map (fun (cl,params,e) ->
+				let e = (match params with
+					| None -> in_loop vars depth e
+					| Some l ->
+						let new_vars = List.fold_left (fun acc (v,t) ->
+							match v with
+							| None -> acc
+							| Some name -> PMap.add name depth acc
+						) (!vars) l in
+						in_loop (ref new_vars) depth e
+				) in
+				cl , params, e
+			) cases in
+			let def = (match def with None -> None | Some e -> Some (in_loop vars depth e)) in
+			{ e with eexpr = TMatch (e1, t, cases, def) }
+		| TBlock l ->
+			let new_vars = (ref !vars) in
+			map_expr (in_loop new_vars depth) e
+		| TFunction _ ->
+			let new_vars = !vars in
+			let used = ref PMap.empty in
+			iter (in_fun new_vars depth used) e;
+			let e = wrap e (!used) in
+			let new_vars = ref (PMap.foldi (fun v _ acc -> PMap.remove v acc) (!used) new_vars) in
+			map_expr (in_loop new_vars (depth + 1)) e
+		| _ ->
+			map_expr (in_loop vars depth) e
+	and out_loop e =
+		match e.eexpr with
+		| TFor _ | TWhile _ ->
+			in_loop (ref PMap.empty) 0 e
+		| _ ->
+			map_expr out_loop e
+	in
+	out_loop e
+
+(* -------------------------------------------------------------------------- *)
+(* STACK MANAGEMENT EMULATION *)
+
+let emk e = mk e (mk_mono()) null_pos
+
+let stack_var = "$s"
+let exc_stack_var = "$e"
+let stack_var_pos = "$spos"
+let stack_e = emk (TLocal stack_var)
+let stack_pop = emk (TCall (emk (TField (stack_e,"pop")),[]))
+
+let stack_push useadd (c,m) =
+	emk (TCall (emk (TField (stack_e,"push")),[
+		if useadd then
+			emk (TBinop (
+				OpAdd,
+				emk (TConst (TString (s_type_path c.cl_path ^ "::"))),
+				emk (TConst (TString m))
+			))
+		else
+			emk (TConst (TString (s_type_path c.cl_path ^ "::" ^ m)))
+	]))
+
+let stack_save_pos =
+	emk (TVars [stack_var_pos, t_dynamic, Some (emk (TField (stack_e,"length")))])
+
+let stack_restore_pos =
+	let ev = emk (TLocal exc_stack_var) in
+	[
+	emk (TBinop (OpAssign, ev, emk (TArrayDecl [])));
+	emk (TWhile (
+		emk (TBinop (OpGte,
+			emk (TField (stack_e,"length")),
+			emk (TLocal stack_var_pos)
+		)),
+		emk (TCall (
+			emk (TField (ev,"unshift")),
+			[emk (TCall (
+				emk (TField (stack_e,"pop")),
+				[]
+			))]
+		)),
+		NormalWhile
+	));
+	emk (TCall (emk (TField (stack_e,"push")),[ emk (TArray (ev,emk (TConst (TInt 0l)))) ]))
+	]
+
+let rec stack_block_loop e =
+	match e.eexpr with
+	| TFunction _ ->
+		e
+	| TReturn None | TReturn (Some { eexpr = TConst _ }) | TReturn (Some { eexpr = TLocal _ }) ->
+		mk (TBlock [
+			stack_pop;
+			e;
+		]) e.etype e.epos
+	| TReturn (Some e) ->
+		mk (TBlock [
+			mk (TVars ["$tmp", t_dynamic, Some (stack_block_loop e)]) t_dynamic e.epos;
+			stack_pop;
+			mk (TReturn (Some (mk (TLocal "$tmp") t_dynamic e.epos))) t_dynamic e.epos
+		]) e.etype e.epos
+	| TTry (v,cases) ->
+		let v = stack_block_loop v in
+		let cases = List.map (fun (n,t,e) ->
+			let e = stack_block_loop e in
+			let e = (match (mk_block e).eexpr with
+				| TBlock l -> mk (TBlock (stack_restore_pos @ l)) e.etype e.epos
+				| _ -> assert false
+			) in
+			n , t , e
+		) cases in
+		mk (TTry (v,cases)) e.etype e.epos
+	| _ ->
+		map_expr stack_block_loop e
+
+let stack_block ?(useadd=false) ctx e =	
+	match (mk_block e).eexpr with
+	| TBlock l -> mk (TBlock (stack_push useadd ctx :: stack_save_pos :: List.map stack_block_loop l @ [stack_pop])) e.etype e.epos
+	| _ -> assert false
+
+(* -------------------------------------------------------------------------- *)
+(* MISC FEATURES *)
+
+let local_find flag vname e =
+	let rec loop2 e =
+		match e.eexpr with
+		| TFunction f ->
+			if not flag && not (List.exists (fun (a,_,_) -> a = vname) f.tf_args) then loop2 f.tf_expr
+		| TBlock _ ->
+			(try
+				Type.iter loop2 e;
+			with
+				Not_found -> ())
+		| TVars vl ->
+			List.iter (fun (v,t,e) ->
+				(match e with
+				| None -> ()
+				| Some e -> loop2 e);
+				if v = vname then raise Not_found;
+			) vl
+		| TConst TSuper ->
+			if vname = "super" then raise Exit
+		| TLocal v ->
+			if v = vname then raise Exit
+		| _ ->
+			iter loop2 e
+	in
+	let rec loop e =
+		match e.eexpr with
+		| TFunction f ->
+			if not (List.exists (fun (a,_,_) -> a = vname) f.tf_args) then loop2 f.tf_expr
+		| TBlock _ ->
+			(try
+				iter loop e;
+			with
+				Not_found -> ())
+		| TVars vl ->
+			List.iter (fun (v,t,e) ->
+				(match e with
+				| None -> ()
+				| Some e -> loop e);
+				if v = vname then raise Not_found;
+			) vl
+		| _ ->
+			iter loop e
+	in
+	try
+		(if flag then loop2 else loop) e;
+		false
+	with
+		Exit ->
+			true
+
+let rec is_volatile t =
+	match t with
+	| TMono r ->
+		(match !r with
+		| Some t -> is_volatile t
+		| _ -> false)
+	| TLazy f ->
+		is_volatile (!f())
+	| TType (t,tl) ->
+		(match t.t_path with
+		| ["mt";"flash"],"Volatile" -> true
+		| _ -> is_volatile (apply_params t.t_types tl t.t_type))
+	| _ ->
+		false

+ 46 - 1
common.ml

@@ -16,6 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *)
+open Type
 
 type package_rule =
 	| Forbidden
@@ -29,23 +30,49 @@ type platform =
 	| Flash9
 	| Php
 
+type pos = Ast.pos
+
+type context_type_api = {
+	(* basic types *)
+	mutable tvoid : t;
+	mutable tint : t;
+	mutable tfloat : t;
+	mutable tbool : t;
+	mutable tnull : t -> t;
+	mutable tstring : t;
+	mutable tarray : t -> t;
+	(* api *)
+	mutable load_module : path -> pos -> module_def;
+	mutable build_instance : module_type -> pos -> ((string * t) list * path * (t list -> t));
+	mutable on_inherit : tclass -> pos -> Ast.class_flag -> bool;
+	mutable on_generate : module_type -> unit;
+	mutable get_type_module : module_type -> module_def;
+}
+
 type context = {
 	(* config *)
 	mutable debug : bool;
 	mutable verbose : bool;
 	mutable platform : platform;
 	mutable class_path : string list;
-	mutable main_class : Type.module_path option; 
+	mutable main_class : Type.path option; 
 	mutable defines : (string,unit) PMap.t;
 	mutable package_rules : (string,package_rule) PMap.t;
+	mutable error : string -> pos -> unit;
+	mutable warning : string -> pos -> unit;
 	(* output *)
 	mutable file : string;
 	mutable flash_version : int;
 	mutable types : Type.module_type list;
 	mutable resources : (string,string) Hashtbl.t;
+	(* typing *)
+	mutable type_api : context_type_api;
 }
 
+exception Abort of string * Ast.pos
+
 let create() =
+	let m = Type.mk_mono() in
 	{
 		debug = false;
 		verbose = false;
@@ -58,11 +85,29 @@ let create() =
 		types = [];
 		flash_version = 8;
 		resources = Hashtbl.create 0;
+		warning = (fun _ _ -> assert false);
+		error = (fun _ _ -> assert false);
+		type_api = {
+			tvoid = m;
+			tint = m;
+			tfloat = m;
+			tbool = m;
+			tnull = (fun _ -> assert false);
+			tstring = m;
+			tarray = (fun _ -> assert false);
+			load_module = (fun _ _ -> assert false);
+			build_instance = (fun _ _ -> assert false);
+			on_inherit = (fun _ _ _ -> true);
+			on_generate = (fun _ -> ());
+			get_type_module = (fun _ -> assert false);
+		};
 	}
 
 let defined ctx v = PMap.mem v ctx.defines
 let define ctx v = ctx.defines <- PMap.add v () ctx.defines
 
+let error msg p = raise (Abort (msg,p))
+
 let platform ctx p = ctx.platform = p
 
 let find_file ctx f =

+ 25 - 10
doc/install.ml

@@ -130,16 +130,31 @@ let compile() =
 	(* HAXE *)
 	Sys.chdir "haxe";
 	command "ocamllex lexer.mll";
-	ocamlc "-I ../ocaml ast.ml type.ml common.ml lexer.ml";
-	ocamlc "-I ../ocaml -pp camlp4o parser.ml";
-	ocamlc "-I ../ocaml -I ../ocaml/swflib -I ../ocaml/xml-light transform.ml typer.ml genswf9.ml genswf8.ml genswf.ml genxml.ml genjs.ml genas3.ml";
-	ocamlc "-I ../ocaml -I ../neko/libs/include/ocaml ../neko/libs/include/ocaml/nast.ml ../neko/libs/include/ocaml/nxml.ml ../neko/libs/include/ocaml/binast.ml genneko.ml";
-	ocamlc "-I ../ocaml -I ../ocaml/extc main.ml";
-	let mlist = ["ast";"type";"common";"lexer";"parser";"transform";"typer";"genswf9";"genswf8";"genswf";"../neko/libs/include/ocaml/nast";"../neko/libs/include/ocaml/nxml";"../neko/libs/include/ocaml/binast";"genneko";"genxml";"genjs";"genas3";"main"] in
-	let libs = ["../ocaml/extLib";"../ocaml/extc/extc";"../ocaml/swflib/swflib";"../ocaml/xml-light/xml-light";"unix"] in
-	let makelibs ext = " " ^ String.concat " " (List.map (fun l -> l ^ ext) libs) ^ " " in
-	if bytecode then command ("ocamlc -custom -o ../bin/haxe-byte" ^ exe_ext ^ makelibs ".cma" ^ modules mlist ".cmo");
-	if native then command ("ocamlopt -o ../bin/haxe" ^ exe_ext ^ makelibs ".cmxa" ^ modules mlist ".cmx");
+	let libs = [
+		"../ocaml/extLib";
+		"../ocaml/extc/extc";
+		"../ocaml/swflib/swflib";
+		"../ocaml/xml-light/xml-light";
+		"unix"
+	] in
+	let paths = [
+		"../ocaml";
+		"../ocaml/swflib";
+		"../ocaml/xml-light";
+		"../neko/libs/include/ocaml"
+	] in
+	let mlist = [
+		"ast";"lexer";"type";"common";"parser";"typecore";
+		"genxml";"typeload";"codegen";"typer";
+		"nast";"binast";"nxml";
+		"genneko";"genas3";"genjs";"genswf8";"genswf9";"genswf";
+		"main";
+	] in
+	let path_str = String.concat " " (List.map (fun s -> "-I " ^ s) paths) in
+	let libs_str ext = " " ^ String.concat " " (List.map (fun l -> l ^ ext) libs) ^ " " in
+	ocamlc (path_str ^ " " ^ modules mlist ".ml");
+	if bytecode then command ("ocamlc -custom -o ../bin/haxe-byte" ^ exe_ext ^ libs_str ".cma" ^ modules mlist ".cmo");
+	if native then command ("ocamlopt -o ../bin/haxe" ^ exe_ext ^ libs_str ".cmxa" ^ modules mlist ".cmx");
 
 in
 let startdir = Sys.getcwd() in

+ 11 - 13
genas3.ml

@@ -22,7 +22,7 @@ open Common
 type context = {
 	ch : out_channel;
 	buf : Buffer.t;
-	path : module_path;
+	path : path;
 	mutable get_sets : (string * bool,string) Hashtbl.t;
 	mutable curclass : tclass;
 	mutable tabs : string;
@@ -135,7 +135,7 @@ let define_local ctx l =
 let spr ctx s = Buffer.add_string ctx.buf s
 let print ctx = Printf.kprintf (fun s -> Buffer.add_string ctx.buf s)
 
-let unsupported = Typer.error "This expression cannot be generated to AS3"
+let unsupported p = error "This expression cannot be generated to AS3" p
 
 let newline ctx =
 	match Buffer.nth ctx.buf (Buffer.length ctx.buf - 1) with
@@ -155,8 +155,6 @@ let open_block ctx =
 	ctx.tabs <- "\t" ^ ctx.tabs;
 	(fun() -> ctx.tabs <- oldt)
 
-let block = Transform.block
-
 let parent e =
 	match e.eexpr with
 	| TParenthesis _ -> e
@@ -375,7 +373,7 @@ and gen_expr ctx e =
 	| TConst c ->
 		gen_constant ctx e.epos c
 	| TLocal s ->
-		spr ctx (try PMap.find s ctx.locals with Not_found -> Typer.error ("Unknown local " ^ s) e.epos)
+		spr ctx (try PMap.find s ctx.locals with Not_found -> error ("Unknown local " ^ s) e.epos)
 	| TEnumField (en,s) ->
 		print ctx "%s.%s" (s_path ctx en.e_path e.epos) (s_ident s)
 	| TArray ({ eexpr = TLocal "__global__" },{ eexpr = TConst (TString s) }) ->
@@ -450,7 +448,7 @@ and gen_expr ctx e =
 		let h = gen_function_header ctx None f [] e.epos in
 		let old = ctx.in_static in
 		ctx.in_static <- true;
-		gen_expr ctx (block f.tf_expr);
+		gen_expr ctx (mk_block f.tf_expr);
 		ctx.in_static <- old;
 		h();
 	| TCall (e,el) ->
@@ -531,13 +529,13 @@ and gen_expr ctx e =
 		handle_break();
 	| TTry (e,catchs) ->
 		spr ctx "try ";
-		gen_expr ctx (block e);
+		gen_expr ctx (mk_block e);
 		List.iter (fun (v,t,e) ->
 			newline ctx;
 			let b = save_locals ctx in
 			let v = define_local ctx v in
 			print ctx "catch( %s : %s )" v (type_str ctx t e.epos);
-			gen_expr ctx (block e);
+			gen_expr ctx (mk_block e);
 			b();
 		) catchs;
 	| TMatch (e,_,cases,def) ->
@@ -568,7 +566,7 @@ and gen_expr ctx e =
 						print ctx "%s : %s = %s.params[%d]" v (type_str ctx t e.epos) tmp n;
 					) l;
 					newline ctx);
-			gen_expr ctx (block e);
+			gen_expr ctx (mk_block e);
 			print ctx "break";
 			newline ctx;
 			b()
@@ -577,7 +575,7 @@ and gen_expr ctx e =
 		| None -> ()
 		| Some e ->
 			spr ctx "default:";
-			gen_expr ctx (block e);
+			gen_expr ctx (mk_block e);
 			print ctx "break";
 			newline ctx;
 		);
@@ -594,7 +592,7 @@ and gen_expr ctx e =
 				gen_value ctx e;
 				spr ctx ":";
 			) el;
-			gen_expr ctx (block e2);
+			gen_expr ctx (mk_block e2);
 			print ctx "break";
 			newline ctx;
 		) cases;
@@ -602,7 +600,7 @@ and gen_expr ctx e =
 		| None -> ()
 		| Some e ->
 			spr ctx "default:";
-			gen_expr ctx (block e);
+			gen_expr ctx (mk_block e);
 			print ctx "break";
 			newline ctx;
 		);
@@ -757,7 +755,7 @@ let generate_field ctx static f =
 		in
 		if not static then loop ctx.curclass;
 		let h = gen_function_header ctx (Some (s_ident f.cf_name)) fd f.cf_params p in
-		gen_expr ctx (block fd.tf_expr);
+		gen_expr ctx (mk_block fd.tf_expr);
 		h()
 	| _ ->
 		if ctx.curclass.cl_path = (["flash"],"Boot") && f.cf_name = "init" then

+ 15 - 17
genjs.ml

@@ -55,7 +55,7 @@ let ident s = if Hashtbl.mem kwds s then "$" ^ s else s
 let spr ctx s = Buffer.add_string ctx.buf s
 let print ctx = Printf.kprintf (fun s -> Buffer.add_string ctx.buf s)
 
-let unsupported = Typer.error "This expression cannot be compiled to Javascript"
+let unsupported p = error "This expression cannot be compiled to Javascript" p
 
 let newline ctx =
 	match Buffer.nth ctx.buf (Buffer.length ctx.buf - 1) with
@@ -70,13 +70,11 @@ let rec concat ctx s f = function
 		spr ctx s;
 		concat ctx s f l
 
-let block = Transform.block
-
 let fun_block ctx f =
 	if ctx.com.debug then
-		Transform.stack_block (ctx.current,fst ctx.curmethod) f.tf_expr
+		Codegen.stack_block (ctx.current,fst ctx.curmethod) f.tf_expr
 	else
-		block f.tf_expr
+		mk_block f.tf_expr
 
 let parent e =
 	match e.eexpr with
@@ -120,7 +118,7 @@ let gen_constant ctx p = function
 	| TInt i -> print ctx "%ld" i
 	| TFloat s -> spr ctx s
 	| TString s ->
-		if String.contains s '\000' then Typer.error "A String cannot contain \\0 characters" p;
+		if String.contains s '\000' then error "A String cannot contain \\0 characters" p;
 		print ctx "\"%s\"" (Ast.s_escape s)
 	| TBool b -> spr ctx (if b then "true" else "false")
 	| TNull -> spr ctx "null"
@@ -332,7 +330,7 @@ and gen_expr ctx e =
 		handle_break();
 	| TTry (e,catchs) ->
 		spr ctx "try ";
-		gen_expr ctx (block e);
+		gen_expr ctx (mk_block e);
 		newline ctx;
 		let id = ctx.id_counter in
 		ctx.id_counter <- ctx.id_counter + 1;
@@ -407,7 +405,7 @@ and gen_expr ctx e =
 						print ctx "%s = $e[%d]" v n;
 					) l;
 					newline ctx);
-			gen_expr ctx (block e);
+			gen_expr ctx (mk_block e);
 			print ctx "break";
 			newline ctx
 		) cases;
@@ -415,7 +413,7 @@ and gen_expr ctx e =
 		| None -> ()
 		| Some e ->
 			spr ctx "default:";
-			gen_expr ctx (block e);
+			gen_expr ctx (mk_block e);
 			print ctx "break";
 			newline ctx;
 		);
@@ -431,7 +429,7 @@ and gen_expr ctx e =
 				gen_value ctx e;
 				spr ctx ":";
 			) el;
-			gen_expr ctx (block e2);
+			gen_expr ctx (mk_block e2);
 			print ctx "break";
 			newline ctx;
 		) cases;
@@ -439,7 +437,7 @@ and gen_expr ctx e =
 		| None -> ()
 		| Some e ->
 			spr ctx "default:";
-			gen_expr ctx (block e);
+			gen_expr ctx (mk_block e);
 			print ctx "break";
 			newline ctx;
 		);
@@ -575,7 +573,7 @@ let gen_class_static_field ctx c f =
 		print ctx "%s%s = null" (s_path c.cl_path) (field f.cf_name);
 		newline ctx
 	| Some e ->
-		let e = Transform.block_vars e in
+		let e = Codegen.block_vars e in
 		match e.eexpr with
 		| TFunction _ ->
 			ctx.curmethod <- (f.cf_name,false);
@@ -593,7 +591,7 @@ let gen_class_field ctx c f =
 		newline ctx
 	| Some e ->
 		ctx.curmethod <- (f.cf_name,false);
-		gen_value ctx (Transform.block_vars e);
+		gen_value ctx (Codegen.block_vars e);
 		newline ctx
 
 let generate_class ctx c =
@@ -604,7 +602,7 @@ let generate_class ctx c =
 	print ctx "%s = " p;
 	(match c.cl_constructor with
 	| Some { cf_expr = Some e } ->
-		(match Transform.block_vars e with
+		(match Codegen.block_vars e with
 		| { eexpr = TFunction f } ->
 			let args  = List.map arg_name f.tf_args in
 			let a, args = (match args with [] -> "p" , ["p"] | x :: _ -> x, args) in
@@ -666,7 +664,7 @@ let generate_type ctx = function
 	| TClassDecl c ->
 		(match c.cl_init with
 		| None -> ()
-		| Some e -> ctx.inits <- Transform.block_vars e :: ctx.inits);
+		| Some e -> ctx.inits <- Codegen.block_vars e :: ctx.inits);
 		if not c.cl_extern then generate_class ctx c
 	| TEnumDecl e when e.e_extern ->
 		()
@@ -696,9 +694,9 @@ let generate com =
 	print ctx "js.Boot.__res = {}";
 	newline ctx;
 	if com.debug then begin
-		print ctx "%s = []" Transform.stack_var;
+		print ctx "%s = []" Codegen.stack_var;
 		newline ctx;
-		print ctx "%s = []" Transform.exc_stack_var;
+		print ctx "%s = []" Codegen.exc_stack_var;
 		newline ctx;
 	end;
 	Hashtbl.iter (fun name data ->

+ 1 - 4
genneko.ml

@@ -31,9 +31,6 @@ type context = {
 	mutable inits : texpr list;
 }
 
-let error msg p =
-	raise (Typer.Error (Typer.Custom msg,p))
-
 let files = Hashtbl.create 0
 
 let pos ctx p =
@@ -191,7 +188,7 @@ let rec gen_big_string ctx p s =
 let gen_constant ctx pe c =
 	let p = pos ctx pe in
 	match c with
-	| TInt i -> (try int p (Int32.to_int i) with _ -> Typer.error "This integer is too big to be compiled to a Neko 31-bit integer. Please use a Float instead" pe)
+	| TInt i -> (try int p (Int32.to_int i) with _ -> error "This integer is too big to be compiled to a Neko 31-bit integer. Please use a Float instead" pe)
 	| TFloat f -> (EConst (Float f),p)
 	| TString s -> call p (field p (ident p "String") "new") [gen_big_string ctx p s]
 	| TBool b -> (EConst (if b then True else False),p)

+ 22 - 19
genswf8.ml

@@ -43,7 +43,7 @@ type context = {
 	packages : (string list,unit) Hashtbl.t;
 	flash6 : bool;
 	mutable idents : (string * bool,int) Hashtbl.t;
-	mutable movieclips : module_path list;
+	mutable movieclips : path list;
 	mutable inits : texpr list;
 	mutable statics : (tclass * bool * string * texpr) list;
 	mutable regs : (string,register) PMap.t;
@@ -62,8 +62,8 @@ type context = {
 	mutable in_loop : bool;
 }
 
-let error p = Typer.error "Invalid expression" p
-let stack_error p = Typer.error "Stack error" p
+let invalid_expr p = error "Invalid expression" p
+let stack_error p = error "Stack error" p
 let protect_all = ref true
 let extern_boot = ref false
 let debug_pass = ref ""
@@ -437,7 +437,7 @@ let segment ctx =
 (* Generation Helpers *)
 
 let define_var ctx v ef exprs =
-	if ctx.flash6 || List.exists (Transform.local_find false v) exprs then begin
+	if ctx.flash6 || List.exists (Codegen.local_find false v) exprs then begin
 		push ctx [VStr (v,false)];
 		ctx.regs <- PMap.add v NoReg ctx.regs;
 		match ef with
@@ -531,9 +531,9 @@ let rec gen_big_string ctx s =
 let rec gen_constant ctx c p =
 	match c with
 	| TInt i -> push ctx [VInt32 i]
-	| TFloat s -> push ctx [VFloat (try float_of_string s with _ -> error p)]
+	| TFloat s -> push ctx [VFloat (try float_of_string s with _ -> invalid_expr p)]
 	| TString s ->
-		if String.contains s '\000' then Typer.error "A String cannot contain \\0 characters" p;
+		if String.contains s '\000' then error "A String cannot contain \\0 characters" p;
 		push ctx [VStr (s,true)]
 	| TBool b -> write ctx (APush [PBool b])
 	| TNull -> push ctx [VNull]
@@ -578,7 +578,7 @@ let rec gen_access ctx forcall e =
 		(match follow e.etype with
 		| TFun _ -> VarClosure
 		| _ ->
-			if not !protect_all && Transform.is_volatile e.etype then
+			if not !protect_all && Codegen.is_volatile e.etype then
 				VarVolatile
 			else
 				VarObj)
@@ -598,7 +598,7 @@ let rec gen_access ctx forcall e =
 		| TEnumDecl e -> gen_path ctx e.e_path false
 		| TTypeDecl _ -> assert false)
 	| _ ->
-		if not forcall then error e.epos;
+		if not forcall then invalid_expr e.epos;
 		gen_expr ctx true e;
 		write ctx (APush [PUndefined]);
 		VarObj
@@ -937,7 +937,7 @@ and gen_expr_2 ctx retval e =
 		let block = open_block ctx in
 		let old_in_loop = ctx.in_loop in
 		let old_meth = ctx.curmethod in
-		let reg_super = Transform.local_find true "super" f.tf_expr in
+		let reg_super = Codegen.local_find true "super" f.tf_expr in
 		if snd ctx.curmethod then
 			ctx.curmethod <- (fst ctx.curmethod ^ "@" ^ string_of_int (Lexer.get_error_line e.epos), true)
 		else
@@ -952,7 +952,7 @@ and gen_expr_2 ctx retval e =
 		ctx.in_loop <- false;
 		let pargs = ref [] in
 		let rargs = List.map (fun (a,_,t) ->
-			let no_reg = ctx.flash6 || Transform.local_find false a f.tf_expr in
+			let no_reg = ctx.flash6 || Codegen.local_find false a f.tf_expr in
 			if no_reg then begin
 				ctx.regs <- PMap.add a NoReg ctx.regs;
 				pargs := unprotect a :: !pargs;
@@ -964,14 +964,17 @@ and gen_expr_2 ctx retval e =
 				r , ""
 			end
 		) f.tf_args in
-		let tf = begin_func ctx reg_super (Transform.local_find true "__arguments__" f.tf_expr) rargs in
+		let tf = begin_func ctx reg_super (Codegen.local_find true "__arguments__" f.tf_expr) rargs in
 		ctx.fun_pargs <- (ctx.code_pos, List.rev !pargs) :: ctx.fun_pargs;
 		if ctx.com.debug then begin
+			let cur = (ctx.curclass,fst ctx.curmethod) in
+			gen_expr ctx false (Codegen.stack_push true cur);
+			gen_expr ctx false Codegen.stack_save_pos;
 			let start_try = gen_try ctx in
-			gen_expr ctx false (Transform.stack_block ~useadd:true (ctx.curclass,fst ctx.curmethod) f.tf_expr);
+			gen_expr ctx false (Codegen.stack_block_loop f.tf_expr);
 			let end_try = start_try() in
 			(* if $spos == 1 , then no upper call, so report as uncaught *)
-			getvar ctx (access_local ctx Transform.stack_var_pos);
+			getvar ctx (access_local ctx Codegen.stack_var_pos);
 			push ctx [VInt 1];
 			write ctx AEqual;
 			write ctx ANot;
@@ -1110,7 +1113,7 @@ let gen_class_static_field ctx c flag f =
 		push ctx [VReg 0; VStr (f.cf_name,flag); VNull];
 		setvar ctx VarObj
 	| Some e ->
-		let e = Transform.block_vars e in
+		let e = Codegen.block_vars e in
 		match e.eexpr with
 		| TFunction _ ->
 			push ctx [VReg 0; VStr (f.cf_name,flag)];
@@ -1135,7 +1138,7 @@ let gen_class_field ctx flag f =
 		push ctx [VNull]
 	| Some e ->
 		ctx.curmethod <- (f.cf_name,false);
-		gen_expr ctx true (Transform.block_vars e));
+		gen_expr ctx true (Codegen.block_vars e));
 	setvar ctx VarObj
 
 let gen_enum_field ctx e f =
@@ -1232,7 +1235,7 @@ let gen_type_def ctx t =
 	| TClassDecl c ->
 		(match c.cl_init with
 		| None -> ()
-		| Some e -> ctx.inits <- Transform.block_vars e :: ctx.inits);
+		| Some e -> ctx.inits <- Codegen.block_vars e :: ctx.inits);
 		gen_package ctx c.cl_path c.cl_extern;
 		if c.cl_extern then
 			()
@@ -1255,7 +1258,7 @@ let gen_type_def ctx t =
 		| Some { cf_expr = Some e } ->
 			have_constr := true;
 			ctx.curmethod <- ("new",false);
-			gen_expr ctx true (Transform.block_vars e)
+			gen_expr ctx true (Codegen.block_vars e)
 		| _ ->
 			let f = begin_func ctx true false [] in
 			f());
@@ -1435,10 +1438,10 @@ let generate com =
 	protect_all := not (Common.defined com "swf-mark");
 	extern_boot := true;
 	if com.debug then begin
-		push ctx [VStr (Transform.stack_var,false); VInt 0];
+		push ctx [VStr (Codegen.stack_var,false); VInt 0];
 		write ctx AInitArray;
 		write ctx ASet;
-		push ctx [VStr (Transform.exc_stack_var,false); VInt 0];
+		push ctx [VStr (Codegen.exc_stack_var,false); VInt 0];
 		write ctx AInitArray;
 		write ctx ASet;
 	end;

+ 14 - 14
genswf9.ml

@@ -93,8 +93,8 @@ type context = {
 	mutable for_call : bool;
 }
 
-let error p = Typer.error "Invalid expression" p
-let stack_error p = Typer.error "Stack error" p
+let invalid_expr p = error "Invalid expression" p
+let stack_error p = error "Stack error" p
 
 let index_int (x : int) : 'a index = Obj.magic (x + 1)
 let index_nz_int (x : int) : 'a index_nz = Obj.magic x
@@ -351,7 +351,7 @@ let pop ctx n =
 	ctx.infos.istack <- old
 
 let define_local ctx ?(init=false) name t el =
-	let l = (if List.exists (Transform.local_find false name) el then begin
+	let l = (if List.exists (Codegen.local_find false name) el then begin
 			let pos = (try
 				let slot , _ , _ = (List.find (fun (_,x,_) -> name = x) ctx.block_vars) in
 				slot
@@ -373,7 +373,7 @@ let define_local ctx ?(init=false) name t el =
 let is_set v = (Obj.magic v) = Write
 
 let gen_local_access ctx name p (forset : 'a)  : 'a access =
-	match (try PMap.find name ctx.locals with Not_found -> Typer.error ("Unbound variable " ^ name) p) with
+	match (try PMap.find name ctx.locals with Not_found -> error ("Unbound variable " ^ name) p) with
 	| LReg r ->
 		VReg r
 	| LScope n ->
@@ -507,7 +507,7 @@ let begin_fun ctx args tret el stat p =
 		match e.eexpr with
 		| TFunction _ -> ()
 		| TConst TThis | TConst TSuper -> raise Exit
-		| _ -> Transform.iter find_this e
+		| _ -> Type.iter find_this e
 	in
 	let this_reg = try List.iter find_this el; false with Exit -> true in
 	ctx.locals <- PMap.foldi (fun name l acc ->
@@ -655,7 +655,7 @@ let gen_constant ctx c t p =
 		write ctx HNull;
 		(match classify ctx t with
 		| KInt | KBool | KUInt | KFloat ->
-			Typer.error ("In Flash9, null can't be used as basic type " ^ s_type (print_context()) t) p
+			error ("In Flash9, null can't be used as basic type " ^ s_type (print_context()) t) p
 		| x -> coerce ctx x)
 	| TThis ->
 		write ctx HThis
@@ -676,7 +676,7 @@ let gen_access ctx e (forset : 'a) : 'a access =
 		gen_local_access ctx i e.epos forset
 	| TField (e1,f) ->
 		let id, k, closure = property f e1.etype in
-		if closure && not ctx.for_call then Typer.error "In Flash9, this method cannot be accessed this way : please define a local function" e1.epos;
+		if closure && not ctx.for_call then error "In Flash9, this method cannot be accessed this way : please define a local function" e1.epos;
 		(match e1.eexpr with
 		| TConst TThis when not ctx.in_static -> write ctx (HFindPropStrict id)
 		| _ -> gen_expr ctx true e1);
@@ -708,7 +708,7 @@ let gen_access ctx e (forset : 'a) : 'a access =
 		if is_set forset then write ctx HGetGlobalScope;
 		VGlobal id
 	| _ ->
-		error e.epos
+		invalid_expr e.epos
 
 let rec gen_expr_content ctx retval e =
 	match e.eexpr with
@@ -819,7 +819,7 @@ let rec gen_expr_content ctx retval e =
 	| TUnop (op,flag,e) ->
 		gen_unop ctx retval op flag e
 	| TTry (e2,cases) ->
-		if ctx.infos.istack <> 0 then Typer.error "Cannot compile try/catch as a right-side expression in Flash9" e.epos;
+		if ctx.infos.istack <> 0 then error "Cannot compile try/catch as a right-side expression in Flash9" e.epos;
 		let branch = begin_branch ctx in
 		let p = ctx.infos.ipos in
 		gen_expr ctx retval e2;
@@ -1349,7 +1349,7 @@ and jump_expr ctx e jif =
 	jump_expr_gen ctx e jif (jump ctx)
 
 let generate_method ctx fdata stat =
-	generate_function ctx { fdata with tf_expr = Transform.block_vars fdata.tf_expr } stat
+	generate_function ctx { fdata with tf_expr = Codegen.block_vars fdata.tf_expr } stat
 
 let generate_construct ctx fdata c =
 	(* make all args optional to allow no-param constructor *)
@@ -1374,7 +1374,7 @@ let generate_construct ctx fdata c =
 			write ctx (HInitProp id);
 		| _ -> ()
 	) c.cl_fields;
-	gen_expr ctx false (Transform.block_vars fdata.tf_expr);
+	gen_expr ctx false (Codegen.block_vars fdata.tf_expr);
 	write ctx HRetVoid;
 	f() , List.length fdata.tf_args
 
@@ -1416,7 +1416,7 @@ let generate_class_statics ctx c =
 				first := false;
 			end;
 			write ctx (HReg r.rid);
-			gen_expr ctx true (Transform.block_vars e);
+			gen_expr ctx true (Codegen.block_vars e);
 			write ctx (HSetSlot !nslot);
 		| _ ->
 			incr nslot
@@ -1537,7 +1537,7 @@ let generate_class ctx c =
 		hlc_interface = c.cl_interface;
 		hlc_namespace = None;
 		hlc_implements = Array.of_list (List.map (fun (c,_) ->
-			if not c.cl_interface then Typer.error "Can't implement class in Flash9" c.cl_pos;
+			if not c.cl_interface then error "Can't implement class in Flash9" c.cl_pos;
 			type_path ctx c.cl_path
 		) c.cl_implements);
 		hlc_construct = cid;
@@ -1720,7 +1720,7 @@ let generate_inits ctx types =
 		| TClassDecl c ->
 			(match c.cl_init with
 			| None -> ()
-			| Some e -> gen_expr ctx false (Transform.block_vars e));
+			| Some e -> gen_expr ctx false (Codegen.block_vars e));
 		| _ -> ()
 	) types;
 	List.iter (fun (t,_) ->

+ 4 - 6
genxml.ml

@@ -117,8 +117,8 @@ let rec exists f c =
 			| None -> true
 			| Some (csup,_) -> exists f csup
 
-let gen_type_decl ctx t =
-	let m = Typer.module_of_type ctx t in
+let gen_type_decl com t =
+	let m = com.type_api.get_type_module t in
 	match t with
 	| TClassDecl c ->
 		let stats = List.map (gen_field ["static","1"]) c.cl_ordered_statics in
@@ -172,9 +172,9 @@ let rec write_xml ch tabs x =
 	| CData s ->
 		IO.printf ch "<![CDATA[%s]]>" s
 
-let generate com ctx file =
+let generate com file =
 	let t = Common.timer "construct xml" in
-	let x = node "haxe" [] (List.map (gen_type_decl ctx) com.types) in
+	let x = node "haxe" [] (List.map (gen_type_decl com) com.types) in
 	t();
 	let t = Common.timer "write xml" in
 	let ch = IO.output_channel (open_out_bin file) in
@@ -188,5 +188,3 @@ let gen_type_string ctx t =
 	write_xml ch "" x;
 	IO.close_out ch
 
-;;
-Typer.generate_meta_data := gen_type_string;

+ 8 - 2
haxe.vcproj

@@ -67,6 +67,9 @@
 		<File
 			RelativePath=".\ast.ml">
 		</File>
+		<File
+			RelativePath=".\codegen.ml">
+		</File>
 		<File
 			RelativePath=".\common.ml">
 		</File>
@@ -98,10 +101,13 @@
 			RelativePath=".\parser.ml">
 		</File>
 		<File
-			RelativePath=".\transform.ml">
+			RelativePath=".\type.ml">
+		</File>
+		<File
+			RelativePath=".\typecore.ml">
 		</File>
 		<File
-			RelativePath=".\type.ml">
+			RelativePath=".\typeload.ml">
 		</File>
 		<File
 			RelativePath=".\typer.ml">

+ 19 - 17
main.ml

@@ -21,7 +21,6 @@ open Genswf
 open Common
 
 let prompt = ref false
-let has_error = ref false
 let display = ref false
 let measure_times = ref false
 
@@ -36,7 +35,7 @@ let normalize_path p =
 		| '\\' | '/' -> p
 		| _ -> p ^ "/"
 
-let warn msg p =
+let message msg p =
 	if p = Ast.null_pos then
 		prerr_endline msg
 	else begin
@@ -54,7 +53,7 @@ let do_exit() =
 	exit 1
 
 let report msg p =
-	warn msg p;
+	message msg p;
 	do_exit()
 
 let htmlescape s =
@@ -69,15 +68,6 @@ let report_list l =
 	) (List.sort (fun (a,_,_) (b,_,_) -> compare a b) l);
 	prerr_endline "</list>"
 
-let type_error e p =
-	warn (Typer.error_msg e) p;
-	has_error := true
-
-let parse_error e p =
-	Lexer.save_lines();
-	warn (Parser.error_msg e) p;
-	has_error := true
-
 let file_extension f =
 	let cl = ExtString.String.nsplit f "." in
 	match List.rev cl with
@@ -186,12 +176,22 @@ try
 	let cmds = ref [] in
 	let excludes = ref [] in
 	let libs = ref [] in
+	let has_error = ref false in
 	let gen_as3 = ref false in
 	let no_output = ref false in
 	let did_something = ref false in
 	let root_packages = ["neko"; "flash"; "flash9"; "js"; "php"] in
 	Common.define com ("haxe_" ^ string_of_int version);
-	Parser.display_error := parse_error;
+	com.warning <- message;
+	com.error <- (fun msg p ->
+		message msg p;
+		has_error := true;
+	);
+	Parser.display_error := (fun e p ->
+		Lexer.save_lines();
+		message (Parser.error_msg e) p;
+		has_error := true;
+	);
 	Parser.use_doc := false;
 	(try
 		let p = Sys.getenv "HAXE_LIBRARY_PATH" in
@@ -391,8 +391,9 @@ try
 	end else begin
 		if com.verbose then print_endline ("Classpath : " ^ (String.concat ";" com.class_path));
 		let t = Common.timer "typing" in
-		let ctx = Typer.context com type_error warn in
-		List.iter (fun cpath -> ignore(Typer.load ctx cpath Ast.null_pos)) (List.rev !classes);
+		Typecore.type_expr_ref := (fun ctx e need_val -> Typer.type_expr ~need_val ctx e);
+		let ctx = Typer.create com in		
+		List.iter (fun cpath -> ignore(com.type_api.load_module cpath Ast.null_pos)) (List.rev !classes);
 		Typer.finalize ctx;
 		t();
 		if !has_error then do_exit();
@@ -421,7 +422,7 @@ try
 		| None -> ()
 		| Some file ->
 			if com.verbose then print_endline ("Generating xml : " ^ com.file);
-			Genxml.generate com ctx file);
+			Genxml.generate com file);
 	end;
 	if not !no_output then List.iter (fun cmd ->
 		let t = Common.timer "command" in
@@ -433,9 +434,10 @@ try
 		t();
 	) (List.rev !cmds)
 with
+	| Common.Abort (m,p) -> report m p
 	| Lexer.Error (m,p) -> report (Lexer.error_msg m) p
 	| Parser.Error (m,p) -> report (Parser.error_msg m) p
-	| Typer.Error (m,p) -> report (Typer.error_msg m) p
+	| Typecore.Error (m,p) -> report (Typecore.error_msg m) p
 	| Failure msg | Arg.Bad msg -> report ("Error : " ^ msg) Ast.null_pos
 	| Arg.Help msg -> print_string msg
 	| Hxml_found -> ()

+ 1 - 1
std/haxe/io/Bytes.hx

@@ -201,7 +201,7 @@ class Bytes {
 		var a = new Array();
 		// utf8-decode
 		for( i in 0...s.length ) {
-			var c : Int = untyped s.cca(i);
+			var c : Int = untyped s["cca"](i);
 			if( c < 0x7F )
 				a.push(c);
 			else if( c < 0x7FF ) {

+ 0 - 331
transform.ml

@@ -1,331 +0,0 @@
-(*
- *  Haxe Compiler
- *  Copyright (c)2005 Nicolas Cannasse
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *)
-open Ast
-open Type
-
-let rec iter f e =
-	match e.eexpr with
-	| TConst _
-	| TLocal _
-	| TEnumField _
-	| TBreak
-	| TContinue
-	| TTypeExpr _ -> ()
-	| TArray (e1,e2)
-	| TBinop (_,e1,e2)
-	| TFor (_,_,e1,e2)
-	| TWhile (e1,e2,_)
-		-> f e1; f e2
-	| TThrow e
-	| TField (e,_)
-	| TParenthesis e
-	| TUnop (_,_,e)
-	| TFunction { tf_expr = e }
-		-> f e
-	| TArrayDecl el 
-	| TNew (_,_,el)
-	| TBlock el
-		-> List.iter f el
-	| TObjectDecl el -> List.iter (fun (_,e) -> f e) el
-	| TCall (e,el) -> f e; List.iter f el
-	| TVars vl -> List.iter (fun (_,_,eo) -> match eo with None -> () | Some e -> f e) vl
-	| TIf (e,e1,e2) -> f e; f e1; (match e2 with None -> () | Some e -> f e)
-	| TSwitch (e,cases,def) -> f e; List.iter (fun (el,e) -> List.iter f el; f e) cases; (match def with None -> () | Some e -> f e)
-	| TMatch (e,_,cases,def) -> f e; List.iter (fun (_,_,e) -> f e) cases; (match def with None -> () | Some e -> f e)
-	| TTry (e,catches) -> f e; List.iter (fun (_,_,e) -> f e) catches
-	| TReturn eo -> (match eo with None -> () | Some e -> f e)
-
-let rec map f e =
-	match e.eexpr with
-	| TConst _
-	| TLocal _
-	| TEnumField _
-	| TBreak
-	| TContinue
-	| TTypeExpr _ ->
-		e
-	| TArray (e1,e2) ->
-		{ e with eexpr = TArray (f e1,f e2) }
-	| TBinop (op,e1,e2) ->
-		{ e with eexpr = TBinop (op,f e1,f e2) }
-	| TFor (v,t,e1,e2) ->
-		{ e with eexpr = TFor (v,t,f e1,f e2) }
-	| TWhile (e1,e2,flag) ->
-		{ e with eexpr = TWhile (f e1,f e2,flag) }
-	| TThrow e1 ->
-		{ e with eexpr = TThrow (f e1) }
-	| TField (e1,v) ->
-		{ e with eexpr = TField (f e1,v) }
-	| TParenthesis e1 ->
-		{ e with eexpr = TParenthesis (f e1) }
-	| TUnop (op,pre,e1) ->
-		{ e with eexpr = TUnop (op,pre,f e1) }
-	| TArrayDecl el ->
-		{ e with eexpr = TArrayDecl (List.map f el) }
-	| TNew (t,pl,el) ->
-		{ e with eexpr = TNew (t,pl,List.map f el) }
-	| TBlock el ->
-		{ e with eexpr = TBlock (List.map f el) }
-	| TObjectDecl el ->
-		{ e with eexpr = TObjectDecl (List.map (fun (v,e) -> v, f e) el) }
-	| TCall (e1,el) ->
-		{ e with eexpr = TCall (f e1, List.map f el) }
-	| TVars vl ->
-		{ e with eexpr = TVars (List.map (fun (v,t,e) -> v , t , match e with None -> None | Some e -> Some (f e)) vl) }
-	| TFunction fu ->
-		{ e with eexpr = TFunction { fu with tf_expr = f fu.tf_expr } }
-	| TIf (ec,e1,e2) ->
-		{ e with eexpr = TIf (f ec,f e1,match e2 with None -> None | Some e -> Some (f e)) }
-	| TSwitch (e1,cases,def) ->
-		{ e with eexpr = TSwitch (f e1, List.map (fun (el,e2) -> List.map f el, f e2) cases, match def with None -> None | Some e -> Some (f e)) }
-	| TMatch (e1,t,cases,def) ->
-		{ e with eexpr = TMatch (f e1, t, List.map (fun (cl,params,e) -> cl, params, f e) cases, match def with None -> None | Some e -> Some (f e)) }
-	| TTry (e1,catches) ->
-		{ e with eexpr = TTry (f e1, List.map (fun (v,t,e) -> v, t, f e) catches) }
-	| TReturn eo ->
-		{ e with eexpr = TReturn (match eo with None -> None | Some e -> Some (f e)) }
-
-let local_find flag vname e =
-	let rec loop2 e =
-		match e.eexpr with
-		| TFunction f ->
-			if not flag && not (List.exists (fun (a,_,_) -> a = vname) f.tf_args) then loop2 f.tf_expr
-		| TBlock _ ->
-			(try
-				iter loop2 e;
-			with
-				Not_found -> ())
-		| TVars vl ->
-			List.iter (fun (v,t,e) ->
-				(match e with
-				| None -> ()
-				| Some e -> loop2 e);
-				if v = vname then raise Not_found;
-			) vl
-		| TConst TSuper ->
-			if vname = "super" then raise Exit
-		| TLocal v ->
-			if v = vname then raise Exit
-		| _ ->
-			iter loop2 e
-	in
-	let rec loop e =
-		match e.eexpr with
-		| TFunction f ->
-			if not (List.exists (fun (a,_,_) -> a = vname) f.tf_args) then loop2 f.tf_expr
-		| TBlock _ ->
-			(try
-				iter loop e;
-			with
-				Not_found -> ())
-		| TVars vl ->
-			List.iter (fun (v,t,e) ->
-				(match e with
-				| None -> ()
-				| Some e -> loop e);
-				if v = vname then raise Not_found;
-			) vl
-		| _ ->
-			iter loop e
-	in
-	try
-		(if flag then loop2 else loop) e;
-		false
-	with
-		Exit ->
-			true
-
-let block_vars e =
-	let add_var map v d = map := PMap.add v d (!map) in
-	let wrap e used =
-		match PMap.foldi (fun v _ acc -> v :: acc) used [] with
-		| [] -> e
-		| vars ->
-			mk (TCall (
-				(mk (TFunction {
-					tf_args = List.map (fun v -> v , false, t_dynamic) vars;
-					tf_type = t_dynamic;
-					tf_expr = mk (TReturn (Some e)) t_dynamic e.epos;
-				}) t_dynamic e.epos),
-				List.map (fun v -> mk (TLocal v) t_dynamic e.epos) vars)
-			) t_dynamic e.epos
-	in
-	let rec in_fun vars depth used_locals e =
-		match e.eexpr with
-		| TLocal v ->
-			(try
-				if PMap.find v vars = depth then add_var used_locals v depth;				
-			with
-				Not_found -> ())
-		| _ ->
-			iter (in_fun vars depth used_locals) e
-
-	and in_loop vars depth e =
-		match e.eexpr with
-		| TVars l ->
-			{ e with eexpr = TVars (List.map (fun (v,t,e) ->
-				let e = (match e with None -> None | Some e -> Some (in_loop vars depth e)) in
-				add_var vars v depth;
-				v, t, e
-			) l) }
-		| TFor (v,t,i,e1) ->
-			let new_vars = PMap.add v depth (!vars) in
-			{ e with eexpr = TFor (v,t,in_loop vars depth i,in_loop (ref new_vars) depth e1) }
-		| TTry (e1,cases) ->
-			let e1 = in_loop vars depth e1 in
-			let cases = List.map (fun (v,t,e) ->
-				let new_vars = PMap.add v depth (!vars) in
-				v , t, in_loop (ref new_vars) depth e
-			) cases in
-			{ e with eexpr = TTry (e1,cases) }
-		| TMatch (e1,t,cases,def) ->
-			let e1 = in_loop vars depth e1 in
-			let cases = List.map (fun (cl,params,e) ->
-				let e = (match params with
-					| None -> in_loop vars depth e
-					| Some l ->
-						let new_vars = List.fold_left (fun acc (v,t) ->
-							match v with
-							| None -> acc
-							| Some name -> PMap.add name depth acc
-						) (!vars) l in
-						in_loop (ref new_vars) depth e
-				) in
-				cl , params, e
-			) cases in
-			let def = (match def with None -> None | Some e -> Some (in_loop vars depth e)) in
-			{ e with eexpr = TMatch (e1, t, cases, def) }
-		| TBlock l ->
-			let new_vars = (ref !vars) in
-			map (in_loop new_vars depth) e
-		| TFunction _ ->
-			let new_vars = !vars in
-			let used = ref PMap.empty in
-			iter (in_fun new_vars depth used) e;
-			let e = wrap e (!used) in
-			let new_vars = ref (PMap.foldi (fun v _ acc -> PMap.remove v acc) (!used) new_vars) in
-			map (in_loop new_vars (depth + 1)) e
-		| _ ->
-			map (in_loop vars depth) e
-	and out_loop e =
-		match e.eexpr with
-		| TFor _ | TWhile _ ->
-			in_loop (ref PMap.empty) 0 e
-		| _ ->
-			map out_loop e
-	in
-	out_loop e
-
-let emk e = mk e (mk_mono()) null_pos
-
-let block e =
-	match e.eexpr with
-	| TBlock (_ :: _) -> e
-	| _ -> mk (TBlock [e]) e.etype e.epos
-
-let stack_var = "$s"
-let exc_stack_var = "$e"
-let stack_var_pos = "$spos"
-let stack_e = emk (TLocal stack_var)
-let stack_pop = emk (TCall (emk (TField (stack_e,"pop")),[]))
-
-let stack_push useadd (c,m) =
-	emk (TCall (emk (TField (stack_e,"push")),[
-		if useadd then
-			emk (TBinop (
-				OpAdd,
-				emk (TConst (TString (s_type_path c.cl_path ^ "::"))),
-				emk (TConst (TString m))
-			))
-		else
-			emk (TConst (TString (s_type_path c.cl_path ^ "::" ^ m)))
-	]))
-
-let stack_save_pos =
-	emk (TVars [stack_var_pos, t_dynamic, Some (emk (TField (stack_e,"length")))])
-
-let stack_restore_pos =
-	let ev = emk (TLocal exc_stack_var) in
-	[
-	emk (TBinop (OpAssign, ev, emk (TArrayDecl [])));
-	emk (TWhile (
-		emk (TBinop (OpGte,
-			emk (TField (stack_e,"length")),
-			emk (TLocal stack_var_pos)
-		)),
-		emk (TCall (
-			emk (TField (ev,"unshift")),
-			[emk (TCall (
-				emk (TField (stack_e,"pop")),
-				[]
-			))]
-		)),
-		NormalWhile
-	));
-	emk (TCall (emk (TField (stack_e,"push")),[ emk (TArray (ev,emk (TConst (TInt 0l)))) ]))
-	]
-
-let stack_block ?(useadd=false) ctx e =
-	let rec loop e =
-		match e.eexpr with
-		| TFunction _ ->
-			e
-		| TReturn None | TReturn (Some { eexpr = TConst _ }) | TReturn (Some { eexpr = TLocal _ }) ->
-			mk (TBlock [
-				stack_pop;
-				e;
-			]) e.etype e.epos
-		| TReturn (Some e) ->
-			mk (TBlock [
-				mk (TVars ["$tmp", t_dynamic, Some (loop e)]) t_dynamic e.epos;
-				stack_pop;
-				mk (TReturn (Some (mk (TLocal "$tmp") t_dynamic e.epos))) t_dynamic e.epos
-			]) e.etype e.epos
-		| TTry (v,cases) ->
-			let v = loop v in
-			let cases = List.map (fun (n,t,e) ->
-				let e = loop e in
-				let e = (match (block e).eexpr with
-					| TBlock l -> mk (TBlock (stack_restore_pos @ l)) e.etype e.epos
-					| _ -> assert false
-				) in
-				n , t , e
-			) cases in
-			mk (TTry (v,cases)) e.etype e.epos
-		| _ ->
-			map loop e
-	in
-	match (block e).eexpr with
-	| TBlock l -> mk (TBlock (stack_push useadd ctx :: stack_save_pos :: List.map loop l @ [stack_pop])) e.etype e.epos
-	| _ -> assert false
-
-let rec is_volatile t =
-	match t with
-	| TMono r ->
-		(match !r with
-		| Some t -> is_volatile t
-		| _ -> false)
-	| TLazy f ->
-		is_volatile (!f())
-	| TType (t,tl) ->
-		(match t.t_path with
-		| ["mt";"flash"],"Volatile" -> true
-		| _ -> is_volatile (apply_params t.t_types tl t.t_type))
-	| _ ->
-		false

+ 69 - 5
type.ml

@@ -18,7 +18,7 @@
  *)
 open Ast
 
-type module_path = string list * string
+type path = string list * string
 
 type field_access =
 	| NormalAccess
@@ -122,7 +122,7 @@ and tclass_kind =
 	| KGenericInstance of tclass * tparams
 
 and tclass = {
-	cl_path : module_path;
+	cl_path : path;
 	cl_pos : Ast.pos;
 	cl_doc : Ast.documentation;
 	cl_private : bool;
@@ -151,7 +151,7 @@ and tenum_field = {
 }
 
 and tenum = {
-	e_path : module_path;
+	e_path : path;
 	e_pos : Ast.pos;
 	e_doc : Ast.documentation;
 	e_private : bool;
@@ -162,7 +162,7 @@ and tenum = {
 }
 
 and tdef = {
-	t_path : module_path;
+	t_path : path;
 	t_pos : Ast.pos;
 	t_doc : Ast.documentation;
 	t_private : bool;
@@ -176,13 +176,18 @@ and module_type =
 	| TTypeDecl of tdef
 
 type module_def = {
-	mpath : module_path;
+	mpath : path;
 	mtypes : module_type list;
 	mutable mimports : (module_def * string option) list;
 }
 
 let mk e t p = { eexpr = e; etype = t; epos = p }
 
+let mk_block e =
+	match e.eexpr with
+	| TBlock (_ :: _) -> e
+	| _ -> mk (TBlock [e]) e.etype e.epos
+
 let not_opened = ref Closed
 let is_closed a = !(a.a_status) <> Opened
 let mk_anon fl = TAnon { a_fields = fl; a_status = not_opened; }
@@ -276,6 +281,15 @@ and s_type_params ctx = function
 	| [] -> ""
 	| l -> "<" ^ String.concat ", " (List.map (s_type ctx) l) ^ ">"
 
+let s_access = function
+	| NormalAccess -> "default"
+	| NoAccess -> "null"
+	| NeverAccess -> "never"
+	| MethodAccess m -> m
+	| MethodCantAccess -> "dynamic"
+	| ResolveAccess -> "resolve"
+	| InlineAccess -> "inline"
+
 let rec is_parent csup c =
 	if c == csup then
 		true
@@ -797,3 +811,53 @@ let rec iter f e =
 		List.iter (fun (_,_,e) -> f e) catches
 	| TReturn eo ->
 		(match eo with None -> () | Some e -> f e)
+
+let rec map_expr f e =
+	match e.eexpr with
+	| TConst _
+	| TLocal _
+	| TEnumField _
+	| TBreak
+	| TContinue
+	| TTypeExpr _ ->
+		e
+	| TArray (e1,e2) ->
+		{ e with eexpr = TArray (f e1,f e2) }
+	| TBinop (op,e1,e2) ->
+		{ e with eexpr = TBinop (op,f e1,f e2) }
+	| TFor (v,t,e1,e2) ->
+		{ e with eexpr = TFor (v,t,f e1,f e2) }
+	| TWhile (e1,e2,flag) ->
+		{ e with eexpr = TWhile (f e1,f e2,flag) }
+	| TThrow e1 ->
+		{ e with eexpr = TThrow (f e1) }
+	| TField (e1,v) ->
+		{ e with eexpr = TField (f e1,v) }
+	| TParenthesis e1 ->
+		{ e with eexpr = TParenthesis (f e1) }
+	| TUnop (op,pre,e1) ->
+		{ e with eexpr = TUnop (op,pre,f e1) }
+	| TArrayDecl el ->
+		{ e with eexpr = TArrayDecl (List.map f el) }
+	| TNew (t,pl,el) ->
+		{ e with eexpr = TNew (t,pl,List.map f el) }
+	| TBlock el ->
+		{ e with eexpr = TBlock (List.map f el) }
+	| TObjectDecl el ->
+		{ e with eexpr = TObjectDecl (List.map (fun (v,e) -> v, f e) el) }
+	| TCall (e1,el) ->
+		{ e with eexpr = TCall (f e1, List.map f el) }
+	| TVars vl ->
+		{ e with eexpr = TVars (List.map (fun (v,t,e) -> v , t , match e with None -> None | Some e -> Some (f e)) vl) }
+	| TFunction fu ->
+		{ e with eexpr = TFunction { fu with tf_expr = f fu.tf_expr } }
+	| TIf (ec,e1,e2) ->
+		{ e with eexpr = TIf (f ec,f e1,match e2 with None -> None | Some e -> Some (f e)) }
+	| TSwitch (e1,cases,def) ->
+		{ e with eexpr = TSwitch (f e1, List.map (fun (el,e2) -> List.map f el, f e2) cases, match def with None -> None | Some e -> Some (f e)) }
+	| TMatch (e1,t,cases,def) ->
+		{ e with eexpr = TMatch (f e1, t, List.map (fun (cl,params,e) -> cl, params, f e) cases, match def with None -> None | Some e -> Some (f e)) }
+	| TTry (e1,catches) ->
+		{ e with eexpr = TTry (f e1, List.map (fun (v,t,e) -> v, t, f e) catches) }
+	| TReturn eo ->
+		{ e with eexpr = TReturn (match eo with None -> None | Some e -> Some (f e)) }

+ 184 - 0
typecore.ml

@@ -0,0 +1,184 @@
+(*
+ *  Haxe Compiler
+ *  Copyright (c)2005-2008 Nicolas Cannasse
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *)
+open Common
+open Type
+
+type typer = {
+	(* shared *)
+	com : context;
+	mutable api : context_type_api;
+	types_module : (path, path) Hashtbl.t;
+	modules : (path , module_def) Hashtbl.t;
+	delays : (unit -> unit) list list ref;
+	constructs : (path , Ast.access list * Ast.type_param list * Ast.func) Hashtbl.t;
+	doinline : bool;
+	mutable std : module_def;
+	mutable untyped : bool;
+	mutable isproxy : bool;
+	mutable super_call : bool;
+	(* per-module *)
+	current : module_def;
+	mutable local_types : module_type list;
+	(* per-class *)
+	mutable curclass : tclass;
+	mutable tthis : t;
+	mutable type_params : (string * t) list;
+	(* per-function *)
+	mutable curmethod : string;
+	mutable in_constructor : bool;
+	mutable in_static : bool;
+	mutable in_loop : bool;
+	mutable in_display : bool;
+	mutable ret : t;
+	mutable locals : (string, t) PMap.t;
+	mutable locals_map : (string, string) PMap.t;
+	mutable locals_map_inv : (string, string) PMap.t;
+	mutable opened : anon_status ref list;
+	mutable param_type : t option;
+}
+
+type error_msg =
+	| Module_not_found of path
+	| Unify of unify_error list
+	| Custom of string
+	| Protect of error_msg
+	| Unknown_ident of string
+	| Stack of error_msg * error_msg
+
+exception Error of error_msg * pos
+
+let type_expr_ref : (typer -> Ast.expr -> bool -> texpr) ref = ref (fun _ _ _ -> assert false)
+
+let unify_error_msg ctx = function
+	| Cannot_unify (t1,t2) ->
+		s_type ctx t1 ^ " should be " ^ s_type ctx t2
+	| Invalid_field_type s ->
+		"Invalid type for field " ^ s ^ " :"
+	| Has_no_field (t,n) ->
+		s_type ctx t ^ " has no field " ^ n
+	| Has_extra_field (t,n) ->
+		s_type ctx t ^ " has extra field " ^ n
+	| Invalid_access (f,get,a,b) ->
+		"Inconsistent " ^ (if get then "getter" else "setter") ^ " for field " ^ f ^ " : " ^ s_access a ^ " should be " ^ s_access b
+	| Invalid_visibility n ->
+		"The field " ^ n ^ " is not public"
+	| Not_matching_optional n ->
+		"Optional attribute of parameter " ^ n ^ " differs"
+	| Cant_force_optional ->
+		"Optional parameters can't be forced"
+
+let rec error_msg = function
+	| Module_not_found m -> "Class not found : " ^ Ast.s_type_path m
+	| Unify l ->
+		let ctx = print_context() in
+		String.concat "\n" (List.map (unify_error_msg ctx) l)
+	| Unknown_ident s -> "Unknown identifier : " ^ s
+	| Custom s -> s
+	| Stack (m1,m2) -> error_msg m1 ^ "\n" ^ error_msg m2
+	| Protect m -> error_msg m
+
+let display_error ctx msg p = ctx.com.error msg p
+
+let type_expr ctx e need_val = (!type_expr_ref) ctx e need_val
+
+let unify ctx t1 t2 p =
+	try
+		Type.unify t1 t2
+	with
+		Unify_error l ->
+			if not ctx.untyped then display_error ctx (error_msg (Unify l)) p
+
+let unify_raise ctx t1 t2 p =
+	try
+		Type.unify t1 t2
+	with
+		Unify_error l ->
+			(* no untyped check *)
+			raise (Error (Unify l,p))
+
+let save_locals ctx =
+	let locals = ctx.locals in
+	let map = ctx.locals_map in
+	let inv = ctx.locals_map_inv in
+	(fun() ->
+		ctx.locals <- locals;
+		ctx.locals_map <- map;
+		ctx.locals_map_inv <- inv;
+	)
+
+let add_local ctx v t =
+	let rec loop n =
+		let nv = (if n = 0 then v else v ^ string_of_int n) in
+		if PMap.mem nv ctx.locals || PMap.mem nv ctx.locals_map_inv then
+			loop (n+1)
+		else begin
+			ctx.locals <- PMap.add v t ctx.locals;
+			if n <> 0 then begin
+				ctx.locals_map <- PMap.add v nv ctx.locals_map;
+				ctx.locals_map_inv <- PMap.add nv v ctx.locals_map_inv;
+			end;
+			nv
+		end
+	in
+	loop 0
+
+let gen_local ctx t =
+	let rec loop n =
+		let nv = (if n = 0 then "_g" else "_g" ^ string_of_int n) in
+		if PMap.mem nv ctx.locals || PMap.mem nv ctx.locals_map_inv then
+			loop (n+1)
+		else
+			nv
+	in
+	add_local ctx (loop 0) t
+
+let rec is_nullable = function
+	| TMono r ->
+		(match !r with None -> true | Some t -> is_nullable t)
+	| TType ({ t_path = ([],"Null") },[_]) ->
+		false
+	| TLazy f ->
+		is_nullable (!f())
+	| TType (t,tl) ->
+		is_nullable (apply_params t.t_types tl t.t_type)
+	| TFun _ ->
+		true
+	| TInst ({ cl_path = (["haxe"],"Int32") },[])
+	| TInst ({ cl_path = ([],"Int") },[])
+	| TInst ({ cl_path = ([],"Float") },[])
+	| TEnum ({ e_path = ([],"Bool") },[]) -> true
+	| _ ->
+		false
+
+let rec is_null = function
+	| TMono r ->
+		(match !r with None -> false | Some t -> is_null t)
+	| TType ({ t_path = ([],"Null") },[t]) ->
+		is_nullable t
+	| TLazy f ->
+		is_null (!f())
+	| TType (t,tl) ->
+		is_null (apply_params t.t_types tl t.t_type)
+	| _ ->
+		false
+
+let null t p = mk (TConst TNull) t p
+
+let tfun pl r = TFun (List.map (fun t -> "",false,t) pl,r)
+

+ 925 - 0
typeload.ml

@@ -0,0 +1,925 @@
+(*
+ *  Haxe Compiler
+ *  Copyright (c)2005-2008 Nicolas Cannasse
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *)
+open Ast
+open Type
+open Common
+open Typecore
+
+let exc_protect f =
+	let rec r = ref (fun() ->
+		try
+			f r
+		with
+			| Error (Protect _,_) as e -> raise e
+			| Error (m,p) -> raise (Error (Protect m,p))
+	) in
+	r
+
+let type_static_var ctx t e p =
+	ctx.in_static <- true;
+	let e = type_expr ctx e true in
+	unify ctx e.etype t p;
+	e
+
+(** since load_type is used in PASS2 , it cannot access the structure of a type **)
+
+let load_type_def ctx p tpath =
+	let no_pack = fst tpath = [] in
+	try
+		List.find (fun t ->
+			let tp = t_path t in
+			tp = tpath || (no_pack && snd tp = snd tpath)
+		) ctx.local_types
+	with
+		Not_found ->
+			let tpath, m = (try
+				if not no_pack || fst ctx.current.mpath = [] then raise Exit;
+				let tpath2 = fst ctx.current.mpath , snd tpath in
+				tpath2, ctx.api.load_module tpath2 p
+			with
+				| Error (Module_not_found _,p2) when p == p2 -> tpath, ctx.api.load_module tpath p
+				| Exit -> tpath, ctx.api.load_module tpath p
+			) in
+			try
+				List.find (fun t -> not (t_private t) && t_path t = tpath) m.mtypes
+			with
+				Not_found -> error ("Module " ^ s_type_path tpath ^ " does not define type " ^ snd tpath) p
+
+let rec load_normal_type ctx t p allow_no_params =
+	try
+		if t.tpackage <> [] then raise Not_found;
+		let pt = List.assoc t.tname ctx.type_params in
+		if t.tparams <> [] then error ("Class type parameter " ^ t.tname ^ " can't have parameters") p;
+		pt
+	with Not_found ->
+		let types , path , f = ctx.api.build_instance (load_type_def ctx p (t.tpackage,t.tname)) p in
+		if allow_no_params && t.tparams = [] then
+			f (List.map (fun (name,t) ->
+				match follow t with
+				| TInst (c,_) -> if c.cl_implements = [] then mk_mono() else error ("Type parameter " ^ name ^ " need constraint") p
+				| _ -> assert false
+			) types)
+		else if path = ([],"Dynamic") then
+			match t.tparams with
+			| [] -> t_dynamic
+			| [TPType t] -> TDynamic (load_type ctx p t)
+			| _ -> error "Too many parameters for Dynamic" p
+		else begin
+			if List.length types <> List.length t.tparams then error ("Invalid number of type parameters for " ^ s_type_path path) p;
+			let tparams = List.map (fun t ->
+				match t with
+				| TPConst c ->
+					let name, const = (match c with
+						| String s -> "S" ^ s, TString s
+						| Int i -> "I" ^ i, TInt (Int32.of_string i)
+						| Float f -> "F" ^ f, TFloat f
+						| _ -> assert false
+					) in
+					let c = mk_class ([],name) p None false in
+					c.cl_kind <- KConstant const;
+					TInst (c,[])
+				| TPType t -> load_type ctx p t
+			) t.tparams in
+			let params = List.map2 (fun t (name,t2) ->
+				let isconst = (match t with TInst ({ cl_kind = KConstant _ },_) -> true | _ -> false) in
+				if isconst <> (name = "Const") && t != t_dynamic then error (if isconst then "Constant value unexpected here" else "Constant value excepted as type parameter") p;
+				(match follow t2 with
+				| TInst (c,[]) ->
+					List.iter (fun (i,params) ->
+						unify ctx t (apply_params types tparams (TInst (i,params))) p
+					) c.cl_implements
+				| _ -> assert false);
+				t
+			) tparams types in
+			f params
+		end
+
+and load_type ctx p t =
+	match t with
+	| TPParent t -> load_type ctx p t
+	| TPNormal t -> load_normal_type ctx t p false
+	| TPExtend (t,l) ->
+		(match load_type ctx p (TPAnonymous l) with
+		| TAnon a ->
+			let rec loop t =
+				match follow t with
+				| TInst (c,tl) ->
+					let c2 = mk_class (fst c.cl_path,"+" ^ snd c.cl_path) p None true in
+					PMap.iter (fun f _ ->
+						try
+							ignore(class_field c f);
+							error ("Cannot redefine field " ^ f) p
+						with
+							Not_found -> ()
+					) a.a_fields;
+					(* do NOT tag as extern - for protect *)
+					c2.cl_kind <- KExtension (c,tl);
+					c2.cl_super <- Some (c,tl);
+					c2.cl_fields <- a.a_fields;
+					TInst (c2,[])
+				| TMono _ ->
+					error "Please ensure correct initialization of cascading signatures" p
+				| TAnon a2 ->
+					PMap.iter (fun f _ ->
+						if PMap.mem f a2.a_fields then error ("Cannot redefine field " ^ f) p
+					) a.a_fields;
+					mk_anon (PMap.foldi PMap.add a.a_fields a2.a_fields)
+				| _ -> error "Cannot only extend classes and anonymous" p
+			in
+			loop (load_normal_type ctx t p false)
+		| _ -> assert false)
+	| TPAnonymous l ->
+		let rec loop acc (n,pub,f,p) =
+			if PMap.mem n acc then error ("Duplicate field declaration : " ^ n) p;
+			let t , get, set = (match f with
+				| AFVar t ->
+					load_type ctx p t, NormalAccess, NormalAccess
+				| AFFun (tl,t) ->
+					let t = load_type ctx p t in
+					let args = List.map (fun (name,o,t) -> name , o, load_type ctx p t) tl in
+					TFun (args,t), NormalAccess, MethodCantAccess
+				| AFProp (t,i1,i2) ->
+					let access m get =
+						match m with
+						| "null" -> NoAccess
+						| "default" -> NormalAccess
+						| "dynamic" -> MethodAccess ((if get then "get_"  else "set_") ^ n)
+						| _ -> MethodAccess m
+					in
+					load_type ctx p t, access i1 true, access i2 false
+			) in
+			PMap.add n {
+				cf_name = n;
+				cf_type = t;
+				cf_public = (match pub with None -> true | Some p -> p);
+				cf_get = get;
+				cf_set = set;
+				cf_params = [];
+				cf_expr = None;
+				cf_doc = None;
+			} acc
+		in
+		mk_anon (List.fold_left loop PMap.empty l)
+	| TPFunction (args,r) ->
+		match args with
+		| [TPNormal { tpackage = []; tparams = []; tname = "Void" }] ->
+			TFun ([],load_type ctx p r)
+		| _ ->
+			TFun (List.map (fun t -> "",false,load_type ctx p t) args,load_type ctx p r)
+
+let hide_types ctx =
+	let old_locals = ctx.local_types in
+	let old_type_params = ctx.type_params in
+	ctx.local_types <- (try (Hashtbl.find ctx.modules ([],"StdTypes")).mtypes with Not_found -> assert false);
+	ctx.type_params <- [];
+	(fun() ->
+		ctx.local_types <- old_locals;
+		ctx.type_params <- old_type_params;
+	)
+
+let load_core_type ctx name =
+	let show = hide_types ctx in
+	let t = load_normal_type ctx { tpackage = []; tname = name; tparams = [] } null_pos false in
+	show();
+	t
+
+let is_int t =
+	match follow t with
+	| TInst (c,[]) ->
+		c.cl_path = ([],"Int")
+	| _ ->
+		false
+
+let is_float t =
+	match follow t with
+	| TInst (c,[]) ->
+		c.cl_path = ([],"Float")
+	| _ ->
+		false
+
+let t_array ctx =
+	let show = hide_types ctx in
+	match load_type_def ctx null_pos ([],"Array") with
+	| TClassDecl c ->
+		show();
+		if List.length c.cl_types <> 1 then assert false;
+		let pt = mk_mono() in
+		TInst (c,[pt]) , pt
+	| _ ->
+		assert false
+
+let t_array_access ctx =
+	let show = hide_types ctx in
+	match load_type_def ctx null_pos ([],"ArrayAccess") with
+	| TClassDecl c ->
+		show();
+		if List.length c.cl_types <> 1 then assert false;
+		let pt = mk_mono() in
+		TInst (c,[pt]) , pt
+	| _ ->
+		assert false
+
+let t_iterator ctx =
+	let show = hide_types ctx in
+	match load_type_def ctx null_pos ([],"Iterator") with
+	| TTypeDecl t ->
+		show();
+		if List.length t.t_types <> 1 then assert false;
+		let pt = mk_mono() in
+		apply_params t.t_types [pt] t.t_type, pt
+	| _ ->
+		assert false
+
+let load_type_opt ?(opt=false) ctx p t =
+	let t = (match t with None -> mk_mono() | Some t -> load_type ctx p t) in
+	if opt then ctx.api.tnull t else t
+
+(* ---------------------------------------------------------------------- *)
+(* Structure check *)
+
+let valid_redefinition ctx f t =
+	let ft = field_type f in
+	match follow ft , follow t with
+	| TFun (args,r) , TFun (targs,tr) when List.length args = List.length targs ->
+		List.iter2 (fun (n,o1,a1) (_,o2,a2) ->
+			if o1 <> o2 then raise (Unify_error [Not_matching_optional n]);
+			type_eq EqStrict a1 a2
+		) args targs;
+		Type.unify r tr
+	| _ , _ ->
+		type_eq EqStrict ft t
+
+let check_overriding ctx c p () =
+	match c.cl_super with
+	| None -> ()
+	| Some (csup,params) ->
+		PMap.iter (fun i f ->
+			try
+				let t , f2 = class_field csup i in
+				let t = apply_params csup.cl_types params t in
+				ignore(follow f.cf_type); (* force evaluation *)
+				let p = (match f.cf_expr with None -> p | Some e -> e.epos) in
+				if not (List.mem i c.cl_overrides) then
+					display_error ctx ("Field " ^ i ^ " should be declared with 'override' since it is inherited from superclass") p
+				else if f.cf_public <> f2.cf_public then
+					display_error ctx ("Field " ^ i ^ " has different visibility (public/private) than superclass one") p
+				else if f2.cf_get = InlineAccess then
+					display_error ctx ("Field " ^ i ^ " is inlined and cannot be overridden") p
+				else if f2.cf_get <> f.cf_get || f2.cf_set <> f.cf_set then
+					display_error ctx ("Field " ^ i ^ " has different property access than in superclass") p
+				else try
+					valid_redefinition ctx f t
+				with
+					Unify_error l ->
+						display_error ctx ("Field " ^ i ^ " overload parent class with different or incomplete type") p;
+						display_error ctx (error_msg (Unify l)) p;
+			with
+				Not_found ->
+					if List.mem i c.cl_overrides then display_error ctx ("Field " ^ i ^ " is declared 'override' but doesn't override any field") p
+		) c.cl_fields
+
+let class_field_no_interf c i =
+	try
+		let f = PMap.find i c.cl_fields in
+		field_type f , f
+	with Not_found ->
+		match c.cl_super with
+		| None ->
+			raise Not_found
+		| Some (c,tl) ->
+			(* rec over class_field *)
+			let t , f = class_field c i in
+			apply_params c.cl_types tl t , f
+
+let rec check_interface ctx c p intf params =
+	PMap.iter (fun i f ->
+		try
+			let t , f2 = class_field_no_interf c i in
+			ignore(follow f.cf_type); (* force evaluation *)
+			let p = (match f.cf_expr with None -> p | Some e -> e.epos) in
+			if f.cf_public && not f2.cf_public then
+				display_error ctx ("Field " ^ i ^ " should be public as requested by " ^ s_type_path intf.cl_path) p
+			else if not(unify_access f2.cf_get f.cf_get) then
+				display_error ctx ("Field " ^ i ^ " has different property access than in " ^ s_type_path intf.cl_path) p
+			else
+				let t1 = apply_params intf.cl_types params (field_type f) in
+				try
+					valid_redefinition ctx f2 t1
+				with
+					Unify_error l ->
+						display_error ctx ("Field " ^ i ^ " has different type than in " ^ s_type_path intf.cl_path) p;
+						display_error ctx (error_msg (Unify l)) p;
+		with
+			Not_found ->
+				if not c.cl_interface then display_error ctx ("Field " ^ i ^ " needed by " ^ s_type_path intf.cl_path ^ " is missing") p
+	) intf.cl_fields;
+	List.iter (fun (i2,p2) ->
+		check_interface ctx c p i2 (List.map (apply_params intf.cl_types params) p2)
+	) intf.cl_implements
+
+let check_interfaces ctx c p () =
+	match c.cl_path with
+	| "Proxy" :: _ , _ -> ()
+	| _ ->
+	List.iter (fun (intf,params) -> check_interface ctx c p intf params) c.cl_implements
+
+let rec return_flow ctx e =
+	let error() = display_error ctx "A return is missing here" e.epos; raise Exit in
+	let return_flow = return_flow ctx in
+	match e.eexpr with
+	| TReturn _ | TThrow _ -> ()
+	| TParenthesis e ->
+		return_flow e
+	| TBlock el ->
+		let rec loop = function
+			| [] -> error()
+			| [e] -> return_flow e
+			| { eexpr = TReturn _ } :: _ | { eexpr = TThrow _ } :: _ -> ()
+			| _ :: l -> loop l
+		in
+		loop el
+	| TIf (_,e1,Some e2) ->
+		return_flow e1;
+		return_flow e2;
+	| TSwitch (v,cases,Some e) ->
+		List.iter (fun (_,e) -> return_flow e) cases;
+		return_flow e
+	| TSwitch (e,cases,None) when (match follow e.etype with TEnum _ -> true | _ -> false) ->
+		List.iter (fun (_,e) -> return_flow e) cases;
+	| TMatch (_,_,cases,def) ->
+		List.iter (fun (_,_,e) -> return_flow e) cases;
+		(match def with None -> () | Some e -> return_flow e)
+	| TTry (e,cases) ->
+		return_flow e;
+		List.iter (fun (_,_,e) -> return_flow e) cases;
+	| _ ->
+		error()
+
+(* ---------------------------------------------------------------------- *)
+(* PASS 1 & 2 : Module and Class Structure *)
+
+let set_heritance ctx c herits p =
+	let rec loop = function
+		| HPrivate | HExtern | HInterface ->
+			()
+		| HExtends t ->
+			if c.cl_super <> None then error "Cannot extend several classes" p;
+			let t = load_normal_type ctx t p false in
+			(match follow t with
+			| TInst (cl,params) ->
+				if is_parent c cl then error "Recursive class" p;
+				if c.cl_interface then error "Cannot extend an interface" p;
+				if cl.cl_interface then error "Cannot extend by using an interface" p;
+				c.cl_super <- Some (cl,params)
+			| _ -> error "Should extend by using a class" p)
+		| HImplements t ->
+			let t = load_normal_type ctx t p false in
+			(match follow t with
+			| TInst (cl,params) ->
+				if is_parent c cl then error "Recursive class" p;
+				c.cl_implements <- (cl, params) :: c.cl_implements
+			| TDynamic t ->
+				if c.cl_dynamic <> None then error "Cannot have several dynamics" p;
+				c.cl_dynamic <- Some t
+			| _ -> error "Should implement by using an interface or a class" p)
+	in
+	List.iter loop (List.filter (ctx.api.on_inherit c p) herits)
+
+let type_type_params ctx path p (n,flags) =
+	let c = mk_class (fst path @ [snd path],n) p None false in
+	c.cl_kind <- KTypeParameter;
+	let t = TInst (c,[]) in
+	match flags with
+	| [] -> n, t
+	| _ ->
+		let r = exc_protect (fun r ->
+			r := (fun _ -> t);
+			set_heritance ctx c (List.map (fun t -> HImplements t) flags) p;
+			t
+		) in
+		ctx.delays := [(fun () -> ignore(!r()))] :: !(ctx.delays);
+		n, TLazy r
+
+let type_function ctx t static constr f p =
+	let locals = save_locals ctx in
+	let fargs , r = (match t with
+		| TFun (args,r) -> List.map (fun (n,opt,t) -> add_local ctx n t, opt, t) args, r
+		| _ -> assert false
+	) in
+	let old_ret = ctx.ret in
+	let old_static = ctx.in_static in
+	let old_constr = ctx.in_constructor in
+	let old_opened = ctx.opened in
+	ctx.in_static <- static;
+	ctx.in_constructor <- constr;
+	ctx.ret <- r;
+	ctx.opened <- [];
+	let e = type_expr ctx f.f_expr false in
+	let rec loop e =
+		match e.eexpr with
+		| TReturn (Some _) -> raise Exit
+		| TFunction _ -> ()
+		| _ -> Type.iter loop e
+	in
+	let have_ret = (try loop e; false with Exit -> true) in
+	if have_ret then
+		(try return_flow ctx e with Exit -> ())
+	else
+		unify ctx r ctx.api.tvoid p;
+	let rec loop e =
+		match e.eexpr with
+		| TCall ({ eexpr = TConst TSuper },_) -> raise Exit
+		| TFunction _ -> ()
+		| _ -> Type.iter loop e
+	in
+	if constr && (match ctx.curclass.cl_super with None -> false | Some (cl,_) -> cl.cl_constructor <> None) then
+		(try
+			loop e;
+			error "Missing super constructor call" p
+		with
+			Exit -> ());
+	locals();
+	List.iter (fun r -> r := Closed) ctx.opened;
+	ctx.ret <- old_ret;
+	ctx.in_static <- old_static;
+	ctx.in_constructor <- old_constr;
+	ctx.opened <- old_opened;
+	e , fargs
+
+let init_class ctx c p herits fields =
+	ctx.type_params <- c.cl_types;
+	c.cl_extern <- List.mem HExtern herits;
+	c.cl_interface <- List.mem HInterface herits;
+	set_heritance ctx c herits p;
+	let tthis = TInst (c,List.map snd c.cl_types) in
+	let rec extends_public c =
+		List.exists (fun (c,_) -> c.cl_path = (["haxe"],"Public") || extends_public c) c.cl_implements ||
+		match c.cl_super with
+		| None -> false
+		| Some (c,_) -> extends_public c
+	in
+	let extends_public = extends_public c in
+	let is_public access parent =
+		if List.mem APrivate access then
+			false
+		else if List.mem APublic access then
+			true
+		else match parent with
+			| Some { cf_public = p } -> p
+			| _ -> c.cl_extern || c.cl_interface || extends_public
+	in
+	let rec get_parent c name = 
+		match c.cl_super with
+		| None -> None
+		| Some (csup,_) ->
+			try
+				Some (PMap.find name csup.cl_fields)
+			with
+				Not_found -> get_parent csup name
+	in
+	let type_opt ?opt ctx p t =
+		match t with
+		| None when c.cl_extern || c.cl_interface ->
+			display_error ctx "Type required for extern classes and interfaces" p;
+			t_dynamic
+		| _ ->
+			load_type_opt ?opt ctx p t
+	in
+	let rec has_field f = function
+		| None -> false
+		| Some (c,_) ->
+			PMap.exists f c.cl_fields || has_field f c.cl_super || List.exists (fun i -> has_field f (Some i)) c.cl_implements
+	in
+	let loop_cf f p =
+		match f with
+		| FVar (name,doc,access,t,e) ->
+			let stat = List.mem AStatic access in
+			let inline = List.mem AInline access in
+			if not stat && has_field name c.cl_super then error ("Redefinition of variable " ^ name ^ " in subclass is not allowed") p;
+			if inline && not stat then error "Inline variable must be static" p;
+			if inline && e = None then error "Inline variable must be initialized" p;
+			let t = (match t with
+				| None ->
+					if not stat then display_error ctx ("Type required for member variable " ^ name) p;
+					mk_mono()
+				| Some t ->
+					let old = ctx.type_params in
+					if stat then ctx.type_params <- [];
+					let t = load_type ctx p t in
+					if stat then ctx.type_params <- old;
+					t
+			) in
+			let cf = {
+				cf_name = name;
+				cf_doc = doc;
+				cf_type = t;
+				cf_get = if inline then InlineAccess else NormalAccess;
+				cf_set = if inline then NeverAccess else NormalAccess;
+				cf_expr = None;
+				cf_public = is_public access None;
+				cf_params = [];
+			} in
+			let delay = (match e with
+				| None -> (fun() -> ())
+				| Some e ->
+					let ctx = { ctx with curclass = c; tthis = tthis } in
+					let r = exc_protect (fun r ->
+						r := (fun() -> t);
+						if ctx.com.verbose then print_endline ("Typing " ^ s_type_path c.cl_path ^ "." ^ name);
+						cf.cf_expr <- Some (type_static_var ctx t e p);
+						t
+					) in
+					cf.cf_type <- TLazy r;
+					(fun () -> ignore(!r()))
+			) in
+			access, false, cf, delay
+		| FFun (name,doc,access,params,f) ->
+			let params = List.map (fun (n,flags) ->
+				match flags with
+				| [] ->
+					type_type_params ctx ([],name) p (n,[])
+				| _ -> error "This notation is not allowed because it can't be checked" p
+			) params in
+			let stat = List.mem AStatic access in
+			let inline = List.mem AInline access in
+			let parent = (if not stat then get_parent c name else None) in
+			let dynamic = List.mem ADynamic access || (match parent with Some { cf_set = NormalAccess } -> true | _ -> false) in
+			let ctx = { ctx with
+				curclass = c;
+				curmethod = name;
+				tthis = tthis;
+				type_params = if stat then params else params @ ctx.type_params;
+			} in
+			let ret = type_opt ctx p f.f_type in
+			let args = List.map (fun (name,opt,t) -> name , opt, type_opt ~opt ctx p t) f.f_args in
+			let t = TFun (args,ret) in
+			let constr = (name = "new") in
+			if constr && c.cl_interface then error "An interface cannot have a constructor" p;
+			if c.cl_interface && not stat && (match f.f_expr with EBlock [] , _ -> false | _ -> true) then error "An interface method cannot have a body" p;
+			if constr then (match f.f_type with
+				| None | Some (TPNormal { tpackage = []; tname = "Void" }) -> ()
+				| _ -> error "A class constructor can't have a return value" p
+			);
+			let cf = {
+				cf_name = name;
+				cf_doc = doc;
+				cf_type = t;
+				cf_get = if inline then InlineAccess else NormalAccess;
+				cf_set = (if inline then NeverAccess else if dynamic then NormalAccess else MethodCantAccess);
+				cf_expr = None;
+				cf_public = is_public access parent;
+				cf_params = params;
+			} in
+			let r = exc_protect (fun r ->
+				r := (fun() -> t);
+				if ctx.com.verbose then print_endline ("Typing " ^ s_type_path c.cl_path ^ "." ^ name);
+				let e , fargs = type_function ctx t stat constr f p in
+				let f = {
+					tf_args = fargs;
+					tf_type = ret;
+					tf_expr = e;
+				} in
+				if stat && name = "__init__" then c.cl_init <- Some e;
+				cf.cf_expr <- Some (mk (TFunction f) t p);
+				t
+			) in
+			let delay = (
+				if (c.cl_extern || c.cl_interface || ctx.isproxy) && cf.cf_name <> "__init__" then
+					(fun() -> ())
+				else begin
+					cf.cf_type <- TLazy r;
+					(fun() -> ignore((!r)()))
+				end
+			) in
+			access, constr, cf, delay
+		| FProp (name,doc,access,get,set,t) ->
+			let ret = load_type ctx p t in
+			let check_get = ref (fun() -> ()) in
+			let check_set = ref (fun() -> ()) in
+			let check_method m t () =
+				try
+					let t2 = (if List.mem AStatic access then (PMap.find m c.cl_statics).cf_type else fst (class_field c m)) in
+					unify_raise ctx t2 t p;
+				with
+					| Error (Unify l,_) -> raise (Error (Stack (Custom ("In method " ^ m ^ " required by property " ^ name),Unify l),p))
+					| Not_found -> if not c.cl_interface then error ("Method " ^ m ^ " required by property " ^ name ^ " is missing") p
+			in
+			let get = (match get with
+				| "null" -> NoAccess
+				| "dynamic" -> MethodAccess ("get_" ^ name)
+				| "default" -> NormalAccess
+				| _ ->
+					check_get := check_method get (TFun ([],ret));
+					MethodAccess get
+			) in
+			let set = (match set with
+				| "null" ->
+					(* standard flash library read-only variables can't be accessed for writing, even in subclasses *)
+					if c.cl_extern && (match c.cl_path with "flash" :: _  , _ -> true | _ -> false) && Common.defined ctx.com "flash9" then
+						NeverAccess
+					else
+						NoAccess
+				| "dynamic" -> MethodAccess ("set_" ^ name)
+				| "default" -> NormalAccess
+				| _ ->
+					check_set := check_method set (TFun (["",false,ret],ret));
+					MethodAccess set
+			) in
+			if set = NormalAccess && (match get with MethodAccess _ -> true | _ -> false) then error "Unsupported property combination" p;
+			let cf = {
+				cf_name = name;
+				cf_doc = doc;
+				cf_get = get;
+				cf_set = set;
+				cf_expr = None;
+				cf_type = ret;
+				cf_public = is_public access None;
+				cf_params = [];
+			} in
+			access, false, cf, (fun() -> (!check_get)(); (!check_set)())
+	in
+	let fl = List.map (fun (f,p) ->
+		let access , constr, f , delayed = loop_cf f p in
+		let is_static = List.mem AStatic access in
+		if is_static && f.cf_name = "name" && Common.defined ctx.com "js" then error "This identifier cannot be used in Javascript for statics" p;
+		if (is_static || constr) && c.cl_interface && f.cf_name <> "__init__" then error "You can't declare static fields in interfaces" p;
+		if constr then begin
+			if c.cl_constructor <> None then error "Duplicate constructor" p;
+			c.cl_constructor <- Some f;
+		end else if not is_static || f.cf_name <> "__init__" then begin
+			if PMap.mem f.cf_name (if is_static then c.cl_statics else c.cl_fields) then error ("Duplicate class field declaration : " ^ f.cf_name) p;
+			if is_static then begin
+				c.cl_statics <- PMap.add f.cf_name f c.cl_statics;
+				c.cl_ordered_statics <- f :: c.cl_ordered_statics;
+			end else begin
+				c.cl_fields <- PMap.add f.cf_name f c.cl_fields;
+				c.cl_ordered_fields <- f :: c.cl_ordered_fields;
+				if List.mem AOverride access then c.cl_overrides <- f.cf_name :: c.cl_overrides;
+			end;
+		end;
+		delayed
+	) fields in
+	c.cl_ordered_statics <- List.rev c.cl_ordered_statics;
+	c.cl_ordered_fields <- List.rev c.cl_ordered_fields;
+	(*
+		define a default inherited constructor.
+		This is actually pretty tricky since we can't assume that the constructor of the
+		superclass has been defined yet because type structure is not stabilized wrt recursion.
+	*)
+	let rec define_constructor ctx c =
+		try
+			Some (Hashtbl.find ctx.constructs c.cl_path)
+		with Not_found ->
+			match c.cl_super with
+			| None -> None
+			| Some (csuper,_) ->
+				match define_constructor ctx csuper with
+				| None -> None
+				| Some (acc,pl,f) as infos ->
+					let p = c.cl_pos in
+					let esuper = (ECall ((EConst (Ident "super"),p),List.map (fun (n,_,_) -> (EConst (Ident n),p)) f.f_args),p) in
+					let acc = (if csuper.cl_extern && acc = [] then [APublic] else acc) in
+					(* remove types that are superclass type-parameters *)
+					let replace_type = function
+						| Some (TPNormal { tpackage = []; tname = name; tparams = [] }) when List.exists (fun (param,_) -> name = param) csuper.cl_types ->
+							None
+						| t -> t
+					in
+					let fnew = { f with f_expr = esuper; f_args = List.map (fun (a,opt,t) -> a,opt,replace_type t) f.f_args } in
+					let _, _, cf, delayed = loop_cf (FFun ("new",None,acc,pl,fnew)) p in
+					c.cl_constructor <- Some cf;
+					Hashtbl.add ctx.constructs c.cl_path (acc,pl,f);
+					ctx.delays := [delayed] :: !(ctx.delays);
+					infos
+	in
+	ignore(define_constructor ctx c);
+	fl
+
+let type_module ctx m tdecls loadp =
+	(* PASS 1 : build module structure - does not load any module or type - should be atomic ! *)
+	let decls = ref [] in
+	let decl_with_name name p priv =
+		let tpath = if priv then (fst m @ ["_" ^ snd m], name) else (fst m, name) in
+		if priv then begin
+			if List.exists (fun t -> tpath = t_path t) (!decls) then error ("Type name " ^ name ^ " is alreday defined in this module") p;
+			tpath
+		end else try
+			let m2 = Hashtbl.find ctx.types_module tpath in
+			if m <> m2 && String.lowercase (s_type_path m2) = String.lowercase (s_type_path m) then error ("Module " ^ s_type_path m2 ^ " is loaded with a different case than " ^ s_type_path m) loadp;
+			error ("Type name " ^ s_type_path tpath ^ " is redefined from module " ^ s_type_path m2) p
+		with
+			Not_found ->
+				Hashtbl.add ctx.types_module (fst m,name) m;
+				tpath
+	in
+	List.iter (fun (d,p) ->
+		match d with
+		| EImport _ -> ()
+		| EClass d ->
+			let priv = List.mem HPrivate d.d_flags in
+			let path = decl_with_name d.d_name p priv in
+			let c = mk_class path p d.d_doc priv in
+			(* store the constructor for later usage *)
+			List.iter (fun (cf,_) ->
+				match cf with
+				| FFun ("new",_,acc,pl,f) -> Hashtbl.add ctx.constructs path (acc,pl,f)
+				| _ -> ()
+			) d.d_data;
+			decls := TClassDecl c :: !decls
+		| EEnum d ->
+			let priv = List.mem EPrivate d.d_flags in
+			let path = decl_with_name d.d_name p priv in
+			let e = {
+				e_path = path;
+				e_pos = p;
+				e_doc = d.d_doc;
+				e_types = [];
+				e_private = priv;
+				e_extern = List.mem EExtern d.d_flags || d.d_data = [];
+				e_constrs = PMap.empty;
+				e_names = [];
+			} in
+			decls := TEnumDecl e :: !decls
+		| ETypedef d ->
+			let priv = List.mem EPrivate d.d_flags in
+			let path = decl_with_name d.d_name p priv in
+			let t = {
+				t_path = path;
+				t_pos = p;
+				t_doc = d.d_doc;
+				t_private = priv;
+				t_types = [];
+				t_type = mk_mono();
+			} in
+			decls := TTypeDecl t :: !decls
+	) tdecls;
+	let m = {
+		mpath = m;
+		mtypes = List.rev !decls;
+		mimports = [];
+	} in
+	Hashtbl.add ctx.modules m.mpath m;
+	(* PASS 2 : build types structure - does not type any expression ! *)
+	let ctx = {
+		com = ctx.com;
+		api = ctx.api;
+		modules = ctx.modules;
+		delays = ctx.delays;
+		constructs = ctx.constructs;
+		types_module = ctx.types_module;
+		curclass = ctx.curclass;
+		tthis = ctx.tthis;
+		std = ctx.std;
+		ret = ctx.ret;
+		isproxy = ctx.isproxy;
+		doinline = ctx.doinline;
+		current = m;
+		locals = PMap.empty;
+		locals_map = PMap.empty;
+		locals_map_inv = PMap.empty;
+		local_types = ctx.std.mtypes @ m.mtypes;
+		type_params = [];
+		curmethod = "";
+		super_call = false;
+		in_constructor = false;
+		in_static = false;
+		in_display = false;
+		in_loop = false;
+		untyped = false;
+		opened = [];
+		param_type = None;
+	} in
+	let delays = ref [] in
+	let get_class name =
+		let c = List.find (fun d -> match d with TClassDecl { cl_path = _ , n } -> n = name | _ -> false) m.mtypes in
+		match c with TClassDecl c -> c | _ -> assert false
+	in
+	let get_enum name =
+		let e = List.find (fun d -> match d with TEnumDecl { e_path = _ , n } -> n = name | _ -> false) m.mtypes in
+		match e with TEnumDecl e -> e | _ -> assert false
+	in
+	let get_tdef name =
+		let s = List.find (fun d -> match d with TTypeDecl { t_path = _ , n } -> n = name | _ -> false) m.mtypes in
+		match s with TTypeDecl s -> s | _ -> assert false
+	in
+	(* here is an additional PASS 1 phase, which handle the type parameters declaration, with lazy contraints *)
+	List.iter (fun (d,p) ->
+		match d with
+		| EImport _ -> ()
+		| EClass d ->
+			let c = get_class d.d_name in
+			c.cl_types <- List.map (type_type_params ctx c.cl_path p) d.d_params;
+		| EEnum d ->
+			let e = get_enum d.d_name in
+			e.e_types <- List.map (type_type_params ctx e.e_path p) d.d_params;
+		| ETypedef d ->
+			let t = get_tdef d.d_name in
+			t.t_types <- List.map (type_type_params ctx t.t_path p) d.d_params;
+	) tdecls;
+	(* back to PASS2 *)
+	List.iter (fun (d,p) ->
+		match d with
+		| EImport (pack,name,topt) ->
+			let md = ctx.api.load_module (pack,name) p in
+			let types = List.filter (fun t -> not (t_private t)) md.mtypes in
+			(match topt with
+			| None -> ctx.local_types <- ctx.local_types @ types
+			| Some t ->
+				try
+					let t = List.find (fun tdecl -> snd (t_path tdecl) = t) types in
+					ctx.local_types <- ctx.local_types @ [t]
+				with
+					Not_found -> error ("Module " ^ s_type_path (pack,name) ^ " does not define type " ^ t) p
+			);
+			m.mimports <- (md,topt) :: m.mimports;
+		| EClass d ->
+			let c = get_class d.d_name in
+			delays := !delays @ check_overriding ctx c p :: check_interfaces ctx c p :: init_class ctx c p d.d_flags d.d_data
+		| EEnum d ->
+			let e = get_enum d.d_name in
+			ctx.type_params <- e.e_types;
+			let et = TEnum (e,List.map snd e.e_types) in
+			let names = ref [] in
+			let index = ref 0 in
+			List.iter (fun (c,doc,t,p) ->
+				if c = "name" && Common.defined ctx.com "js" then error "This identifier cannot be used in Javascript" p;
+				let t = (match t with
+					| [] -> et
+					| l -> TFun (List.map (fun (s,opt,t) -> s, opt, load_type_opt ~opt ctx p (Some t)) l, et)
+				) in
+				if PMap.mem c e.e_constrs then error ("Duplicate constructor " ^ c) p;
+				e.e_constrs <- PMap.add c {
+					ef_name = c;
+					ef_type = t;
+					ef_pos = p;
+					ef_doc = doc;
+					ef_index = !index;
+				} e.e_constrs;
+				incr index;
+				names := c :: !names;
+			) d.d_data;
+			e.e_names <- List.rev !names;
+		| ETypedef d ->
+			let t = get_tdef d.d_name in
+			ctx.type_params <- t.t_types;
+			let tt = load_type ctx p d.d_data in
+			if t.t_type == follow tt then error "Recursive typedef is not allowed" p;
+			(match t.t_type with
+			| TMono r ->
+				(match !r with
+				| None -> r := Some tt;
+				| Some _ -> assert false);
+			| _ -> assert false);
+	) tdecls;
+	(* PASS 3 : type checking, delayed until all modules and types are built *)
+	ctx.delays := !delays :: !(ctx.delays);
+	m.mimports <- List.rev m.mimports;
+	m
+
+let load_module ctx m p =
+	try
+		Hashtbl.find ctx.modules m
+	with
+		Not_found ->
+			let file = (match m with
+				| [] , name -> name
+				| x :: l , name ->
+					let x = (try
+						match PMap.find x ctx.com.package_rules with
+						| Forbidden -> error ("You can't access the " ^ x ^ " package with current compilation flags") p;
+						| Directory d -> d
+						with Not_found -> x
+					) in
+					String.concat "/" (x :: l) ^ "/" ^ name
+			) ^ ".hx" in
+			let file = (try Common.find_file ctx.com file with Not_found -> raise (Error (Module_not_found m,p))) in
+			let ch = (try open_in_bin file with _ -> error ("Could not open " ^ file) p) in
+			let t = Common.timer "parsing" in
+			let pack , decls = (try Parser.parse ctx.com (Lexing.from_channel ch) file with e -> close_in ch; t(); raise e) in
+			t();
+			close_in ch;
+			if ctx.com.verbose then print_endline ("Parsed " ^ file);
+			if pack <> fst m then begin
+				let spack m = if m = [] then "<empty>" else String.concat "." m in
+				if p == Ast.null_pos then
+					error ("Invalid commandline class : " ^ s_type_path m ^ " should be " ^ s_type_path (pack,snd m)) p
+				else
+					error ("Invalid package : " ^ spack (fst m) ^ " should be " ^ spack pack) p
+			end;
+			type_module ctx m decls p

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 35 - 828
typer.ml


Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác