10 people like it.

IronJS Boxing Struct

This is the struct IronJS uses internally to do NaN-tagging of boxed values, using the technique described here http://blog.mozilla.com/rob-sayre/2010/08/02/mozillas-new-javascript-value-representation/ and here http://article.gmane.org/gmane.comp.lang.lua.general/58908

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
64: 
65: 
66: 
67: 
68: 
69: 
70: 
71: 
72: 
73: 
74: 
75: 
76: 
77: 
78: 
79: 
80: 
81: 
82: 
83: 
84: 
85: 
86: 
87: 
88: 
89: 
90: 
91: 
92: 
93: 
94: 
95: 
96: 
97: 
98: 
open System
open System.Reflection
open System.Reflection.Emit
open System.Runtime.InteropServices
open System.Globalization

//------------------------------------------------------------------------------
// A dynamic value whos type is unknown at runtime.
type [<NoComparison>] [<StructLayout(LayoutKind.Explicit)>] BoxedValue =
  struct 
    //Reference Types
    [<FieldOffset(0)>] val mutable Clr : Object 
    [<FieldOffset(0)>] val mutable Object : CommonObject
    [<FieldOffset(0)>] val mutable Array : ArrayObject
    [<FieldOffset(0)>] val mutable Func : FunctionObject
    [<FieldOffset(0)>] val mutable String : String
    [<FieldOffset(0)>] val mutable Scope : BoxedValue array

    //Value Types
    [<FieldOffset(8)>] val mutable Bool : bool
    [<FieldOffset(8)>] val mutable Number : double

    //Type & Tag
    [<FieldOffset(12)>] val mutable Tag : uint32
    [<FieldOffset(14)>] val mutable Marker : uint16

    member x.IsNumber = x.Marker < Markers.Tagged
    member x.IsTagged = x.Marker > Markers.Number
    member x.IsString = x.IsTagged && x.Tag = TypeTags.String
    member x.IsObject = x.IsTagged && x.Tag >= TypeTags.Object
    member x.IsFunction = x.IsTagged && x.Tag >= TypeTags.Function
    member x.IsBoolean = x.IsTagged && x.Tag = TypeTags.Bool
    member x.IsUndefined = x.IsTagged && x.Tag = TypeTags.Undefined
    member x.IsClr = x.IsTagged && x.Tag = TypeTags.Clr

    member x.IsPrimitive =
      if x.IsNumber then 
        true

      else 
        match x.Tag with
        | TypeTags.String
        | TypeTags.Bool -> true
        | _ -> false

    member x.ClrBoxed =
      if x.IsNumber 
        then x.Number :> obj
        elif x.Tag = TypeTags.Bool 
          then x.Bool :> obj
          else x.Clr

    member x.Unbox<'a>() = x.ClrBoxed :?> 'a

    static member Box(value:CommonObject) =
      let mutable box = BoxedValue()
      box.Clr <- value
      box.Tag <- TypeTags.Object
      box

    static member Box(value:FunctionObject) =
      let mutable box = BoxedValue()
      box.Clr <- value
      box.Tag <- TypeTags.Function
      box

    static member Box(value:String) =
      let mutable box = BoxedValue()
      box.Clr <- value
      box.Tag <- TypeTags.String
      box

    static member Box(value:double) =
      let mutable box = BoxedValue()
      box.Number <- value
      box

    static member Box(value:bool) =
      let mutable box = BoxedValue()
      box.Number <- TaggedBools.ToTagged value
      box

    static member Box(value:Object) =
      let mutable box = BoxedValue()
      box.Clr <- value
      box.Tag <- TypeTags.Clr
      box

    static member Box(value:Object, tag:uint32) =
      let mutable box = BoxedValue()
      box.Clr <- value
      box.Tag <- tag
      box

    static member Box(value:Undefined) =
      Utils2.BoxedUndefined

  end
namespace System
namespace System.Reflection
namespace System.Reflection.Emit
namespace System.Runtime
namespace System.Runtime.InteropServices
namespace System.Globalization
Multiple items
type NoComparisonAttribute =
  inherit Attribute
  new : unit -> NoComparisonAttribute

