瀏覽代碼

fixed identifier resolution order
replaced @:multitype by @:overload

Nicolas Cannasse 14 年之前
父節點
當前提交
e5bf7bbb56
共有 2 個文件被更改,包括 66 次插入58 次删除
  1. 2 1
      doc/CHANGES.txt
  2. 64 57
      typer.ml

+ 2 - 1
doc/CHANGES.txt

@@ -1,6 +1,6 @@
 2011-??-??: 2.08
 	js : added js.JQuery
-	all : added @:multitype
+	all : added @:overload
 	js : upgraded js.SWFObject from 1.4.4 inlined to 1.5 embedded
 	js : code generator beautify
 	all : ensure that modifying returned Type.getEnumConstructs array does not affect enum
@@ -29,6 +29,7 @@
 	flash9 : store resources in bytes tag instead of bytecode
 	all : allow $ prefixed identifiers (for macros usage only)
 	all : allow to access modules subtype statics with pack.Mod.Type.value
+		and fixed identifier resolution order
 
 2011-01-30: 2.07
 	all : fixed completion support with --remap

+ 64 - 57
typer.ml

@@ -120,14 +120,34 @@ let type_expr_with_type ctx e t =
 	| _ ->
 		type_expr ctx e true
 
-let unify_call_params ctx name el args p inline =
+let rec unify_call_params ctx name el args r p inline =
+	let next() =
+		match name with
+		| None -> None
+		| Some (n,meta) ->
+			let rec loop = function
+				| [] -> None
+				| (":overload",[(EFunction (None,f),p)],_) :: l ->
+					let topt = function None -> error "Explicit type required" p | Some t -> Typeload.load_complex_type ctx p t in
+					let args = List.map (fun (a,opt,t,_) ->  a,opt,topt t) f.f_args in
+					Some (unify_call_params ctx (Some (n,l)) el args (topt f.f_type) p inline)
+				| _ :: l -> loop l
+			in
+			loop meta
+	in
 	let error txt =
+		match next() with
+		| Some l -> l
+		| None ->
 		let format_arg = (fun (name,opt,_) -> (if opt then "?" else "") ^ name) in
 		let argstr = "Function " ^ (match name with None -> "" | Some (n,_) -> "'" ^ n ^ "' ") ^ "requires " ^ (if args = [] then "no arguments" else "arguments : " ^ String.concat ", " (List.map format_arg args)) in
-		display_error ctx (txt ^ " arguments\n" ^ argstr) p
+		display_error ctx (txt ^ " arguments\n" ^ argstr) p;
+		[], r
 	in
 	let arg_error ul name opt p =
-		raise (Error (Stack (Unify ul,Custom ("For " ^ (if opt then "optional " else "") ^ "function argument '" ^ name ^ "'")), p))
+		match next() with
+		| Some l -> l
+		| None -> raise (Error (Stack (Unify ul,Custom ("For " ^ (if opt then "optional " else "") ^ "function argument '" ^ name ^ "'")), p))
 	in
 	let rec no_opt = function
 		| [] -> []
@@ -159,27 +179,19 @@ let unify_call_params ctx name el args p inline =
 	let rec loop acc l l2 skip =
 		match l , l2 with
 		| [] , [] ->
-			if (match name with Some (_,meta) -> has_meta ":multitype" meta | _ -> false) then
-				let args = List.map fst (List.filter (fun o -> not (snd o)) acc) in
-				match List.rev args with
-				| [] -> error "Not enough"; []
-				| _ :: [] -> args
-				| args -> error "Too many"; args
-			else if not (inline && ctx.g.doinline) && (match ctx.com.platform with Flash | Flash9 | Js -> true | _ -> false) then
-				List.rev (no_opt acc)
+			if not (inline && ctx.g.doinline) && (match ctx.com.platform with Flash | Flash9 | Js -> true | _ -> false) then
+				List.rev (no_opt acc), r
 			else
-				List.rev (List.map fst acc)
+				List.rev (List.map fst acc), r
 		| [] , (_,false,_) :: _ ->
