OSDN Git Service

add abcIn
authormzp <mzpppp@gmail.com>
Wed, 23 Sep 2009 23:00:42 +0000 (08:00 +0900)
committermzp <mzpppp@gmail.com>
Wed, 23 Sep 2009 23:00:42 +0000 (08:00 +0900)
swflib/OMakefile
swflib/abc.ml [deleted file]
swflib/abcIn.ml [new file with mode: 0644]
swflib/abcIn.mli [new file with mode: 0644]
swflib/abcInTest.ml [new file with mode: 0644]
swflib/abcType.ml
swflib/lowInst.mlp
swflib/lowInstTest.ml
xml/parsec.ml

index 3281867..808bb8c 100644 (file)
@@ -12,6 +12,7 @@ FILES[] =
        label
        abcType
        abcOut
+       abcIn
        lowInst
        methodType
        methodOut
@@ -38,6 +39,7 @@ OCamlProgram(gen_typemap,gen_typemap)
 OUnitTest(label    , label)
 OUnitTest(bytesOut , bytesOut label)
 OUnitTest(bytesIn  , bytesIn)
+OUnitTest(abcIn    , abcIn)
 OUnitTest(lowInst  , lowInst bytesOut bytesIn label)
 OUnitTest(highInst , highInst label cpool revList)
 OUnitTest(abcOut   , abcOut label bytesOut)
