summaryrefslogtreecommitdiff
path: root/AST.hs
blob: cd7fed23302288a642ea0ae5125b0fb3a52c8ceb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
module AST where

import Data.List
import Data.Word


type Byte = Word8
type Offset = Int


newtype Program = Program [Instruction]
  deriving (Show, Eq)

data Instruction
    = IAdd Byte Offset
    | ISet Byte Offset
    | ICopy Offset Offset Byte  -- ICopy from to multiplier
    | ISlide Offset
    | ILoop [Instruction] Offset
    | IInput Offset
    | IOutput Offset
    | IStart
  deriving (Show, Eq)

isIAdd :: Instruction -> Bool
isIAdd (IAdd _ _) = True
isIAdd _ = False

isISet :: Instruction -> Bool
isISet (ISet _ _) = True
isISet _ = False

isICopy :: Instruction -> Bool
isICopy (ICopy _ _ _) = True
isICopy _ = False

isISlide :: Instruction -> Bool
isISlide (ISlide _) = True
isISlide _ = False

isIStart :: Instruction -> Bool
isIStart IStart = True
isIStart _ = False

offsetOf :: Instruction -> Offset
offsetOf (IAdd _ o) = o
offsetOf (ISet _ o) = o
offsetOf (ICopy o _ _) = o
offsetOf (ISlide _) = undefined
offsetOf (ILoop _ _) = undefined
offsetOf (IInput o) = o
offsetOf (IOutput o) = o
offsetOf IStart = 0

astSuccinct :: Program -> String
astSuccinct (Program inss) = intercalate " " $ map insSuccinct inss
  where
    insSuccinct :: Instruction -> String
    insSuccinct (IAdd v o) =
        let sv = signedByte v
        in (if sv >= 0 then "+" else "") ++ show (signedByte v) ++ ',' : show o
    insSuccinct (ISet v o) = '=' : show (signedByte v) ++ ',' : show o
    insSuccinct (ICopy from to v) = 'C' : show from ++ ',' : show to ++ ',' : show v
    insSuccinct (ISlide o) = '>' : show o
    insSuccinct (ILoop inss' off) = "[(" ++ show off ++ ')' : intercalate " " (map insSuccinct inss') ++ "]"
    insSuccinct (IInput o) = ',' : show o
    insSuccinct (IOutput o) = '.' : show o
    insSuccinct IStart = "$"

    signedByte :: Byte -> Int
    signedByte v
        | v < 128 = fromIntegral v
        | otherwise = fromIntegral v - 256