typecore.ml 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  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. }
  82. and typer = {
  83. (* shared *)
  84. com : context;
  85. t : basic_types;
  86. g : typer_globals;
  87. mutable meta : metadata;
  88. mutable this_stack : texpr list;
  89. mutable with_type_stack : with_type list;
  90. mutable call_argument_stack : Ast.expr list list;
  91. (* variable *)
  92. mutable pass : typer_pass;
  93. (* per-module *)
  94. mutable m : typer_module;
  95. (* per-class *)
  96. mutable curclass : tclass;
  97. mutable tthis : t;
  98. mutable type_params : (string * t) list;
  99. (* per-function *)
  100. mutable curfield : tclass_field;
  101. mutable untyped : bool;
  102. mutable in_super_call : bool;
  103. mutable in_loop : bool;
  104. mutable in_display : bool;
  105. mutable in_macro : bool;
  106. mutable macro_depth : int;
  107. mutable curfun : current_fun;
  108. mutable ret : t;
  109. mutable locals : (string, tvar) PMap.t;
  110. mutable opened : anon_status ref list;
  111. mutable vthis : tvar option;
  112. (* events *)
  113. mutable on_error : typer -> string -> pos -> unit;
  114. }
  115. type call_error =
  116. | Not_enough_arguments
  117. | Too_many_arguments
  118. | Could_not_unify of error_msg
  119. | Cannot_skip_non_nullable of string
  120. and error_msg =
  121. | Module_not_found of path
  122. | Type_not_found of path * string
  123. | Unify of unify_error list
  124. | Custom of string
  125. | Unknown_ident of string
  126. | Stack of error_msg * error_msg
  127. | Call_error of call_error
  128. exception Fatal_error of string * Ast.pos
  129. exception Forbid_package of (string * path * pos) * pos list * string
  130. exception Error of error_msg * pos
  131. exception DisplayTypes of t list
  132. exception DisplayPosition of Ast.pos list
  133. let make_call_ref : (typer -> texpr -> texpr list -> t -> pos -> texpr) ref = ref (fun _ _ _ _ _ -> assert false)
  134. let type_expr_ref : (typer -> Ast.expr -> with_type -> texpr) ref = ref (fun _ _ _ -> assert false)
  135. let type_module_type_ref : (typer -> module_type -> t list option -> pos -> texpr) ref = ref (fun _ _ _ _ -> assert false)
  136. let unify_min_ref : (typer -> texpr list -> t) ref = ref (fun _ _ -> assert false)
  137. 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)
  138. let get_pattern_locals_ref : (typer -> Ast.expr -> Type.t -> (string, tvar * pos) PMap.t) ref = ref (fun _ _ _ -> assert false)
  139. let get_constructor_ref : (typer -> tclass -> t list -> Ast.pos -> (t * tclass_field)) ref = ref (fun _ _ _ _ -> assert false)
  140. let cast_or_unify_ref : (typer -> t -> texpr -> Ast.pos -> texpr) ref = ref (fun _ _ _ _ -> assert false)
  141. 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)
  142. (* Source: http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance#OCaml *)
  143. let levenshtein a b =
  144. let x = Array.init (String.length a) (fun i -> a.[i]) in
  145. let y = Array.init (String.length b) (fun i -> b.[i]) in
  146. let minimum (x:int) y z =
  147. let m' (a:int) b = if a < b then a else b in
  148. m' (m' x y) z
  149. in
  150. let init_matrix n m =
  151. let init_col = Array.init m in
  152. Array.init n (function
  153. | 0 -> init_col (function j -> j)
  154. | i -> init_col (function 0 -> i | _ -> 0)
  155. )
  156. in
  157. match Array.length x, Array.length y with
  158. | 0, n -> n
  159. | m, 0 -> m
  160. | m, n ->
  161. let matrix = init_matrix (m + 1) (n + 1) in
  162. for i = 1 to m do
  163. let s = matrix.(i) and t = matrix.(i - 1) in
  164. for j = 1 to n do
  165. let cost = abs (compare x.(i - 1) y.(j - 1)) in
  166. s.(j) <- minimum (t.(j) + 1) (s.(j - 1) + 1) (t.(j - 1) + cost)
  167. done
  168. done;
  169. matrix.(m).(n)
  170. let string_error_raise s sl msg =
  171. if sl = [] then msg else
  172. let cl = List.map (fun s2 -> s2,levenshtein s s2) sl in
  173. let cl = List.sort (fun (_,c1) (_,c2) -> compare c1 c2) cl in
  174. let rec loop sl = match sl with
  175. | (s2,i) :: sl when i <= (min (String.length s) (String.length s2)) / 3 -> s2 :: loop sl
  176. | _ -> []
  177. in
  178. match loop cl with
  179. | [] -> raise Not_found
  180. | [s] -> Printf.sprintf "%s (Suggestion: %s)" msg s
  181. | sl -> Printf.sprintf "%s (Suggestions: %s)" msg (String.concat ", " sl)
  182. let string_error s sl msg =
  183. try string_error_raise s sl msg
  184. with Not_found -> msg
  185. let string_source t = match follow t with
  186. | TInst(c,_) -> List.map (fun cf -> cf.cf_name) c.cl_ordered_fields
  187. | TAnon a -> PMap.fold (fun cf acc -> cf.cf_name :: acc) a.a_fields []
  188. | TAbstract({a_impl = Some c},_) -> List.map (fun cf -> cf.cf_name) c.cl_ordered_statics
  189. | _ -> []
  190. let short_type ctx t =
  191. let tstr = s_type ctx t in
  192. if String.length tstr > 150 then String.sub tstr 0 147 ^ "..." else tstr
  193. let unify_error_msg ctx = function
  194. | Cannot_unify (t1,t2) ->
  195. s_type ctx t1 ^ " should be " ^ s_type ctx t2
  196. | Invalid_field_type s ->
  197. "Invalid type for field " ^ s ^ " :"
  198. | Has_no_field (t,n) ->
  199. string_error n (string_source t) (short_type ctx t ^ " has no field " ^ n)
  200. | Has_no_runtime_field (t,n) ->
  201. s_type ctx t ^ "." ^ n ^ " is not accessible at runtime"
  202. | Has_extra_field (t,n) ->
  203. short_type ctx t ^ " has extra field " ^ n
  204. | Invalid_kind (f,a,b) ->
  205. (match a, b with
  206. | Var va, Var vb ->
  207. let name, stra, strb = if va.v_read = vb.v_read then
  208. "setter", s_access false va.v_write, s_access false vb.v_write
  209. else if va.v_write = vb.v_write then
  210. "getter", s_access true va.v_read, s_access true vb.v_read
  211. else
  212. "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 ^ ")"
  213. in
  214. "Inconsistent " ^ name ^ " for field " ^ f ^ " : " ^ stra ^ " should be " ^ strb
  215. | _ ->
  216. "Field " ^ f ^ " is " ^ s_kind a ^ " but should be " ^ s_kind b)
  217. | Invalid_visibility n ->
  218. "The field " ^ n ^ " is not public"
  219. | Not_matching_optional n ->
  220. "Optional attribute of parameter " ^ n ^ " differs"
  221. | Cant_force_optional ->
  222. "Optional parameters can't be forced"
  223. | Invariant_parameter _ ->
  224. "Type parameters are invariant"
  225. | Constraint_failure name ->
  226. "Constraint check failure for " ^ name
  227. | Missing_overload (cf, t) ->
  228. cf.cf_name ^ " has no overload for " ^ s_type ctx t
  229. | Unify_custom msg ->
  230. msg
  231. let rec error_msg = function
  232. | Module_not_found m -> "Class not found : " ^ Ast.s_type_path m
  233. | Type_not_found (m,t) -> "Module " ^ Ast.s_type_path m ^ " does not define type " ^ t
  234. | Unify l ->
  235. let ctx = print_context() in
  236. String.concat "\n" (List.map (unify_error_msg ctx) l)
  237. | Unknown_ident s -> "Unknown identifier : " ^ s
  238. | Custom s -> s
  239. | Stack (m1,m2) -> error_msg m1 ^ "\n" ^ error_msg m2
  240. | Call_error err -> s_call_error err
  241. and s_call_error = function
  242. | Not_enough_arguments -> "Not enough arguments"
  243. | Too_many_arguments -> "Too many arguments"
  244. | Could_not_unify err -> error_msg err
  245. | Cannot_skip_non_nullable s -> "Cannot skip non-nullable argument " ^ s
  246. let pass_name = function
  247. | PBuildModule -> "build-module"
  248. | PBuildClass -> "build-class"
  249. | PTypeField -> "type-field"
  250. | PCheckConstraint -> "check-constraint"
  251. | PForce -> "force"
  252. | PFinal -> "final"
  253. let display_error ctx msg p = ctx.on_error ctx msg p
  254. let error msg p = raise (Error (Custom msg,p))
  255. let make_call ctx e el t p = (!make_call_ref) ctx e el t p
  256. let type_expr ctx e with_type = (!type_expr_ref) ctx e with_type
  257. let unify_min ctx el = (!unify_min_ref) ctx el
  258. let match_expr ctx e cases def with_type p = !match_expr_ref ctx e cases def with_type p
  259. let make_static_call ctx c cf map args t p =
  260. let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
  261. let ethis = mk (TTypeExpr (TClassDecl c)) ta p in
  262. let monos = List.map (fun _ -> mk_mono()) cf.cf_params in
  263. let map t = map (apply_params cf.cf_params monos t) in
  264. let ef = mk (TField (ethis,(FStatic (c,cf)))) (map cf.cf_type) p in
  265. make_call ctx ef args (map t) p
  266. let unify ctx t1 t2 p =
  267. try
  268. Type.unify t1 t2
  269. with
  270. Unify_error l ->
  271. if not ctx.untyped then display_error ctx (error_msg (Unify l)) p
  272. let unify_raise ctx t1 t2 p =
  273. try
  274. Type.unify t1 t2
  275. with
  276. Unify_error l ->
  277. (* no untyped check *)
  278. raise (Error (Unify l,p))
  279. let save_locals ctx =
  280. let locals = ctx.locals in
  281. (fun() -> ctx.locals <- locals)
  282. let add_local ctx n t =
  283. let v = alloc_var n t in
  284. ctx.locals <- PMap.add n v ctx.locals;
  285. v
  286. let gen_local_prefix = "`"
  287. let gen_local ctx t =
  288. (* ensure that our generated local does not mask an existing one *)
  289. let rec loop n =
  290. let nv = (if n = 0 then gen_local_prefix else gen_local_prefix ^ string_of_int n) in
  291. if PMap.mem nv ctx.locals then
  292. loop (n+1)
  293. else
  294. nv
  295. in
  296. add_local ctx (loop 0) t
  297. let is_gen_local v =
  298. String.unsafe_get v.v_name 0 = String.unsafe_get gen_local_prefix 0
  299. let not_opened = ref Closed
  300. let mk_anon fl = TAnon { a_fields = fl; a_status = not_opened; }
  301. let delay ctx p f =
  302. let rec loop = function
  303. | [] -> [p,[f]]
  304. | (p2,l) :: rest ->
  305. if p2 = p then
  306. (p, f :: l) :: rest
  307. else if p2 < p then
  308. (p2,l) :: loop rest
  309. else
  310. (p,[f]) :: (p2,l) :: rest
  311. in
  312. ctx.g.delayed <- loop ctx.g.delayed
  313. let rec flush_pass ctx p (where:string) =
  314. match ctx.g.delayed with
  315. | (p2,l) :: rest when p2 <= p ->
  316. (match l with
  317. | [] ->
  318. ctx.g.delayed <- rest;
  319. | f :: l ->
  320. ctx.g.delayed <- (p2,l) :: rest;
  321. f());
  322. flush_pass ctx p where
  323. | _ ->
  324. ()
  325. let make_pass ctx f = f
  326. let init_class_done ctx =
  327. ctx.pass <- PTypeField
  328. let exc_protect ctx f (where:string) =
  329. let rec r = ref (fun() ->
  330. try
  331. f r
  332. with
  333. | Error (m,p) ->
  334. raise (Fatal_error ((error_msg m),p))
  335. ) in
  336. r
  337. let fake_modules = Hashtbl.create 0
  338. let create_fake_module ctx file =
  339. let file = Common.unique_full_path file in
  340. let mdep = (try Hashtbl.find fake_modules file with Not_found ->
  341. let mdep = {
  342. m_id = alloc_mid();
  343. m_path = (["$DEP"],file);
  344. m_types = [];
  345. m_extra = module_extra file (Common.get_signature ctx.com) (file_time file) MFake;
  346. } in
  347. Hashtbl.add fake_modules file mdep;
  348. mdep
  349. ) in
  350. Hashtbl.replace ctx.g.modules mdep.m_path mdep;
  351. mdep
  352. (* -------------- debug functions to activate when debugging typer passes ------------------------------- *)
  353. (*/*
  354. let delay_tabs = ref ""
  355. let context_ident ctx =
  356. if Common.defined ctx.com Common.Define.CoreApi then
  357. " core "
  358. else if Common.defined ctx.com Common.Define.Macro then
  359. "macro "
  360. else
  361. " out "
  362. let debug ctx str =
  363. if Common.raw_defined ctx.com "cdebug" then prerr_endline (context_ident ctx ^ !delay_tabs ^ str)
  364. let init_class_done ctx =
  365. debug ctx ("init_class_done " ^ Ast.s_type_path ctx.curclass.cl_path);
  366. init_class_done ctx
  367. let ctx_pos ctx =
  368. let inf = Ast.s_type_path ctx.m.curmod.m_path in
  369. let inf = (match snd ctx.curclass.cl_path with "" -> inf | n when n = snd ctx.m.curmod.m_path -> inf | n -> inf ^ "." ^ n) in
  370. let inf = (match ctx.curfield.cf_name with "" -> inf | n -> inf ^ ":" ^ n) in
  371. inf
  372. let pass_infos ctx p =
  373. let inf = pass_name p ^ " (" ^ ctx_pos ctx ^ ")" in
  374. let inf = if ctx.pass > p then inf ^ " ??CURPASS=" ^ pass_name ctx.pass else inf in
  375. inf
  376. let delay ctx p f =
  377. let inf = pass_infos ctx p in
  378. let rec loop = function
  379. | [] -> [p,[f,inf,ctx]]
  380. | (p2,l) :: rest ->
  381. if p2 = p then
  382. (p, (f,inf,ctx) :: l) :: rest
  383. else if p2 < p then
  384. (p2,l) :: loop rest
  385. else
  386. (p,[f,inf,ctx]) :: (p2,l) :: rest
  387. in
  388. ctx.g.debug_delayed <- loop ctx.g.debug_delayed;
  389. debug ctx ("add " ^ inf)
  390. let pending_passes ctx =
  391. let rec loop acc = function
  392. | (p,l) :: pl when p < ctx.pass -> loop (acc @ l) pl
  393. | _ -> acc
  394. in
  395. match loop [] ctx.g.debug_delayed with
  396. | [] -> ""
  397. | l -> " ??PENDING[" ^ String.concat ";" (List.map (fun (_,i,_) -> i) l) ^ "]"
  398. let display_error ctx msg p =
  399. debug ctx ("ERROR " ^ msg);
  400. display_error ctx msg p
  401. let make_pass ?inf ctx f =
  402. let inf = (match inf with None -> pass_infos ctx ctx.pass | Some inf -> inf) in
  403. (fun v ->
  404. debug ctx ("run " ^ inf ^ pending_passes ctx);
  405. let old = !delay_tabs in
  406. delay_tabs := !delay_tabs ^ "\t";
  407. let t = (try
  408. f v
  409. with
  410. | Fatal_error (e,p) ->
  411. delay_tabs := old;
  412. raise (Fatal_error (e,p))
  413. | exc when not (Common.raw_defined ctx.com "stack") ->
  414. debug ctx ("FATAL " ^ Printexc.to_string exc);
  415. delay_tabs := old;
  416. raise exc
  417. ) in
  418. delay_tabs := old;
  419. t
  420. )
  421. let rec flush_pass ctx p where =
  422. let rec loop() =
  423. match ctx.g.debug_delayed with
  424. | (p2,l) :: rest when p2 <= p ->
  425. (match l with
  426. | [] ->
  427. ctx.g.debug_delayed <- rest
  428. | (f,inf,ctx2) :: l ->
  429. ctx.g.debug_delayed <- (p2,l) :: rest;
  430. match p2 with
  431. | PTypeField | PBuildClass -> f()
  432. | _ -> (make_pass ~inf ctx f)());
  433. loop()
  434. | _ ->
  435. ()
  436. in
  437. match ctx.g.debug_delayed with
  438. | (p2,_) :: _ when p2 <= p ->
  439. let old = !delay_tabs in
  440. debug ctx ("flush " ^ pass_name p ^ "(" ^ where ^ ")");
  441. delay_tabs := !delay_tabs ^ "\t";
  442. loop();
  443. delay_tabs := old;
  444. debug ctx "flush-done";
  445. | _ ->
  446. ()
  447. let make_where ctx where =
  448. where ^ " (" ^ ctx_pos ctx ^ ")"
  449. let exc_protect ctx f (where:string) =
  450. let f = make_pass ~inf:(make_where ctx where) ctx f in
  451. let rec r = ref (fun() ->
  452. try
  453. f r
  454. with
  455. | Error (m,p) ->
  456. raise (Fatal_error (error_msg m,p))
  457. ) in
  458. r
  459. */*)
  460. (* --------------------------------------------------- *)