aboutsummaryrefslogblamecommitdiff
path: root/ABC/Assembler.icl
blob: 9cf29611395eeadf4ec9f8f3403e7efa74fafde8 (plain) (tree)
1
2
3
4
5
6
7
8

                                   
                 


                  

                                                   
                                                                   
                                                           


                                                                           
                                                                        
                                                     
                                                                        

                                                                                 



                                                                         



                                                                                    



                                                                      




                                        








                                                            
                                     
                           
                           



                                                                 



                                                                             












                                                 






















                                                                      

                                                                             
                                       
                                                     












                                                                            
                                                              
                                                              
                                                              
































































                                                                                   
                                                 


                                                 
                                                 
                                                 
                                                 
                                                 
implementation module ABC.Assembler

import StdEnv
import StdGeneric

import ABC.Machine
import ABC.Misc

instance toString Assembler
where
	toString []                            = ""
	toString [stm=:(Label l):r]            = stm <+ "\r\n" <+ r
	toString [stm=:(Descriptor _ _ _ _):r] = toString r
	toString [stm                      :r] = "\t" <+ stm <+ "\r\n" <+ r

instance <<< Assembler
where
	<<< f [                           ] = f
	<<< f [stm=:(Label _)           :r] = f <<< stm <<< "\r\n" <<< r
	<<< f [stm=:(Descriptor _ _ _ _):r] = f <<< r
	<<< f [stm=:(Annotation _)      :r] = f <<< stm <<< "\r\n" <<< r
	<<< f [stm=:(Raw _)             :r] = f <<< stm <<< "\r\n" <<< r
	<<< f [stm                      :r] = f <<< "\t" <<< stm <<< "\r\n" <<< r

instance <<< Statement where <<< f st = f <<< toString st

generic gPrint a :: !a -> [Char]
gPrint{|Int|}          x          = fromString (toString x)
gPrint{|Bool|}         x          = map toLower (fromString (toString x))
gPrint{|String|}       x          = fromString x
gPrint{|Annotation|}   x          = fromString (printAnnot x)
where
	printAnnot :: Annotation -> String
	printAnnot (DAnnot a bs) = ".d " <+ a <+ " " <+ length bs <+ " " <+ types bs
	printAnnot (OAnnot a bs) = ".o " <+ a <+ " " <+ length bs <+ " " <+ types bs
	printAnnot (RawAnnot s)  = foldl (+++) "." (intersperse " " s)
	where
		intersperse g []     = []
		intersperse g [x]    = [x]
		intersperse g [x:xs] = [x:g:intersperse g xs]

	types :: ([BasicType] -> [Char])
	types = map toC
	where
		toC BT_Bool = 'b'
		toC BT_Int  = 'i'
gPrint{|UNIT|}         x          = []
gPrint{|EITHER|} fl fr (LEFT x)   = fl x
gPrint{|EITHER|} fl fr (RIGHT x)  = fr x
gPrint{|PAIR|}   fl fr (PAIR x y) = fl x ++ ['\t':fr y]
gPrint{|OBJECT|} fx    (OBJECT x) = fx x
gPrint{|CONS of d|} fx (CONS x)   = case d.gcd_name of
	"Label"      = fx x
	"Descriptor" = []
	"Dump"       = ['dump\t"']  ++ quote (fx x) ++ ['"']
	"Print"      = ['print\t"'] ++ quote (fx x) ++ ['"']
	"Comment"    = ['| '] ++ fx x
	"Annotation" = fx x
	"Raw"        = fx x
	name         = tl (cons (fromString name)) ++ ['\t':fx x]
where
	cons :: ![Char] -> [Char]
	cons [] = []
	cons [c:cs]
	| isUpper c
		| isMember c ['IB'] && isEmpty cs   = [c]
		| isMember c ['IB'] && hd cs == '_' = [c            :cons cs]
		| otherwise                         = ['_':toLower c:cons cs]
	| otherwise                             = [c            :cons cs]

derive gPrint Statement

instance toString Statement
where
	toString stm = toString (gPrint{|*|} stm)

quote :: ![Char] -> [Char]
quote []        = []
quote ['\\':cs] = ['\\':'\\':quote cs]
quote ['\n':cs] = ['\\':'n' :quote cs]
quote ['"' :cs] = ['\\':'"' :quote cs]
quote [c   :cs] = [c        :quote cs]

assemble :: Assembler -> ([Instruction], [Desc])
assemble stms = (translate stms loc_counter syms, descTable stms syms)
where
	loc_counter  = 0
	desc_counter = 0
	syms         = collect stms loc_counter desc_counter

:: SymType  =   LabSym | DescSym

instance == SymType
where
	(==) LabSym  LabSym  = True
	(==) DescSym DescSym = True
	(==) _       _       = False

instance toString SymType
where
	toString LabSym  = "label"
	toString DescSym = "descriptor"

:: SymTable :== [(Name, Int, SymType)]

collect :: Assembler Int Int -> SymTable
collect []                       _  _  = []
collect [Label l            :r] lc dc = [(l,lc,LabSym)  :collect r lc dc]
collect [Descriptor dl _ _ _:r] lc dc = [(dl,dc,DescSym):collect r lc (dc+1)]
collect [_                  :r] lc dc = collect r (lc+1) dc

