module GcodeLow (offsetSize ,shortNeedheap,shortNeedstack,shortPush,shortPop ,shortPushArg,shortZapArg,shortHeapCval,shortHeap ,gcodeSize,gcodeNeed,primNeed,primStack,gcodeStack ,gcodeDump,gcodeHeader ,lowInteger,extra ,wsize,con0,cap0,caf,fun,cfun,string,consttable,foreignfun ,profstatic,profmodule,tprofmodule,tprofmodulesub ,proftype,profproducer,profconstructor,align ,fixStr,showId ) where import Gcode import Util.Extra(strStr,splitIntegral,SplitIntegral(..)) import IntState(strIS,dummyIntState) import Prim(strPrim) import Machine import Char(isAlphaNum) extra = 4::Int -- make room for largest profile info align :: Int -> Int -> Int align a p = case p `mod` a of 0 -> 0 x -> a-x con0 = "C0_" cap0 = "F0_" caf = "CF_" fun = "FN_" cfun = "" string = "ST_" consttable = "CT_" foreignfun = "FR_" profstatic = "PS_" profmodule = "PM_" proftype = "PT_" profproducer = "PP_" profconstructor = "PC_" tprofmodule = "TM_" tprofmodulesub = "TMSUB_" groupW [] = [] groupW xs = case splitAt wsize xs of (w,xs) -> take wsize (w ++ repeat 0) : groupW xs fixW xs = foldr ( \ d a -> d+256*a ) 0 xs lowInteger i = case splitIntegral i of SplitNeg xs -> let xsW = groupW xs in DATA_CONW (length xsW) 1 : map (DATA_W . fixW) xsW SplitZero -> [DATA_CONW 0 0 ] SplitPos xs -> let xsW = groupW xs in DATA_CONW (length xsW) 0 : map (DATA_W . fixW) xsW offsetSize i = if i >=256 || i<= -256 then 2 else 1 shortNeedheap :: Int -> (Bool,String) shortNeedheap i = (i <= 32,"32") shortNeedstack :: Int -> (Bool,String) shortNeedstack i = (i <= 16,"16") shortPush :: Int -> (Bool,String) shortPush i = (i==1,"1") shortPop :: Int -> (Bool,String) shortPop i = (i==1,"1") shortPushArg :: Int -> (Bool,String) shortPushArg i = (1<= i && i <= 3, show i) shortZapArg :: Int -> (Bool,String) shortZapArg i = (1<= i && i <= 3, show i) shortHeapCval :: Int -> (Bool,String) shortHeapCval i = (i == -3 || (3<= i && i <= 5), if i == -3 then "N3" else show i) shortHeap :: Int -> (Bool,String) shortHeap i = (i==1 || i==2, show i) gcodeSize (NEEDHEAP i) = if fst(shortNeedheap i) then 1 else 1 + offsetSize i gcodeSize (NEEDSTACK i) = if fst(shortNeedstack i) then 1 else 1 + offsetSize i gcodeSize (LABEL i) = 0 gcodeSize (LOCAL s i) = 0 gcodeSize (GLOBAL s i) = 0 gcodeSize (JUMP i) = 3 gcodeSize (JUMPFALSE i) = 3 -- DAVID gcodeSize (PRIMITIVE) = 1 gcodeSize (PRIM prim) = 1 gcodeSize (NOP) = 1 gcodeSize (TABLESWITCH size pad ls) = 2 + pad + size * 2 -- DAVID gcodeSize (LOOKUPSWITCH size pad tls def) = 2 + pad + size * 4 + 2 -- DAVID gcodeSize (MKIORETURN) = 1 -- MW {------- DAVID ------------ gcodeSize (MATCHCON) = 1 gcodeSize (MATCHINT) = 1 gcodeSize (JUMPS_T) = 1 gcodeSize (JUMPTABLE l) = 2 gcodeSize (JUMPS_L) = 1 gcodeSize (JUMPLENGTH s l) = 4 gcodeSize (JUMPLIST v l) = 4 --------- DAVID ---------- -} gcodeSize (ZAP_STACK i) = 1 + offsetSize i gcodeSize (ZAP_ARG i) = if fst (shortZapArg i) then 1 else 2 -- Stack gcodeSize (PUSH_CADR i) = 1 + offsetSize i gcodeSize (PUSH_CVAL i) = 1 + offsetSize i gcodeSize (PUSH_INT i) = 1 + offsetSize i gcodeSize (PUSH_CHAR i) = 1 + offsetSize i gcodeSize (PUSH_ARG i) = if fst (shortPushArg i) then 1 else 2 gcodeSize (PUSH_ZAP_ARG i) = if fst (shortPushArg i) then 1 else 2 gcodeSize (PUSH i) = if fst (shortPush i) then 1 else 1 + offsetSize i gcodeSize (PUSH_HEAP) = 1 gcodeSize (POP i) = if fst (shortPop i) then 1 else 1 + offsetSize i gcodeSize (SLIDE i) = 1 + offsetSize i gcodeSize (UNPACK i) = 2 -- selector gcodeSize (SELECTOR_EVAL) = 1 gcodeSize (SELECT i) = 2 -- evaluation gcodeSize (APPLY i) = 2 gcodeSize (EVAL) = 1 gcodeSize (RETURN) = 1 gcodeSize (RETURN_EVAL) = 1 -- Heap gcodeSize (HEAP_CADR i) = 1 + offsetSize i gcodeSize (HEAP_CVAL i) = if fst (shortHeapCval i) then 1 else 1 + offsetSize i gcodeSize (HEAP_INT i) = 1 + offsetSize i gcodeSize (HEAP_CHAR i) = 1 + offsetSize i gcodeSize (HEAP_ARG i) = 2 gcodeSize (HEAP_ARG_ARG i j) = 3 gcodeSize (HEAP_ARG_ARG_RET_EVAL i j) = 3 gcodeSize (HEAP i) = if fst (shortHeap i) then 1 else 1 + offsetSize i gcodeSize (HEAP_OFF i) = 1 + offsetSize i gcodeSize (HEAP_CREATE) = 1 gcodeSize (HEAP_SPACE) = 1 gcodeSize (DATA_CREATE) = wsize gcodeSize (DATA_CAPITEM a b ) = 2 gcodeSize (DATA_CONSTHEADER a b) = wsize gcodeSize (DATA_W i) = wsize gcodeSize (DATA_F f) = if floatIsDouble then 8 else 4 gcodeSize (DATA_S s) = wsize gcodeSize (DATA_D d) = 8 gcodeSize (DATA_NOP) = 0 gcodeSize (DATA_CLABEL i) = wsize gcodeSize (DATA_FLABEL i) = wsize gcodeSize (DATA_GLB s i) = wsize gcodeSize (DATA_VAP i) = wsize gcodeSize (DATA_CAP i s) = wsize gcodeSize (DATA_CON s c) = wsize gcodeSize (DATA_CONW s e) = wsize gcodeSize (DATA_CONP s e) = wsize gcodeStack g = fst (gcodeNeed 0 g) gcodeNeed :: Int -> Gcode -> (Int,Int) gcodeNeed extra (PUSH_CADR i) = ( 1,0) gcodeNeed extra (PUSH_CVAL i) = ( 1,0) gcodeNeed extra (PUSH_INT i) = ( 1,0) gcodeNeed extra (PUSH_CHAR i) = ( 1,0) gcodeNeed extra (PUSH_ARG i) = ( 1,0) gcodeNeed extra (PUSH_ZAP_ARG i) = ( 1,0) -- gcodeNeed extra (PUSH i) = ( 1,0) gcodeNeed extra (PUSH_HEAP) = ( 1,0) gcodeNeed extra (POP i) = (-i,0) -- gcodeNeed extra (SLIDE i) = (-i,0) -- gcodeNeed extra (UNPACK i) = (i-1,0) -- gcodeNeed extra (SELECTOR_EVAL)= ( 1,0) -- gcodeNeed extra (RETURN) = (-1,0) -- gcodeNeed extra (RETURN_EVAL) = (-1,0) -- gcodeNeed extra (APPLY i) = (-i,10+i*(3+extra)) -- Not always correct (10 is a large application but they can be larger) gcodeNeed extra (HEAP_CADR i) = (0,1) gcodeNeed extra (HEAP_CVAL i) = (0,1) gcodeNeed extra (HEAP_INT i) = (0,1) gcodeNeed extra (HEAP_CHAR i) = (0,1) gcodeNeed extra (HEAP_ARG i) = (0,1) gcodeNeed extra (HEAP_ARG_ARG i j) = (0,2) gcodeNeed extra (HEAP_ARG_ARG_RET_EVAL i j) = (0,2) gcodeNeed extra (HEAP i) = (0,1) gcodeNeed extra (HEAP_OFF i) = (0,1) gcodeNeed extra (HEAP_CREATE) = (0,1) gcodeNeed extra (HEAP_SPACE) = (0,1) gcodeNeed extra (NEEDSTACK i) = (0,0) gcodeNeed extra (ALIGN ) = (0,0) gcodeNeed extra (ALIGN_CONST) = (0,0) gcodeNeed extra (DATA_CREATE) = (0,0) gcodeNeed extra (DATA_CAPITEM _ _)=(0,0) gcodeNeed extra (DATA_CONSTHEADER _ _) = (0,0) gcodeNeed extra (DATA_W _) = (0,0) gcodeNeed extra (DATA_S _) = (0,0) gcodeNeed extra (DATA_F _) = (0,0) gcodeNeed extra (DATA_D _) = (0,0) gcodeNeed extra (DATA_NOP) = (0,0) -- does not generate anything, used after DATA_D to keep 1 DATA/WORD gcodeNeed extra (DATA_CLABEL _) = (0,0) gcodeNeed extra (DATA_FLABEL _) = (0,0) gcodeNeed extra (DATA_GLB _ _) = (0,0) gcodeNeed extra (DATA_VAP _) = (0,0) gcodeNeed extra (DATA_CAP _ _) = (0,0) gcodeNeed extra (DATA_CON _ _) = (0,0) gcodeNeed extra (DATA_CONW _ _) = (0,0) gcodeNeed extra (DATA_CONP _ _) = (0,0) -- gcodeNeed extra MATCHCON = (0,0) -- DAVID -- gcodeNeed extra MATCHINT = (0,0) -- DAVID gcodeNeed extra (MKIORETURN) = (0,2) -- MW gcodeNeed extra g = error ("gcodeNeed " ++ strGcode dummyIntState g) primStack prim = fst (primNeed 0 prim) primNeed :: Int -> Prim -> (Int,Int) primNeed extra (ADD op) = (-1,opNeed extra op) primNeed extra (SUB op) = (-1,opNeed extra op) primNeed extra (MUL op) = (-1,opNeed extra op) primNeed extra (ABS op) = ( 0,opNeed extra op) primNeed extra (SIGNUM op) = ( 0,opNeed extra op) primNeed extra (EXP op) = ( 0,opNeed extra op) primNeed extra (POW op) = (-1,opNeed extra op) primNeed extra (LOG op) = ( 0,opNeed extra op) primNeed extra (SQRT op) = ( 0,opNeed extra op) primNeed extra (SIN op) = ( 0,opNeed extra op) primNeed extra (COS op) = ( 0,opNeed extra op) primNeed extra (TAN op) = ( 0,opNeed extra op) primNeed extra (ASIN op) = ( 0,opNeed extra op) primNeed extra (ACOS op) = ( 0,opNeed extra op) primNeed extra (ATAN op) = ( 0,opNeed extra op) primNeed extra (SLASH op) = (-1,opNeed extra op) primNeed extra (CMP_EQ op) = (-1,0) primNeed extra (CMP_NE op) = (-1,0) primNeed extra (CMP_LT op) = (-1,0) primNeed extra (CMP_LE op) = (-1,0) primNeed extra (CMP_GT op) = (-1,0) primNeed extra (CMP_GE op) = (-1,0) primNeed extra (NEG op) = ( 0,opNeed extra op) primNeed extra (QUOT) = (-1,2+extra) primNeed extra (REM) = (-1,2+extra) primNeed extra (AND) = (-1,0) primNeed extra (OR) = (-1,0) primNeed extra (NOT) = ( 0,0) primNeed extra (ORD) = ( 0,2+extra) primNeed extra (CHR) = ( 0,1+extra) primNeed extra (SEQ) = (-1,0) primNeed extra (STRING) = ( 0,3+2+3+3*extra) primNeed extra (HGETS) = ( 0,3+2+3+3*extra ) primNeed extra (HGETC) = ( 0, 2+extra ) primNeed extra (HPUTC) = ( -1, 2+extra ) opNeed :: Int -> PrimOp -> Int opNeed extra OpWord = 2+extra opNeed extra OpFloat = 2+extra opNeed extra OpDouble = 3+extra showId state i = fixStr (strIS state (toEnum i)) fixStr s | all isAlphaNum s = showString s | otherwise = fixStr' s fixStr' [] = id fixStr' (c:cs) | isAlphaNum c = showChar c . fixStr' cs | otherwise = showChar '_' . shows (fromEnum c) . fixStr' cs showJump j i = showString " DB " . showString j . showChar ',' . shows l . showChar ',' . shows h . showChar '\n' where (h,l) = divMod i 256 showOp op = showString " DB " . showString op . showChar '\n' showOp1 op i = showString " DB " . showString op . showChar ',' . shows i . showChar '\n' showOp2 op i j = showString " DB " . showString op . showChar ',' . shows i . showChar ',' . shows j . showChar '\n' showOp12 op i = if i < 0 then case (-i) `divMod` 256 of (0,l) -> showString " DB " . showString op . showString "_N1," . shows l . showChar '\n' (h,l) -> showString " DB " . showString op . showString "_N2," . shows l . showChar ',' . shows h . showChar '\n' else case i `divMod` 256 of (0,l) -> showString " DB " . showString op . showString "_P1," . shows l . showChar '\n' (h,l) -> showString " DB " . showString op . showString "_P2," . shows l . showChar ',' . shows h . showChar '\n' gcodeHeader = showString "#include \"codemacros.h\"\n\n STARTBYTECODE\n AL\n" shortQ pred defgen opstr arg = case pred arg of (True,argstr) -> showOp (opstr ++ "_I" ++ argstr) _ -> defgen opstr arg gcodeDump state (ALIGN) = showString " AL\n" -- gcodeDump state (ALIGN_CONST) = showString " AL_D\n" -- DAVID gcodeDump state (ALIGN_CONST) = showOp "ENDCODE" . showString " AL_D\n" --DAVID gcodeDump state (NEEDHEAP i) = shortQ shortNeedheap showOp12 "NEEDHEAP" i gcodeDump state (NEEDSTACK i) = shortQ shortNeedstack showOp12 "NEEDSTACK" i gcodeDump state (LABEL i) = showString "DL(" . showId state i . showString ")\n" gcodeDump state (LOCAL s i) = showString "DL(" . showString s . showId state i . showString ")\n" gcodeDump state (GLOBAL s i) = let l = showString s . showId state i in showString " EX L(" . l . showString ")\nDL(" . l . showString ")\n" gcodeDump state (JUMP i) = showJump "JUMP" i gcodeDump state (JUMPFALSE i) = showJump "JUMPFALSE" i -- DAVID gcodeDump state (PRIMITIVE) = showOp "PRIMITIVE" gcodeDump state (PRIM prim) = showOp (strPrim prim) gcodeDump state (NOP) = showOp "NOP" gcodeDump state (TABLESWITCH size pad ls) = -- DAVID showOp1 "TABLESWITCH" size . someNops pad . someLabels ls gcodeDump state (LOOKUPSWITCH size pad tls def) = -- DAVID showOp1 "LOOKUPSWITCH" size . someNops pad . someLabels (concatMap (\(f,s) -> [f,s]) tls ++ [def]) gcodeDump state (MKIORETURN) = showOp "MKIORETURN" -- MW {----------- DAVID --------------- gcodeDump state (MATCHCON) = showOp "MATCHCON" gcodeDump state (MATCHINT) = showOp "MATCHINT" gcodeDump state (JUMPS_T) = showOp "JUMPS_T" gcodeDump state (JUMPTABLE l) = showString " JT(" . shows l . showString ")\n" gcodeDump state (JUMPS_L) = showOp "JUMPS_L" gcodeDump state (JUMPLENGTH v l) = showString " JT(" . shows v . showString ")\n JT(" . shows l . showString ")\n" gcodeDump state (JUMPLIST v l) = showString " JT(" . shows v . showString ")\n JT(" . shows l . showString ")\n" ------------ DAVID ---------------- -} gcodeDump state (ZAP_ARG i) = shortQ shortZapArg showOp1 "ZAP_ARG" i gcodeDump state (ZAP_STACK i) = showOp12 "ZAP_STACK" i -- Stack gcodeDump state (PUSH_CADR i) = showOp12 "PUSH_CADR" i gcodeDump state (PUSH_CVAL i) = showOp12 "PUSH_CVAL" i gcodeDump state (PUSH_INT i) = showOp12 "PUSH_INT" i gcodeDump state (PUSH_CHAR i) = showOp12 "PUSH_CHAR" i gcodeDump state (PUSH_ARG i) = shortQ shortPushArg showOp1 "PUSH_ARG" i gcodeDump state (PUSH_ZAP_ARG i)= shortQ shortPushArg showOp1 "PUSH_ZAP_ARG" i gcodeDump state (PUSH i) = shortQ shortPush showOp12 "PUSH" i gcodeDump state (PUSH_HEAP) = showOp "PUSH_HEAP" gcodeDump state (POP i) = shortQ shortPop showOp12 "POP" i gcodeDump state (SLIDE i) = showOp12 "SLIDE" i gcodeDump state (UNPACK i) = showOp1 "UNPACK" i -- selector gcodeDump state (SELECTOR_EVAL) = showOp "SELECTOR_EVAL" gcodeDump state (SELECT i) = showOp1 "SELECT" i -- evaluation gcodeDump state (APPLY i) = showOp1 "APPLY" i gcodeDump state (EVAL) = showOp "EVAL" gcodeDump state (RETURN) = showOp "RETURN" gcodeDump state (RETURN_EVAL) = showOp "RETURN_EVAL" -- Heap gcodeDump state (HEAP_CADR i) = showOp12 "HEAP_CADR" i gcodeDump state (HEAP_CVAL i) = shortQ shortHeapCval showOp12 "HEAP_CVAL" i gcodeDump state (HEAP_INT i) = showOp12 "HEAP_INT" i gcodeDump state (HEAP_CHAR i) = showOp12 "HEAP_CHAR" i gcodeDump state (HEAP_ARG i) = showOp1 "HEAP_ARG" i gcodeDump state (HEAP_ARG_ARG i j) = showOp2 "HEAP_ARG_ARG" i j gcodeDump state (HEAP_ARG_ARG_RET_EVAL i j) = showOp2 "HEAP_ARG_ARG_RET_EVAL" i j gcodeDump state (HEAP i) = shortQ shortHeap showOp12 "HEAP" i gcodeDump state (HEAP_OFF i) = showOp12 "HEAP_OFF" i gcodeDump state (HEAP_CREATE) = showOp "HEAP_CREATE" gcodeDump state (HEAP_SPACE) = showOp "HEAP_SPACE" gcodeDump state (DATA_CREATE) = showString " DW 0\n" gcodeDump state (DATA_CAPITEM a b) = showString " DB " . shows b . showChar ',' . shows a . showChar '\n' gcodeDump state (DATA_CONSTHEADER a b) = showString " DW HW(" . shows a . showChar ',' . shows b . showString ")\n" gcodeDump state (DATA_W i) = showString " DW " . shows i . showChar '\n' gcodeDump state (DATA_F f) = if floatIsDouble then showString " DD(" . shows f . showString ")\n" else showString " DF(" . shows f . showString ")\n" gcodeDump state (DATA_S s) = chopString s where chopString "" = showString " DB 0\n AL\n" -- DAVID chopString x = case splitAt (40::Int) x of (x,xs) -> showString " DS " . showString (strStr x) . showString "\n" . chopString xs gcodeDump state (DATA_D d) = showString " DD(" . shows d . showString ")\n" gcodeDump state (DATA_NOP) = id gcodeDump state (DATA_CLABEL i) = showString " DW L(" . showCLabel state i . showString ")\n" gcodeDump state (DATA_FLABEL i) = showString " DW L(" . showString foreignfun . showId state i . showString ")\n" gcodeDump state (DATA_GLB s 0) = showString " DW L(" . showString s . showString ")\n" gcodeDump state (DATA_GLB s i) = showString " DW L(" . showString s . showId state i . showString ")\n" gcodeDump state (DATA_VAP i) = showString " DW VAPTAG(" . showString fun . showId state i . showString ")\n" gcodeDump state (DATA_CAP i s) = showString " DW CAPTAG(" . showString fun . showId state i . showChar ',' . shows s . showString ")\n" gcodeDump state (DATA_CON s c) = showString " DW CONSTR(" . shows c . showChar ',' . shows s . showChar ',' . showChar '0' . showString ")\n" gcodeDump state (DATA_CONW s e) = showString " DW CONSTRW(" . shows s . showChar ',' . shows e . showString ")\n" gcodeDump state (DATA_CONP s e) = showString " DW CONSTRP(" . shows s . showChar ',' . shows e . showString ")\n" someNops :: Int -> String -> String -- DAVID someNops pad = foldr (.) id (take pad (repeat (showOp "NOP"))) someLabels :: [ Int ] -> String -> String -- DAVID someLabels cls = foldr (.) id (map (\l -> showString " JT(" . shows l . showString ")\n") cls)