diff --git a/swflib/abc.ml b/swflib/abc.ml
deleted file mode 100644 (file)
index 45c09cc..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-module A = AbcOut.Make(LowInst)
-module C = MethodOut.Make(HighInst)
-
-type abc  = LowInst.t AbcType.t
-type meth = HighInst.s MethodType.method_
-
-let asm : abc -> BytesOut.t list                     = A.to_bytes
-let compile : Cpool.multiname list -> meth -> abc = C.to_abc
-
diff --git a/swflib/abcIn.ml b/swflib/abcIn.ml
new file mode 100644 (file)
index 0000000..fa9d016
--- /dev/null
@@ -0,0 +1,384 @@
+open Base
+open BytesIn
+open ExtString
+
+module type Inst = sig
+  type t
+  val of_bytes : int Stream.t -> t
+end
+
+module Make(Inst : Inst) = struct
+  open AbcType
+
+  let rec repeat n f stream =
+    if n <= 0 then
+      []
+    else
+      match stream with parser
+         [<c = f>] ->
+           c::repeat (n-1) f stream
+       | [<>] ->
+           raise (Stream.Error "invalid format")
+
+  let rec many parse stream =
+    match stream with parser
+       [< e = parse; s>] -> e::many parse s
+      | [<>] -> []
+
+  let array f stream =
+    let n =
+      u30 stream in
+      repeat n f stream
+
+  let carray f stream =
+    let n =
+      u30 stream in
+      repeat (n-1) f stream
+
+  (* constant pool *)
+  let string_info stream =
+    let cs =
+      List.map char_of_int @@ array u8 stream in
+      String.implode cs
+
+  let namespace_info stream =
+    let kind =
+      u8 stream in
+    let name =
+      u30 stream in
+      {kind=kind; namespace_name=name}
+(* TDOO *)
+(*      match kind with
+         0x08 ->
+           `Namespace name
+       | 0x16 ->
+           `PackageNamespace name
+       | 0x17 ->
+           `PackageInternaNs name
+       | 0x18 ->
+           `ProtectedNamespace name
+       | 0x19 ->
+           `ExplicitNamespace name
+       | 0x1A ->
+           `StaticProtectedNs name
+       | 0x05 ->
+           `PrivateNs name
+       | _ ->
+           failwith "must not happen"
+*)
+  let ns_set_info stream =
+    array u30 stream
+
+  let multiname_info stream =
+    let kind =
+      u8 stream in
+      match kind with
+         0x07 ->
+           let ns =
+             u30 stream in
+           let name=
+             u30 stream in
+           QName (ns,name)
+       | 0x09 ->
+           let name =
+             u30 stream in
+           let ns_set =
+             u30 stream in
+           Multiname (name,ns_set)
+       | _ ->
+           failwith "invalid format"
+(* TODO *)
+(*      match kind with
+         0x07 ->
+           `QName { ns=u30 stream; name=u30 stream }
+       | 0x0D ->
+           `QNameA { ns=u30 stream; name=u30 stream }
+       | 0x0F ->
+           `RTQName { name=u30 stream }
+       | 0x10 ->
+           `RTQNameA { name=u30 stream }
+       | 0x11 ->
+           `RTQNameL
+       | 0x12 ->
+           `RTQNameLA
+       | 0x09 ->
+           `Multiname {name=u30 stream; ns_set=u30 stream}
+       | 0x0E ->
+           `MultinameA {name=u30 stream; ns_set=u30 stream}
+       | 0x1B ->
+           `MultinameL {ns_set=u30 stream}
+       | 0x1C ->
+           `MultinameLA {ns_set=u30 stream}
+       | _ ->
+           failwith "invalid format"
+*)
+
+  let constant_pool stream =
+    {
+      int           = List.map (Int32.to_int) @@ carray s32 stream;
+      uint          = List.map (Int32.to_int) @@ carray u32 stream;
+      double        = carray d64 stream;
+      string        = carray string_info stream;
+      namespace     = carray namespace_info stream;
+      namespace_set = carray ns_set_info stream;
+      multiname     = carray multiname_info stream
+    }
+
+  (* method info *)
+  let option_detail stream =
+    let value =
+      u30 stream in
+      match u8 stream with
+         0x03 ->
+           `Int value
+       | 0x04 ->
+           `UInt value
+       | 0x06 ->
+           `Double value
+       | 0x01 ->
+           `String value
+       | 0x0B ->
+           `Bool true
+       | 0x0A ->
+           `Bool false
+       | 0x0C ->
+           `Null
+       | 0x00 ->
+           `Undefined
+       | 0x08 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x05 ->
+           `Namespace value
+       | _ ->
+           failwith "invalid format"
+
+  let option_info stream =
+    array option_detail stream
+
+  let has x y =
+    x land y = y
+
+  let method_info stream =
+    let param_count =
+      u30 stream in
+    let return_type =
+      u30 stream in
+    let param_types =
+      repeat param_count u30 stream in
+    let name =
+      u30 stream in
+    let flags =
+      u8 stream in
+(*    let options =
+      if has flags 0x08 then
+       Some (option_info stream )
+      else
+       None in
+    let param_names =
+      if has flags 0x80 then
+       Some (repeat param_count u30 stream)
+      else
+       None in*)
+      { params     = param_types;
+       return     = return_type;
+       method_name            = name;
+       method_flags = flags
+      (*       need_arguments  = has flags 0x01;
+       need_activation = has flags 0x02;
+       need_rest       = has flags 0x04;
+       set_dxns        = has flags 0x40;
+       options         = options;
+       param_names     = param_names*)
+      }
+
+  (* metadata *)
+  let item_info stream =
+    let key=u30 stream in
+    let value=u30 stream in
+      (key,value)
+
+  let metadata_info stream =
+    {
+      metadata_name  = u30 stream;
+      items = array item_info stream
+    }
+
+  (* 4.8 Traits *)
+  let trait_info stream =
+    let name =
+      u30 stream in
+    let kind =
+      u8 stream in
+    let data =
+      match kind land 0x0F with
+         0 | 6 ->
+           let slot_id   =
+             u30 stream in
+           let type_name =
+             u30 stream in
+           let vindex =
+             u30 stream in
+           let vkind =
+             if vindex = 0 then
+               0
+             else
+               u8 stream in
+             if kind = 0 then
+               SlotTrait(slot_id,type_name,vindex,vkind)
+             else
+               ConstTrait(slot_id,type_name,vindex,vkind)
+       | 4 ->
+           let id =
+             u30 stream in
+           let classi =
+             u30 stream in
+             ClassTrait(id,classi)
+       | 5 ->
+           let slot_id=
+             u30 stream in
+           let functioni=
+             u30 stream in
+           FunctionTrait (slot_id,functioni)
+       | 1 | 2 | 3 as k ->
+           let disp_id=
+             u30 stream in
+           let methodi=
+             u30 stream in
+           let flag =
+             kind lsr 4 in
+           let attrs = List.concat [
+             if has flag 0x01 then [ATTR_Final] else [];
+             if has flag 0x02 then [ATTR_Override] else [];
+             if has flag 0x04 then [ATTR_Medadata] else [];
+           ] in
+             begin match k with
+                 1 -> MethodTrait (disp_id,methodi,attrs)
+               | 2 -> GetterTrait (disp_id,methodi,attrs)
+               | 3 -> SetterTrait (disp_id,methodi,attrs)
+               | _ -> failwith "must not happen"
+             end
+       | _ ->
+           failwith "invalid format" in
+(* TODO *)
+(*    let metadata =
+      if has attr 0x4 then
+       Some (array u30 stream)
+      else
+       None in*)
+      {
+       trait_name    = name;
+       data          = data;
+      }
+
+  (* 4.7 Instance *)
+  let instance_info stream =
+    let name =
+      u30 stream in
+    let super_name =
+      u30 stream in
+    let flags =
+      u8 stream in
+    let protectedNs =
+      if has flags 0x08 then
+       [ProtectedNs (u30 stream)]
+      else
+       [] in
+    let interface =
+      array u30 stream in
+    let iinit =
+      u30 stream in
+    let traits =
+      array trait_info stream in
+      { instance_name = name;
+       super_name = super_name;
+       interface = interface;
+       iinit           = iinit;
+       instance_traits = traits;
+       instance_flags = List.concat [
+         if has flags 0x01 then [Sealed] else [];
+         if has flags 0x02 then [Final] else [];
+         if has flags 0x04 then [Interface] else [];
+         protectedNs]
+      }
+
+  (* 4.9 Class *)
+  let class_info stream =
+    { cinit = u30 stream; traits = array trait_info stream}
+
+  (* 4.10 Script*)
+  let script_info stream =
+    { init = u30 stream; traits = array trait_info stream }
+
+  (* 4.12 Exception *)
+  let exception_info stream =
+    { from_pos = u30 stream;
+     to_pos   = u30 stream;
+     target   = u30 stream;
+     exc_type = u30 stream;
+     var_name = u30 stream
+    }
+
+  (* 4.11 Method body *)
+  let method_body_info stream =
+    let methodi =
+      u30 stream in
+    let max_stack =
+      u30 stream in
+    let local_count =
+      u30 stream in
+    let init_scope_depth =
+      u30 stream in
+    let max_scope_depth =
+      u30 stream in
+    let code =
+      array u8 stream in
+    let exceptions =
+      array exception_info stream in
+    let traits =
+      array trait_info stream in
+      {
+       methodi          = methodi;
+       max_stack        = max_stack;
+       local_count      = local_count;
+       init_scope_depth = init_scope_depth;
+       max_scope_depth  = max_scope_depth;
+       code             = many Inst.of_bytes @@ Stream.of_list code;
+       exceptions       = exceptions;
+       traits           = traits
+      }
+
+  (* 4.2 ABC File *)
+  let abcFile stream =
+    let minor_version =
+      u16 stream in
+    let major_version =
+      u16 stream in
+    let constant_pool =
+      constant_pool stream in
+    let methods =
+      array method_info stream in
+    let metadata =
+      array metadata_info stream in
+    let class_count =
+      u30 stream in
+    let instances =
+      repeat class_count instance_info stream in
+    let classes =
+      repeat class_count class_info stream in
+    let script =
+      array script_info stream in
+    let method_body =
+      array method_body_info stream in
+      {
+       minor_version = minor_version;
+       major_version = major_version;
+       constant_pool = constant_pool;
+       methods       = methods;
+       metadata      = metadata;
+       instances     = instances;
+       classes       = classes;
+       script        = script;
+       method_body   = method_body
+      }
+
+  let of_bytes stream =
+    abcFile stream
+end
diff --git a/swflib/abcIn.mli b/swflib/abcIn.mli
new file mode 100644 (file)
index 0000000..dd6e75e
--- /dev/null
@@ -0,0 +1,9 @@
+module type Inst = sig
+  type t
+  val of_bytes : int Stream.t -> t
+end
+
+module Make : functor (S : Inst) -> sig
+  open AbcType
+  val of_bytes : int Stream.t -> S.t AbcType.t
+end
diff --git a/swflib/abcInTest.ml b/swflib/abcInTest.ml
new file mode 100644 (file)
index 0000000..e47b05b
--- /dev/null
@@ -0,0 +1,110 @@
+open Base
+open OUnit
+
+let ok x y =
+  OUnit.assert_equal ~printer:Std.dump x y
+
+let example name =
+  let ch =
+    open_in_bin @@ Printf.sprintf "example/%s.abc" name in
+    Abc.of_stream @@ Byte.of_channel ch
+
+let abc =
+  example "hello"
+
+let cpool =
+  abc#constant_pool
+
+let _ =
+  ("asm module test" >::: [
+     "major/minor version" >::
+       (fun () ->
+         ok 16 abc#minor_version;
+         ok 46 abc#major_version);
+     "cpool" >::: [
+       "integer" >::
+        (fun () -> ok [] cpool#integer);
+       "uinteger" >::
+        (fun () -> ok [] cpool#uinteger);
+       "double" >::
+        (fun () -> ok [] cpool#double);
+       "string" >::
+        (fun () -> ok [""; "Hello,world!!";"print"] cpool#string);
+       "namespace" >::
+        (fun () ->
+           match cpool#namespace with
+               [ns] ->
+                 ok (`Namespace 1l) ns
+             | _ ->
+                 assert_failure "list size is over");
+       "namespace set" >::
+        (fun () ->
+           ok [] cpool#ns_set);
+       "multiname" >::
+        (fun () ->
+           match cpool#multiname with
+               [`QName x;`QName y] ->
+                 ok 1 (Int32.to_int x#ns);
+                 ok 1 (Int32.to_int x#name);
+                 ok 1 (Int32.to_int y#ns);
+                 ok 3 (Int32.to_int y#name);
+             | _  ->
+                 assert_failure "not qname")
+     ];
+   "method signature" >::
+     (fun () ->
+       match abc#methods with
+           [m] ->
+             ok [] m#param_types;
+             ok 0l m#return_type;
+             ok 1l m#name;
+             ok false m#need_activation;
+             ok false m#need_arguments;
+             ok false m#need_rest;
+             ok false m#set_dxns;
+             ok None  m#options;
+             ok None  m#param_names
+         | _   ->
+             assert_failure "over size");
+   "metadata test" >::
+     (fun () ->
+       ok [] abc#metadata);
+   "class and instance size has same size" >::
+     (fun () ->
+        ok (List.length abc#instances) (List.length abc#classes));
+   "instance" >::
+     (fun () ->
+       ok [] abc#instances);
+   "class" >::
+     (fun () ->
+       ok [] abc#classes);
+   "script" >::
+     (fun () ->
+       match abc#script with
+           [s] ->
+             ok 0l s#init;
+             ok [] s#traits
+         | _   ->
+             assert_failure "error");
+   "method body" >::
+     (fun () ->
+        match abc#method_body with
+           [m] ->
+             ok 0l m#methodi;
+             ok [] m#exceptions;
+             ok 1l m#local_count;
+             ok 0l m#init_scope_depth;
+             ok 1l m#max_scope_depth;
+             ok 2l m#max_stack;
+             ok [] m#traits;
+             flip ok m#code [
+               `GetLocal_0;
+               `PushScope;
+               `FindPropStrict 2l;
+               `PushString 2l;
+               `CallPropLex (2l,1l);
+               `Pop;
+               `ReturnVoid ]
+         | _   ->
+             assert_failure "error");
+   ]) +> run_test_tt_main
index dbf50a8..e966869 100644 (file)
@@ -27,6 +27,7 @@ type method_info = {
   method_flags: int;
 }
 
+(* TODO *)
 type trait_attr =
     ATTR_Final | ATTR_Override | ATTR_Medadata
 
@@ -77,6 +78,11 @@ type 'a method_body = {
   method_traits:    trait list
 }
 
+type metedata = {
+  metadata_name : int;
+  items: (int*int) list
+}
+
 type 'a t = {
   cpool:         cpool;
   method_info:   method_info list;
index bf95f0e..300abbf 100644 (file)
@@ -17,6 +17,6 @@ let op n stream =
     | _ ->
        raise Stream.Failure
 
-let of_int_list : int Stream.t -> t =
+let of_bytes : int Stream.t -> t =
     parser
 #include "disasm.inst.h"
index 51ce9f6..26b2f4e 100644 (file)
@@ -5,7 +5,7 @@ open BytesOut
 
 let ok x y =
   assert_equal x @@ to_bytes y;
-  assert_equal y @@ of_int_list @@ Stream.of_list @@ BytesOut.to_int_list x
+  assert_equal y @@ of_bytes @@ Stream.of_list @@ BytesOut.to_int_list x
 
 let _ =
   ("lowInst.ml" >::: [
index e9a02c7..6b513a7 100644 (file)
@@ -20,11 +20,11 @@ let rec repeat n f stream =
 
 let repeat_l n f stream =
   repeat (Int32.to_int n) f stream
-  
-let string str stream = 
+
+let string str stream =
   let cs =
     ExtString.String.explode str in
-  let n = 
+  let n =
     List.length cs in
     match Stream.npeek n stream with
        ys when cs = ys ->
@@ -62,12 +62,12 @@ let option f stream =
   with Stream.Failure ->
     None
 
-let (<|>) f g = 
-  parser 
+let (<|>) f g =
+  parser
       [<e = f>] -> e
     | [<e = g>] -> e
 
-let rec many parse stream = 
+let rec many parse stream =
   match stream with parser
       [< e = parse; s>] -> e::many parse s
     | [<>] -> []
@@ -77,7 +77,7 @@ let many1 parse stream =
     parse stream in
     x::many parse stream
 
-let alpha stream = 
+let alpha stream =
   match Stream.peek stream with
       Some ('a'..'z') | Some ('A'..'Z') ->
        Stream.next stream
@@ -92,9 +92,9 @@ let digit stream =
        fail ()
 
 let try_ f stream =
-  (* 
+  (*
      Use black-magic to save stream state
-     
+
      from stream.ml:
      type 'a t = { count : int; data : 'a data }
   *)