-			error "Not enough";
-			[]
+			error "Not enough"
 		| [] , (name,true,t) :: l ->
 			loop (default_value t :: acc) [] l skip
 		| _ , [] ->
 			(match List.rev skip with
 			| [] -> error "Too many"
 			| [name,ul] -> arg_error ul name true p
-			| _ -> error "Invalid");
-			[]
+			| _ -> error "Invalid")			
 		| ee :: l, (name,opt,t) :: l2 ->
 			let e = type_expr_with_type ctx ee (Some t) in
 			try
@@ -194,10 +206,6 @@ let unify_call_params ctx name el args p inline =
 	in
 	loop [] el args []
 
-let type_local ctx i p =
-	let v = PMap.find i ctx.locals in
-	mk (TLocal v) v.v_type p
-
 let rec type_module_type ctx t tparams p =
 	match t with
 	| TClassDecl c ->
@@ -482,8 +490,8 @@ let type_ident ctx i is_type p mode =
 			AKNo i
 	| _ ->
 	try
-		let e = type_local ctx i p in
-		AKExpr e
+		let v = PMap.find i ctx.locals in		
+		AKExpr (mk (TLocal v) v.v_type p)
 	with Not_found -> try
 		(* member variable lookup *)
 		if ctx.in_static then raise Not_found;
@@ -498,8 +506,8 @@ let type_ident ctx i is_type p mode =
 		let e = type_type ctx ctx.curclass.cl_path p in
 		(* check_locals_masking already done in type_type *)
 		field_access ctx mode f (field_type f) e p
-	with Not_found -> try
-		(* lookup imported *)
+	with Not_found ->
+		(* lookup imported enums *)
 		let rec loop l =
 			match l with
 			| [] -> raise Not_found
@@ -524,22 +532,6 @@ let type_ident ctx i is_type p mode =
 			AKNo i
 		else
 			AKExpr e
-	with Not_found -> try
-		(* lookup type *)
-		if not is_type then raise Not_found;
-		let e = (try type_type ctx ([],i) p with Error (Module_not_found ([],name),_) when name = i -> raise Not_found) in
-		AKExpr e
-	with Not_found ->
-		if ctx.untyped then begin
-			if i = "__this__" then
-				AKExpr (mk (TConst TThis) ctx.tthis p)
-			else
-				let t = mk_mono() in
-				AKExpr (mk (TLocal (alloc_var i t)) t p)
-		end else begin
-			if ctx.in_static && PMap.mem i ctx.curclass.cl_fields then error ("Cannot access " ^ i ^ " in static function") p;
-			raise (Error (Unknown_ident i,p))
-		end
 
 let rec type_field ctx e i p mode =
 	let no_field() =
@@ -1118,12 +1110,28 @@ and type_switch ctx e cases def need_val p =
 		let cases = List.map exprs cases in
 		mk (TSwitch (eval,cases,def)) (!t) p
 
-and type_ident_noerr ctx s t p mode =
+and type_ident_noerr ctx i is_type p mode =
 	try
-		type_ident ctx s t p mode
-	with Error (Unknown_ident _ as e,p) when not ctx.in_display ->
-		display_error ctx (error_msg e) p;
-		AKExpr (mk (TConst TNull) t_dynamic p)
+		type_ident ctx i is_type p mode
+	with Not_found -> try
+		(* lookup type *)
+		if not is_type then raise Not_found;
+		let e = (try type_type ctx ([],i) p with Error (Module_not_found ([],name),_) when name = i -> raise Not_found) in
+		AKExpr e
+	with Not_found ->
+		if ctx.untyped then begin
+			if i = "__this__" then
+				AKExpr (mk (TConst TThis) ctx.tthis p)
+			else
+				let t = mk_mono() in
+				AKExpr (mk (TLocal (alloc_var i t)) t p)
+		end else begin
+			if ctx.in_static && PMap.mem i ctx.curclass.cl_fields then error ("Cannot access " ^ i ^ " in static function") p;
+			let err = Unknown_ident i in
+			if ctx.in_display then raise (Error (err,p));
+			display_error ctx (error_msg err) p;
+			AKExpr (mk (TConst TNull) t_dynamic p)
+		end
 
 and type_access ctx e p mode =
 	match e with
@@ -1191,7 +1199,7 @@ and type_access ctx e p mode =
 			| [] -> assert false
 			| (name,_,p) :: pnext ->
 				try
-					fields pnext (fun _ -> AKExpr (type_local ctx name p))
+					fields pnext (fun _ -> type_ident ctx name false p MGet)
 				with
 					Not_found -> loop [] path
 		in
