-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtrans-old.hs
151 lines (136 loc) · 5.7 KB
/
trans-old.hs
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
data Stmt = Conti | Break
| Exp String
| Goto Integer -- only support number label
| Label Integer -- only support number label
| If String [Stmt] [Stmt] -- If condition true-statements false-statements
| While String [Stmt] -- While condition statements
| Do [Stmt] String -- Do statements condition
| For String String String [Stmt] -- For initial condition increase statements
| Switch String [(String, [Stmt])] [Stmt] -- Switch expression [(constant, statements)] default-statements
deriving (Show)
-- simplified statement
data SStmt = SExp String
| SLabel Integer
| SGoto Integer
| SIf String SStmt -- If condition true-statement
deriving (Show)
trans :: [Stmt] -> Integer -> ([SStmt], Integer)
trans (Exp s : rt) e
= (SExp s : rt', e') where (rt', e') = trans rt e
trans (Goto s : rt) e
= (SGoto s : rt', e') where (rt', e') = trans rt e
trans (Label s : rt) e
= (SLabel s : rt', e') where (rt', e') = trans rt e
-- optimizations for if
-- one expression in true-statement, no expression in false-statement
trans (If cond [Exp s] [] : rt) e
= (SIf cond (SExp s) : rt', e') where (rt', e') = trans rt e
trans (If cond [Goto g] [] : rt) e
= (SIf cond (SGoto g) : rt', e') where (rt', e') = trans rt e
-- no true-statement or false-statement
trans (If cond [] [] : rt) e
= trans rt e
-- only false-statement
trans (If cond [] fs : rt) e
= (SIf cond (SGoto e) : fs' ++ SLabel e : rt', e1)
where
(fs', e0) = trans fs (e + 1)
(rt', e1) = trans rt e0
-- only true-statement
trans (If cond ts [] : rt) e
= trans (If ("!(" ++ cond ++ ")") [] ts : rt) e
-- general if statement
trans (If cond ts fs : rt) e
= (SIf cond (SGoto e) : fs'
++ SGoto (e + 1) : SLabel e : ts'
++ SLabel (e + 1) : rt', e2)
where
(fs', e0) = trans fs (e + 2)
(ts', e1) = trans ts e0
(rt', e2) = trans rt e1
trans (While cond [] : rt) e
= trans rt e
trans (While cond sts : rt) e
= (SLabel e : sts' ++ SLabel (e + 1) : rt', e1)
where
neosts = replace sts e (e + 1)
(sts', e0) = trans [If cond (neosts ++ [Goto e]) []] (e + 2)
(rt', e1) = trans rt e0
trans (Do [] cond : rt) e
= trans rt e
trans (Do sts cond : rt) e
= (SLabel e : sts' ++ SIf cond (SGoto e) : SLabel (e + 1) : rt', e1)
where
neosts = replace sts e (e + 1)
(sts', e0) = trans neosts (e + 2)
(rt', e1) = trans rt e0
trans (For init cond inc sts : rt) e
= (SExp init : SLabel e : sts' ++ SLabel (e + 2) : rt', e1)
where
neosts = replace sts (e + 1) (e + 2) ++ [Label (e + 1), Exp inc, Goto e]
(sts', e0) = trans [If cond neosts []] (e + 3)
(rt', e1) = trans rt e0
trans (Switch exp [] deft : rt) e
= trans (deft ++ rt) e
trans (Switch exp [(const, code)] deft : rt) e
= trans (If (exp ++ " == " ++ const) code deft : rt) e
trans (Switch exp ((const, code) : xs) deft : rt) e
= trans (If (exp ++ " == " ++ const) code [(Switch exp xs deft)] : rt) e
-- trans (Conti : rt) e = let (rt', e') = trans rt e in (SExp "continue" : rt', e')
-- trans (Break : rt) e = let (rt', e') = trans rt e in (SExp "break" : rt', e')
trans [] e = ([], e)
-- replace continue or break, don't replace for loop statements
replace :: [Stmt] -> Integer -> Integer -> [Stmt]
replace (Conti : rt) ct bk = Goto ct : replace rt ct bk
replace (Exp "continue" : rt) ct bk = replace (Conti : rt) ct bk
replace (Break : rt) ct bk = Goto bk : replace rt ct bk
replace (Exp "break" : rt) ct bk = replace (Break : rt) ct bk
replace (If cond ts fs : rt) ct bk = If cond (replace ts ct bk) (replace fs ct bk) : replace rt ct bk
-- replace (Switch exp [] deft : rt) ct bk = Switch exp [] (replace deft ct bk) : replace rt ct bk
-- replace (Switch exp ((const, code) : xs) deft : rt) ct bk
-- = Switch exp ((const, (replace code ct bk)) : xs') deft' : rt'
-- where
-- (Switch _ xs' deft') : rt' = replace (Switch exp xs deft : rt) ct bk
replace [] _ _ = []
-- skip other kinds of statements
replace (s : ss) ct bk = s : replace ss ct bk
-- print sstmts
printElements :: [SStmt] -> IO ()
printElements (SExp x : xs) = putStrLn (x ++ ";") >> printElements xs
printElements (SLabel x : xs) = putStrLn ("L" ++ show x ++ ":;") >> printElements xs
printElements (SGoto x : xs) = putStrLn ("goto L" ++ show x ++ ";") >> printElements xs
printElements (SIf cond st : xs) = putStr ("if (" ++ cond ++ ") ") >> printElements (st : xs)
printElements [] = return ()
-- use: ts s0
ts :: [Stmt] -> IO ()
ts s = let (ss, _) = trans s 0 in printElements ss
-- examples
s0 = [Exp "int i = 0", Exp "++i", Exp "printf(\"%d\\n\", i)"]
s1 = [Exp "int i = 0",
If "i == 0" [Exp "printf(\"%d\\n\", j + 1)"] []]
s2 = [Exp "int i = 0",
While "i < 100"
[Exp "printf(\"%d\\n\", i)",
If "i == 66" [Break] [],
Exp "++i"]]
s3 = [Exp "int i = 0", Do [Exp "++i", If "i % 2 == 0" [Conti] [], Exp "printf(\"%d\\n\", i)"] "i < 100"]
s4 = [Exp "int i = 0",
Switch "i"
[("0", [Exp "printf(\"%d = 0\\n\", i)"]),
("1", [Exp "printf(\"%d = 1\\n\", i)"]),
("2", [Exp "printf(\"%d = 2\\n\", i)"])]
[Exp "printf(\"other\\n\")"]]
s4' = [Exp "int i = 0",
Switch "i"
[("0", [Break]),
("1", [Conti])]
[Break]]
-- perfect numbers 1 - 10000
s5 = [Exp "int i = 1",
While "i <= 10000"
[Exp "int acc = 0",
(For "int j = 1" "j < i" "++j"
[If "i % j == 0" [Exp "acc += j"] []]),
(If "i == acc" [Exp "printf(\"%d\\n\", i)"] []),
(Exp "++i")]]
s6 = [If "j % 2 == 0" [If "j % 3 == 0" [Exp "printf(\"%d\\n\", j)", Exp "print j + 1"] []] [], Exp "int i = 0"]