lookup :: Label SymType SymTable -> Int
lookup l t [] = abortn (l <+ " not defined as " <+ t)
lookup l t [(name,n,type):r]
| l == name && t == type = n
| otherwise              = lookup l t r

descTable :: Assembler SymTable -> [Desc]
descTable []                      _    = []
descTable [Descriptor dl e a n:r] syms = [Desc ap_addr a n:descTable r syms]
where ap_addr = lookup e LabSym syms
descTable [_                  :r] syms = descTable r syms

translate :: Assembler Int SymTable -> [Instruction]
translate []                     _  _    = []
translate [Label _           :r] lc syms = translate r lc syms
translate [Descriptor _ _ _ _:r] lc syms = translate r lc syms
translate [Comment _         :r] lc syms = translate r lc syms
translate [Annotation _      :r] lc syms = translate r lc syms
translate [Raw _             :r] lc syms = translate r lc syms
translate [stm               :r] lc syms
	= [trans stm lc syms:translate r (lc+1) syms]
where
	trans :: Statement Int SymTable -> Instruction
	trans (Br n)               lc _    = jmp            (lc+n+1)
	trans (BrFalse n)          lc _    = jmp_false      (lc+n+1)
	trans (BrTrue n)           lc _    = jmp_true       (lc+n+1)
	trans (Dump s)             _  _    = dump           s
	trans (AddArgs s n d)      _  _    = add_args       s n d
	trans Create               _  _    = create
	trans (DelArgs s n d)      _  _    = del_args       s n d
	trans (EqDesc dl s)        _  syms = eq_desc        daddr s
		where daddr = (lookup dl DescSym syms)
	trans (EqDescArity dl a s) _  syms = eq_desc_arity  daddr a s
		where daddr = (lookup dl DescSym syms)
	trans EqB                  _  _    = eqB
	trans (EqB_a b s)          _  _    = eqB_a b s
	trans (EqB_b b s)          _  _    = eqB_b b s
	trans EqI                  _  _    = eqI
	trans (EqI_a i s)          _  _    = eqI_a i s
	trans (EqI_b i s)          _  _    = eqI_b i s
	trans (Fill l n e d)       _  syms = fill daddr     n eaddr d
		where (daddr,eaddr) = (lookup l DescSym syms, lookup e LabSym syms)
	trans (Fill_a s d)         _  _    = fill_a s d
	trans (FillB b d)          _  _    = fillB b d
	trans (FillB_b s d)        _  _    = fillB_b s d
	trans (FillI i d)          _  _    = fillI i d
	trans (FillI_b s d)        _  _    = fillI_b s d
	trans (GetDescArity s)     _  _    = get_desc_arity s
	trans (GetNodeArity s)     _  _    = get_node_arity s
	trans Halt                 _  _    = halt
	trans (Jmp l)              _  syms = jmp            addr
		where addr = lookup l LabSym syms
	trans JmpEval              _  _    = jmp_eval
	trans (JmpFalse l)         _  syms = jmp_false      addr
		where addr = lookup l LabSym syms
	trans (JmpTrue l)          _  syms = jmp_true       addr
		where addr = lookup l LabSym syms
	trans (Jsr l)              _  syms = jsr            addr
		where addr = lookup l LabSym syms
	trans JsrEval              _  _    = jsr_eval
	trans NoOp                 _  _    = no_op
	trans (Pop_a n)            _  _    = pop_a          n
	trans (Pop_b n)            _  _    = pop_b          n
	trans (Print s)            _  _    = print          s
	trans (PrintSymbol s)      _  _    = print_symbol   s
	trans (Push_a s)           _  _    = push_a         s
	trans (PushAPEntry s)      _  _    = push_ap_entry  s
	trans (PushArg s a n)      _  _    = push_arg       s a n
	trans (PushArg_b s)        _  _    = push_arg_b     s
	trans (PushArgs s a n)     _  _    = push_args      s a n
	trans (PushArgs_b s)       _  _    = push_args_b    s
	trans (Push_b i)           _  _    = push_b         i
	trans (PushB b)            _  _    = pushB          b
	trans (PushB_a s)          _  _    = pushB_a        s
	trans (PushI i)            _  _    = pushI          i
	trans (PushI_a s)          _  _    = pushI_a        s
	trans (ReplArgs a n)       _  _    = repl_args      a n
	trans ReplArgs_b           _  _    = repl_args_b
	trans Rtn                  _  _    = rtn
	trans (SetEntry l d)       _  syms = set_entry      addr d
		where addr = lookup l LabSym syms
	trans (Update_a s d)       _  _    = update_a       s d
	trans (Update_b s d)       _  _    = update_b       s d
	trans AddI                 _  _    = addI
	trans DecI                 _  _    = decI
	trans DivI                 _  _    = divI
	trans GtI                  _  _    = gtI
	trans IncI                 _  _    = incI
	trans LtI                  _  _    = ltI
	trans MulI                 _  _    = mulI
	trans NegI                 _  _    = negI
	trans RemI                 _  _    = remI
	trans SubI                 _  _    = subI
	trans NotB                 _  _    = notB