Full name: Microsoft.FSharp.Core.NoComparisonAttribute

--------------------
new : unit -> NoComparisonAttribute
Multiple items
type StructLayoutAttribute =
  inherit Attribute
  new : layoutKind:LayoutKind -> StructLayoutAttribute + 1 overload
  val Pack : int
  val Size : int
  val CharSet : CharSet
  member Value : LayoutKind

Full name: System.Runtime.InteropServices.StructLayoutAttribute

--------------------
StructLayoutAttribute(layoutKind: LayoutKind) : unit
StructLayoutAttribute(layoutKind: int16) : unit
type LayoutKind =
  | Sequential = 0
  | Explicit = 2
  | Auto = 3

Full name: System.Runtime.InteropServices.LayoutKind
field LayoutKind.Explicit = 2
type BoxedValue =
  struct
    val mutable Clr: Object
    val mutable Object: obj
    val mutable Array: obj
    val mutable Func: obj
    val mutable String: String
    val mutable Scope: BoxedValue array
    val mutable Bool: bool
    val mutable Number: double
    val mutable Tag: uint32
    val mutable Marker: uint16
    ...
  end

Full name: Script.BoxedValue
Multiple items
type FieldOffsetAttribute =
  inherit Attribute
  new : offset:int -> FieldOffsetAttribute
  member Value : int

Full name: System.Runtime.InteropServices.FieldOffsetAttribute

--------------------
FieldOffsetAttribute(offset: int) : unit
BoxedValue.Clr: Object
Multiple items
type Object =
  new : unit -> obj
  member Equals : obj:obj -> bool
  member GetHashCode : unit -> int
  member GetType : unit -> Type
  member ToString : unit -> string
  static member Equals : objA:obj * objB:obj -> bool
  static member ReferenceEquals : objA:obj * objB:obj -> bool

Full name: System.Object

--------------------
Object() : unit
Multiple items
BoxedValue.Object: obj

--------------------
type Object =
  new : unit -> obj
  member Equals : obj:obj -> bool
  member GetHashCode : unit -> int
  member GetType : unit -> Type
  member ToString : unit -> string
  static member Equals : objA:obj * objB:obj -> bool
  static member ReferenceEquals : objA:obj * objB:obj -> bool

Full name: System.Object

--------------------
Object() : unit
Multiple items
BoxedValue.Array: obj

--------------------
type Array =
  member Clone : unit -> obj
  member CopyTo : array:Array * index:int -> unit + 1 overload
  member GetEnumerator : unit -> IEnumerator
  member GetLength : dimension:int -> int
  member GetLongLength : dimension:int -> int64
  member GetLowerBound : dimension:int -> int
  member GetUpperBound : dimension:int -> int
  member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
  member Initialize : unit -> unit
  member IsFixedSize : bool
  ...

Full name: System.Array
Multiple items
BoxedValue.Func: obj

--------------------
type Func<'TResult> =
  delegate of unit -> 'TResult

Full name: System.Func<_>

--------------------
type Func<'T,'TResult> =
  delegate of 'T -> 'TResult

Full name: System.Func<_,_>

--------------------
type Func<'T1,'T2,'TResult> =
  delegate of 'T1 * 'T2 -> 'TResult

Full name: System.Func<_,_,_>

--------------------
type Func<'T1,'T2,'T3,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 -> 'TResult

Full name: System.Func<_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 -> 'TResult

Full name: System.Func<_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 -> 'TResult

Full name: System.Func<_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 * 'T15 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_>

--------------------
type Func<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15,'T16,'TResult> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 * 'T15 * 'T16 -> 'TResult

Full name: System.Func<_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_>
Multiple items
BoxedValue.String: String

--------------------
type String =
  new : value:char -> string + 7 overloads
  member Chars : int -> char
  member Clone : unit -> obj
  member CompareTo : value:obj -> int + 1 overload
  member Contains : value:string -> bool
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EndsWith : value:string -> bool + 2 overloads
  member Equals : obj:obj -> bool + 2 overloads
  member GetEnumerator : unit -> CharEnumerator
  member GetHashCode : unit -> int
  ...

Full name: System.String

