+decode :: String -> MTaskMSGRecv
+decode x
+| size x == 0 = MTEmpty
+= case x.[0] of
+ '\0' = MTEmpty
+ '\n' = 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