summaryrefslogtreecommitdiff
path: root/hs/AST.hs
blob: a809d6ebd69b82580c314f74f3b9eb4d06a85923 (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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
module AST where

import Data.List
import qualified GCStore as GCS (Id)


type Name = String

data Program = Program Block
  deriving (Show)

data Block = Block [Statement]
  deriving (Show)

data Statement
    = Declaration Name Expression
    | Assignment Name Expression
    | Condition Expression Block Block
    | Dive Name [Expression] Block
    | Expr Expression
  deriving (Show)

data Expression
    = EBin BinaryOp Expression Expression
    | EUn UnaryOp Expression
    | ELit Literal
  deriving (Show)

data Literal
    = LNum Double
    | LStr String
    | LVar Name
    | LBlock BlockType ArgList Block
    | LGCSId GCS.Id
    | LNil
  deriving (Show)

type ArgList = [Name]

data BlockType = BT0 | BT1 | BT2  -- the number of ?'s
  deriving (Show, Enum, Eq)

data BinaryOp
    = BOPlus | BOMinus | BOMul | BODiv | BOMod | BOPow
    | BOLess | BOGreater | BOEqual | BOLEq | BOGEq
    | BOBoolAnd | BOBoolOr
  deriving (Show, Eq)

data UnaryOp
    = UONeg | UONot
  deriving (Show, Eq)


class ASTPretty a where
    astPrettyI :: Int -> a -> String

    astPretty :: a -> String
    astPretty = astPrettyI 0


indent :: Int -> String
indent n = replicate (4*n) ' '

instance ASTPretty Program where
    astPrettyI i (Program (Block sts)) =
        let pr = map (astPrettyI i) sts
        in intercalate "\n" $ map (uncurry (++)) $ zip ("" : cycle [indent i]) pr

instance ASTPretty Block where
    astPrettyI _ (Block []) = "{}"
    astPrettyI i (Block sts) =
        let lns = map (('\n' : indent (i+1)) ++) $ map (astPrettyI (i+1)) sts
        in "{" ++ concat lns ++ "\n" ++ indent i ++ "}"

instance ASTPretty Statement where
    astPrettyI i (Declaration n e) = n ++ " := " ++ astPrettyI i e ++ ";"
    astPrettyI i (Assignment n e) = n ++ " = " ++ astPrettyI i e ++ ";"
    astPrettyI i (Condition c b1 b2) =
        "if " ++ astPrettyI i c ++ " " ++ astPrettyI i b1 ++ " else " ++ astPrettyI i b2
    astPrettyI i (Dive n [] b) = n ++ " " ++ astPrettyI i b
    astPrettyI i (Dive n al b) =
        n ++ "(" ++ intercalate ", " (map (astPrettyI i) al) ++ ") " ++ astPrettyI i b
    astPrettyI i (Expr e) = astPrettyI i e ++ ";"

instance ASTPretty Expression where
    astPrettyI i (EBin bo e1 e2) =
        "(" ++ astPrettyI i e1 ++ ") " ++ astPrettyI i bo ++ " (" ++ astPrettyI i e2 ++ ")"
    astPrettyI i (EUn uo e) =
        astPrettyI i uo ++ "(" ++ astPrettyI i e ++ ")"
    astPrettyI i (ELit l) = astPrettyI i l

instance ASTPretty Literal where
    astPrettyI _ (LNum m) = show m
    astPrettyI _ (LStr s) = show s
    astPrettyI _ (LVar n) = n
    astPrettyI i (LBlock bt [] b) = replicate (fromEnum bt) '?' ++ astPrettyI i b
    astPrettyI i (LBlock bt al b) =
        replicate (fromEnum bt) '?' ++ "(" ++ intercalate ", " al ++ ")" ++ astPrettyI i b
    astPrettyI _ (LGCSId d) = "<[" ++ show d ++ "]>"
    astPrettyI _ LNil = "nil"

instance ASTPretty BinaryOp where
    astPrettyI _ bo = case bo of
        BOPlus -> "+"
        BOMinus -> "-"
        BOMul -> "*"
        BODiv -> "/"
        BOMod -> "%"
        BOPow -> "**"
        BOLess -> "<"
        BOGreater -> ">"
        BOEqual -> "=="
        BOLEq -> "<="
        BOGEq -> ">="
        BOBoolAnd -> "&&"
        BOBoolOr -> "||"

instance ASTPretty UnaryOp where
    astPrettyI _ uo = case uo of
        UONeg -> "-"
        UONot -> "!"