typecore.ml 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. (*
  2. * Copyright (C)2005-2013 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. *)
  22. open Common
  23. open Type
  24. type with_type =
  25. | NoValue
  26. | Value
  27. | WithType of t
  28. | WithTypeResume of t
  29. type type_patch = {
  30. mutable tp_type : Ast.complex_type option;
  31. mutable tp_remove : bool;
  32. mutable tp_meta : Ast.metadata;
  33. }
  34. type current_fun =
  35. | FunMember
  36. | FunStatic
  37. | FunConstructor
  38. | FunMemberAbstract
  39. | FunMemberClassLocal
  40. | FunMemberAbstractLocal
  41. type macro_mode =
  42. | MExpr
  43. | MBuild
  44. | MMacroType
  45. type typer_pass =
  46. | PBuildModule (* build the module structure and setup module type parameters *)
  47. | PBuildClass (* build the class structure *)
  48. | PTypeField (* type the class field, allow access to types structures *)
  49. | PCheckConstraint (* perform late constraint checks with inferred types *)
  50. | PForce (* usually ensure that lazy have been evaluated *)
  51. | PFinal (* not used, only mark for finalize *)
  52. type typer_globals = {
  53. types_module : (path, path) Hashtbl.t;
  54. modules : (path , module_def) Hashtbl.t;
  55. mutable delayed : (typer_pass * (unit -> unit) list) list;
  56. mutable debug_delayed : (typer_pass * ((unit -> unit) * string * typer) list) list;
  57. doinline : bool;
  58. mutable core_api : typer option;
  59. mutable macros : ((unit -> unit) * typer) option;
  60. mutable std : module_def;
  61. mutable hook_generate : (unit -> unit) list;
  62. type_patches : (path, (string * bool, type_patch) Hashtbl.t * type_patch) Hashtbl.t;
  63. mutable global_metadata : (string list * Ast.metadata_entry * (bool * bool * bool)) list;
  64. mutable get_build_infos : unit -> (module_type * t list * Ast.class_field list) option;
  65. delayed_macros : (unit -> unit) DynArray.t;
  66. mutable global_using : tclass list;
  67. (* api *)
  68. do_inherit : typer -> Type.tclass -> Ast.pos -> Ast.class_flag -> bool;
  69. do_create : Common.context -> typer;
  70. do_macro : typer -> macro_mode -> path -> string -> Ast.expr list -> Ast.pos -> Ast.expr option;
  71. do_load_module : typer -> path -> pos -> module_def;
  72. do_optimize : typer -> texpr -> texpr;
  73. do_build_instance : typer -> module_type -> pos -> ((string * t) list * path * (t list -> t));
  74. }
  75. and typer_module = {
  76. curmod : module_def;
  77. mutable module_types : module_type list;
  78. mutable module_using : tclass list;
  79. mutable module_globals : (string, (module_type * string)) PMap.t;
  80. mutable wildcard_packages : string list list;
  81. mutable module_imports : Ast.import list;
  82. }
  83. and typer = {
  84. (* shared *)
  85. com : context;
  86. t : basic_types;
  87. g : typer_globals;
  88. mutable meta : metadata;
  89. mutable this_stack : texpr list;
  90. mutable with_type_stack : with_type list;
  91. mutable call_argument_stack : Ast.expr list list;
  92. (* variable *)
  93. mutable pass : typer_pass;
  94. (* per-module *)
  95. mutable m : typer_module;
  96. (* per-class *)
  97. mutable curclass : tclass;
  98. mutable tthis : t;
  99. mutable type_params : (string * t) list;
  100. (* per-function *)
  101. mutable curfield : tclass_field;
  102. mutable untyped : bool;
  103. mutable in_super_call : bool;
  104. mutable in_loop : bool;
  105. mutable in_display : bool;
  106. mutable in_macro : bool;
  107. mutable macro_depth : int;
  108. mutable curfun : current_fun;
  109. mutable ret : t;
  110. mutable locals : (string, tvar) PMap.t;
  111. mutable opened : anon_status ref list;
  112. mutable vthis : tvar option;
  113. (* events *)
  114. mutable on_error : typer -> string -> pos -> unit;
  115. }
  116. type call_error =
  117. | Not_enough_arguments of (string * bool * t) list
  118. | Too_many_arguments
  119. | Could_not_unify of error_msg
  120. | Cannot_skip_non_nullable of string
  121. and error_msg =
  122. | Module_not_found of path
  123. | Type_not_found of path * string
  124. | Unify of unify_error list
  125. | Custom of string
  126. | Unknown_ident of string
  127. | Stack of error_msg * error_msg
  128. | Call_error of call_error
  129. exception Fatal_error of string * Ast.pos
  130. exception Forbid_package of (string * path * pos) * pos list * string
  131. exception Error of error_msg * pos
  132. exception DisplayTypes of t list
  133. exception DisplayPosition of Ast.pos list
  134. let make_call_ref : (typer -> texpr -> texpr list -> t -> pos -> texpr) ref = ref (fun _ _ _ _ _ -> assert false)
  135. let type_expr_ref : (typer -> Ast.expr -> with_type -> texpr) ref = ref (fun _ _ _ -> assert false)
  136. let type_module_type_ref : (typer -> module_type -> t list option -> pos -> texpr) ref = ref (fun _ _ _ _ -> assert false)
  137. let unify_min_ref : (typer -> texpr list -> t) ref = ref (fun _ _ -> assert false)
  138. let match_expr_ref : (typer -> Ast.expr -> (Ast.expr list * Ast.expr option * Ast.expr option) list -> Ast.expr option option -> with_type -> Ast.pos -> decision_tree) ref = ref (fun _ _ _ _ _ _ -> assert false)
  139. let get_pattern_locals_ref : (typer -> Ast.expr -> Type.t -> (string, tvar * pos) PMap.t) ref = ref (fun _ _ _ -> assert false)
  140. let get_constructor_ref : (typer -> tclass -> t list -> Ast.pos -> (t * tclass_field)) ref = ref (fun _ _ _ _ -> assert false)
  141. let cast_or_unify_ref : (typer -> t -> texpr -> Ast.pos -> texpr) ref = ref (fun _ _ _ _ -> assert false)
  142. let find_array_access_raise_ref : (typer -> tabstract -> tparams -> texpr -> texpr option -> pos -> (tclass_field * t * t * texpr * texpr option)) ref = ref (fun _ _ _ _ _ _ -> assert false)
  143. (* Source: http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance#OCaml *)
  144. let levenshtein a b =
  145. let x = Array.init (String.length a) (fun i -> a.[i]) in
  146. let y = Array.init (String.length b) (fun i -> b.[i]) in
  147. let minimum (x:int) y z =
  148. let m' (a:int) b = if a < b then a else b in
  149. m' (m' x y) z
  150. in
  151. let init_matrix n m =
  152. let init_col = Array.init m in
  153. Array.init n (function
  154. | 0 -> init_col (function j -> j)
  155. | i -> init_col (function 0 -> i | _ -> 0)
  156. )
  157. in
  158. match Array.length x, Array.length y with
  159. | 0, n -> n
  160. | m, 0 -> m
  161. | m, n ->
  162. let matrix = init_matrix (m + 1) (n + 1) in
  163. for i = 1 to m do
  164. let s = matrix.(i) and t = matrix.(i - 1) in
  165. for j = 1 to n do
  166. let cost = abs (compare x.(i - 1) y.(j - 1)) in
  167. s.(j) <- minimum (t.(j) + 1) (s.(j - 1) + 1) (t.(j - 1) + cost)
  168. done
  169. done;
  170. matrix.(m).(n)
  171. let string_error_raise s sl msg =
  172. if sl = [] then msg else
  173. let cl = List.map (fun s2 -> s2,levenshtein s s2) sl in
  174. let cl = List.sort (fun (_,c1) (_,c2) -> compare c1 c2) cl in
  175. let rec loop sl = match sl with
  176. | (s2,i) :: sl when i <= (min (String.length s) (String.length s2)) / 3 -> s2 :: loop sl
  177. | _ -> []
  178. in
  179. match loop cl with
  180. | [] -> raise Not_found
  181. | [s] -> Printf.sprintf "%s (Suggestion: %s)" msg s
  182. | sl -> Printf.sprintf "%s (Suggestions: %s)" msg (String.concat ", " sl)
  183. let string_error s sl msg =
  184. try string_error_raise s sl msg
  185. with Not_found -> msg
  186. let string_source t = match follow t with
  187. | TInst(c,_) -> List.map (fun cf -> cf.cf_name) c.cl_ordered_fields
  188. | TAnon a -> PMap.fold (fun cf acc -> cf.cf_name :: acc) a.a_fields []
  189. | TAbstract({a_impl = Some c},_) -> List.map (fun cf -> cf.cf_name) c.cl_ordered_statics
  190. | _ -> []
  191. let short_type ctx t =
  192. let tstr = s_type ctx t in
  193. if String.length tstr > 150 then String.sub tstr 0 147 ^ "..." else tstr
  194. let unify_error_msg ctx = function
  195. | Cannot_unify (t1,t2) ->
  196. s_type ctx t1 ^ " should be " ^ s_type ctx t2
  197. | Invalid_field_type s ->
  198. "Invalid type for field " ^ s ^ " :"
  199. | Has_no_field (t,n) ->
  200. string_error n (string_source t) (short_type ctx t ^ " has no field " ^ n)
  201. | Has_no_runtime_field (t,n) ->
  202. s_type ctx t ^ "." ^ n ^ " is not accessible at runtime"
  203. | Has_extra_field (t,n) ->
  204. short_type ctx t ^ " has extra field " ^ n
  205. | Invalid_kind (f,a,b) ->
  206. (match a, b with
  207. | Var va, Var vb ->
  208. let name, stra, strb = if va.v_read = vb.v_read then
  209. "setter", s_access false va.v_write, s_access false vb.v_write
  210. else if va.v_write = vb.v_write then
  211. "getter", s_access true va.v_read, s_access true vb.v_read
  212. else
  213. "access", "(" ^ s_access true va.v_read ^ "," ^ s_access false va.v_write ^ ")", "(" ^ s_access true vb.v_read ^ "," ^ s_access false vb.v_write ^ ")"
  214. in
  215. "Inconsistent " ^ name ^ " for field " ^ f ^ " : " ^ stra ^ " should be " ^ strb
  216. | _ ->
  217. "Field " ^ f ^ " is " ^ s_kind a ^ " but should be " ^ s_kind b)
  218. | Invalid_visibility n ->
  219. "The field " ^ n ^ " is not public"
  220. | Not_matching_optional n ->
  221. "Optional attribute of parameter " ^ n ^ " differs"
  222. | Cant_force_optional ->
  223. "Optional parameters can't be forced"
  224. | Invariant_parameter _ ->
  225. "Type parameters are invariant"
  226. | Constraint_failure name ->
  227. "Constraint check failure for " ^ name
  228. | Missing_overload (cf, t) ->
  229. cf.cf_name ^ " has no overload for " ^ s_type ctx t
  230. | Unify_custom msg ->
  231. msg
  232. let rec error_msg = function
  233. | Module_not_found m -> "Type not found : " ^ Ast.s_type_path m
  234. | Type_not_found (m,t) -> "Module " ^ Ast.s_type_path m ^ " does not define type " ^ t
  235. | Unify l ->
  236. let ctx = print_context() in
  237. String.concat "\n" (List.map (unify_error_msg ctx) l)
  238. | Unknown_ident s -> "Unknown identifier : " ^ s
  239. | Custom s -> s
  240. | Stack (m1,m2) -> error_msg m1 ^ "\n" ^ error_msg m2
  241. | Call_error err -> s_call_error err
  242. and s_call_error = function
  243. | Not_enough_arguments tl ->
  244. let pctx = print_context() in
  245. "Not enough arguments, expected " ^ (String.concat ", " (List.map (fun (n,_,t) -> n ^ ":" ^ (short_type pctx t)) tl))
  246. | Too_many_arguments -> "Too many arguments"
  247. | Could_not_unify err -> error_msg err
  248. | Cannot_skip_non_nullable s -> "Cannot skip non-nullable argument " ^ s
  249. let pass_name = function
  250. | PBuildModule -> "build-module"
  251. | PBuildClass -> "build-class"
  252. | PTypeField -> "type-field"
  253. | PCheckConstraint -> "check-constraint"
  254. | PForce -> "force"
  255. | PFinal -> "final"
  256. let display_error ctx msg p = ctx.on_error ctx msg p
  257. let error msg p = raise (Error (Custom msg,p))
  258. let make_call ctx e el t p = (!make_call_ref) ctx e el t p
  259. let type_expr ctx e with_type = (!type_expr_ref) ctx e with_type
  260. let unify_min ctx el = (!unify_min_ref) ctx el
  261. let match_expr ctx e cases def with_type p = !match_expr_ref ctx e cases def with_type p
  262. let make_static_call ctx c cf map args t p =
  263. let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
  264. let ethis = mk (TTypeExpr (TClassDecl c)) ta p in
  265. let monos = List.map (fun _ -> mk_mono()) cf.cf_params in
  266. let map t = map (apply_params cf.cf_params monos t) in
  267. let ef = mk (TField (ethis,(FStatic (c,cf)))) (map cf.cf_type) p in
  268. make_call ctx ef args (map t) p
  269. let unify ctx t1 t2 p =
  270. try
  271. Type.unify t1 t2
  272. with
  273. Unify_error l ->
  274. if not ctx.untyped then display_error ctx (error_msg (Unify l)) p
  275. let unify_raise ctx t1 t2 p =
  276. try
  277. Type.unify t1 t2
  278. with
  279. Unify_error l ->
  280. (* no untyped check *)
  281. raise (Error (Unify l,p))
  282. let save_locals ctx =
  283. let locals = ctx.locals in
  284. (fun() -> ctx.locals <- locals)
  285. let add_local ctx n t =
  286. let v = alloc_var n t in
  287. ctx.locals <- PMap.add n v ctx.locals;
  288. v
  289. let gen_local_prefix = "`"
  290. let gen_local ctx t =
  291. (* ensure that our generated local does not mask an existing one *)
  292. let rec loop n =
  293. let nv = (if n = 0 then gen_local_prefix else gen_local_prefix ^ string_of_int n) in
  294. if PMap.mem nv ctx.locals then
  295. loop (n+1)
  296. else
  297. nv
  298. in
  299. add_local ctx (loop 0) t
  300. let is_gen_local v =
  301. String.unsafe_get v.v_name 0 = String.unsafe_get gen_local_prefix 0
  302. let not_opened = ref Closed
  303. let mk_anon fl = TAnon { a_fields = fl; a_status = not_opened; }
  304. let delay ctx p f =
  305. let rec loop = function
  306. | [] -> [p,[f]]
  307. | (p2,l) :: rest ->
  308. if p2 = p then
  309. (p, f :: l) :: rest
  310. else if p2 < p then
  311. (p2,l) :: loop rest
  312. else
  313. (p,[f]) :: (p2,l) :: rest
  314. in
  315. ctx.g.delayed <- loop ctx.g.delayed
  316. let rec flush_pass ctx p (where:string) =
  317. match ctx.g.delayed with
  318. | (p2,l) :: rest when p2 <= p ->
  319. (match l with
  320. | [] ->
  321. ctx.g.delayed <- rest;
  322. | f :: l ->
  323. ctx.g.delayed <- (p2,l) :: rest;
  324. f());
  325. flush_pass ctx p where
  326. | _ ->
  327. ()
  328. let make_pass ctx f = f
  329. let init_class_done ctx =
  330. ctx.pass <- PTypeField
  331. let exc_protect ctx f (where:string) =
  332. let rec r = ref (fun() ->
  333. try
  334. f r
  335. with
  336. | Error (m,p) ->
  337. raise (Fatal_error ((error_msg m),p))
  338. ) in
  339. r
  340. let fake_modules = Hashtbl.create 0
  341. let create_fake_module ctx file =
  342. let file = Common.unique_full_path file in
  343. let mdep = (try Hashtbl.find fake_modules file with Not_found ->
  344. let mdep = {
  345. m_id = alloc_mid();
  346. m_path = (["$DEP"],file);
  347. m_types = [];
  348. m_extra = module_extra file (Common.get_signature ctx.com) (file_time file) MFake;
  349. } in
  350. Hashtbl.add fake_modules file mdep;
  351. mdep
  352. ) in
  353. Hashtbl.replace ctx.g.modules mdep.m_path mdep;
  354. mdep
  355. (* -------------- debug functions to activate when debugging typer passes ------------------------------- *)
  356. (*/*
  357. let delay_tabs = ref ""
  358. let context_ident ctx =
  359. if Common.defined ctx.com Common.Define.CoreApi then
  360. " core "
  361. else if Common.defined ctx.com Common.Define.Macro then
  362. "macro "
  363. else
  364. " out "
  365. let debug ctx str =
  366. if Common.raw_defined ctx.com "cdebug" then prerr_endline (context_ident ctx ^ !delay_tabs ^ str)
  367. let init_class_done ctx =
  368. debug ctx ("init_class_done " ^ Ast.s_type_path ctx.curclass.cl_path);
  369. init_class_done ctx
  370. let ctx_pos ctx =
  371. let inf = Ast.s_type_path ctx.m.curmod.m_path in
  372. let inf = (match snd ctx.curclass.cl_path with "" -> inf | n when n = snd ctx.m.curmod.m_path -> inf | n -> inf ^ "." ^ n) in
  373. let inf = (match ctx.curfield.cf_name with "" -> inf | n -> inf ^ ":" ^ n) in
  374. inf
  375. let pass_infos ctx p =
  376. let inf = pass_name p ^ " (" ^ ctx_pos ctx ^ ")" in
  377. let inf = if ctx.pass > p then inf ^ " ??CURPASS=" ^ pass_name ctx.pass else inf in
  378. inf
  379. let delay ctx p f =
  380. let inf = pass_infos ctx p in
  381. let rec loop = function
  382. | [] -> [p,[f,inf,ctx]]
  383. | (p2,l) :: rest ->
  384. if p2 = p then
  385. (p, (f,inf,ctx) :: l) :: rest
  386. else if p2 < p then
  387. (p2,l) :: loop rest
  388. else
  389. (p,[f,inf,ctx]) :: (p2,l) :: rest
  390. in
  391. ctx.g.debug_delayed <- loop ctx.g.debug_delayed;
  392. debug ctx ("add " ^ inf)
  393. let pending_passes ctx =
  394. let rec loop acc = function
  395. | (p,l) :: pl when p < ctx.pass -> loop (acc @ l) pl
  396. | _ -> acc
  397. in
  398. match loop [] ctx.g.debug_delayed with
  399. | [] -> ""
  400. | l -> " ??PENDING[" ^ String.concat ";" (List.map (fun (_,i,_) -> i) l) ^ "]"
  401. let display_error ctx msg p =
  402. debug ctx ("ERROR " ^ msg);
  403. display_error ctx msg p
  404. let make_pass ?inf ctx f =
  405. let inf = (match inf with None -> pass_infos ctx ctx.pass | Some inf -> inf) in
  406. (fun v ->
  407. debug ctx ("run " ^ inf ^ pending_passes ctx);
  408. let old = !delay_tabs in
  409. delay_tabs := !delay_tabs ^ "\t";
  410. let t = (try
  411. f v
  412. with
  413. | Fatal_error (e,p) ->
  414. delay_tabs := old;
  415. raise (Fatal_error (e,p))
  416. | exc when not (Common.raw_defined ctx.com "stack") ->
  417. debug ctx ("FATAL " ^ Printexc.to_string exc);
  418. delay_tabs := old;
  419. raise exc
  420. ) in
  421. delay_tabs := old;
  422. t
  423. )
  424. let rec flush_pass ctx p where =
  425. let rec loop() =
  426. match ctx.g.debug_delayed with
  427. | (p2,l) :: rest when p2 <= p ->
  428. (match l with
  429. | [] ->
  430. ctx.g.debug_delayed <- rest
  431. | (f,inf,ctx2) :: l ->
  432. ctx.g.debug_delayed <- (p2,l) :: rest;
  433. match p2 with
  434. | PTypeField | PBuildClass -> f()
  435. | _ -> (make_pass ~inf ctx f)());
  436. loop()
  437. | _ ->
  438. ()
  439. in
  440. match ctx.g.debug_delayed with
  441. | (p2,_) :: _ when p2 <= p ->
  442. let old = !delay_tabs in
  443. debug ctx ("flush " ^ pass_name p ^ "(" ^ where ^ ")");
  444. delay_tabs := !delay_tabs ^ "\t";
  445. loop();
  446. delay_tabs := old;
  447. debug ctx "flush-done";
  448. | _ ->
  449. ()
  450. let make_where ctx where =
  451. where ^ " (" ^ ctx_pos ctx ^ ")"
  452. let exc_protect ctx f (where:string) =
  453. let f = make_pass ~inf:(make_where ctx where) ctx f in
  454. let rec r = ref (fun() ->
  455. try
  456. f r
  457. with
  458. | Error (m,p) ->
  459. raise (Fatal_error (error_msg m,p))
  460. ) in
  461. r
  462. */*)
  463. (* --------------------------------------------------- *)