module DotNet.Show (strILCode,ppIns) where
import Util.Extra
import DotNet.IL
import qualified Data.Map as Map
import Id(Id)
import TokenId(splitM)
import Info
import IntState(IntState,getSymbolTable,getErrorsIS,strIS,arityIS,mrpsIS,lookupIS)
import Maybe(isJust, fromJust)
import qualified Data.Set as Set
import Data.Char(toUpper)
import Data.PackedString(unpackPS)
import Text.PrettyPrint
strILCode decls = render (
text ".assembly extern Haskell.Runtime" $$
char '{' $$
char '}' $$
vcat (map ppILDecl decls))
ppILDecl (Namespace name decls) =
text ".namespace" <+> text name $$
char '{' $+$
nest 4 (vcat (map ppILDecl decls)) $$
char '}'
ppILDecl (Class name base decls) =
text ".class private auto ansi beforefieldinit" <+> text name $$
text " extends" <+> ppClassSignature base $$
char '{' $+$
nest 4 (vcat (map ppILClassDecl decls)) $$
char '}'
ppILDecl (Prim name pos) = text "PRIM" <+> text "Prim"
ppILDecl (External name pos arity cname cc fl) = text "EXTERNAL" <+> text "EXTERNAL" <> text ("[" ++ cname ++ "]("++ show arity ++") flags="++show fl++"\n")
ppILMethodArg (ILMethodArg sig name) =
ppTypeSignature sig <+> text name
ppILAccess ILPublic = text "public"
ppILAccess ILPrivate = text "private"
ppILStorage ILStatic = text "static"
ppILStorage ILInstance = empty
ppILStorage ILVirtual = text "virtual"
ppILClassDecl (ILClassField access storage sig name) =
text ".field" <+> ppILAccess access <+> ppILStorage storage <+> ppTypeSignature sig <+> text name
ppILClassDecl (ILClassConstr access storage args locals instrs) =
text ".method" <+> ppILAccess access <+> ppILStorage storage <+> text "hidebysig specialname rtspecialname" $$
text " void" <+> ppName <> parens (hcat (punctuate comma (map ppILMethodArg args))) $$
char '{' $+$
nest 4 (text ".locals init" <+> parens (hcat (punctuate comma (map ppTypeSignature locals)))) $+$
vcat (map ppILInstrLabel instrs) $$
char '}'
where
ppName | storage == ILStatic = text ".cctor"
| otherwise = text ".ctor"
ppILClassDecl (ILClassMethod access storage retSig name args locals instrs) =
text ".method" <+> ppILAccess access <+> ppILStorage storage <+> text "hidebysig" $$
text " " <> ppTypeSignature retSig <+> text name <> parens (hcat (punctuate comma (map ppILMethodArg args))) $$
char '{' $+$
nest 4 (text ".locals init" <+> parens (hcat (punctuate comma (map ppTypeSignature locals)))) $+$
vcat (map ppILInstrLabel instrs) $$
char '}'
ppILInstrLabel (LABEL n) = ppLabel n <> char ':'
ppILInstrLabel i = nest 4 (ppILInstr i)
ppILInstr i = ppIns i
ppLabel l = text ("L_"++show l)
ppIns (LDC_I4 n) = text "ldc.i4" <+> int n
ppIns (LDC_R4 f) = text "ldc.r4" <+> float f
ppIns (LDC_R8 d) = text "ldc.r8" <+> double d
ppIns (LDSTR s) = text "ldstr" <+> text (show s)
ppIns (LDTOKEN t) = text "ldtoken" <+> ppTypeSignature t
ppIns (LDTOKEN_METHOD r t n as) = text "ldtoken method instance" <+> ppTypeSignature r <+> ppClassSignature t <> text "::" <> text n <> parens (hcat (punctuate comma (map ppTypeSignature as)))
ppIns (LDLOC n)
| n == 0 = text "ldloc.0"
| n == 1 = text "ldloc.1"
| n == 2 = text "ldloc.2"
| n == 3 = text "ldloc.3"
| n < 256 = text "ldloc.s" <+> int n
| otherwise = text "ldloc" <+> int n
ppIns (STLOC n)
| n == 0 = text "stloc.0"
| n == 1 = text "stloc.1"
| n == 2 = text "stloc.2"
| n == 3 = text "stloc.3"
| n < 256 = text "stloc.s" <+> int n
| otherwise = text "stloc" <+> int n
ppIns (LDARG n)
| n == 0 = text "ldarg.0"
| n == 1 = text "ldarg.1"
| n == 2 = text "ldarg.2"
| n == 3 = text "ldarg.3"
| n < 256 = text "ldarg.s" <+> int n
| otherwise = text "ldarg" <+> int n
ppIns (STARG n)
| n == 0 = text "starg.0"
| n == 1 = text "starg.1"
| n == 2 = text "starg.2"
| n == 3 = text "starg.3"
| n < 256 = text "starg.s" <+> int n
| otherwise = text "starg" <+> int n
ppIns (LDSFLD r t n) = text "ldsfld" <+> ppTypeSignature r <+> ppClassSignature t <> text "::" <> text n
ppIns (STSFLD r t n) = text "stsfld" <+> ppTypeSignature r <+> ppClassSignature t <> text "::" <> text n
ppIns (LDFLD r t n) = text "ldfld" <+> ppTypeSignature r <+> ppClassSignature t <> text "::" <> text n
ppIns (STFLD r t n) = text "stfld" <+> ppTypeSignature r <+> ppClassSignature t <> text "::" <> text n
ppIns (NEWOBJ sig args)=text "newobj instance void" <+> ppClassSignature sig <> text "::.ctor" <> parens (hcat (punctuate comma (map ppTypeSignature args)))
ppIns (ISINST sig) = text "isinst" <+> ppClassSignature sig
ppIns (DUP) = text "dup"
ppIns (POP) = text "pop"
ppIns (ADD) = text "add"
ppIns (SUB) = text "sub"
ppIns (MUL) = text "mul"
ppIns (DIV) = text "div"
ppIns (REM) = text "rem"
ppIns (CEQ) = text "ceq"
ppIns (CLT) = text "clt"
ppIns (CGT) = text "cgt"
ppIns (NOT) = text "not"
ppIns (NEG) = text "neg"
ppIns (BRTRUE l) = text "brtrue" <+> ppLabel l
ppIns (BRFALSE l) = text "brfalse" <+> ppLabel l
ppIns (BR l) = text "br" <+> ppLabel l
ppIns (BEQ l) = text "beq" <+> ppLabel l
ppIns (BNE l) = text "bne.un" <+> ppLabel l
ppIns (CALL r t n as) = text "call instance" <+> ppTypeSignature r <+> ppClassSignature t <> text "::" <> text n <> parens (hcat (punctuate comma (map ppTypeSignature as)))
ppIns (CALLVIRT r t n as) = text "callvirt" <+> ppTypeSignature r <+> ppClassSignature t <> text "::" <> text n <> parens (hcat (punctuate comma (map ppTypeSignature as)))
ppIns (CALLCLASS r t n as)= text "call" <+> ppTypeSignature r <+> ppClassSignature t <> text "::" <> text n <> parens (hcat (punctuate comma (map ppTypeSignature as)))
ppIns (TAIL) = text "tail."
ppIns (RET) = text "ret"
ppIns (THROW) = text "throw"
ppIns (LABEL f) = text "LABEL" <+> ppLabel f
ppTypeSignature (ClassSignature pkg cls)
| null pkg = text "class" <+> text cls
| otherwise = text "class" <+> brackets (text pkg) <> text cls
ppTypeSignature (ValueSignature pkg cls)
| null pkg = text "valuetype" <+> text cls
| otherwise = text "valuetype" <+> brackets (text pkg) <> text cls
ppTypeSignature Int32Signature = text "int32"
ppTypeSignature CharSignature = text "char"
ppTypeSignature DoubleSignature = text "float64"
ppTypeSignature FloatSignature = text "float32"
ppTypeSignature BoolSignature = text "bool"
ppTypeSignature VoidSignature = text "void"
ppClassSignature (ClassSignature pkg cls)
| null pkg = text cls
| otherwise = brackets (text pkg) <> text cls
ppClassSignature _ = empty
|