implementation module mTaskInterpret //import iTasks import gdynamic, gCons, GenEq, StdMisc, StdArray, GenBimap import GenPrint import StdEnum import mTask import StdFile import StdString from StdFunc import o, const import StdBool import StdTuple import Data.Tuple import Data.Monoid import Data.Functor import StdList from Data.Func import $ from Text import class Text(concat,join,toUpperCase), instance Text String import qualified Data.Map as DM import Text.Encodings.Base64 encode :: MTaskMSGSend -> String encode (MTSds i v) = "s" +++ to16bit i +++ v +++ "\n" encode (MTTask to data) = "t" +++ to16bit to +++ to16bit (size data) +++ data +++ "\n" encode (MTUpd i v) = "u" +++ to16bit i +++ v +++ "\n" decode :: String -> MTaskMSGRecv decode x | size x == 0 = MTEmpty = case x.[0] of '\0' = MTEmpty 'm' = MTMessage x 'u' = MTPub (from16bit (x % (1,3))) (x % (3,5)) _ = abort ("Didn't understand message: " +++ join " " [toString (toInt c)\\c<-: x] +++ "\n") safePrint :== toString o toJSON instance toString MTaskMSGSend where toString (MTSds i v) = "Sds id: " +++ toString i +++ " value " +++ safePrint v toString (MTTask to data) = "Task timeout: " +++ toString to +++ " data " +++ safePrint data toString (MTUpd i v) = "Update id: " +++ toString i +++ " value " +++ safePrint v instance toString MTaskMSGRecv where toString (MTPub i v) = "Publish id: " +++ toString i +++ " value " +++ safePrint v toString MTEmpty = "Empty message" bclength :: BC -> Int bclength (BCPush _) = 3 bclength (BCLab _) = 2 bclength (BCSdsStore _) = 2 bclength (BCSdsFetch _) = 2 bclength (BCSdsPublish _) = 2 bclength (BCAnalogRead _) = 2 bclength (BCAnalogWrite _) = 2 bclength (BCDigitalRead _) = 2 bclength (BCDigitalWrite _) = 2 bclength (BCJmp i) = 2 bclength (BCJmpT i) = 2 bclength (BCJmpF i) = 2 bclength _ = 1 toByteVal :: BC -> [Char] toByteVal b # bt = toChar $ consIndex{|*|} b + 1 = [bt:case b of (BCPush i) = i (BCLab i) = [toChar i] (BCSdsStore i) = [toChar i] (BCSdsFetch i) = [toChar i] (BCSdsPublish i) = [toChar i] (BCAnalogRead i) = [toChar i] (BCAnalogWrite i) = [toChar i] (BCDigitalRead i) = [toChar i] (BCDigitalWrite i) = [toChar i] (BCJmp i) = [toChar i] (BCJmpT i) = [toChar i] (BCJmpF i) = [toChar i] _ = []] instance Semigroup (ByteCode a p) where mappend m n = BC \s->let (b1, (b2, t)) = runBC m <$> runBC m s in (b1 ++ b2, t) instance Monoid (ByteCode a p) where mempty = retrn [] (<++>) infixl 2 :: (ByteCode a p) (ByteCode b q) -> ByteCode c r (<++>) m n = BC \s->let (b1, (b2, t)) = runBC n <$> runBC m s in (b1 ++ b2, t) (<+->) infixr 1 (<+->) m n :== m <++> retrn n runBC (BC m) = m retrn :: ([BC] -> ByteCode a p) retrn = BC o tuple fmp :: ([BC] -> [BC]) (ByteCode a p) -> ByteCode a q fmp f b = BC \s->let (bc, s`) = runBC b s in (f bc, s`) instance toByteCode Bool where toByteCode True = [toChar 1] toByteCode False = [toChar 0] instance toByteCode Int where toByteCode n = map toChar [n/256,n rem 256] instance toByteCode Long where toByteCode (L n) = toByteCode n instance toByteCode Char where toByteCode c = [c] instance toByteCode String where toByteCode s = undef instance toByteCode Button where toByteCode s = [toChar $ consIndex{|*|} s] instance toChar Pin where toChar (Digital p) = toChar $ consIndex{|*|} p + 1 toChar (Analog p) = toChar $ consIndex{|*|} p + 1 derive gPrint BC, AnalogPin, Pin, DigitalPin derive consIndex BC, Pin, Button derive consName BC, Pin, Button instance arith ByteCode where lit x = retrn [BCPush $ toByteCode x] (+.) x y = x <++> y <+-> [BCAdd] (-.) x y = x <++> y <+-> [BCSub] (*.) x y = x <++> y <+-> [BCMul] (/.) x y = x <++> y <+-> [BCDiv] instance boolExpr ByteCode where (&.) x y = x <++> y <+-> [BCAnd] (|.) x y = x <++> y <+-> [BCOr] Not x = x <+-> [BCNot] (==.) x y = x <++> y <+-> [BCEq] (!=.) x y = x <++> y <+-> [BCNeq] (<.) x y = x <++> y <+-> [ BCLes] (>.) x y = x <++> y <+-> [BCGre] (<=.) x y = x <++> y <+-> [BCLeq] (>=.) x y = x <++> y <+-> [BCGeq] instance analogIO ByteCode where analogRead p = retrn [BCAnalogRead $ pin p] analogWrite p b = b <+-> [BCAnalogWrite $ pin p] instance digitalIO ByteCode where digitalRead p = retrn [BCDigitalRead $ pin p] digitalWrite p b = b <+-> [BCDigitalWrite $ pin p] //instance If ByteCode Stmt Stmt Stmt where If b t e = BCIfStmt b t e //instance If ByteCode e Stmt Stmt where If b t e = BCIfStmt b t e //instance If ByteCode Stmt e Stmt where If b t e = BCIfStmt b t e instance If ByteCode x y Stmt where If b t e = BCIfStmt b t e instance IF ByteCode where IF b t e = BCIfStmt b t e (?) b t = BCIfStmt b t $ retrn [] BCIfStmt b t e = withLabel \else->withLabel \endif-> b <++> retrn [BCJmpF else] <++> t <++> retrn [BCJmp endif,BCLab else] <++> e <++> retrn [BCLab endif] instance noOp ByteCode where noOp = mempty withLabel :: (Int -> (ByteCode b q)) -> ByteCode b q withLabel f = BC \s->let [fresh:fs] = s.freshl in runBC (f fresh) {s & freshl=fs} withSDS :: (Int -> (ByteCode b q)) -> ByteCode b q withSDS f = BC \s->let [fresh:fs] = s.freshs in runBC (f fresh) {s & freshs=fs} setSDS :: Int v -> ByteCode b q | toByteCode v setSDS ident val = BC \s->([], {s & sdss = [(ident, toByteCode val):s.sdss]}) instance sds ByteCode where sds f = {main = withSDS \sds-> let (v In body) = f $ retrn [BCSdsFetch sds] in setSDS sds v <++> unMain body } con f = undef pub x = fmp makePub x // pub _ = undef instance assign ByteCode where (=.) v e = e <++> fmp makeStore v makePub [] = [] makePub [x:xs] = case x of BCSdsFetch i = [BCSdsPublish i:xs] y = [y:xs] makeStore [] = [] makeStore [x:xs] = case x of BCSdsFetch i = [BCSdsStore i:xs] y = [y:xs] instance seq ByteCode where (>>=.) _ _ = abort "undef on >>=." (:.) x y = x <++> y instance serial ByteCode where serialAvailable = retrn [BCSerialAvail] serialPrint s = retrn [BCSerialPrint] serialPrintln s = retrn [BCSerialPrintln] serialRead = retrn [BCSerialRead] serialParseInt = retrn [BCSerialParseInt] instance zero BCState where zero = {freshl=[1..], freshs=[1..], sdss=[]} toRealByteCode :: (ByteCode a b) -> (String, BCState) toRealByteCode x # (bc, st) = runBC x zero # (bc, gtmap) = computeGotos bc 1 = (concat $ map (toString o toByteVal) (map (implGotos gtmap) bc), st) implGotos map (BCJmp t) = BCJmp $ fromJust ('DM'.get t map) implGotos map (BCJmpT t) = BCJmpT $ fromJust ('DM'.get t map) implGotos map (BCJmpF t) = BCJmpF $ fromJust ('DM'.get t map) implGotos _ i = i computeGotos :: [BC] Int -> ([BC], 'DM'.Map Int Int) computeGotos [] _ = ([], 'DM'.newMap) computeGotos [BCLab l:xs] i = appSnd ('DM'.put l i) (computeGotos xs i) computeGotos [x:xs] i = appFst (\bc->[x:bc]) (computeGotos xs (i+(bclength x))) readable :: BC -> String readable (BCPush d) = "BCPush " +++ concat (map safe d) where safe c | isControl c = "\\d" +++ toString (toInt c) = toString c readable b = printToString b toReadableByteCode :: (ByteCode a b) -> (String, BCState) toReadableByteCode x # (bc, st) = runBC x zero # (bc, gtmap) = computeGotos bc 0 = (join "\n" $ map readable (map (implGotos gtmap) bc), st) //Start :: String //Start = toReadableByteCode bc // where // bc :: ByteCode Int Expr // bc = (lit 36 +. lit 42) +. lit 44 toMessages :: Int (String, BCState) -> ([MTaskMSGSend], BCState) toMessages interval (bytes, st=:{sdss}) = ([MTSds i (toString b)\\(i,b)<-sdss] ++ [MTTask interval bytes], st) toSDSUpdate :: Int Int -> [MTaskMSGSend] toSDSUpdate i v = [MTUpd i (to16bit v)] Start = toMessages 500 $ toRealByteCode (unMain bc) //Start = fst $ toReadableByteCode $ unMain bc where bc = sds \x=5 In sds \y=4 In {main = If (y ==. lit 0) (pub x) (x =. x *. y :. y =. y -. lit 1)} //pub :: (ByteCode a b) -> ByteCode a b //pub x = fmp makePub x to16bit :: Int -> String to16bit i = toString (toChar (i/256)) +++ toString (toChar (i rem 256)) from16bit :: String -> Int from16bit s = toInt s.[0] * 256 + toInt s.[1]