~ubuntu-branches/ubuntu/oneiric/haxe/oneiric

« back to all changes in this revision

Viewing changes to ocaml/swflib/as3hlparse.ml

  • Committer: Bazaar Package Importer
  • Author(s): Jens Peter Secher
  • Date: 2008-06-15 11:04:09 UTC
  • mfrom: (2.1.6 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080615110409-7pyykgwmk5v0cues
Tags: 1:1.19-3
* Remove bashism in script.
  (Closes: #484390)
* Upgrade to Policy 3.8.0 by including a README.source explaining how to
  use dpatch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(*
 
2
 *  This file is part of SwfLib
 
3
 *  Copyright (c)2004-2008 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
open As3
 
20
open As3hl
 
21
 
 
22
type parse_ctx = {
 
23
        as3 : as3_tag;
 
24
        mutable namespaces : hl_namespace array;
 
25
        mutable nsets : hl_ns_set array;
 
26
        mutable names : hl_name array;
 
27
        mutable methods : hl_method array;
 
28
        mutable classes : hl_class array;
 
29
        mutable jumps : (int * int) list;
 
30
        mutable pos : int;
 
31
}
 
32
 
 
33
let get = As3parse.iget
 
34
let no_nz = As3parse.no_nz
 
35
let idx n = As3parse.index_int n - 1
 
36
 
 
37
let ident ctx i = get ctx.as3.as3_idents i
 
38
let name ctx n = ctx.names.(idx n)
 
39
let method_type ctx n = ctx.methods.(idx (no_nz n))
 
40
let getclass ctx n = ctx.classes.(idx (no_nz n))
 
41
 
 
42
let global_mark = ref 0
 
43
 
 
44
let alloc_mark() =
 
45
        incr global_mark;
 
46
        !global_mark
 
47
 
 
48
let opt f ctx = function
 
49
        | None -> None
 
50
        | Some x -> Some (f ctx x)
 
51
 
 
52
let stack_delta = function
 
53
        | HBreakPoint -> 0
 
54
        | HNop -> 0
 
55
        | HThrow -> -1
 
56
        | HGetSuper _ -> 1  (* ??? *)
 
57
        | HSetSuper _ -> -1 (* ??? *)
 
58
        | HRegKill _ -> 0
 
59
        | HLabel -> 0
 
60
        | HJump (cond,_) ->
 
61
                (match cond with
 
62
                | J3Always -> 0
 
63
                | J3True
 
64
                | J3False -> -1
 
65
                | _ -> -2)
 
66
        | HSwitch _ -> -1
 
67
        | HPushWith -> -1
 
68
        | HPopScope -> 0
 
69
        | HForIn -> -1
 
70
        | HHasNext -> -1
 
71
        | HNull
 
72
        | HUndefined -> 1
 
73
        | HForEach -> -1
 
74
        | HSmallInt _
 
75
        | HInt _
 
76
        | HTrue
 
77
        | HFalse
 
78
        | HString _
 
79
        | HIntRef _
 
80
        | HUIntRef _
 
81
        | HFunction _
 
82
        | HFloat _
 
83
        | HNaN -> 1
 
84
        | HPop -> -1
 
85
        | HDup -> 1
 
86
        | HSwap -> 0
 
87
        | HScope -> -1
 
88
        | HNamespace _ -> 1
 
89
        | HNext _ -> 1
 
90
        | HCallStack n -> -(n + 1)
 
91
        | HConstruct n -> -n
 
92
        | HCallMethod (_,n) -> -n
 
93
        | HCallStatic (_,n) -> -n
 
94
        | HCallSuper (_,n) -> -n
 
95
        | HCallProperty (_,n) -> -n
 
96
        | HRetVoid -> 0
 
97
        | HRet -> -1
 
98
        | HConstructSuper n -> -(n + 1)
 
99
        | HConstructProperty (_,n) -> -n
 
100
        | HCallPropLex (_,n) -> -n
 
101
        | HCallSuperVoid (_,n) -> -(n + 1)
 
102
        | HCallPropVoid (_,n) -> -(n + 1)
 
103
        | HObject n -> -(n * 2) + 1
 
104
        | HArray n -> -n + 1
 
105
        | HNewBlock -> 1
 
106
        | HClassDef _ -> 0
 
107
        | HCatch _ -> 1
 
108
        | HFindPropStrict _ -> 1
 
109
        | HFindProp _ -> 1
 
110
        | HFindDefinition _ -> 1
 
111
        | HGetLex _ -> 1
 
112
        | HSetProp _ -> -2
 
113
        | HReg _ -> 1
 
114
        | HSetReg _ | HSetThis -> -1
 
115
        | HGetGlobalScope | HGetScope _ -> 1
 
116
        | HGetProp _ -> 0
 
117
        | HInitProp _ -> -2
 
118
        | HDeleteProp _ -> -1 (* true/false *)
 
119
        | HGetSlot _ -> 0
 
120
        | HSetSlot _ -> -2
 
121
        | HToString
 
122
        | HToXml
 
123
        | HToXmlAttr
 
124
        | HToInt
 
125
        | HToUInt
 
126
        | HToNumber
 
127
        | HToObject
 
128
        | HAsAny
 
129
        | HAsType _
 
130
        | HIsType _
 
131
        | HAsObject
 
132
        | HAsString
 
133
        | HToBool -> 0
 
134
        | HCheckIsXml -> 0
 
135
        | HCast _ -> 0
 
136
        | HTypeof -> 0
 
137
        | HInstanceOf -> -1
 
138
        | HIncrReg _ | HDecrReg _ | HIncrIReg _ | HDecrIReg _ -> 0
 
139
        | HThis -> 1
 
140
        | HDebugReg _
 
141
        | HDebugLine _
 
142
        | HBreakPointLine _
 
143
        | HTimestamp
 
144
        | HDebugFile _ -> 0
 
145
        | HOp op ->
 
146
                (match op with
 
147
                | A3ONeg | A3OINeg | A3OIncr | A3ODecr | A3ONot | A3OBitNot | A3OIIncr | A3OIDecr -> 0
 
148
                | _ -> -1)
 
149
        | HUnk _ -> assert false
 
150
 
 
151
let parse_opcode ctx i = function
 
152
        | A3BreakPoint -> HBreakPoint
 
153
        | A3Nop -> HNop
 
154
        | A3Throw -> HThrow
 
155
        | A3GetSuper n -> HGetSuper (name ctx n)
 
156
        | A3SetSuper n -> HSetSuper (name ctx n)
 
157
        | A3RegKill r -> HRegKill r
 
158
        | A3Label -> HLabel
 
159
        | A3Jump (j,n) ->
 
160
                ctx.jumps <- (i,ctx.pos) :: ctx.jumps;
 
161
                HJump (j,n)
 
162
        | A3Switch (n,infos) as op ->
 
163
                ctx.jumps <- (i,ctx.pos - As3code.length op) :: ctx.jumps;
 
164
                HSwitch(n,infos)
 
165
        | A3PushWith -> HPushWith
 
166
        | A3PopScope -> HPopScope
 
167
        | A3ForIn -> HForIn
 
168
        | A3HasNext -> HHasNext
 
169
        | A3Null -> HNull
 
170
        | A3Undefined -> HUndefined
 
171
        | A3ForEach -> HForEach
 
172
        | A3SmallInt n -> HSmallInt n
 
173
        | A3Int n -> HInt n
 
174
        | A3True -> HTrue
 
175
        | A3False -> HFalse
 
176
        | A3NaN -> HNaN
 
177
        | A3Pop -> HPop
 
178
        | A3Dup -> HDup
 
179
        | A3Swap -> HSwap
 
180
        | A3String i -> HString (ident ctx i)
 
181
        | A3IntRef i -> HIntRef (get ctx.as3.as3_ints i)
 
182
        | A3UIntRef i -> HUIntRef (get ctx.as3.as3_uints i)
 
183
        | A3Float f -> HFloat (get ctx.as3.as3_floats f)
 
184
        | A3Scope -> HScope
 
185
        | A3Namespace n -> HNamespace ctx.namespaces.(idx n)
 
186
        | A3Next (r1,r2) -> HNext (r1,r2)
 
187
        | A3Function f -> HFunction (method_type ctx f)
 
188
        | A3CallStack n -> HCallStack n
 
189
        | A3Construct n -> HConstruct n
 
190
        | A3CallMethod (s,n) -> HCallMethod (s,n)
 
191
        | A3CallStatic (m,n) -> HCallStatic (ctx.methods.(idx m),n)
 
192
        | A3CallSuper (p,n) -> HCallSuper (name ctx p,n)
 
193
        | A3CallProperty (p,n) -> HCallProperty (name ctx p,n)
 
194
        | A3RetVoid -> HRetVoid
 
195
        | A3Ret -> HRet
 
196
        | A3ConstructSuper n -> HConstructSuper n
 
197
        | A3ConstructProperty (p,n) -> HConstructProperty (name ctx p,n)
 
198
        | A3CallPropLex (p,n) -> HCallPropLex (name ctx p,n)
 
199
        | A3CallSuperVoid (p,n) -> HCallSuperVoid (name ctx p,n)
 
200
        | A3CallPropVoid (p,n) -> HCallPropVoid (name ctx p,n)
 
201
        | A3Object n -> HObject n
 
202
        | A3Array n -> HArray n
 
203
        | A3NewBlock -> HNewBlock
 
204
        | A3ClassDef n -> HClassDef (getclass ctx n)
 
205
        | A3Catch n -> HCatch n
 
206
        | A3FindPropStrict p -> HFindPropStrict (name ctx p)
 
207
        | A3FindProp p -> HFindProp (name ctx p)
 
208
        | A3FindDefinition p -> HFindDefinition (name ctx p)
 
209
        | A3GetLex p -> HGetLex (name ctx p)
 
210
        | A3SetProp p -> HSetProp (name ctx p)
 
211
        | A3Reg r -> HReg r
 
212
        | A3SetReg r -> HSetReg r
 
213
        | A3GetGlobalScope -> HGetGlobalScope
 
214
        | A3GetScope n -> HGetScope n
 
215
        | A3GetProp p -> HGetProp (name ctx p)
 
216
        | A3InitProp p -> HInitProp (name ctx p)
 
217
        | A3DeleteProp p -> HDeleteProp (name ctx p)
 
218
        | A3GetSlot n -> HGetSlot n
 
219
        | A3SetSlot n -> HSetSlot n
 
220
        | A3ToString -> HToString
 
221
        | A3ToXml -> HToXml
 
222
        | A3ToXmlAttr -> HToXmlAttr
 
223
        | A3ToInt -> HToInt
 
224
        | A3ToUInt -> HToUInt
 
225
        | A3ToNumber -> HToNumber
 
226
        | A3ToBool -> HToBool
 
227
        | A3ToObject -> HToObject
 
228
        | A3CheckIsXml -> HCheckIsXml
 
229
        | A3Cast p -> HCast (name ctx p)
 
230
        | A3AsAny -> HAsAny
 
231
        | A3AsString -> HAsString
 
232
        | A3AsType p -> HAsType (name ctx p)
 
233
        | A3AsObject -> HAsObject
 
234
        | A3IncrReg r -> HIncrReg r
 
235
        | A3DecrReg r -> HDecrReg r
 
236
        | A3Typeof -> HTypeof
 
237
        | A3InstanceOf -> HInstanceOf
 
238
        | A3IsType p -> HIsType (name ctx p)
 
239
        | A3IncrIReg r -> HIncrIReg r
 
240
        | A3DecrIReg r -> HDecrIReg r
 
241
        | A3This -> HThis
 
242
        | A3SetThis -> HSetThis
 
243
        | A3DebugReg (id,r,n) -> HDebugReg (ident ctx id,r,n)
 
244
        | A3DebugLine n -> HDebugLine n
 
245
        | A3DebugFile p -> HDebugFile (ident ctx p)
 
246
        | A3BreakPointLine n -> HBreakPointLine n
 
247
        | A3Timestamp -> HTimestamp
 
248
        | A3Op op -> HOp op
 
249
        | A3Unk n -> HUnk n
 
250
 
 
251
let parse_code ctx f trys =
 
252
        let code = f.fun3_code in
 
253
        let old = ctx.pos , ctx.jumps in
 
254
        let indexes = DynArray.create() in
 
255
        ctx.pos <- 0;
 
256
        ctx.jumps <- [];
 
257
        let codepos pos delta =
 
258
                let id = (try DynArray.get indexes (pos + delta) with _ -> -1) in
 
259
                if id = -1 then begin
 
260
                        Printf.eprintf "MISALIGNED JUMP AT %d %c %d IN #%d\n" pos (if delta < 0 then '-' else '+') (if delta < 0 then -delta else delta) (idx (no_nz f.fun3_id));
 
261
                        DynArray.get indexes pos; (* jump 0 *)
 
262
                end else
 
263
                        id
 
264
        in
 
265
        let hcode = Array.mapi (fun i op ->
 
266
                let len = As3code.length op in
 
267
                DynArray.add indexes i;
 
268
                for k = 2 to len do DynArray.add indexes (-1); done;
 
269
                ctx.pos <- ctx.pos + len;
 
270
                parse_opcode ctx i op
 
271
        ) code in
 
272
        (* in case we have a dead-jump at the end of code *)
 
273
        DynArray.add indexes (Array.length code);
 
274
        (* patch jumps *)
 
275
        List.iter (fun (j,pos) ->
 
276
                Array.set hcode j (match Array.get hcode j with
 
277
                        | HJump (jc,n) ->
 
278
                                HJump (jc,codepos pos n - j)
 
279
                        | HSwitch (n,infos) ->
 
280
                                HSwitch (codepos pos n - j, List.map (fun n -> codepos pos n - j) infos)
 
281
                        | _ -> assert false)
 
282
        ) ctx.jumps;
 
283
        (* patch try/catches *)
 
284
        Array.iteri (fun i t ->
 
285
                Array.set trys i {
 
286
                        hltc_start = codepos 0 t.hltc_start;
 
287
                        hltc_end = codepos 0 t.hltc_end;
 
288
                        hltc_handle = codepos 0 t.hltc_handle;
 
289
                        hltc_type = t.hltc_type;
 
290
                        hltc_name = t.hltc_name;
 
291
                }
 
292
        ) trys;
 
293
        ctx.pos <- fst old;
 
294
        ctx.jumps <- snd old;
 
295
        hcode
 
296
 
 
297
let parse_metadata ctx m =
 
298
        {
 
299
                hlmeta_name = ident ctx m.meta3_name;
 
300
                hlmeta_data = Array.map (fun (i1,i2) -> opt ident ctx i1, ident ctx i2) m.meta3_data;
 
301
        }
 
302
 
 
303
let parse_method ctx m =
 
304
        {
 
305
                hlm_type = method_type ctx m.m3_type;
 
306
                hlm_final = m.m3_final;
 
307
                hlm_override = m.m3_override;
 
308
                hlm_kind = m.m3_kind;
 
309
        }
 
310
 
 
311
let parse_value ctx = function
 
312
        | A3VNone -> HVNone
 
313
        | A3VNull -> HVNull
 
314
        | A3VBool b -> HVBool b
 
315
        | A3VString s -> HVString (ident ctx s)
 
316
        | A3VInt i -> HVInt (get ctx.as3.as3_ints i)
 
317
        | A3VUInt i -> HVUInt (get ctx.as3.as3_uints i)
 
318
        | A3VFloat f -> HVFloat (get ctx.as3.as3_floats f)
 
319
        | A3VNamespace (n,ns) -> HVNamespace (n,ctx.namespaces.(idx ns))
 
320
 
 
321
let parse_var ctx v =
 
322
        {
 
323
                hlv_type = opt name ctx v.v3_type;
 
324
                hlv_value = parse_value ctx v.v3_value;
 
325
                hlv_const = v.v3_const;
 
326
        }
 
327
 
 
328
let parse_field_kind ctx = function
 
329
        | A3FMethod m -> HFMethod (parse_method ctx m)
 
330
        | A3FVar v -> HFVar (parse_var ctx v)
 
331
        | A3FFunction f -> HFFunction (method_type ctx f)
 
332
        | A3FClass c -> HFClass (getclass ctx c)
 
333
 
 
334
let parse_field ctx f =
 
335
        {
 
336
                hlf_name = name ctx f.f3_name;
 
337
                hlf_slot = f.f3_slot;
 
338
                hlf_kind = parse_field_kind ctx f.f3_kind;
 
339
                hlf_metas =
 
340
                        match f.f3_metas with
 
341
                        | None -> None
 
342
                        | Some a ->
 
343
                                Some (Array.map (fun i ->
 
344
                                        parse_metadata ctx (get ctx.as3.as3_metadatas (no_nz i))
 
345
                                ) a);
 
346
        }
 
347
 
 
348
let parse_static ctx s =
 
349
        {
 
350
                hls_method = method_type ctx s.st3_method;
 
351
                hls_fields = Array.map (parse_field ctx) s.st3_fields;
 
352
        }
 
353
 
 
354
let parse_namespace ctx = function
 
355
        | A3NPrivate id -> HNPrivate (opt ident ctx id)
 
356
        | A3NPublic id -> HNPublic (opt ident ctx id)
 
357
        | A3NInternal id -> HNInternal (opt ident ctx id)
 
358
        | A3NProtected id -> HNProtected (ident ctx id)
 
359
        | A3NNamespace id -> HNNamespace (ident ctx id)
 
360
        | A3NExplicit id -> HNExplicit (ident ctx id)
 
361
        | A3NStaticProtected id -> HNStaticProtected (opt ident ctx id)
 
362
 
 
363
let parse_nset ctx l = List.map (fun n -> ctx.namespaces.(idx n)) l
 
364
 
 
365
let rec parse_name ctx = function
 
366
        | A3MName (id,ns) ->
 
367
                (match ctx.namespaces.(idx ns) with
 
368
                | HNPublic p ->
 
369
                        let pack = (match p with None -> [] | Some i -> ExtString.String.nsplit i ".") in
 
370
                        HMPath (pack, ident ctx id)
 
371
                | ns ->
 
372
                        HMName (ident ctx id, ns))
 
373
        | A3MMultiName (id,ns) -> HMMultiName (opt ident ctx id,ctx.nsets.(idx ns))
 
374
        | A3MRuntimeName id -> HMRuntimeName (ident ctx id)
 
375
        | A3MRuntimeNameLate -> HMRuntimeNameLate
 
376
        | A3MMultiNameLate ns -> HMMultiNameLate ctx.nsets.(idx ns)
 
377
        | A3MAttrib multi -> HMAttrib (parse_name ctx multi)
 
378
 
 
379
let parse_try_catch ctx t =
 
380
        {
 
381
                hltc_start = t.tc3_start;
 
382
                hltc_end = t.tc3_end;
 
383
                hltc_handle = t.tc3_handle;
 
384
                hltc_type = opt name ctx t.tc3_type;
 
385
                hltc_name = opt name ctx t.tc3_name;
 
386
        }
 
387
 
 
388
let parse_function ctx f =
 
389
        {
 
390
                hlf_stack_size = f.fun3_stack_size;
 
391
                hlf_nregs = f.fun3_nregs;
 
392
                hlf_init_scope = f.fun3_init_scope;
 
393
                hlf_max_scope = f.fun3_max_scope;
 
394
                hlf_code = [||]; (* keep for later *)
 
395
                hlf_trys = Array.map (parse_try_catch ctx) f.fun3_trys;
 
396
                hlf_locals = Array.map (fun f ->
 
397
                        if f.f3_metas <> None then assert false;
 
398
                        match f.f3_kind with
 
399
                        | A3FVar v ->
 
400
                                if v.v3_const then assert false;
 
401
                                (* v3_value can be <> None if it's a fun parameter with a default value
 
402
                                        - which looks like a bug of the AS3 compiler *)
 
403
                                name ctx f.f3_name , opt name ctx v.v3_type , f.f3_slot
 
404
                        | _ -> assert false
 
405
                ) f.fun3_locals;
 
406
        }
 
407
 
 
408
let parse_method_type ctx m f =
 
409
        {
 
410
                hlmt_mark = alloc_mark();
 
411
                hlmt_ret = opt name ctx m.mt3_ret;
 
412
                hlmt_args = List.map (opt name ctx) m.mt3_args;
 
413
                hlmt_native = m.mt3_native;
 
414
                hlmt_var_args = m.mt3_var_args;
 
415
                hlmt_arguments_defined = m.mt3_arguments_defined;
 
416
                hlmt_uses_dxns = m.mt3_uses_dxns;
 
417
                hlmt_new_block = m.mt3_new_block;
 
418
                hlmt_unused_flag = m.mt3_unused_flag;
 
419
                hlmt_debug_name = opt ident ctx m.mt3_debug_name;
 
420
                hlmt_dparams = opt (fun ctx -> List.map (parse_value ctx)) ctx m.mt3_dparams;
 
421
                hlmt_pnames = opt (fun ctx -> List.map (opt ident ctx)) ctx m.mt3_pnames;
 
422
                hlmt_function = opt parse_function ctx f;
 
423
        }
 
424
 
 
425
let parse_class ctx c s =
 
426
        {
 
427
                hlc_name = name ctx c.cl3_name;
 
428
                hlc_super = opt name ctx c.cl3_super;
 
429
                hlc_sealed = c.cl3_sealed;
 
430
                hlc_final = c.cl3_final;
 
431
                hlc_interface = c.cl3_interface;
 
432
                hlc_namespace = opt (fun ctx i -> ctx.namespaces.(idx i)) ctx c.cl3_namespace;
 
433
                hlc_implements = Array.map (name ctx) c.cl3_implements;
 
434
                hlc_construct = method_type ctx c.cl3_construct;
 
435
                hlc_fields = Array.map (parse_field ctx) c.cl3_fields;
 
436
                hlc_static_construct = method_type ctx s.st3_method;
 
437
                hlc_static_fields = Array.map (parse_field ctx) s.st3_fields;
 
438
        }
 
439
 
 
440
let parse_static ctx s =
 
441
        {
 
442
                hls_method = method_type ctx s.st3_method;
 
443
                hls_fields = Array.map (parse_field ctx) s.st3_fields;
 
444
        }
 
445
 
 
446
let parse t =
 
447
        let ctx = {
 
448
                as3 = t;
 
449
                namespaces = [||];
 
450
                nsets = [||];
 
451
                names = [||];
 
452
                methods = [||];
 
453
                classes = [||];
 
454
                jumps = [];
 
455
                pos = 0;
 
456
        } in
 
457
        ctx.namespaces <- Array.map (parse_namespace ctx) t.as3_namespaces;
 
458
        ctx.nsets <- Array.map (parse_nset ctx) t.as3_nsets;
 
459
        ctx.names <- Array.map (parse_name ctx) t.as3_names;
 
460
        let hfunctions = Hashtbl.create 0 in
 
461
        Array.iter (fun f -> Hashtbl.add hfunctions (idx (no_nz f.fun3_id)) f) t.as3_functions;
 
462
        ctx.methods <- Array.mapi (fun i m ->
 
463
                parse_method_type ctx t.as3_method_types.(i) (try Some (Hashtbl.find hfunctions i) with Not_found -> None);
 
464
        ) t.as3_method_types;
 
465
        ctx.classes <- Array.mapi (fun i c ->
 
466
                parse_class ctx c t.as3_statics.(i)
 
467
        ) t.as3_classes;
 
468
        let inits = List.map (parse_static ctx) (Array.to_list t.as3_inits) in
 
469
        Array.iter (fun f ->
 
470
                match (method_type ctx f.fun3_id).hlmt_function with
 
471
                | None -> assert false
 
472
                | Some fl -> fl.hlf_code <- parse_code ctx f fl.hlf_trys
 
473
        ) t.as3_functions;
 
474
        inits
 
475
 
 
476
(* ************************************************************************ *)
 
477
(*                      FLATTEN                                                                                                                 *)
 
478
(* ************************************************************************ *)
 
479
 
 
480
type ('hl,'item,'key) gen_lookup = {
 
481
        h : ('key,int) Hashtbl.t;
 
482
        a : 'item DynArray.t;
 
483
        f : flatten_ctx -> 'hl -> 'item;
 
484
        k : 'hl -> 'key;
 
485
}
 
486
 
 
487
and ('hl,'item) lookup = ('hl,'item,'hl) gen_lookup
 
488
 
 
489
and flatten_ctx = {
 
490
        fints : (hl_int,as3_int) lookup;
 
491
        fuints : (hl_uint,as3_uint) lookup;
 
492
        ffloats : (hl_float,as3_float) lookup;
 
493
        fidents : (hl_ident,as3_ident) lookup;
 
494
        fnamespaces : (hl_namespace,as3_namespace) lookup;
 
495
        fnsets : (hl_ns_set,as3_ns_set) lookup;
 
496
        fnames : (hl_name,as3_multi_name) lookup;
 
497
        fmetas : (hl_metadata,as3_metadata) lookup;
 
498
        fmethods : (hl_method,as3_method_type,int) gen_lookup;
 
499
        fclasses : (hl_class,as3_class * as3_static,hl_name) gen_lookup;
 
500
        mutable ffunctions : as3_function list;
 
501
        mutable fjumps : int list;
 
502
}
 
503
 
 
504
let new_gen_lookup f k =
 
505
        {
 
506
                h = Hashtbl.create 0;
 
507
                a = DynArray.create();
 
508
                f = f;
 
509
                k = k;
 
510
        }
 
511
 
 
512
let new_lookup f = new_gen_lookup f (fun x -> x)
 
513
 
 
514
let lookup_array l = DynArray.to_array l.a
 
515
 
 
516
let lookup ctx (l:('a,'b,'k) gen_lookup) item : 'b index =
 
517
        let key = l.k item in
 
518
        let idx = try
 
519
                Hashtbl.find l.h key
 
520
        with Not_found ->
 
521
                let idx = DynArray.length l.a in
 
522
                (* set dummy value for recursion *)
 
523
                DynArray.add l.a (Obj.magic 0);
 
524
                Hashtbl.add l.h key (idx + 1);
 
525
                DynArray.set l.a idx (l.f ctx item);
 
526
                idx + 1
 
527
        in
 
528
        As3parse.magic_index idx
 
529
 
 
530
let lookup_nz ctx l item =
 
531
        As3parse.magic_index_nz (As3parse.index_int (lookup ctx l item) - 1)
 
532
 
 
533
let lookup_ident ctx i = lookup ctx ctx.fidents i
 
534
 
 
535
let lookup_name ctx n = lookup ctx ctx.fnames n
 
536
 
 
537
let lookup_method ctx m : as3_method_type index_nz =
 
538
        lookup_nz ctx ctx.fmethods m
 
539
 
 
540
let lookup_class ctx c : as3_class index_nz =
 
541
        lookup_nz ctx ctx.fclasses c
 
542
 
 
543
let flatten_namespace ctx = function
 
544
        | HNPrivate i -> A3NPrivate (opt lookup_ident ctx i)
 
545
        | HNPublic i -> A3NPublic (opt lookup_ident ctx i)
 
546
        | HNInternal i -> A3NInternal (opt lookup_ident ctx i)
 
547
        | HNProtected i -> A3NProtected (lookup_ident ctx i)
 
548
        | HNNamespace i -> A3NNamespace (lookup_ident ctx i)
 
549
        | HNExplicit i -> A3NExplicit (lookup_ident ctx i)
 
550
        | HNStaticProtected i -> A3NStaticProtected (opt lookup_ident ctx i)
 
551
 
 
552
let flatten_ns_set ctx n =
 
553
        List.map (lookup ctx ctx.fnamespaces) n
 
554
 
 
555
let rec flatten_name ctx = function
 
556
        | HMPath (pack,i) ->
 
557
                let ns = HNPublic (match pack with [] -> None | l -> Some (String.concat "." l)) in
 
558
                A3MName (lookup_ident ctx i,lookup ctx ctx.fnamespaces ns)
 
559
        | HMName (i,n) -> A3MName (lookup_ident ctx i,lookup ctx ctx.fnamespaces n)
 
560
        | HMMultiName (i,ns) -> A3MMultiName (opt lookup_ident ctx i,lookup ctx ctx.fnsets ns)
 
561
        | HMRuntimeName i -> A3MRuntimeName (lookup_ident ctx i)
 
562
        | HMRuntimeNameLate -> A3MRuntimeNameLate
 
563
        | HMMultiNameLate ns -> A3MMultiNameLate (lookup ctx ctx.fnsets ns)
 
564
        | HMAttrib n -> A3MAttrib (flatten_name ctx n)
 
565
 
 
566
let flatten_meta ctx m =
 
567
        {
 
568
                meta3_name = lookup_ident ctx m.hlmeta_name;
 
569
                meta3_data = Array.map (fun (i,i2) -> opt lookup_ident ctx i, lookup_ident ctx i2) m.hlmeta_data;
 
570
        }
 
571
 
 
572
let flatten_value ctx = function
 
573
        | HVNone -> A3VNone
 
574
        | HVNull -> A3VNull
 
575
        | HVBool b -> A3VBool b
 
576
        | HVString s -> A3VString (lookup_ident ctx s)
 
577
        | HVInt i -> A3VInt (lookup ctx ctx.fints i)
 
578
        | HVUInt i -> A3VUInt (lookup ctx ctx.fuints i)
 
579
        | HVFloat f -> A3VFloat (lookup ctx ctx.ffloats f)
 
580
        | HVNamespace (n,ns) -> A3VNamespace (n,lookup ctx ctx.fnamespaces ns)
 
581
 
 
582
let flatten_field ctx f =
 
583
        {
 
584
                f3_name = lookup_name ctx f.hlf_name;
 
585
                f3_slot = f.hlf_slot;
 
586
                f3_kind = (match f.hlf_kind with
 
587
                        | HFMethod m ->
 
588
                                A3FMethod {
 
589
                                        m3_type = lookup_method ctx m.hlm_type;
 
590
                                        m3_final = m.hlm_final;
 
591
                                        m3_override = m.hlm_override;
 
592
                                        m3_kind = m.hlm_kind;
 
593
                                }
 
594
                        | HFVar v ->
 
595
                                A3FVar {
 
596
                                        v3_type = opt lookup_name ctx v.hlv_type;
 
597
                                        v3_value = flatten_value ctx v.hlv_value;
 
598
                                        v3_const = v.hlv_const;
 
599
                                }
 
600
                        | HFFunction f ->
 
601
                                A3FFunction (lookup_method ctx f)
 
602
                        | HFClass c ->
 
603
                                A3FClass (lookup_class ctx c)
 
604
                );
 
605
                f3_metas = opt (fun ctx -> Array.map (fun m -> lookup_nz ctx ctx.fmetas m)) ctx f.hlf_metas;
 
606
        }
 
607
 
 
608
let flatten_class ctx c =
 
609
        {
 
610
                cl3_name = lookup_name ctx c.hlc_name;
 
611
                cl3_super = opt lookup_name ctx c.hlc_super;
 
612
                cl3_sealed = c.hlc_sealed;
 
613
                cl3_final = c.hlc_final;
 
614
                cl3_interface = c.hlc_interface;
 
615
                cl3_namespace = opt (fun ctx -> lookup ctx ctx.fnamespaces) ctx c.hlc_namespace;
 
616
                cl3_implements = Array.map (lookup_name ctx) c.hlc_implements;
 
617
                cl3_construct = lookup_method ctx c.hlc_construct;
 
618
                cl3_fields = Array.map (flatten_field ctx) c.hlc_fields;
 
619
        },
 
620
        {
 
621
                st3_method = lookup_method ctx c.hlc_static_construct;
 
622
                st3_fields = Array.map (flatten_field ctx) c.hlc_static_fields;
 
623
        }
 
624
 
 
625
let flatten_opcode ctx i = function
 
626
        | HBreakPoint -> A3BreakPoint
 
627
        | HNop -> A3Nop
 
628
        | HThrow -> A3Throw
 
629
        | HGetSuper n -> A3GetSuper (lookup_name ctx n)
 
630
        | HSetSuper n -> A3SetSuper (lookup_name ctx n)
 
631
        | HRegKill r -> A3RegKill r
 
632
        | HLabel -> A3Label
 
633
        | HJump (j,n) ->
 
634
                ctx.fjumps <- i :: ctx.fjumps;
 
635
                A3Jump (j,n)
 
636
        | HSwitch (n,l) ->
 
637
                ctx.fjumps <- i :: ctx.fjumps;
 
638
                A3Switch (n,l)
 
639
        | HPushWith -> A3PushWith
 
640
        | HPopScope -> A3PopScope
 
641
        | HForIn -> A3ForIn
 
642
        | HHasNext -> A3HasNext
 
643
        | HNull -> A3Null
 
644
        | HUndefined -> A3Undefined
 
645
        | HForEach -> A3ForEach
 
646
        | HSmallInt n -> A3SmallInt n
 
647
        | HInt n -> A3Int n
 
648
        | HTrue -> A3True
 
649
        | HFalse -> A3False
 
650
        | HNaN -> A3NaN
 
651
        | HPop -> A3Pop
 
652
        | HDup -> A3Dup
 
653
        | HSwap -> A3Swap
 
654
        | HString s -> A3String (lookup_ident ctx s)
 
655
        | HIntRef i -> A3IntRef (lookup ctx ctx.fints i)
 
656
        | HUIntRef i -> A3UIntRef (lookup ctx ctx.fuints i)
 
657
        | HFloat f -> A3Float (lookup ctx ctx.ffloats f)
 
658
        | HScope -> A3Scope
 
659
        | HNamespace n -> A3Namespace (lookup ctx ctx.fnamespaces n)
 
660
        | HNext (r1,r2) -> A3Next (r1,r2)
 
661
        | HFunction m -> A3Function (lookup_method ctx m)
 
662
        | HCallStack n -> A3CallStack n
 
663
        | HConstruct n -> A3Construct n
 
664
        | HCallMethod (s,n) -> A3CallMethod (s,n)
 
665
        | HCallStatic (m,n) -> A3CallStatic (no_nz (lookup_method ctx m),n)
 
666
        | HCallSuper (i,n) -> A3CallSuper (lookup_name ctx i,n)
 
667
        | HCallProperty (i,n) -> A3CallProperty (lookup_name ctx i,n)
 
668
        | HRetVoid -> A3RetVoid
 
669
        | HRet -> A3Ret
 
670
        | HConstructSuper n -> A3ConstructSuper n
 
671
        | HConstructProperty (i,n) -> A3ConstructProperty (lookup_name ctx i,n)
 
672
        | HCallPropLex (i,n) -> A3CallPropLex (lookup_name ctx i,n)
 
673
        | HCallSuperVoid (i,n) -> A3CallSuperVoid (lookup_name ctx i,n)
 
674
        | HCallPropVoid (i,n)-> A3CallPropVoid (lookup_name ctx i,n)
 
675
        | HObject n -> A3Object n
 
676
        | HArray n -> A3Array n
 
677
        | HNewBlock -> A3NewBlock
 
678
        | HClassDef c -> A3ClassDef (As3parse.magic_index_nz (As3parse.index_nz_int (lookup_class ctx c)))
 
679
        | HCatch n -> A3Catch n
 
680
        | HFindPropStrict i -> A3FindPropStrict (lookup_name ctx i)
 
681
        | HFindProp i -> A3FindProp (lookup_name ctx i)
 
682
        | HFindDefinition i -> A3FindDefinition (lookup_name ctx i)
 
683
        | HGetLex i -> A3GetLex (lookup_name ctx i)
 
684
        | HSetProp i -> A3SetProp (lookup_name ctx i)
 
685
        | HReg r -> A3Reg r
 
686
        | HSetReg r -> A3SetReg r
 
687
        | HGetGlobalScope -> A3GetGlobalScope
 
688
        | HGetScope n -> A3GetScope n
 
689
        | HGetProp n -> A3GetProp (lookup_name ctx n)
 
690
        | HInitProp n -> A3InitProp (lookup_name ctx n)
 
691
        | HDeleteProp n -> A3DeleteProp (lookup_name ctx n)
 
692
        | HGetSlot s -> A3GetSlot s
 
693
        | HSetSlot s -> A3SetSlot s
 
694
        | HToString -> A3ToString
 
695
        | HToXml -> A3ToXml
 
696
        | HToXmlAttr -> A3ToXmlAttr
 
697
        | HToInt -> A3ToInt
 
698
        | HToUInt -> A3ToUInt
 
699
        | HToNumber -> A3ToNumber
 
700
        | HToBool -> A3ToBool
 
701
        | HToObject -> A3ToObject
 
702
        | HCheckIsXml -> A3CheckIsXml
 
703
        | HCast n -> A3Cast (lookup_name ctx n)
 
704
        | HAsAny -> A3AsAny
 
705
        | HAsString -> A3AsString
 
706
        | HAsType n -> A3AsType (lookup_name ctx n)
 
707
        | HAsObject -> A3AsObject
 
708
        | HIncrReg r -> A3IncrReg r
 
709
        | HDecrReg r -> A3DecrReg r
 
710
        | HTypeof -> A3Typeof
 
711
        | HInstanceOf -> A3InstanceOf
 
712
        | HIsType t -> A3IsType (lookup_name ctx t)
 
713
        | HIncrIReg r -> A3IncrIReg r
 
714
        | HDecrIReg r -> A3DecrIReg r
 
715
        | HThis -> A3This
 
716
        | HSetThis -> A3SetThis
 
717
        | HDebugReg (i,r,l) -> A3DebugReg (lookup_ident ctx i,r,l)
 
718
        | HDebugLine l -> A3DebugLine l
 
719
        | HDebugFile f -> A3DebugFile (lookup_ident ctx f)
 
720
        | HBreakPointLine n -> A3BreakPointLine n
 
721
        | HTimestamp -> A3Timestamp
 
722
        | HOp op -> A3Op op
 
723
        | HUnk c -> A3Unk c
 
724
 
 
725
let flatten_code ctx hcode trys =
 
726
        let positions = Array.create (Array.length hcode + 1) 0 in
 
727
        let pos = ref 0 in
 
728
        let old = ctx.fjumps in
 
729
        ctx.fjumps <- [];
 
730
        let code = Array.mapi (fun i op ->
 
731
                let op = flatten_opcode ctx i op in
 
732
                pos := !pos + As3code.length op;
 
733
                Array.set positions (i + 1) !pos;
 
734
                op
 
735
        ) hcode in
 
736
        (* patch jumps *)
 
737
        List.iter (fun j ->
 
738
                Array.set code j (match Array.get code j with
 
739
                        | A3Jump (jc,n) ->
 
740
                                A3Jump (jc,positions.(j+n) - positions.(j+1))
 
741
                        | A3Switch (n,infos) -> 
 
742
                                A3Switch (positions.(j+n) - positions.(j),List.map (fun n -> positions.(j+n) - positions.(j)) infos)
 
743
                        | _ -> assert false);
 
744
        ) ctx.fjumps;
 
745
        (* patch trys *)
 
746
        let trys = Array.mapi (fun i t ->
 
747
                {
 
748
                        tc3_start = positions.(t.hltc_start);
 
749
                        tc3_end = positions.(t.hltc_end);
 
750
                        tc3_handle = positions.(t.hltc_handle);
 
751
                        tc3_type = opt lookup_name ctx t.hltc_type;
 
752
                        tc3_name = opt lookup_name ctx t.hltc_name;
 
753
                }
 
754
        ) trys in
 
755
        ctx.fjumps <- old;
 
756
        code, trys
 
757
 
 
758
let flatten_function ctx f mid =
 
759
        let code, trys = flatten_code ctx f.hlf_code f.hlf_trys in
 
760
        {
 
761
                fun3_id = mid;
 
762
                fun3_stack_size = f.hlf_stack_size;
 
763
                fun3_nregs = f.hlf_nregs;
 
764
                fun3_init_scope = f.hlf_init_scope;
 
765
                fun3_max_scope = f.hlf_max_scope;
 
766
                fun3_code = code;
 
767
                fun3_trys = trys;
 
768
                fun3_locals = Array.map (fun (n,t,s) ->
 
769
                        {
 
770
                                f3_name = lookup_name ctx n;
 
771
                                f3_slot = s;
 
772
                                f3_kind = A3FVar { v3_type = opt lookup_name ctx t; v3_value = A3VNone; v3_const = false  };
 
773
                                f3_metas = None;
 
774
                        }
 
775
                ) f.hlf_locals;
 
776
        }
 
777
 
 
778
let flatten_method ctx m =
 
779
        let mid = lookup_method ctx m in
 
780
        (match m.hlmt_function with
 
781
        | None -> ()
 
782
        | Some f -> ctx.ffunctions <- flatten_function ctx f mid :: ctx.ffunctions);
 
783
        {
 
784
                mt3_ret = opt lookup_name ctx m.hlmt_ret;
 
785
                mt3_args = List.map (opt lookup_name ctx) m.hlmt_args;
 
786
                mt3_native = m.hlmt_native;
 
787
                mt3_var_args = m.hlmt_var_args;
 
788
                mt3_arguments_defined = m.hlmt_arguments_defined;
 
789
                mt3_uses_dxns = m.hlmt_uses_dxns;
 
790
                mt3_new_block = m.hlmt_new_block;
 
791
                mt3_unused_flag = m.hlmt_unused_flag;
 
792
                mt3_debug_name = opt lookup_ident ctx m.hlmt_debug_name;
 
793
                mt3_dparams = opt (fun ctx -> List.map (flatten_value ctx)) ctx m.hlmt_dparams;
 
794
                mt3_pnames = opt (fun ctx -> List.map (opt lookup_ident ctx)) ctx m.hlmt_pnames;
 
795
        }
 
796
 
 
797
let flatten_static ctx s =
 
798
        {
 
799
                st3_method = lookup_method ctx s.hls_method;
 
800
                st3_fields = Array.map (flatten_field ctx) s.hls_fields;
 
801
        }
 
802
 
 
803
let flatten t =
 
804
        let id _ x = x in
 
805
        let rec ctx = {
 
806
                fints = new_lookup id;
 
807
                fuints = new_lookup id;
 
808
                ffloats = new_lookup id;
 
809
                fidents = new_lookup id;
 
810
                fnamespaces = new_lookup flatten_namespace;
 
811
                fnsets = new_lookup flatten_ns_set;
 
812
                fnames = new_lookup flatten_name;
 
813
                fmetas = new_lookup flatten_meta;
 
814
                fmethods = new_gen_lookup flatten_method (fun m -> m.hlmt_mark);
 
815
                fclasses = new_gen_lookup flatten_class (fun c -> c.hlc_name);
 
816
                fjumps = [];
 
817
                ffunctions = [];
 
818
        } in
 
819
        ignore(lookup_ident ctx "");
 
820
        let inits = List.map (flatten_static ctx) t in
 
821
        {
 
822
                as3_ints = lookup_array ctx.fints;
 
823
                as3_uints = lookup_array ctx.fuints;
 
824
                as3_floats = lookup_array ctx.ffloats;
 
825
                as3_idents = lookup_array ctx.fidents;
 
826
                as3_namespaces = lookup_array ctx.fnamespaces;
 
827
                as3_nsets = lookup_array ctx.fnsets;
 
828
                as3_names = lookup_array ctx.fnames;
 
829
                as3_metadatas = lookup_array ctx.fmetas;
 
830
                as3_method_types = lookup_array ctx.fmethods;
 
831
                as3_classes = Array.map fst (lookup_array ctx.fclasses);
 
832
                as3_statics = Array.map snd (lookup_array ctx.fclasses);
 
833
                as3_functions = Array.of_list (List.rev ctx.ffunctions);
 
834
                as3_inits = Array.of_list inits;
 
835
                as3_unknown = "";
 
836
        }