{-# LANGUAGE GADTs #-} module Language.Huckleberry.V10101 ( translate ,pre ,label ,ifThenElse ,ifThen ,forStepNext ,forNext ,a ,b ,c ,d ,e ,f ,g ,h ,i ,j ,k ,l ,m ,n ,o ,p ,q ,r ,s ,t ,u ,v ,w ,x ,y ,z ,arr ,let' ,(=:) ,print ,(++) ,led ,wait ,run ,list ,list' ,goto ,end ,btn ,new ,locate ,cls ,rnd ,save ,save' ,load ,load' ,files ,beep ,beep' ,play ,play' ,tempo ,(+) ,(-) ,(*) ,(/) ,(%) ,input ,tick ,clt ,inkey ,chr ,chr' ,asc ,scroll ,scr ,scr' ,vpeek ,vpeek' ,(==) ,(/=) ,(>=) ,(>) ,(<=) ,(<) ,(&&) ,(||) ,not ,clv ,clear ,clk ,abs ,gosub ,return ,sound ,free ,ver ,renum ,renum' ,lrun ,file ,sleep ,video ,peek ,poke ,clp ,help ,ana ,out ,out' ,in' ,in'' ,hex ,hex' ,bin ,bin' ,(.&.) ,(.|.) ,xor ,shiftR ,shiftL ,complement ,bps ,i2cr ,i2cw ,usr ) where import Prelude hiding (print,(++),(+),(-),(*),(/),(%),(==),(/=),(>=),(>),(<=),(<),(&&),(||),not,abs,return) import Data.Int(Int16) import Data.List(intercalate) import qualified Prelude as P import qualified Data.String as S import Control.Monad.Writer(Writer,execWriter,tell) import qualified IchigoJam as IJ data Expr r where Number :: (Num r) => r -> Expr r Str :: (S.IsString r) => r -> Expr r -- 優先して評価(カッコの代わり) Pre :: Expr Int16 -> Expr Int16 A :: Expr Int16 B :: Expr Int16 C :: Expr Int16 D :: Expr Int16 E :: Expr Int16 F :: Expr Int16 G :: Expr Int16 H :: Expr Int16 I :: Expr Int16 J :: Expr Int16 K :: Expr Int16 L :: Expr Int16 M :: Expr Int16 N :: Expr Int16 O :: Expr Int16 P :: Expr Int16 Q :: Expr Int16 R :: Expr Int16 S :: Expr Int16 T :: Expr Int16 U :: Expr Int16 V :: Expr Int16 W :: Expr Int16 X :: Expr Int16 Y :: Expr Int16 Z :: Expr Int16 Array :: Expr Int16 -> Expr Int16 Concat :: (Show a, Show b, S.IsString c) => Expr a -> Expr b -> Expr c -- -- Beginner's -- -- [TODO] 数:0(付属ボタン)/UP/DOWN/RIGHT/LEFT/SPACE、省略で0 Btn :: Expr Int16 -> Expr Int16 Rnd :: Expr Int16 -> Expr Int16 Add :: Expr Int16 -> Expr Int16 -> Expr Int16 Subtract :: Expr Int16 -> Expr Int16 -> Expr Int16 Multiply :: Expr Int16 -> Expr Int16 -> Expr Int16 Divide :: Expr Int16 -> Expr Int16 -> Expr Int16 Remind :: Expr Int16 -> Expr Int16 -> Expr Int16 Tick :: Expr Int16 Inkey :: Expr Int16 Chr :: [Expr Int16] -> Expr String Asc :: String -> Expr Int16 Scr :: Expr Int16 -> Expr Int16 -> Expr Int16 Scr' :: Expr Int16 -- 指定なしで現在位置 Equal :: Expr Int16 -> Expr Int16 -> Expr Int16 NotEqual :: Expr Int16 -> Expr Int16 -> Expr Int16 GreaterThanEqual :: Expr Int16 -> Expr Int16 -> Expr Int16 GreaterThan :: Expr Int16 -> Expr Int16 -> Expr Int16 LessThanEqual :: Expr Int16 -> Expr Int16 -> Expr Int16 LessThan :: Expr Int16 -> Expr Int16 -> Expr Int16 And :: Expr Int16 -> Expr Int16 -> Expr Int16 Or :: Expr Int16 -> Expr Int16 -> Expr Int16 Not :: Expr Int16 -> Expr Int16 -- -- Expert's -- Abs :: Expr Int16 -> Expr Int16 Sound :: Expr Int16 Free :: Expr Int16 Ver :: Expr Int16 File :: Expr Int16 Peek :: Expr Int16 -> Expr Int16 Ana :: Expr Int16 -> Expr Int16 In' :: Expr Int16 -> Expr Int16 In'' :: Expr Int16 -- 数を省略してまとめて入力できる Hex :: Expr Int16 -> Expr Int16 -> Expr String Hex' :: Expr Int16 -> Expr String -- 2番目の数は桁数、省略可 Bin :: Expr Int16 -> Expr Int16 -> Expr String Bin' :: Expr Int16 -> Expr String -- 2番目の数は桁数、省略可 BitAnd :: Expr Int16 -> Expr Int16 -> Expr Int16 BitOr :: Expr Int16 -> Expr Int16 -> Expr Int16 XOr :: Expr Int16 -> Expr Int16 -> Expr Int16 ShiftR :: Expr Int16 -> Expr Int16 -> Expr Int16 ShiftL :: Expr Int16 -> Expr Int16 -> Expr Int16 Complement :: Expr Int16 -> Expr Int16 I2CR :: Expr Int16 -> Expr Int16 -> Expr Int16 -> Expr Int16 -> Expr Int16 -> Expr Int16 I2CW :: Expr Int16 -> Expr Int16 -> Expr Int16 -> Expr Int16 -> Expr Int16 -> Expr Int16 USR :: Expr Int16 -> Expr Int16 -> Expr Int16 -- Num Literal instance (Num a) => Num (Expr a) where (+) (Number n1) (Number n2) = Number (n1 P.+ n2) (-) (Number n1) (Number n2) = Number (n1 P.- n2) (*) (Number n1) (Number n2) = Number (n1 P.* n2) negate (Number n) = Number (negate n) abs (Number n) = Number (P.abs n) signum (Number n) = Number (signum n) fromInteger n = Number (fromInteger n) -- OverloadedStrings instance (S.IsString a) => S.IsString (Expr a) where fromString s = Str (S.fromString s) data Stmt where Label :: Int16 -> [Stmt] -> Stmt -- IFは入れ子にできる IfThenElse :: Expr Int16 -> [Stmt] -> [Stmt] -> Stmt IfThen :: Expr Int16 -> [Stmt] -> Stmt ForStepNext :: Expr Int16 -> Expr Int16 -> Expr Int16 -> Expr Int16 -> [Stmt] -> Stmt ForNext :: Expr Int16 -> Expr Int16 -> Expr Int16 -> [Stmt] -> Stmt -- -- Beginner's -- Let' :: Expr Int16 -> [Expr Int16] -> Stmt Assign :: Expr Int16 -> Expr Int16 -> Stmt Print :: (Show r) => Expr r -> Stmt Led :: Expr Int16 -> Stmt Wait :: Expr Int16 -> Stmt Run :: Stmt List :: Expr Int16 -> Expr Int16 -> Stmt List' :: Stmt -- 行番号は共に省略可 Goto :: Expr Int16 -> Stmt End :: Stmt New :: Stmt Locate :: Expr Int16 -> Expr Int16 -> Stmt Cls :: Stmt Save :: Expr Int16 -> Stmt Save' :: Stmt -- 省略で前回使用した数 Load :: Expr Int16 -> Stmt Load' :: Stmt -- 省略で前回使用した数 Files :: Expr Int16 -> Stmt Beep :: Expr Int16 -> Expr Int16 -> Stmt Beep' :: Stmt -- 周期(1-255)と長さ(1/60秒単位)は省略可 Play :: String -> Stmt Play' :: Stmt -- MML省略で停止 Tempo :: Expr Int16 -> Stmt Input :: String -> Expr Int16 -> Stmt Clt :: Stmt Scroll :: Expr Int16 -> Stmt -- -- Expert's -- Clv :: Stmt Clk :: Stmt Gosub :: Expr Int16 -> Stmt Return :: Stmt Renum :: Expr Int16 -> Stmt Renum' :: Stmt -- 数省略で10 LRun :: Expr Int16 -> Stmt Sleep :: Stmt Video :: Expr Int16 -> Stmt Poke :: Expr Int16 -> Expr Int16 -> Stmt Clp :: Stmt Help :: Stmt Out :: Expr Int16 -> Expr Int16 -> Stmt Out' :: Expr Int16 -> Stmt -- 数2を省略でまとめて出力できる Bps :: Expr Int16 -> Stmt reify :: (Show r) => Expr r -> String reify (Number v) = show v reify (Str v) = show v reify (Pre v) = concat ["(", reify v, ")"] reify (A) = "A" reify (B) = "B" reify (C) = "C" reify (D) = "D" reify (E) = "E" reify (F) = "F" reify (G) = "G" reify (H) = "H" reify (I) = "I" reify (J) = "J" reify (K) = "K" reify (L) = "L" reify (M) = "M" reify (N) = "N" reify (O) = "O" reify (P) = "P" reify (Q) = "Q" reify (R) = "R" reify (S) = "S" reify (T) = "T" reify (U) = "U" reify (V) = "V" reify (W) = "W" reify (X) = "X" reify (Y) = "Y" reify (Z) = "Z" reify (Array i) = concat ["[", reify i, "]"] reify (Concat v1 v2) = concat [reify v1, ";", reify v2] reify (Btn v) = concat ["BTN(", reify v, ")"] reify (Rnd v) = concat ["RND(", reify v, ")"] reify (Add v1 v2) = concat [reify v1, "+", reify v2] reify (Subtract v1 v2) = concat [reify v1, "-", reify v2] reify (Multiply v1 v2) = concat [reify v1, "*", reify v2] reify (Divide v1 v2) = concat [reify v1, "/", reify v2] reify (Remind v1 v2) = concat [reify v1, "%", reify v2] reify (Tick) = "TICK()" reify (Inkey) = "INKEY()" reify (Chr v) = concat ["CHR$(",(intercalate "," (fmap reify v)), ")"] reify (Asc v) = concat ["ASC(\"", v, "\")"] reify (Scr') = concat ["SCR()"] reify (Scr v1 v2) = concat ["SCR(", reify v1, ",", reify v2, ")"] reify (Equal v1 v2) = concat [reify v1, "=", reify v2] reify (NotEqual v1 v2) = concat [reify v1, "!=", reify v2] reify (GreaterThanEqual v1 v2) = concat [reify v1, ">=", reify v2] reify (GreaterThan v1 v2) = concat [reify v1, ">", reify v2] reify (LessThanEqual v1 v2) = concat [reify v1, "<=", reify v2] reify (LessThan v1 v2) = concat [reify v1, "<", reify v2] reify (And v1 v2) = concat [reify v1, "AND", reify v2] reify (Or v1 v2) = concat [reify v1, "OR", reify v2] reify (Not v) = concat ["!", reify v] reify (Abs v) = concat ["ABS(", reify v, ")"] reify (Sound) = "SOUND()" reify (Free) = "FREE()" reify (Ver) = "VER()" reify (File) = "FILE()" reify (Peek v) = concat ["PEEK(", reify v, ")"] reify (Ana v) = concat ["ANA(", reify v, ")"] reify (In' v) = concat ["IN(", reify v, ")"] reify (In'') = concat ["IN()"] reify (Hex v1 v2) = concat ["HEX$(", reify v1, ",", reify v2, ")"] reify (Hex' v) = concat ["HEX$(", reify v, ")"] reify (Bin v1 v2) = concat ["BIN$(", reify v1, ",", reify v2, ")"] reify (Bin' v) = concat ["BIN$(", reify v, ")"] reify (BitAnd v1 v2) = concat [reify v1, "&", reify v2] reify (BitOr v1 v2) = concat [reify v1, "|", reify v2] reify (XOr v1 v2) = concat [reify v1, "^", reify v2] reify (ShiftR v1 v2) = concat [reify v1, ">>", reify v2] reify (ShiftL v1 v2) = concat [reify v1, "<<", reify v2] reify (Complement v) = concat ["~", reify v] reify (I2CR v1 v2 v3 v4 v5) = concat ["I2CR(", reify v1, ",", reify v2, ",", reify v3, ",", reify v4, ",", reify v5, ")"] reify (I2CW v1 v2 v3 v4 v5) = concat ["I2CW(", reify v1, ",", reify v2, ",", reify v3, ",", reify v4, ",", reify v5, ")"] reify (USR v1 v2) = concat ["USR(", reify v1, ",", reify v2, ")"] lToString :: [Stmt] -> String lToString st = intercalate ":" $ map toString st toString :: Stmt -> String toString (Label n st) = concat [(show n), " ", lToString st] toString (IfThenElse c st1 st2) = concat ["IF", reify c, lToString st1, "ELSE", lToString st2] toString (IfThen c st) = concat ["IF", reify c, lToString st] toString (ForStepNext v ini inc step st) = concat ["FOR", reify v, "=", reify ini, "TO", reify inc, "STEP", reify step, ":", lToString st, ":NEXT"] toString (ForNext v ini inc st) = concat ["FOR", reify v, "=", reify ini, "TO", reify inc, ":", lToString st, ":NEXT"] toString (Let' v1 v2) = concat ["LET", reify v1, ",", (intercalate "," (fmap reify v2))] toString (Assign v1 v2) = concat [reify v1, "=", reify v2] toString (Print v) = concat ["?", reify v] toString (Led v) = concat ["LED", reify v] toString (Wait v) = concat ["WAIT", reify v] toString (Run) = "RUN" toString (List v1 v2) = concat ["LIST", reify v1, ",", reify v2] toString (List') = "LIST" toString (Goto v) = concat ["GOTO", reify v] toString (End) = "END" toString (New) = "NEW" toString (Locate v1 v2) = concat ["LC", reify v1, ",", reify v2] toString (Cls) = "CLS" toString (Save v) = concat ["SAVE", reify v] toString (Save') = "SAVE" toString (Load v) = concat ["LOAD", reify v] toString (Load') = "LOAD" toString (Files v) = concat ["FILES", reify v] toString (Beep v1 v2) = concat ["BEEP", reify v1, ",", reify v2] toString (Beep') = "BEEP" toString (Play v) = concat ["PLAY\"", v, "\""] toString (Play') = "PLAY" toString (Tempo v) = concat ["TEMPO", reify v] toString (Input v1 v2) = concat ["INPUT\"", v1, "\",", reify v2] toString (Clt) = "CLT" toString (Scroll v) = concat ["SCROLL", reify v] toString (Clv) = "CLV" toString (Clk) = "CLK" toString (Gosub v) = concat ["GOSUB", reify v] toString (Return) = "RETURN" toString (Renum v) = concat ["RENUM", reify v] toString (Renum') = "RENUM" toString (LRun v) = concat ["LRUN", reify v] toString (Sleep) = "SLEEP" toString (Video v) = concat ["VIDEO", reify v] toString (Poke v1 v2) = concat ["POKE", reify v1, ",", reify v2] toString (Clp) = "CLP" toString (Help) = "HELP" toString (Out v1 v2) = concat ["OUT", reify v1, ",", reify v2] toString (Out' v) = concat ["OUT", reify v] toString (Bps v) = concat ["BPS", reify v] type Code = Writer [Stmt] translate :: Code() -> String translate c = (intercalate "\n" $ map toString (execWriter c)) P.++ "\n" pre = Pre label :: Int16 -> Code() -> Code() label l st = tell [Label l (execWriter st)] ifThenElse :: Expr Int16 -> Code() -> Code() -> Code() ifThenElse c st1 st2 = tell [IfThenElse c (execWriter st1) (execWriter st2)] ifThen :: Expr Int16 -> Code() -> Code() ifThen c st = tell [IfThen c (execWriter st)] forStepNext :: Expr Int16 -> Expr Int16 -> Expr Int16 -> Expr Int16 -> Code() -> Code() forStepNext v ini inc step st = tell [ForStepNext v ini inc step (execWriter st)] forNext :: Expr Int16 -> Expr Int16 -> Expr Int16 -> Code() -> Code() forNext v ini inc st = tell [ForNext v ini inc (execWriter st)] a = A b = B c = C d = D e = E f = F g = G h = H i = I j = J k = K l = L m = M n = N o = O p = P q = Q r = R s = S t = T u = U v = V w = W x = X y = Y z = Z arr = Array -- -- Beginner's -- let' :: Expr Int16 -> [Expr Int16] -> Code() let' v1 v2 = tell [Let' v1 v2] (=:) :: Expr Int16 -> Expr Int16 -> Code() (=:) v1 v2 = tell [Assign v1 v2] infix 2 =: print :: (Show r) => Expr r -> Code() print x = tell [Print x] (++) :: (Show a, Show b, S.IsString c) => Expr a -> Expr b -> Expr c (++) = Concat infixl 2 ++ led :: Expr Int16 -> Code() led s = tell [Led s] wait :: Expr Int16 -> Code() wait t = tell [Wait t] run :: Code() run = tell [Run] list :: Expr Int16 -> Expr Int16 -> Code() list v1 v2 = tell [List v1 v2] list' :: Code() list' = tell [List'] goto :: Expr Int16 -> Code() goto t = tell [Goto t] end :: Code() end = tell [End] btn = Btn new :: Code() new = tell [New] locate :: Expr Int16 -> Expr Int16 -> Code() locate v1 v2 = tell [Locate v1 v2] cls :: Code() cls = tell [Cls] rnd = Rnd save :: Expr Int16 -> Code() save v = tell [Save v] save' :: Code() save' = tell [Save'] load :: Expr Int16 -> Code() load v = tell [Load v] load' :: Code() load' = tell [Load'] files :: Expr Int16 -> Code() files v = tell [Files v] beep :: Expr Int16 -> Expr Int16 -> Code() beep v1 v2 = tell [Beep v1 v2] beep' :: Code() beep' = tell [Beep'] play :: String -> Code() play c = tell [Play c] play' :: Code() play' = tell [Play'] tempo :: Expr Int16 -> Code() tempo t = tell [Tempo t] (+) = Add infixl 6 + (-) = Subtract infixl 6 - (*) = Multiply infixl 7 * (/) = Divide infixl 7 / (%) = Remind infixl 7 % input :: String -> Expr Int16 -> Code() input s v = tell [Input s v] tick = Tick clt :: Code() clt = tell [Clt] inkey = Inkey chr :: Expr Int16 -> Expr String chr v = Chr [v] -- コンマ区切りで連続表記可 chr' :: [Expr Int16] -> Expr String chr' = Chr asc = Asc scroll :: Expr Int16 -> Code() scroll v = tell [Scroll v] scr = Scr scr' = Scr' vpeek = scr -- alias vpeek' = scr' -- alias (==) = Equal infix 5 == (/=) = NotEqual infix 5 /= (>=) = GreaterThanEqual infix 5 >= (>) = GreaterThan infix 5 > (<=) = LessThanEqual infix 5 <= (<) = LessThan infix 5 < (&&) = And infixr 4 && (||) = Or infixr 3 || not = Not -- -- Expert's -- clv :: Code() clv = tell [Clv] clear = clv -- alias clk :: Code() clk = tell [Clk] abs = Abs gosub :: Expr Int16 -> Code() gosub t = tell [Gosub t] return :: Code() return = tell [Return] sound = Sound free = Free ver = Ver renum :: Expr Int16 -> Code() renum v = tell [Renum v] renum' :: Code() renum' = tell [Renum'] lrun :: Expr Int16 -> Code() lrun v = tell [LRun v] file = File sleep :: Code() sleep = tell [Sleep] video :: Expr Int16 -> Code() video sw = tell [Video sw] peek = Peek poke :: Expr Int16 -> Expr Int16 -> Code() poke v1 v2 = tell [Poke v1 v2] clp :: Code() clp = tell [Clp] help :: Code() help = tell [Help] ana = Ana out :: Expr Int16 -> Expr Int16 -> Code() out v1 v2 = tell [Out v1 v2] out' :: Expr Int16 -> Code() out' v = tell [Out' v] in' = In' in'' = In'' hex = Hex hex' = Hex' bin = Bin bin' = Bin' (.&.) = BitAnd infixl 7 .&. (.|.) = BitOr infixl 6 .|. xor = XOr infixl 7 `xor` shiftR = ShiftR infixl 7 `shiftR` shiftL = ShiftL infixl 7 `shiftL` complement = Complement bps :: Expr Int16 -> Code() bps s = tell [Bps s] i2cr = I2CR i2cw = I2CW usr = USR