forked from eugenkiss/loopgotowhile
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest
312 lines (240 loc) · 7.98 KB
/
test
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
x2 := 5;
x2 := x2 + 1;
LOOP x2 DO
x0 := x0 + 1
END // -> 6
//---------------------------------------------------
// t(0) = 0, t(1) = 1, t(2) = 0, t(3) = 0, t(4) = 1, t(10) = 1, t(4) = 20,
LOOP x1 DO
x5 := x5 + 1;
x6 := 0; x4 := 0;
LOOP x5 DO
x4 := x4 + 1;
x3 := 0; x2 := 0;
LOOP x4 DO
x2 := x2 + 1;
x3 := x3 + x2
END; // x3 = d(x4 )
x6 := x6 + x3
END; // x6 = t(x5 )
IF x6 = x1 THEN x0 := 1 END
END
-----------------------------------------------------
WHILE a o b DO
P
END
=>
IF a o b THEN
c := 1
ELSE
c := 0
END;
WHILE c != 0 DO
P;
IF a o b THEN
c := 1
ELSE
c := 0
END
END
Where c is a previously unused variable that represents a "boolean value".
-------------------
Function definition
-------------------
Does anything speak against nested function definitions? -> No, but outer
function is not inside the scope of the inner function. Thus, one cannot really
implement recursive functions. However, what I call n-recursive functions is
possible :):
FUN fac DO
FUN fac DO
FUN fac DO
x0 := x1;
END;
x0 := x1 * fac(x-1)
END;
x0 := x1 * fac(x-1)
END
Sensible output is only defined for the parameter 3.
FUN sqrt DO
LOOP x1 DO
c := c + 1;
t := c * c;
IF t = x1 THEN x0 := c END
END
END
All the variables in a function definition are local. No way to access global.
So the x1 in sqrt is another x1 than the one outside. Function definition is
a statement so can come anywhere where a statement can come in the code.
function definitions are saved in a separate environment. If two functions with
the same name are declared, the latter overwrites the definition of the former
for the following code. This way I can include and implicit prelude but the
user can overwrite e.g. sqrt with his own definition if he wants to.
Actually, functions are rather macros than "real functions".
The following is an example useage
x2 := sqrt(4) + 1
becomes (after "macro-expansion") -->
x5 := 4;
LOOP x5 DO
c := c + 1;
t := c * c;
IF t = x5 THEN x2 := c END
END;
x2 := x2 + 1
where x5, c and t are unused variables.
----------------------------------------------------
How to reuse code / data types? (Open data types?)
--------------------------------------------------
- Show languages and show how they are to be interpreted and transformed into Haskell structures.
- Explain that the code examples are rather pseudocode where a lot of definitions are omitted to only show the core idea / problem
### Solution 1
Make a big language that incorporates handling of LOOPs, WHILEs etc. and
for each particular language only parse the allowed constructs. E.g.
data BigStat
= Assign VarIdent AExp
| If BExp BigStat
| IfElse BExp BigStat BigStat
| Loop VarIdent BigStat
| While BExp BigStat
| Seq [BigStat]
Loop does not parse WHILEs:
import BigLanguage (parseIfElseStat, parseIfStat, parseLoopStat, parseAssignStat)
type LoopStat = BigStat
parseStat :: Parser LoopStat
parseStat = choice
[ try parseIfElseStat
, parseIfStat
, parseLoopStat
, try parseAssignStat
]
While does not parse LOOPs:
import BigLanguage (parseIfElseStat, parseIfStat, parseWhileStat, parseAssignStat)
type WhileStat = BigStat
parseStat :: Parser WhileStat
parseStat = choice
[ try parseIfElseStat
, parseIfStat
, parseWhileStat
, try parseAssignStat
]
While this approach works I don't like it conceptually. A big monolithic
language is created and then reduced to fit the respective sublanguages whereas
I'd like to create a small core of shared language constructs and extend them
to fit the suplanguage. I find the latter approach more natural, more flexible
and conceptually more beautiful.
However, I don't see an easy solution in Haskell mostly since data types are
closed as opposed to e.g. classes in OO languages. If I used an OO language
I would have an idea how to design the code the second way simply because
I could extend the definitions of the core language. So here comes a failed
approach in Haskell:
### Failution 2
"Core" data type and constructors. These language constructs are shared by
the particular languages (not every data definition is shown).
data Stat
= Assign VarIdent AExp
| If BExp Stat
| IfElse BExp Stat Stat
| Seq [Stat]
parseIfStat :: Parser Stat
parseIfStat = do
reserved "IF"
cond <- parseRelExp
reserved "THEN"
thenpart <- parseStat
reserved "END"
return $ If cond thenpart
Now, Loop and While data types are (ill-)defined like this:
data LoopStat
= Loop VarIdent LoopStat
| CoreStat Stat
data WhileStat
= While BExp WhileStat
| CoreStat Stat
Obviously, this won't work, e.g.
LOOP x1 DO
x3 := 0;
LOOP x3 DO
x4 := 1
END
END
becomes
LoopStat (VarIdent x1) (CoreStat (Seq [Assign x3 (Const 0),
{- Here's the Problem: Loops cannot become a Stat -}
LoopStat x3 (Assign x4 (Const 1))])) -- This is impossible with the above definition of LoopStat!
Similarly, these definitions are ill-defined as well as LOOPs / WHILEs cannot
be nested:
data LoopStat
= Loop VarIdent CoreStat
| CoreStat CoreStat
data WhileStat
= While BExp CoreStat
| CoreStat CoreStat
But I think the general idea how I want to structure the code becomes clear
- even with these examples full of failure. So I had the idea to parameterize
everything which leads to:
### Solution 3
TODO Type classes, parametrization...
class Translatable a where
translate :: Stat -> a
translateForLoop :: Stat -> State [VarIdent] a
oder
-- not (necessarily) bijective
class Corephism a where
fromCore :: Stat -> a
toCore :: a -> Stat -- probably a partial function
data Stat
= Assign VarIdent AExp
| If BExp Stat
| IfElse BExp Stat Stat
| ForLoop VarIdent Stat
| Seq [Stat]
instance Corephism Stat where
fromCore = id
toCore = id
parseIfStat :: Corephism a => Parser a
parseIfStat = do
reserved "IF"
cond <- parseRelExp
reserved "THEN"
thenpart <- parseStat
reserved "END"
return $ fromCore $ If cond thenpart
{-...-}
--
import qualified CoreLanguage as C
data LoopStat
= Assign VarIdent AExp
| If BExp LoopStat
| IfElse BExp LoopStat LoopStat
| Loop VarIdent LoopStat
| Seq [LoopStat]
-- TODO: Would view patterns improve this code?
instance C.Corephism LoopStat where
fromCore (C.Assign ident aexp) = Assign ident aexp
fromCore (C.If bexp stat) = If bexp (fromCore stat)
fromCore (C.IfElse bexp stat1 stat2) = IfElse bexp (fromCore stat1) (fromCore stat2)
fromCore (C.ForLoop i stat) = Loop i (fromCore stat)
fromCore (C.Seq stats) = Seq $ map translate stats
parseLoopStat :: Parser LoopStat
parseLoopStat = do
reserved "LOOP"
ident <- parseVar
reserved "DO"
body <- parseStat
reserved "END"
return $ Loop ident body
parseStat :: Parser LoopStat
parseStat = choice
[ try parseIfElseStat
, parseIfStat
, parseLoopStat
, try parseAssignStat
]
--
the same for while
### Conclusion
Can you help me? Maybe some advanced things like type families can help me
(although I don't really looked into them yet)? I hope my problem became clear.
-------------------------------------------------------------------------------
class Core a where
toCore :: a -> CoreStat
fromCore :: CoreStat -> a