binast.ml 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. (*
  2. * Neko Binary AST for OCaml
  3. * Copyright (c)2005-2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  18. *)
  19. open Nast
  20. type context = {
  21. ch : unit IO.output;
  22. mutable curfile : string;
  23. mutable curline : int;
  24. mutable scount : int;
  25. strings : (string,int) Hashtbl.t;
  26. }
  27. let b ctx n =
  28. IO.write_byte ctx.ch n
  29. let write_ui24 ctx n =
  30. IO.write_byte ctx.ch n;
  31. IO.write_byte ctx.ch (n lsr 8);
  32. IO.write_byte ctx.ch (n lsr 16)
  33. let write_string ctx s =
  34. try
  35. let x = ctx.scount - Hashtbl.find ctx.strings s in
  36. if x > 0xFF then raise Not_found;
  37. b ctx x;
  38. with
  39. Not_found ->
  40. Hashtbl.replace ctx.strings s ctx.scount;
  41. ctx.scount <- ctx.scount + 1;
  42. b ctx 0;
  43. IO.write_ui16 ctx.ch (String.length s);
  44. IO.nwrite_string ctx.ch s
  45. let write_constant ctx = function
  46. | True -> b ctx 0
  47. | False -> b ctx 1
  48. | Null -> b ctx 2
  49. | This -> b ctx 3
  50. | Int n ->
  51. if n >= 0 && n <= 0xFF then begin
  52. b ctx 4;
  53. b ctx n;
  54. end else begin
  55. b ctx 5;
  56. IO.write_i32 ctx.ch n;
  57. end
  58. | Float s ->
  59. b ctx 6;
  60. write_string ctx s
  61. | String s ->
  62. b ctx 7;
  63. write_string ctx s
  64. | Builtin s ->
  65. b ctx 8;
  66. write_string ctx s
  67. | Ident s ->
  68. b ctx 9;
  69. write_string ctx s
  70. | Int32 n ->
  71. b ctx 5; (* same as Int *)
  72. IO.write_real_i32 ctx.ch n
  73. let write_op ctx op =
  74. b ctx (match op with
  75. | "+" -> 0
  76. | "-" -> 1
  77. | "/" -> 2
  78. | "*" -> 3
  79. | "%" -> 4
  80. | "<<" -> 5
  81. | ">>" -> 6
  82. | ">>>" -> 7
  83. | "|" -> 8
  84. | "&" -> 9
  85. | "^" -> 10
  86. | "==" -> 11
  87. | "!=" -> 12
  88. | ">" -> 13
  89. | ">=" -> 14
  90. | "<" -> 15
  91. | "<=" -> 16
  92. | "=" -> 17
  93. | "&&" -> 18
  94. | "||" -> 19
  95. | "++=" -> 20
  96. | "--=" -> 21
  97. | "+=" -> 22
  98. | "-=" -> 23
  99. | "/=" -> 24
  100. | "*=" -> 25
  101. | "%=" -> 26
  102. | "<<=" -> 27
  103. | ">>=" -> 28
  104. | ">>>=" -> 29
  105. | "|=" -> 30
  106. | "&=" -> 31
  107. | "^=" -> 32
  108. | op -> failwith ("Invalid neko ast op " ^ op))
  109. let rec write_expr_opt ctx = function
  110. | None ->
  111. b ctx 0;
  112. | Some e ->
  113. b ctx 1;
  114. write_expr ctx e
  115. and write_expr ctx (e,p) =
  116. if p.psource <> ctx.curfile then begin
  117. b ctx 0;
  118. write_string ctx p.psource;
  119. write_ui24 ctx p.pline;
  120. ctx.curfile <- p.psource;
  121. ctx.curline <- p.pline;
  122. end else if p.pline <> ctx.curline then begin
  123. b ctx 1;
  124. write_ui24 ctx p.pline;
  125. ctx.curline <- p.pline;
  126. end;
  127. match e with
  128. | EConst c ->
  129. b ctx 2;
  130. write_constant ctx c
  131. | EBlock el ->
  132. let n = List.length el in
  133. if n <= 0xFF then begin
  134. b ctx 3;
  135. b ctx n;
  136. end else begin
  137. b ctx 4;
  138. write_ui24 ctx n;
  139. end;
  140. List.iter (write_expr ctx) el
  141. | EParenthesis e ->
  142. b ctx 5;
  143. write_expr ctx e;
  144. | EField (e,f) ->
  145. b ctx 6;
  146. write_expr ctx e;
  147. write_string ctx f;
  148. | ECall (e,el) ->
  149. let n = List.length el in
  150. if n <= 0xFF then begin
  151. b ctx 7;
  152. write_expr ctx e;
  153. b ctx n;
  154. end else begin
  155. b ctx 28;
  156. write_expr ctx e;
  157. write_ui24 ctx n;
  158. end;
  159. List.iter (write_expr ctx) el;
  160. | EArray (e1,e2) ->
  161. b ctx 8;
  162. write_expr ctx e1;
  163. write_expr ctx e2;
  164. | EVars vl ->
  165. b ctx 9;
  166. b ctx (List.length vl);
  167. List.iter (fun (v,e) ->
  168. write_string ctx v;
  169. write_expr_opt ctx e;
  170. ) vl;
  171. | EWhile (e1,e2,NormalWhile) ->
  172. b ctx 10;
  173. write_expr ctx e1;
  174. write_expr ctx e2;
  175. | EWhile (e1,e2,DoWhile) ->
  176. b ctx 11;
  177. write_expr ctx e1;
  178. write_expr ctx e2;
  179. | EIf (e1,e2,eo) ->
  180. b ctx 12;
  181. write_expr ctx e1;
  182. write_expr ctx e2;
  183. write_expr_opt ctx eo;
  184. | ETry (e1,v,e2) ->
  185. b ctx 13;
  186. write_expr ctx e1;
  187. write_string ctx v;
  188. write_expr ctx e2;
  189. | EFunction (pl,e) ->
  190. b ctx 14;
  191. b ctx (List.length pl);
  192. List.iter (write_string ctx) pl;
  193. write_expr ctx e;
  194. | EBinop (op,e1,e2) ->
  195. b ctx 15;
  196. write_op ctx op;
  197. write_expr ctx e1;
  198. write_expr ctx e2;
  199. | EReturn None ->
  200. b ctx 16;
  201. | EReturn (Some e) ->
  202. b ctx 17;
  203. write_expr ctx e;
  204. | EBreak None ->
  205. b ctx 18;
  206. | EBreak (Some e) ->
  207. b ctx 19;
  208. write_expr ctx e;
  209. | EContinue ->
  210. b ctx 20;
  211. | ENext (e1,e2) ->
  212. b ctx 21;
  213. write_expr ctx e1;
  214. write_expr ctx e2;
  215. | EObject fl ->
  216. let n = List.length fl in
  217. if n <= 0xFF then begin
  218. b ctx 22;
  219. b ctx n;
  220. end else begin
  221. b ctx 23;
  222. write_ui24 ctx n;
  223. end;
  224. List.iter (fun (f,e) ->
  225. write_string ctx f;
  226. write_expr ctx e;
  227. ) fl;
  228. | ELabel l ->
  229. b ctx 24;
  230. write_string ctx l;
  231. | ESwitch (e,cases,eo) ->
  232. let n = List.length cases in
  233. if n <= 0xFF then begin
  234. b ctx 25;
  235. b ctx n;
  236. end else begin
  237. b ctx 26;
  238. write_ui24 ctx n;
  239. end;
  240. write_expr ctx e;
  241. List.iter (fun (e1,e2) ->
  242. write_expr ctx e1;
  243. write_expr ctx e2;
  244. ) cases;
  245. write_expr_opt ctx eo;
  246. | ENeko s ->
  247. b ctx 27;
  248. write_ui24 ctx (String.length s);
  249. IO.nwrite_string ctx.ch s
  250. let write ch e =
  251. let ctx = {
  252. ch = ch;
  253. curfile = "";
  254. curline = -1;
  255. scount = 0;
  256. strings = Hashtbl.create 0;
  257. } in
  258. IO.nwrite_string ctx.ch "NBA\001";
  259. write_expr ctx e