@@ -1471,9 +1479,9 @@ and type_expr ctx ?(need_val=true) (e,p) =
 			(match f.cf_kind with
 			| Var { v_read = AccRequire r } -> error_require r p
 			| _ -> ());
-			let el = (match follow (apply_params c.cl_types params (field_type f)) with
+			let el, _ = (match follow (apply_params c.cl_types params (field_type f)) with
 			| TFun (args,r) ->
-				unify_call_params ctx (Some ("new",f.cf_meta)) el args p false
+				unify_call_params ctx (Some ("new",f.cf_meta)) el args r p false
 			| _ ->
 				error "Constructor is not a function" p
 			) in
@@ -1686,9 +1694,9 @@ and type_call ctx e el p =
 		| None -> error "Current class does not have a super" p
 		| Some (c,params) ->
 			let f = get_constructor c p in
-			let el = (match follow (apply_params c.cl_types params (field_type f)) with
-			| TFun (args,_) ->
-				unify_call_params ctx (Some ("new",f.cf_meta)) el args p false
+			let el, _ = (match follow (apply_params c.cl_types params (field_type f)) with
+			| TFun (args,r) ->
+				unify_call_params ctx (Some ("new",f.cf_meta)) el args r p false
 			| _ ->
 				error "Constructor is not a function" p
 			) in
@@ -1702,7 +1710,7 @@ and type_call ctx e el p =
 		match type_access ctx (fst e) (snd e) MCall with
 		| AKInline (ethis,f,t) ->
 			let params, tret = (match follow t with
-				| TFun (args,r) -> unify_call_params ctx (Some (f.cf_name,f.cf_meta)) el args p true, r
+				| TFun (args,r) -> unify_call_params ctx (Some (f.cf_name,f.cf_meta)) el args r p true
 				| _ -> error (s_type (print_context()) t ^ " cannot be called") p
 			) in
 			make_call ctx (mk (TField (ethis,f.cf_name)) t p) params tret p
@@ -1724,7 +1732,7 @@ and type_call ctx e el p =
 					| _ -> assert false)
 				| AKExpr _ | AKField _ | AKInline _ ->
 					let params, tret = (match follow et.etype with
-						| TFun ( _ :: args,r) -> unify_call_params ctx (Some (ef.cf_name,ef.cf_meta)) el args p false, r
+						| TFun ( _ :: args,r) -> unify_call_params ctx (Some (ef.cf_name,ef.cf_meta)) el args r p false
 						| _ -> assert false
 					) in
 					make_call ctx et (eparam::params) tret p
@@ -1759,8 +1767,7 @@ and type_call ctx e el p =
 			let el , t = (match follow e.etype with
 			| TFun (args,r) ->
 				let fopts = (match acc with AKField (_,f) -> Some (f.cf_name,f.cf_meta) | _ -> match e.eexpr with TField (e,f) -> Some (f,[]) | _ -> None) in
-				let el = unify_call_params ctx fopts el args p false in
-				el , r
+				unify_call_params ctx fopts el args r p false
 			| TMono _ ->
 				let t = mk_mono() in
 				let el = List.map (type_expr ctx) el in
@@ -2211,7 +2218,7 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 			incr index;
 			(EArray ((EArrayDecl [e],p),(EConst (Int (string_of_int (!index))),p)),p)
 		) el in
-		let elt = unify_call_params ctx2 (Some (f,[])) constants (List.map fst eargs) p false in
+		let elt, _ = unify_call_params ctx2 (Some (f,[])) constants (List.map fst eargs) t_dynamic p false in
 		List.map2 (fun (_,ise) e ->
 			let e, et = (match e.eexpr with
 				(* get back our index and real expression *)
@@ -2272,7 +2279,7 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 
 let call_macro ctx path meth args p =
 	let ctx2, (margs,_,_), call = load_macro ctx path meth p in
-	let el = unify_call_params ctx2 (Some (meth,[])) args margs p false in
+	let el, _ = unify_call_params ctx2 (Some (meth,[])) args margs t_dynamic p false in
 	call (List.map (fun e -> try Interp.make_const e with Exit -> error "Parameter should be a constant" e.epos) el)
 
 let call_init_macro ctx e =