asil-1.2: src/PrettyTree.ag
MODULE {PrettyTree} {ppSwf,ppAbc} {}
INCLUDE "ByteCodeAst.ag"
INCLUDE "SymViewAst.ag"
INCLUDE "ByteCodeLocationInfo.ag"
imports
{
import Codec.Binary.UTF8.String
import Data.ByteString.Lazy(ByteString,unpack)
import Data.Word
import Data.Monoid
import ByteCode
import PrettyUtil
import Options
import SymView
import ProgInfo
}
WRAPPER SwfFile
WRAPPER AbcFile
{
ppSwf :: Options -> [SymbolTables] -> SwfFile -> Doc
ppSwf opts tbls m = out where
inh = Inh_SwfFile { opts_Inh_SwfFile = opts, tbls_Inh_SwfFile = tbls }
sem = sem_SwfFile m
syn = wrap_SwfFile sem inh
out = output_Syn_SwfFile syn
ppAbc :: Options -> [SymbolTables] -> AbcFile -> Doc
ppAbc opts tbls m = out where
inh = Inh_AbcFile { opts_Inh_AbcFile = opts, tbls_Inh_AbcFile = tbls }
sem = sem_AbcFile m
syn = wrap_AbcFile sem inh
out = output_Syn_AbcFile syn
}
ATTR (AllSwf - TagKind AbcFlags AbcFlag NamespaceInfo MultinameInfo ParamNames NamespaceKind)
[ opts : Options | | output USE {$+$} {empty} : Doc ]
SEM SwfFile | File
lhs.output = text "SWF" <+> space <+> props
[ ("compressed", bool @compressed)
, ("version", num @version)
, ("length", num @length)
]
$+$ @tags.output
ATTR OnlySwfAbc [ | tbls : {[SymbolTables]} | ]
ATTR AllAbc [ tbls : SymbolTables | | ]
-- Associate a symbol table with the right abcfile in a SWF file
SEM AbcFile | File
loc.tbls = head @lhs.tbls
lhs.tbls = tail @lhs.tbls
{
bool :: Bool -> Doc
bool True = text "yes"
bool False = text "no"
num :: Num a => a -> Doc
num x = text (show x)
str :: ByteString -> Doc
str = text . decode . unpack
props :: [(String, Doc)] -> Doc
props xs = hsep $ punctuate (text ",") [ text k <> text ":" <+> v | (k,v) <- xs ]
}
SEM Tag
| Abc
lhs.output = text "TAG Abc" <+> space <+> props
[ ("lazy init", bool @flags.doLazyInit)
, ("name", str @name)
]
$+$ @file.output
| FileAttributes
lhs.output = text "TAG FileAttributes" <+> space <+> props
[ ("use blit", bool @useDirectBlit)
, ("use gpu", bool @useGPU)
, ("hasAS3", bool @hasAS3)
, ("use network", bool @useNetwork)
]
| Opaque
lhs.output = text "TAG" <+> text (show @kind.self) <+> space <+> props
[ ("length", num @length)
]
ATTR TagKind [ | | self : SELF ]
ATTR AbcFlags AbcFlag [ | | doLazyInit USE {||} {False} : Bool ]
SEM AbcFlag | LazyInit lhs.doLazyInit = True
SEM AbcFile | File
lhs.output = text "ABC" <+> space <+> props
[ ("major version", num @majorVersion)
, ("minor version", num @minorVersion)
, ("classes", num @classes.length)
, ("methods", num @bodies.length)
]
$+$ @constantPool.output
$+$ @classes.output
$+$ @instances.output
$+$ @bodies.output
ATTR BodyInfos ClassInfos BodyInfo ClassInfo [ | | length USE {+} {0} : Int ]
SEM ClassInfo | Info lhs.length = 1
SEM BodyInfo | Info lhs.length = 1
--
-- Pretty-print constant pool
--
SEM PoolInfo | Info
lhs.output = vert $ map (\(k,v) -> text "TABLE" <+> text k $+$ nest 2 v)
[ ("integers", @integers.output)
, ("uintegers", @uintegers.output)
, ("doubles", @doubles.output)
, ("strings", @strings.output)
, ("namespaces", @namespaces.output)
, ("namesets", @namesets.output)
, ("multinames", @multinames.output)
]
ATTR PoolInts PoolUInts PoolDoubles PoolStrings NamespaceInfos SetInfos MultinameInfos [ index : Word32 | | ]
SEM PoolInfo | Info
integers.index = 1
uintegers.index = 1
doubles.index = 1
strings.index = 1
namespaces.index = 1
namesets.index = 1
multinames.index = 1
SEM PoolInts | Cons tl.index = 1 + @lhs.index
SEM PoolUInts | Cons tl.index = 1 + @lhs.index
SEM PoolDoubles | Cons tl.index = 1 + @lhs.index
SEM PoolStrings | Cons tl.index = 1 + @lhs.index
SEM NamespaceInfos | Cons tl.index = 1 + @lhs.index
SEM SetInfos | Cons tl.index = 1 + @lhs.index
SEM MultinameInfos | Cons tl.index = 1 + @lhs.index
SEM PoolInts | Cons lhs.output = num @lhs.index <+> text "->" <+> num @hd $+$ @tl.output
SEM PoolUInts | Cons lhs.output = num @lhs.index <+> text "->" <+> num @hd $+$ @tl.output
SEM PoolDoubles | Cons lhs.output = num @lhs.index <+> text "->" <+> num @hd $+$ @tl.output
SEM PoolStrings | Cons lhs.output = num @lhs.index <+> text "->" <+> str @hd $+$ @tl.output
SEM NamespaceInfos | Cons lhs.output = num @lhs.index <+> text "->" <+> @pp.output $+$ @tl.output
SEM SetInfos | Cons lhs.output = num @lhs.index <+> text "->" <+> @hd.output $+$ @tl.output
SEM MultinameInfos | Cons lhs.output = num @lhs.index <+> text "->" <+> @pp.output $+$ @tl.output
SEM NamespaceInfos | Cons
inst.pp : NsV
inst.pp = namespaceView @lhs.tbls (Ref @lhs.index)
pp.info = Verbose
SEM MultinameInfos | Cons
inst.pp : NmV
inst.pp = nameView @lhs.tbls (Ref @lhs.index)
pp.info = Verbose
SEM SetInfo | Info
lhs.output = text "SET" <+> @names.output
SEM NamespaceNames | Cons
lhs.output = @pp.output <+> braces (text "ns-id:" <+> num @hd) <+> @tl.output
inst.pp : NsV
inst.pp = namespaceView @lhs.tbls (Ref @hd)
pp.info = Short
--
-- Pretty-printing of view on symbol table
--
{
data PPInfo = Short | Verbose
}
ATTR StrV MbStrV MbNmV NmV NsV [ | | isEmpty : Bool ]
SEM StrV | Str lhs.isEmpty = null @val
SEM MbStrV | Nothing lhs.isEmpty = True
SEM MbNmV | Nothing lhs.isEmpty = True
SEM NmV | Other lhs.isEmpty = False
SEM NmV | Qual lhs.isEmpty = @nm.isEmpty
SEM NmV | Quals lhs.isEmpty = False
SEM NsV | Ns lhs.isEmpty = @nm.isEmpty
ATTR FileV TablesV TableV ClassesV
ClassV MbSuperV SuperV ItfsV ItfV TraitsV TraitV
NmV NmsV NsSetV NssV NsV StrV MbStrV MbNmV MethodsV MethodV SigV ParamV TypeV
[ info : PPInfo | | output USE {$+$} {empty} : Doc ]
ATTR ParamsV [ info : PPInfo | | output USE {++} {[]} : {[Doc]} ]
SEM NmV
| Qual loc.nmOut = if @nm.isEmpty
then text "*"
else @nm.output
lhs.output = case @lhs.info of
Short -> if @ns.isEmpty
then @loc.nmOut
else @ns.output <> text ":" <> @loc.nmOut
Verbose -> props [ ("namespace", @ns.output), ("name", @nm.output) ]
| Quals lhs.output = @set.output <> text ":" <> @nm.output
loc.info = Short
| Other lhs.output = text "name/other" <> parens (text $ show $ refVal @id)
SEM NsV | Ns
lhs.output = if (refVal @id) == 0
then text "*"
else case @lhs.info of
Short -> @nm.output
Verbose -> @nm.output <+> braces (text "ns-id:" <+> num (refVal @id))
SEM NsSetV | Set
lhs.output = braces @spaces.output
SEM NssV
| Cons lhs.output = @hd.output <+> @tl.output
| Nil lhs.output = empty
SEM StrV | Str
lhs.output = case @lhs.info of
Short -> text @val
Verbose -> text @val <+> braces (text "str-id:" <+> num (refVal @id))
SEM MbStrV | Nothing
lhs.output = text "_"
SEM MbNmV | Nothing
lhs.output = text "_"
SEM MethodV | Method
mbNm.info = Short
sig.info = Short
lhs.output = if @mbNm.isDefined
then @mbNm.output <> @sig.output
else @sig.output
ATTR MbNmV [ | | isDefined : Bool ]
SEM MbNmV
| Just lhs.isDefined = True
| Nothing lhs.isDefined = False
ATTR MbStrV [ | | isDefined : Bool ]
SEM MbStrV
| Just lhs.isDefined = True
| Nothing lhs.isDefined = False
SEM SigV | Sig
params.info = Short
ret.info = Short
lhs.output = parens (hsep $ punctuate (text ",") @params.output) <> text ":" <> @ret.output
SEM ParamsV
| Cons lhs.output = @hd.output : @tl.output
| Nil lhs.output = []
SEM ParamV | Param
lhs.output = @tp.output
SEM ClassV | Class
lhs.output = @nm.output
--
-- Pretty print instance information
-- (the dynamic aspects of a class/type)
--
ATTR ClassInfos ClassInfo InstanceInfos InstanceInfo [ index : Word32 | | ]
SEM AbcFile | File
instances.index = 0
classes.index = 0
SEM ClassInfos | Cons tl.index = 1 + @lhs.index
SEM InstanceInfos | Cons tl.index = 1 + @lhs.index
SEM InstanceInfo | Info
inst.nm : NmV
inst.nm = nameView @lhs.tbls (Ref @name)
nm.info = Short
inst.s : NmV
inst.s = nameView @lhs.tbls (Ref @super)
s.info = Short
inst.con : MethodV
inst.con = methodView @lhs.tbls (Ref @constructor)
con.info = Short
inst.ns : NsV
inst.ns = namespaceView @lhs.tbls (Ref @protectedNs)
ns.info = Verbose
lhs.output = text "INSTANCE" <+> @nm.output
$+$ nest 2 ( text "SUPER" <+> @s.output
$+$ @interfaces.output
$+$ @flags.output
$+$ text "CON" <+> @con.output
$+$ text "NS" <+> @ns.output
$+$ @traits.output
)
SEM InstanceFlag
| ClassSealed lhs.output = text "FLAG sealed"
| ClassFinal lhs.output = text "FLAG final"
| ClassInterface lhs.output = text "FLAG is interface"
| ClassProtected lhs.output = text "FLAG has protected namespace"
--
-- Pretty print traits
--
SEM Trait | Trait
inst.nm : NmV
inst.nm = nameView @lhs.tbls (Ref @name)
nm.info = Short
lhs.output = text "TRAIT" <+> @nm.output <+> parens (text $ show @name) <+>
space <+> @attrs.output
$+$ nest 2 @data.output
SEM TraitAttrs | Cons lhs.output = @hd.output <+> @tl.output
SEM TraitAttr
| Final lhs.output = text "final"
| Override lhs.output = text "override"
| Metadata lhs.output = text "metadata"
SEM TraitData
| Slot loc.desc = text "SLOT"
| Const loc.desc = text "CONST"
| Method loc.desc = text "METHOD"
| Getter loc.desc = text "GETTER"
| Setter loc.desc = text "SETTER"
| Function loc.desc = text "FUN"
| Slot Const
inst.nm : NmV
inst.nm = nameView @lhs.tbls (Ref @tp)
nm.info = Short
lhs.output = @loc.desc <+> props
[ ("slotid", num @slotId)
, ("type", @nm.output)
, ("vindex", num @vindex)
, ("vkind", @vkind.output)
]
| Method Getter Setter Function
inst.m : MethodV
inst.m = methodView @lhs.tbls (Ref @method)
m.info = Short
lhs.output = @loc.desc <+> props
[ ("disp-id", num @dispId)
, ("method", @m.output)
]
| Class
loc.key = Ref @class
loc.descr = lookupClass @loc.key @lhs.tbls
inst.nm : NmV
inst.nm = nameView @lhs.tbls (clName @loc.descr)
nm.info = Short
lhs.output = text "CLASS" <+> @nm.output
--
-- Pretty print class information
-- (the constructor + static traits)
--
SEM ClassInfo | Info
loc.key = Ref @lhs.index
loc.descr = lookupClass @loc.key @lhs.tbls
inst.nm : NmV
inst.nm = nameView @lhs.tbls (clName @loc.descr)
nm.info = Short
inst.m : MethodV
inst.m = methodView @lhs.tbls (Ref @con)
m.info = Short
lhs.output = text "CLASS" <+> @nm.output
$+$ nest 2 (text "CON" <+> @m.output)
$+$ nest 2 @traits.output
--
-- Pretty print method bodies
--
SEM BodyInfo | Info
inst.m : MethodV
inst.m = methodView @lhs.tbls (Ref @method)
m.info = Short
lhs.output = text "METHOD" <+> @m.output <+> space <+> props
[ ("max stack", num @maxStack)
, ("locals", num @localCount)
, ("init scopes", num @initScopeDepth)
, ("max scopes", num @maxScopeDepth)
]
$+$ nest 2 @instructions.output
$+$ nest 2 @exceptions.output
SEM Exception | Info
inst.nm : NmV
inst.nm = nameView @lhs.tbls (Ref @tp)
nm.info = Short
lhs.output = text "EXCEPTION" <+> @nm.output <+> space <+> props
[ ("from", num @from)
, ("to", num @to)
, ("target", num @target)
]
--
-- Instructions and location information
--
ATTR Instructions Instruction [ | mbLoc : {Maybe Int} | ]
SEM BodyInfo | Info
instructions.mbLoc = Nothing
SEM Instruction
| * - Location
lhs.mbLoc = Nothing
loc.lbl = case @lhs.mbLoc of
Nothing -> text (replicate 8 ' ')
Just i -> let str = show i
sps = replicate (max 0 (6 - length str)) ' '
in text str <> text sps <> text ": "
loc.prefix = @loc.lbl <> text "INSTR"
lhs.output = @loc.prefix <+> @loc.descr
| Location
lhs.mbLoc = Just @index
lhs.output = empty -- hide
-- Exception environment
ATTR Exceptions Exception [ index : Word32 | | gathExcptEnv USE {`mappend`} {mempty} : ExceptionDescrs ]
SEM BodyInfo | Info exceptions.index = 0
SEM Exceptions | Cons tl.index = 1 + @lhs.index
SEM Exception | Info lhs.gathExcptEnv = singleEnv @lhs.index ExceptionDescr
{ expFrom = @from
, expTo = @to
, expTarget = @target
, expTp = Ref @tp
, expName = Ref @name
}
ATTR Instructions Instruction [ excptEnv : ExceptionDescrs | | ]
SEM BodyInfo | Info instructions.excptEnv = @exceptions.gathExcptEnv
-- Names, methods, etc.
SEM Instruction
| ApplyType AsType CallInterface Coerce ConstructProp DeleteProperty GetLex
FindPropertyGlobalStrict FindPropertyGlobal FindProperty FindPropStrict GetDescendants
CallProp CallPropLex CallPropVoid CallSuper CallSuperVoid
GetOuterScope GetProperty GetSuper InitProperty IsType
SetProperty SetSuper FindDef
inst.nm : NmV
inst.nm = nameView @lhs.tbls (Ref @name)
nm.info = Short
| Debug Dxns PushString DebugFile
inst.nm : StrV
inst.nm = stringView @lhs.tbls (Ref @name)
nm.info = Short
| PushNamespace
inst.nms : NsV
inst.nms = namespaceView @lhs.tbls (Ref @name)
nms.info = Short
| CallStatic NewFunction
inst.m : MethodV
inst.m = methodView @lhs.tbls (Ref @method)
m.info = Short
| NewCatch
loc.edesc = lookupException (Ref @exception) @lhs.excptEnv
inst.nm : NmV
inst.nm = nameView @lhs.tbls (expName @loc.edesc)
nm.info = Short
inst.tp : NmV
inst.tp = nameView @lhs.tbls (expTp @loc.edesc)
tp.info = Short
| NewClass
loc.cdesc = lookupClass (Ref @class) @lhs.tbls
inst.nm : NmV
inst.nm = nameView @lhs.tbls (clName @loc.cdesc)
nm.info = Short
| PushInt loc.val = lookupInt (Ref @name) @lhs.tbls
| PushUInt loc.val = lookupUInt (Ref @name) @lhs.tbls
| PushDouble loc.val = lookupDouble (Ref @name) @lhs.tbls
SEM Instruction
| Add loc.descr = text "Add"
| Add_i loc.descr = text "Add_i"
| Add_d loc.descr = text "Add_d"
| ApplyType loc.descr = text "Apply type" <+> @nm.output
| AsType loc.descr = text "As type" <+> @nm.output
| AsTypeLate loc.descr = text "As type (late)"
| Breakpoint loc.descr = text "Breakpoint"
| BreakLine loc.descr = text "Break line" <+> num @line
| BitAnd loc.descr = text "BitAnd"
| BitNot loc.descr = text "BitNot"
| BitOr loc.descr = text "BitOr"
| BitXor loc.descr = text "BitXor"
| Call loc.descr = text "Call" <+> props [("args", num @argCount)]
| CallInterface loc.descr = text "Call interface" <+> @nm.output <+> props [("args", num @argCount)]
| CallMethod loc.descr = text "Call method" <+> props [("index", num @index), ("args", num @argCount)]
| CallProp loc.descr = text "Call prop" <+> @nm.output <+> props [("args", num @argCount)]
| CallPropLex loc.descr = text "Call prop (lex)" <+> @nm.output <+> props [("args", num @argCount)]
| CallPropVoid loc.descr = text "Call prop (void)" <+> @nm.output <+> props [("args", num @argCount)]
| CallStatic loc.descr = text "Call static" <+> props [("method", @m.output), ("args", num @argCount)]
| CallSuper loc.descr = text "Call super" <+> @nm.output <+> props [("args",num @argCount)]
| CallSuperId loc.descr = text "Call super (id)"
| CallSuperVoid loc.descr = text "Call super (void)" <+> @nm.output <+> props [("args",num @argCount)]
| CheckFilter loc.descr = text "CheckFilter"
| Coerce loc.descr = text "Coerce" <+> @nm.output
| Coerce_a loc.descr = text "Coerce_a (any type)"
| Coerce_b loc.descr = text "Coerce_b"
| Coerce_d loc.descr = text "Coerce_d (double)"
| Coerce_i loc.descr = text "Coerce_i (signed integer)"
| Coerce_o loc.descr = text "Coerce_o"
| Coerce_s loc.descr = text "Coerce_s (string)"
| Coerce_u loc.descr = text "Coerce_u (unsigned integer)"
| Concat loc.descr = text "Concat"
| Construct loc.descr = text "Construct" <+> props [("args", num @argCount)]
| ConstructProp loc.descr = text "Construct prop" <+> @nm.output <+> props [("args", num @argCount)]
| ConstructSuper loc.descr = text "Construct super" <+> props [("args", num @argCount)]
| Convert_b loc.descr = text "Convert_b"
| Convert_i loc.descr = text "Convert_i (signed integer)"
| Convert_d loc.descr = text "Convert_d (double)"
| Convert_o loc.descr = text "Convert_o"
| Convert_u loc.descr = text "Convert_u (unsigned integer)"
| Convert_s loc.descr = text "Convert_s (string)"
| Debug loc.descr = text "Debug" <+> @nm.output <+> props [("reg", num @reg)]
| DebugFile loc.descr = text "Debug file" <+> @nm.output
| DebugLine loc.descr = text "Debug line" <+> num @line
| DecLocal loc.descr = text "DecLocal (number)" <+> num @reg
| DecLocal_i loc.descr = text "DecLocal_i (integer)" <+> num @reg
| Decrement loc.descr = text "Decrement (number)"
| Decrement_i loc.descr = text "Decrement_i (integer)"
| DeleteProperty loc.descr = text "Delete property" <+> @nm.output
| DeletePropertyLate loc.descr = text "Delete property (late)"
| Divide loc.descr = text "Divide"
| Dup loc.descr = text "Dup"
| Dxns loc.descr = text "Default namespace" <+> @nm.output
| DxnsLate loc.descr = text "Default namespace (late)"
| Equals loc.descr = text "Equals"
| EscXAttr loc.descr = text "Escape Xml Attr"
| EscXElem loc.descr = text "Escape Xml Elem"
| FindDef loc.descr = text "Find Definition" <+> @nm.output
| FindPropertyGlobalStrict loc.descr = text "Find property global (strict)" <+> @nm.output
| FindPropertyGlobal loc.descr = text "Find property global" <+> @nm.output
| FindProperty loc.descr = text "Find property" <+> @nm.output
| FindPropStrict loc.descr = text "Find property strict" <+> @nm.output
| GetDescendants loc.descr = text "Get descendants" <+> @nm.output
| GetGlobalScope loc.descr = text "Get global scope"
| GetGlobalSlot loc.descr = text "Set global slot" <+> num @slot
| GetLex loc.descr = text "Get lex (find+get prop)" <+> @nm.output
| GetLocal loc.descr = text "Get local" <+> num @reg
| GetLocal0 loc.descr = text "Get local0"
| GetLocal1 loc.descr = text "Get local1"
| GetLocal2 loc.descr = text "Get local2"
| GetLocal3 loc.descr = text "Get local3"
| GetOuterScope loc.descr = text "Get outer scope" <+> @nm.output
| GetProperty loc.descr = text "Get property" <+> @nm.output
| GetScopeObject loc.descr = text "Get scope object" <+> props [("index", num @index)]
| GetSlot loc.descr = text "Get slot" <+> num @slot
| GetSuper loc.descr = text "Get super" <+> @nm.output
| GreaterEquals loc.descr = text "Greater or equals"
| GreaterThan loc.descr = text "Greater than"
| HasNext loc.descr = text "Has next"
| HasNext2 loc.descr = text "Has next 2" <+> props [("object register", num @objectReg),("index register", num @indexReg)]
| IfEq loc.descr = text "If equal" <+> num @loc.target <+> parens (num @loc.relative)
| IfFalse loc.descr = text "If false" <+> num @loc.target <+> parens (num @loc.relative)
| IfGe loc.descr = text "If greater or equal" <+> num @loc.target <+> parens (num @loc.relative)
| IfGt loc.descr = text "If greater" <+> num @loc.target <+> parens (num @loc.relative)
| IfLe loc.descr = text "If less or equal" <+> num @loc.target <+> parens (num @loc.relative)
| IfLt loc.descr = text "If less than" <+> num @loc.target <+> parens (num @loc.relative)
| IfNGe loc.descr = text "If not greater or equal" <+> num @loc.target <+> parens (num @loc.relative)
| IfNGt loc.descr = text "If not greater than" <+> num @loc.target <+> parens (num @loc.relative)
| IfNLe loc.descr = text "If not less or equal" <+> num @loc.target <+> parens (num @loc.relative)
| IfNLt loc.descr = text "If not less than" <+> num @loc.target <+> parens (num @loc.relative)
| IfNe loc.descr = text "If not equal" <+> num @loc.target <+> parens (num @loc.relative)
| IfStrictEq loc.descr = text "If equal (strict)" <+> num @loc.target <+> parens (num @loc.relative)
| IfStrictNe loc.descr = text "If not equal (strict)" <+> num @loc.target <+> parens (num @loc.relative)
| IfTrue loc.descr = text "If true" <+> num @loc.target <+> parens (num @loc.relative)
| In loc.descr = text "In (tests existence of property in object)"
| IncLocal loc.descr = text "Increment local (number)" <+> num @reg
| IncLocal_i loc.descr = text "Increment local (integer)" <+> num @reg
| Increment loc.descr = text "Increment (number)"
| Increment_i loc.descr = text "Increment (integer)"
| InitProperty loc.descr = text "Init property" <+> @nm.output
| InstanceOf loc.descr = text "Instance of"
| IsType loc.descr = text "Is type" <+> @nm.output
| IsTypeLate loc.descr = text "Is type (late)"
| Jump loc.descr = text "Jump" <+> num @loc.target <+> parens (num @loc.relative)
| Kill loc.descr = text "Kill register" <+> num @reg
| Label loc.descr = text "Label (nop)"
| LessEquals loc.descr = text "Less or equals"
| LessThan loc.descr = text "Less than"
| LoadFloat32 loc.descr = text "Load float 32"
| LoadFloat64 loc.descr = text "Load float 64"
| LoadIndirect8 loc.descr = text "Load indirect 8"
| LoadIndirect16 loc.descr = text "Load indirect 16"
| LoadIndirect32 loc.descr = text "Load indirect 32"
| LookupSwitch loc.descr = text "Switch" <+> num @loc.target <+> parens (num @loc.relative)
$+$ @caseOffsets.output
| Lshift loc.descr = text "Left shift"
| Modulo loc.descr = text "Modulo"
| Multiply loc.descr = text "Multiply (number)"
| Multiply_i loc.descr = text "Multiply (integer)"
| Negate loc.descr = text "Negate (number)"
| Negate_i loc.descr = text "Negate (integer)"
| NewActivation loc.descr = text "New activation"
| NewArray loc.descr = text "New array" <+> props [("entries", num @argCount)]
| NewCatch loc.descr = text "New catch" <+> props
[ ("from", num $ expFrom @loc.edesc), ("to", num $ expTo @loc.edesc)
, ("target", num $ expTarget @loc.edesc)
, ("type", @tp.output), ("name", @nm.output) ]
| NewClass loc.descr = text "New class" <+> @nm.output
| NewFunction loc.descr = text "New function" <+> @m.output
| NewObject loc.descr = text "New object" <+> props [("args", num @argCount)]
| NextName loc.descr = text "NextName"
| NextValue loc.descr = text "NextValue"
| Nop loc.descr = text "Nop"
| Not loc.descr = text "Not"
| Pop loc.descr = text "Pop"
| PopScope loc.descr = text "Pop scope"
| PushByte loc.descr = text "Push byte" <+> num @val
| PushDouble loc.descr = text "Push double" <+> num @loc.val
| PushFalse loc.descr = text "Push false"
| PushInt loc.descr = text "Push signed integer" <+> num @loc.val
| PushNamespace loc.descr = text "Push namespace" <+> @nms.output
| PushNaN loc.descr = text "Push NaN"
| PushNull loc.descr = text "Push null"
| PushScope loc.descr = text "Push scope"
| PushShort loc.descr = text "Push short" <+> num @val
| PushString loc.descr = text "Push string" <+> @nm.output
| PushTrue loc.descr = text "Push true"
| PushUInt loc.descr = text "Push unsigned integer" <+> num @loc.val
| PushUndefined loc.descr = text "Push undefined"
| PushWith loc.descr = text "Push with-scope"
| ReturnValue loc.descr = text "Return (value)"
| ReturnVoid loc.descr = text "Return (void)"
| Rshift loc.descr = text "Right shift"
| SetLocal loc.descr = text "Set local" <+> num @reg
| SetLocal0 loc.descr = text "Set local0"
| SetLocal1 loc.descr = text "Set local1"
| SetLocal2 loc.descr = text "Set local2"
| SetLocal3 loc.descr = text "Set local3"
| SetGlobalSlot loc.descr = text "Set global slot" <+> num @slot
| SetProperty loc.descr = text "Set property" <+> @nm.output
| SetPropertyLate loc.descr = text "Set property (late)"
| SetSlot loc.descr = text "Set slot" <+> num @slot
| SetSuper loc.descr = text "Set super" <+> @nm.output
| SignExtend1 loc.descr = text "Sign extend 1"
| SignExtend8 loc.descr = text "Sign extend 8"
| SignExtend16 loc.descr = text "Sign extend 16"
| StoreFloat32 loc.descr = text "Store float 32"
| StoreFloat64 loc.descr = text "Store float 64"
| StoreIndirect32 loc.descr = text "Store indirect 32"
| StoreIndirect16 loc.descr = text "Store indirect 16"
| StoreIndirect8 loc.descr = text "Store indirect 8"
| StrictEquals loc.descr = text "Equals (strict)"
| Substract loc.descr = text "Substract (number)"
| Substract_i loc.descr = text "Substract (integer)"
| Swap loc.descr = text "Swap"
| Throw loc.descr = text "Throw"
| Timestamp loc.descr = text "Timestamp"
| TypeOf loc.descr = text "Type of"
| Urshift loc.descr = text "Unsigned right shift"
SEM CaseOffsets | Cons
lhs.output = text "CASE" <+> num @loc.target <+> parens (num @loc.relative)
SEM BodyInfo | Info
instructions.mbLoc < instructions.revLocation