type.ml 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. (*
  2. * Haxe Compiler
  3. * Copyright (c)2005 Nicolas Cannasse
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. *)
  19. type module_path = string list * string
  20. type field_access =
  21. | NormalAccess
  22. | NoAccess
  23. | MethodAccess of string
  24. type t =
  25. | TMono of t option ref
  26. | TEnum of tenum * t list
  27. | TInst of tclass * t list
  28. | TFun of (string * t) list * t
  29. | TAnon of (string, tclass_field) PMap.t * string option
  30. | TDynamic of t
  31. | TLazy of (unit -> t) ref
  32. and tconstant =
  33. | TInt of string
  34. | TFloat of string
  35. | TString of string
  36. | TBool of bool
  37. | TNull
  38. | TThis
  39. | TSuper
  40. and tfunc = {
  41. tf_args : (string * t) list;
  42. tf_type : t;
  43. tf_expr : texpr;
  44. }
  45. and texpr_expr =
  46. | TConst of tconstant
  47. | TLocal of string
  48. | TEnumField of tenum * string
  49. | TArray of texpr * texpr
  50. | TBinop of Ast.binop * texpr * texpr
  51. | TField of texpr * string
  52. | TType of module_type
  53. | TParenthesis of texpr
  54. | TObjectDecl of (string * texpr) list
  55. | TArrayDecl of texpr list
  56. | TCall of texpr * texpr list
  57. | TNew of tclass * t list * texpr list
  58. | TUnop of Ast.unop * Ast.unop_flag * texpr
  59. | TFunction of tfunc
  60. | TVars of (string * t * texpr option) list
  61. | TBlock of texpr list
  62. | TFor of string * texpr * texpr
  63. | TIf of texpr * texpr * texpr option
  64. | TWhile of texpr * texpr * Ast.while_flag
  65. | TSwitch of texpr * (texpr * texpr) list * texpr option
  66. | TMatch of texpr * (tenum * t list) * (string * (string * t) list option * texpr) list * texpr option
  67. | TTry of texpr * (string * t * texpr) list
  68. | TReturn of texpr option
  69. | TBreak
  70. | TContinue
  71. | TThrow of texpr
  72. and texpr = {
  73. eexpr : texpr_expr;
  74. etype : t;
  75. epos : Ast.pos;
  76. }
  77. and tclass_field = {
  78. cf_name : string;
  79. mutable cf_type : t;
  80. cf_public : bool;
  81. cf_doc : Ast.documentation;
  82. cf_get : field_access;
  83. cf_set : field_access;
  84. mutable cf_expr : texpr option;
  85. }
  86. and tclass = {
  87. cl_path : module_path;
  88. cl_pos : Ast.pos;
  89. cl_doc : Ast.documentation;
  90. cl_private : bool;
  91. mutable cl_extern : bool;
  92. mutable cl_interface : bool;
  93. mutable cl_locked : bool;
  94. mutable cl_types : (string * t) list;
  95. mutable cl_super : (tclass * t list) option;
  96. mutable cl_implements : (tclass * t list) list;
  97. mutable cl_fields : (string , tclass_field) PMap.t;
  98. mutable cl_statics : (string, tclass_field) PMap.t;
  99. mutable cl_ordered_statics : tclass_field list;
  100. mutable cl_dynamic : t option;
  101. mutable cl_constructor : tclass_field option;
  102. }
  103. and tenum_field = {
  104. ef_name : string;
  105. ef_type : t;
  106. ef_pos : Ast.pos;
  107. ef_doc : Ast.documentation;
  108. }
  109. and tenum = {
  110. e_path : module_path;
  111. e_pos : Ast.pos;
  112. e_doc : Ast.documentation;
  113. e_private : bool;
  114. mutable e_types : (string * t) list;
  115. mutable e_constrs : (string , tenum_field) PMap.t;
  116. }
  117. and module_type =
  118. | TClassDecl of tclass
  119. | TEnumDecl of tenum
  120. type module_def = {
  121. mpath : module_path;
  122. mtypes : module_type list;
  123. }
  124. let mk e t p = { eexpr = e; etype = t; epos = p }
  125. let mk_mono() = TMono (ref None)
  126. let rec t_dynamic = TDynamic t_dynamic
  127. let mk_class path pos doc priv =
  128. {
  129. cl_path = path;
  130. cl_pos = pos;
  131. cl_doc = doc;
  132. cl_private = priv;
  133. cl_extern = false;
  134. cl_interface = false;
  135. cl_locked = false;
  136. cl_types = [];
  137. cl_super = None;
  138. cl_implements = [];
  139. cl_fields = PMap.empty;
  140. cl_ordered_statics = [];
  141. cl_statics = PMap.empty;
  142. cl_dynamic = None;
  143. cl_constructor = None;
  144. }
  145. let null_class = mk_class ([],"") Ast.null_pos None true
  146. let t_private = function
  147. | TClassDecl c -> c.cl_private
  148. | TEnumDecl e -> e.e_private
  149. let t_path = function
  150. | TClassDecl c -> c.cl_path
  151. | TEnumDecl e -> e.e_path
  152. let print_context() = ref []
  153. let rec s_type ctx t =
  154. match t with
  155. | TMono r ->
  156. (match !r with
  157. | None -> Printf.sprintf "Unknown<%d>" (try List.assq t (!ctx) with Not_found -> let n = List.length !ctx in ctx := (t,n) :: !ctx; n)
  158. | Some t -> s_type ctx t)
  159. | TEnum (e,tl) ->
  160. Ast.s_type_path e.e_path ^ s_type_params ctx tl
  161. | TInst (c,tl) ->
  162. Ast.s_type_path c.cl_path ^ s_type_params ctx tl
  163. | TFun ([],t) ->
  164. "Void -> " ^ s_type ctx t
  165. | TFun (l,t) ->
  166. String.concat " -> " (List.map (fun (s,t) -> (if s = "" then "" else s ^ " : ") ^ match t with TFun _ -> "(" ^ s_type ctx t ^ ")" | _ -> s_type ctx t) l) ^ " -> " ^ s_type ctx t
  167. | TAnon (fl,name) ->
  168. (match name with
  169. | Some s -> s
  170. | None ->
  171. let fl = PMap.fold (fun f acc -> (" " ^ f.cf_name ^ " : " ^ s_type ctx f.cf_type) :: acc) fl [] in
  172. "{" ^ String.concat "," fl ^ " }");
  173. | TDynamic t2 ->
  174. "Dynamic" ^ s_type_params ctx (if t == t2 then [] else [t2])
  175. | TLazy f ->
  176. s_type ctx (!f())
  177. and s_type_params ctx = function
  178. | [] -> ""
  179. | l -> "<" ^ String.concat ", " (List.map (s_type ctx) l) ^ ">"
  180. let type_path t =
  181. match t with
  182. | TClassDecl c -> c.cl_path
  183. | TEnumDecl e -> e.e_path
  184. let rec follow t =
  185. match t with
  186. | TMono r ->
  187. (match !r with
  188. | Some t -> follow t
  189. | _ -> t)
  190. | TLazy f ->
  191. follow (!f())
  192. | _ -> t
  193. let rec is_parent csup c =
  194. if c == csup then
  195. true
  196. else match c.cl_super with
  197. | None -> false
  198. | Some (c,_) -> is_parent csup c
  199. let rec link e a b =
  200. let rec loop t =
  201. if t == a then
  202. true
  203. else match t with
  204. | TMono t -> (match !t with None -> false | Some t -> loop t)
  205. | TEnum (_,tl) -> List.exists loop tl
  206. | TInst (_,tl) -> List.exists loop tl
  207. | TFun (tl,t) -> List.exists (fun (_,t) -> loop t) tl || loop t
  208. | TDynamic t2 ->
  209. if t == t2 then
  210. false
  211. else
  212. loop t2
  213. | TLazy f ->
  214. loop (!f())
  215. | TAnon (fl,_) ->
  216. try
  217. PMap.iter (fun _ f -> if loop f.cf_type then raise Exit) fl;
  218. false
  219. with
  220. Exit -> true
  221. in
  222. if loop b then
  223. false
  224. else begin
  225. e := Some b;
  226. true
  227. end
  228. (* substitute parameters with other types *)
  229. let apply_params cparams params t =
  230. let rec loop l1 l2 =
  231. match l1, l2 with
  232. | [] , [] -> []
  233. | (_,t1) :: l1 , t2 :: l2 -> (t1,t2) :: loop l1 l2
  234. | _ -> assert false
  235. in
  236. let subst = loop cparams params in
  237. let rec loop t =
  238. try
  239. List.assq t subst
  240. with Not_found ->
  241. match t with
  242. | TMono r ->
  243. (match !r with
  244. | None -> t
  245. | Some t -> loop t)
  246. | TEnum (e,tl) ->
  247. TEnum (e,List.map loop tl)
  248. | TInst (c,tl) ->
  249. (match tl with
  250. | [TMono r] ->
  251. (match !r with
  252. | Some tt when t == tt ->
  253. (* for dynamic *)
  254. let pt = mk_mono() in
  255. let t = TInst (c,[pt]) in
  256. (match pt with TMono r -> r := Some t | _ -> assert false);
  257. t
  258. | _ -> TInst (c,List.map loop tl))
  259. | _ ->
  260. TInst (c,List.map loop tl))
  261. | TFun (tl,r) ->
  262. TFun (List.map (fun (s,t) -> s, loop t) tl,loop r)
  263. | TAnon (fl,name) ->
  264. TAnon (PMap.map (fun f -> { f with cf_type = loop f.cf_type }) fl,name)
  265. | TLazy f ->
  266. loop (!f())
  267. | TDynamic t2 ->
  268. if t == t2 then
  269. t
  270. else
  271. TDynamic (loop t2)
  272. in
  273. loop t
  274. let monomorphs eparams t =
  275. apply_params eparams (List.map (fun _ -> mk_mono()) eparams) t
  276. let rec type_eq param a b =
  277. if a == b || (param && b == t_dynamic) then
  278. true
  279. else match a , b with
  280. | TLazy f , _ -> type_eq param (!f()) b
  281. | _ , TLazy f -> type_eq param a (!f())
  282. | TMono t , _ -> (match !t with None -> link t a b | Some t -> type_eq param t b)
  283. | _ , TMono t -> (match !t with None -> link t b a | Some t -> type_eq param a t)
  284. | TEnum (a,tl1) , TEnum (b,tl2) -> a == b && List.for_all2 (type_eq param) tl1 tl2
  285. | TInst (c1,tl1) , TInst (c2,tl2) ->
  286. c1 == c2 && List.for_all2 (type_eq param) tl1 tl2
  287. | TFun (l1,r1) , TFun (l2,r2) when List.length l1 = List.length l2 ->
  288. type_eq param r1 r2 && List.for_all2 (fun (_,t1) (_,t2) -> type_eq param t1 t2) l1 l2
  289. | TDynamic a , TDynamic b ->
  290. type_eq param a b
  291. | TAnon (fl1,_), TAnon (fl2,_) ->
  292. let keys1 = PMap.fold (fun f acc -> f :: acc) fl1 [] in
  293. let keys2 = PMap.fold (fun f acc -> f :: acc) fl2 [] in
  294. (try
  295. List.iter2 (fun f1 f2 ->
  296. if f1.cf_name <> f2.cf_name || not (type_eq param f1.cf_type f2.cf_type) then raise Not_found;
  297. if f1.cf_get <> f2.cf_get || f1.cf_set <> f2.cf_set then raise Not_found;
  298. ) keys1 keys2;
  299. true
  300. with
  301. _ -> false)
  302. | _ , _ ->
  303. false
  304. (* perform unification with subtyping.
  305. the first type is always the most down in the class hierarchy
  306. it's also the one that is pointed by the position.
  307. It's actually a typecheck of A :> B where some mutations can happen *)
  308. type unify_error =
  309. | Cannot_unify of t * t
  310. | Invalid_field_type of string
  311. | Has_no_field of t * string
  312. | Invalid_access of string * bool
  313. exception Unify_error of unify_error list
  314. let cannot_unify a b = Cannot_unify (a,b)
  315. let invalid_field n = Invalid_field_type n
  316. let invalid_access n get = Invalid_access (n,get)
  317. let has_no_field t n = Has_no_field (t,n)
  318. let error l = raise (Unify_error l)
  319. let unify_types a b tl1 tl2 =
  320. List.iter2 (fun ta tb ->
  321. if not (type_eq true ta tb) then error [cannot_unify a b; cannot_unify ta tb]
  322. ) tl1 tl2
  323. let rec unify a b =
  324. if a == b then
  325. ()
  326. else match a, b with
  327. | TLazy f , _ -> unify (!f()) b
  328. | _ , TLazy f -> unify a (!f())
  329. | TMono t , _ ->
  330. (match !t with
  331. | None -> if not (link t a b) then error [cannot_unify a b]
  332. | Some t -> unify t b)
  333. | _ , TMono t ->
  334. (match !t with
  335. | None -> if not (link t b a) then error [cannot_unify a b]
  336. | Some t -> unify a t)
  337. | TEnum (ea,tl1) , TEnum (eb,tl2) ->
  338. if ea != eb then error [cannot_unify a b];
  339. unify_types a b tl1 tl2
  340. | TInst (c1,tl1) , TInst (c2,tl2) ->
  341. let rec loop c tl =
  342. if c == c2 then begin
  343. unify_types a b tl tl2;
  344. true
  345. end else (match c.cl_super with
  346. | None -> false
  347. | Some (cs,tls) ->
  348. loop cs (List.map (apply_params c.cl_types tl) tls)
  349. ) || List.exists (fun (cs,tls) ->
  350. loop cs (List.map (apply_params c.cl_types tl) tls)
  351. ) c.cl_implements
  352. in
  353. if not (loop c1 tl1) then error [cannot_unify a b]
  354. | TFun (l1,r1) , TFun (l2,r2) when List.length l1 = List.length l2 ->
  355. (try
  356. unify r1 r2;
  357. List.iter2 (fun (_,t1) (_,t2) -> unify t1 t2) l2 l1 (* contravariance *)
  358. with
  359. Unify_error l -> error (cannot_unify a b :: l))
  360. | TInst (c,tl) , TAnon (fl,_) ->
  361. (try
  362. PMap.iter (fun n f2 ->
  363. let f1 = (try PMap.find n c.cl_fields with Not_found -> error [has_no_field a n]) in
  364. if f1.cf_get <> f2.cf_get then error [invalid_access n true];
  365. if f1.cf_set <> f2.cf_set then error [invalid_access n false];
  366. try
  367. unify (apply_params c.cl_types tl f1.cf_type) f2.cf_type
  368. with
  369. Unify_error l -> error (invalid_field n :: l)
  370. ) fl
  371. with
  372. Unify_error l -> error (cannot_unify a b :: l))
  373. | TAnon (fl,_) , TInst (c,tl) ->
  374. let rec loop c tl =
  375. PMap.iter (fun n f2 ->
  376. let f1 = (try PMap.find n fl with Not_found -> error [has_no_field a n]) in
  377. if f1.cf_get <> f2.cf_get then error [invalid_access n true];
  378. if f1.cf_set <> f2.cf_set then error [invalid_access n false];
  379. try
  380. unify f1.cf_type (apply_params c.cl_types tl f2.cf_type)
  381. with
  382. Unify_error l -> error (invalid_field n :: l)
  383. ) c.cl_fields;
  384. List.iter (fun (c,t) -> loop c t) c.cl_implements;
  385. match c.cl_super with
  386. | None -> ()
  387. | Some (c,tl) -> loop c tl
  388. in
  389. if c.cl_locked then error [cannot_unify a b];
  390. (try
  391. loop c tl;
  392. with
  393. Unify_error l -> error (cannot_unify a b :: l))
  394. | TAnon (fl1,_) , TAnon (fl2,_) ->
  395. (try
  396. PMap.iter (fun n f2 ->
  397. let f1 = (try PMap.find n fl1 with Not_found -> error [has_no_field a n]) in
  398. if f1.cf_get <> f2.cf_get then error [invalid_access n true];
  399. if f1.cf_set <> f2.cf_set then error [invalid_access n false];
  400. try
  401. unify f1.cf_type f2.cf_type;
  402. with
  403. Unify_error l -> error (invalid_field n :: l)
  404. ) fl2;
  405. with
  406. Unify_error l -> error (cannot_unify a b :: l))
  407. | TDynamic t , _ ->
  408. if t == a then
  409. ()
  410. else (match b with
  411. | TDynamic t2 ->
  412. if t2 != b && not (type_eq true t t2) then error [cannot_unify a b; cannot_unify t t2];
  413. | _ ->
  414. error [cannot_unify a b])
  415. | _ , TDynamic t ->
  416. if t == b then
  417. ()
  418. else (match a with
  419. | TDynamic t2 ->
  420. if t2 != a && not (type_eq true t t2) then error [cannot_unify a b; cannot_unify t t2]
  421. | _ ->
  422. error [cannot_unify a b])
  423. | _ , _ ->
  424. error [cannot_unify a b]
  425. let rec iter f e =
  426. match e.eexpr with
  427. | TConst _
  428. | TLocal _
  429. | TEnumField _
  430. | TBreak
  431. | TContinue
  432. | TType _ ->
  433. ()
  434. | TArray (e1,e2)
  435. | TBinop (_,e1,e2)
  436. | TFor (_,e1,e2)
  437. | TWhile (e1,e2,_) ->
  438. f e1;
  439. f e2;
  440. | TThrow e
  441. | TField (e,_)
  442. | TParenthesis e
  443. | TUnop (_,_,e) ->
  444. f e
  445. | TArrayDecl el
  446. | TNew (_,_,el)
  447. | TBlock el ->
  448. List.iter f el
  449. | TObjectDecl fl ->
  450. List.iter (fun (_,e) -> f e) fl
  451. | TCall (e,el) ->
  452. f e;
  453. List.iter f el
  454. | TVars vl ->
  455. List.iter (fun (_,_,e) -> match e with None -> () | Some e -> f e) vl
  456. | TFunction fu ->
  457. f fu.tf_expr
  458. | TIf (e,e1,e2) ->
  459. f e;
  460. f e1;
  461. (match e2 with None -> () | Some e -> f e)
  462. | TSwitch (e,cases,def) ->
  463. f e;
  464. List.iter (fun (e1,e2) -> f e1; f e2) cases;
  465. (match def with None -> () | Some e -> f e)
  466. | TMatch (e,_,cases,def) ->
  467. f e;
  468. List.iter (fun (_,_,e) -> f e) cases;
  469. (match def with None -> () | Some e -> f e)
  470. | TTry (e,catches) ->
  471. f e;
  472. List.iter (fun (_,_,e) -> f e) catches
  473. | TReturn eo ->
  474. (match eo with None -> () | Some e -> f e)