--------------------
String(value: nativeptr<char>) : unit
String(value: nativeptr<sbyte>) : unit
String(value: char []) : unit
String(c: char, count: int) : unit
String(value: nativeptr<char>, startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
String(value: char [], startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Text.Encoding) : unit
BoxedValue.Scope: BoxedValue array
type 'T array = 'T []

Full name: Microsoft.FSharp.Core.array<_>
BoxedValue.Bool: bool
type bool = Boolean

Full name: Microsoft.FSharp.Core.bool
BoxedValue.Number: double
Multiple items
val double : value:'T -> float (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.double

--------------------
type double = Double

Full name: Microsoft.FSharp.Core.double
BoxedValue.Tag: uint32
Multiple items
val uint32 : value:'T -> uint32 (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.uint32

--------------------
type uint32 = UInt32

Full name: Microsoft.FSharp.Core.uint32
BoxedValue.Marker: uint16
Multiple items
val uint16 : value:'T -> uint16 (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.uint16

--------------------
type uint16 = UInt16

Full name: Microsoft.FSharp.Core.uint16
val x : byref<BoxedValue>
member BoxedValue.IsNumber : bool

Full name: Script.BoxedValue.IsNumber
member BoxedValue.IsTagged : bool

Full name: Script.BoxedValue.IsTagged
member BoxedValue.IsString : bool

Full name: Script.BoxedValue.IsString
Multiple items
type String =
  new : value:char -> string + 7 overloads
  member Chars : int -> char
  member Clone : unit -> obj
  member CompareTo : value:obj -> int + 1 overload
  member Contains : value:string -> bool
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EndsWith : value:string -> bool + 2 overloads
  member Equals : obj:obj -> bool + 2 overloads
  member GetEnumerator : unit -> CharEnumerator
  member GetHashCode : unit -> int
  ...

Full name: System.String

--------------------
String(value: nativeptr<char>) : unit
String(value: nativeptr<sbyte>) : unit
String(value: char []) : unit
String(c: char, count: int) : unit
String(value: nativeptr<char>, startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
String(value: char [], startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Text.Encoding) : unit
member BoxedValue.IsObject : bool

Full name: Script.BoxedValue.IsObject
member BoxedValue.IsFunction : bool

Full name: Script.BoxedValue.IsFunction
member BoxedValue.IsBoolean : bool

Full name: Script.BoxedValue.IsBoolean
member BoxedValue.IsUndefined : bool

Full name: Script.BoxedValue.IsUndefined
member BoxedValue.IsClr : bool

Full name: Script.BoxedValue.IsClr
member BoxedValue.IsPrimitive : bool

Full name: Script.BoxedValue.IsPrimitive
member BoxedValue.ClrBoxed : obj

Full name: Script.BoxedValue.ClrBoxed
type obj = Object

Full name: Microsoft.FSharp.Core.obj
member BoxedValue.Unbox : unit -> 'a

Full name: Script.BoxedValue.Unbox
static member BoxedValue.Box : value:'d -> BoxedValue

Full name: Script.BoxedValue.Box
val value : 'd
val mutable box : BoxedValue
static member BoxedValue.Box : value:'c -> BoxedValue

Full name: Script.BoxedValue.Box
val value : 'c
static member BoxedValue.Box : value:String -> BoxedValue

Full name: Script.BoxedValue.Box
val value : String
static member BoxedValue.Box : value:double -> BoxedValue

Full name: Script.BoxedValue.Box
val value : double
static member BoxedValue.Box : value:bool -> BoxedValue

Full name: Script.BoxedValue.Box
val value : bool
static member BoxedValue.Box : value:Object -> BoxedValue

Full name: Script.BoxedValue.Box
val value : Object
static member BoxedValue.Box : value:Object * tag:uint32 -> BoxedValue

Full name: Script.BoxedValue.Box
val tag : uint32
static member BoxedValue.Box : value:'a -> 'b

Full name: Script.BoxedValue.Box
val value : 'a
Next Version Raw view Test code New version

More information

Link:http://fssnip.net/2N
Posted:13 years ago
Author:fholm
Tags: ironjs , structs