-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdatatypes.sml
486 lines (438 loc) · 18 KB
/
datatypes.sml
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
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
structure DataTypes =
struct
datatype AST = PROG of BLK
and BLK = BLK of (DEC list) * (CMD list)
and DEC = VDEC of ( Type * (string list) ) | PDEC of PDEF list
and PDEF = PDEF of Type2 * string * BLK
and Type = Int | Bool | Rational
and Type2 = procedure
and CMD = SET of string * Exp | Call of string | Read of string | Print of Exp | ITE of Exp * ( CMD list ) * ( CMD list ) | WH of Exp * ( CMD list )
and Exp = REXP of REXP | IEXP of IEXP | BEXP of BEXP | EXP of Exp | EQEXP of Exp * Exp | NEQEX of Exp * Exp
and REXP = NEGR of REXP
| INVERSE of REXP
| ADDRAT of REXP * REXP
| SUBRAT of REXP * REXP
| MULRAT of REXP * REXP
| DIVRAT of REXP * REXP
| MAKERAT of IEXP * IEXP
| RAT of IEXP
| SHOWRAT of REXP
| SHOWDECIMAL of REXP
| FROMDECIMAL of REXP
| TODECIMAL of REXP
| RNUM of string
| IDR of string
| EQR of REXP * REXP
| NEQR of REXP * REXP
| GTR of REXP * REXP
| GTER of REXP * REXP
| LTR of REXP * REXP
| LTER of REXP * REXP
and IEXP = NEG of IEXP
| ADD of IEXP * IEXP
| SUB of IEXP * IEXP
| MUL of IEXP * IEXP
| DIV of IEXP * IEXP
| MOD of IEXP * IEXP
| EQ of IEXP * IEXP
| NEQ of IEXP * IEXP
| GT of IEXP * IEXP
| GTE of IEXP * IEXP
| LT of IEXP * IEXP
| LTE of IEXP * IEXP
| ID of string
| POSNUM of string
and BEXP = NOT of BEXP
| AND of BEXP * BEXP
| OR of BEXP * BEXP
| EQB of BEXP * BEXP
| NEQB of BEXP * BEXP
| TTT of string
| FFF of string
| IDB of string
fun strip(x:string)=
let
val stripper= String.concat (String.tokens (fn c => c = #"\n") x);
in
stripper
end
fun length nil = 0 | length (x::xs) = 1 + (length xs); (*Function to calculate
the length of a given list*)
datatype dict = Dict of (string * (Type * string)) list
exception NotFoundTheElement
exception Redeclaration
exception TypeMisMatch
fun copyDict (Dict lst) =
let
fun copyPair (key, (t, value)) = (key, (t, value))
in
Dict (List.map copyPair lst)
end
fun bogus()=132
fun error()= raise Redeclaration
fun error2()= raise TypeMisMatch
fun printDictList (dictList: dict ref list ref) =
let
fun printDict (dict: dict ref) =
let
val Dict lst = !dict
fun printPair (key, (typ, value)) =
print (key ^ " : " ^ " : " ^ value ^ "\n")
in
List.app printPair lst
end
in
List.app printDict (!dictList)
end
fun printDict2 (dict: dict ref) =
let
val Dict lst = !dict
fun printPair (key, (typ, value)) =
print (key ^ " : " ^ " : " ^ value ^ "\n")
in
List.app printPair lst
end
fun find_id (Dict lst, id) =
case List.find (fn (x, _) => x = id) lst of
SOME (_, value) => value
| NONE =>let val _ = print(id) in
raise NotFoundTheElement end
fun update_id (Dict lst, name, intboolrat , value) =
let
val updatedList = List.map (fn (x, (t, v)) => if x = name andalso t = intboolrat then (x, (t, value)) else (x, (t, v))) lst
in
Dict updatedList
end;
fun exist_id (Dict lst, id) =
case List.find (fn (x, _) => x = id) lst of
SOME (_, value) => 1
| NONE => 0
fun add_id (Dict lst, id ,t: Type, str: string) =
if List.exists (fn (x, _) => x = id) lst then
update_id(Dict lst,id,t,str)
else
Dict ((id, (t, str))::lst)
fun get_value (Dict lst, name)=
let
val (t, str) = find_id (Dict lst, name);
in
str
end;
fun get_type (Dict lst, name)=
let
val (ty, str) = find_id (Dict lst, name);
in
ty
end;
fun get_proceed ( lst,name)=
case List.find (fn (x, _) => x = name) lst of
SOME (_, value) => value
| NONE => raise NotFoundTheElement
val stack = ref ( [ ref (Dict [])] );
val globaldict =hd(!stack);
val procedlist = ref ( [] : (string * BLK) list);
val output = ref( [] : string list);
fun addvars(ty: Type ,ids: string list)=
if length(ids)=0 then 1
else
if exist_id(!globaldict,hd(ids))=1 then
let
val new_dict = update_id(!globaldict,hd(ids),ty,"NULL")
in
globaldict := new_dict;
addvars(ty,tl(ids))
end
else
let
val new_dict = add_id(!globaldict,hd(ids),ty,"NULL")
in
globaldict := new_dict;
addvars(ty,tl(ids))
end
fun procedupdate(x : PDEF list)=
if length(x)=0 then 1
else
let
val curr_proced=hd(x);
val PDEF(a,b,c)=hd(x);
in
procedlist := [(b,c)] @ !procedlist;
procedupdate(tl(x))
end
fun dechandle(x: DEC list)=
if length(x)=0 then 1
else
let
val decl = hd(x)
in
case decl of
PDEC(pdefs)=>
let
in
1
end
|VDEC(ty,ids)=>
let
val new_dict = addvars(ty,ids)
in
dechandle(tl(x))
end
end
fun y(xi: bool)=
if xi then "true" else "false"
fun y2(xi: bool)=
if xi then "false" else "true"
fun ynot(xi: string)=
if xi="true" then "false" else "true"
fun yand(xi: string, xi2: string)=
if xi="true" andalso xi2="true" then "true" else "false"
fun yor(xi: string , xi2: string)=
if xi="true" orelse xi2="true" then "true" else "false"
fun yeq(x1: string,x2: string)=
if x1="true" andalso x2="true" then "true"
else if x1="false" andalso x2="false" then "true"
else "false"
fun intex(x)=
let
open BigInt
in
case x of
NEG(ex)=> BigInt.toString(BigInt.neg(valOf(BigInt.fromString(intex(ex)))))
|ADD(ex1,ex2)=> BigInt.toString(BigInt.add(valOf(BigInt.fromString(intex(ex1))),valOf(BigInt.fromString(intex(ex2)))))
|SUB(ex1,ex2)=> BigInt.toString(BigInt.sub(valOf(BigInt.fromString(intex(ex1))),valOf(BigInt.fromString(intex(ex2)))))
|MUL(ex1,ex2)=> BigInt.toString(BigInt.mul(valOf(BigInt.fromString(intex(ex1))),valOf(BigInt.fromString(intex(ex2)))))
|DIV(ex1,ex2)=> BigInt.toString(BigInt.divb(valOf(BigInt.fromString(intex(ex1))),valOf(BigInt.fromString(intex(ex2)))))
|MOD(ex1,ex2)=> BigInt.toString(BigInt.modb(valOf(BigInt.fromString(intex(ex1))),valOf(BigInt.fromString(intex(ex2)))))
|EQ(ex1,ex2) => y(BigInt.eq(valOf(BigInt.fromString(intex(ex1))),valOf(BigInt.fromString(intex(ex2)))))
|NEQ(ex1,ex2)=> y2((BigInt.eq(valOf(BigInt.fromString(intex(ex1))),valOf(BigInt.fromString(intex(ex2))))))
|LT(ex1,ex2)=> y(BigInt.lt(valOf(BigInt.fromString(intex(ex1))),valOf(BigInt.fromString(intex(ex2)))))
|LTE(ex1,ex2)=> y(BigInt.le(valOf(BigInt.fromString(intex(ex1))),valOf(BigInt.fromString(intex(ex2)))))
|GT(ex1,ex2)=> y(BigInt.gt(valOf(BigInt.fromString(intex(ex1))),valOf(BigInt.fromString(intex(ex2)))))
|GTE(ex1,ex2)=> y(BigInt.ge(valOf(BigInt.fromString(intex(ex1))),valOf(BigInt.fromString(intex(ex2)))))
|ID(idix)=> get_value(!globaldict,idix)
|POSNUM(num)=> num
end
fun booo(ex)=
let
in
case ex of
NOT(ex1)=> ynot(booo(ex1))
|AND(ex1,ex2)=> yand(booo(ex1),booo(ex2))
|OR(ex1,ex2)=> yand(booo(ex1),booo(ex2))
|EQB(ex1,ex2)=> yeq(booo(ex1),booo(ex2))
|NEQB(ex1,ex2)=> ynot(yeq(booo(ex1),booo(ex2)))
|IDB(idix)=>get_value(!globaldict,idix)
|TTT(_)=>"true"
|FFF(_)=>"false"
end
fun ratatouille(ex)=
let
open Rational;
open BigInt;
in
case ex of
NEGR(ex)=> Rational.toDecimal(Rational.neg(Rational.fromDecimal(ratatouille(ex))))
|INVERSE(ex)=> Rational.toDecimal(valOf(Rational.inverse(Rational.fromDecimal(ratatouille(ex)))))
|ADDRAT(ex1,ex2)=>Rational.toDecimal(Rational.add(Rational.fromDecimal(ratatouille(ex1)),Rational.fromDecimal(ratatouille(ex2))))
|SUBRAT(ex1,ex2)=>Rational.toDecimal(Rational.subtract(Rational.fromDecimal(ratatouille(ex1)),Rational.fromDecimal(ratatouille(ex2))))
|MULRAT(ex1,ex2)=>Rational.toDecimal(Rational.multiply(Rational.fromDecimal(ratatouille(ex1)),Rational.fromDecimal(ratatouille(ex2))))
|DIVRAT(ex1,ex2)=>Rational.toDecimal(valOf(Rational.divide(Rational.fromDecimal(ratatouille(ex1)),Rational.fromDecimal(ratatouille(ex2)))))
|MAKERAT(ex1,ex2)=>Rational.toDecimal(valOf(Rational.make_rat(valOf(BigInt.fromString(intex(ex1))),valOf(BigInt.fromString(intex(ex2))))))
|RAT(ex)=>Rational.toDecimal(valOf(Rational.rat(valOf(BigInt.fromString(intex(ex))))))
|SHOWRAT(ex)=>"1"
|SHOWDECIMAL(ex)=>"1"
|FROMDECIMAL(ex)=>"1"
|TODECIMAL(ex)=>"1"
|RNUM(xyz)=>xyz
|IDR(idix)=>get_value(!globaldict,idix)
|EQR(ex1,ex2)=>y(Rational.equal(Rational.fromDecimal(ratatouille(ex1)),Rational.fromDecimal(ratatouille(ex2))))
|NEQR(ex1,ex2)=>y2(Rational.equal(Rational.fromDecimal(ratatouille(ex1)),Rational.fromDecimal(ratatouille(ex2))))
|LTR(ex1,ex2)=>y(Rational.less(Rational.fromDecimal(ratatouille(ex1)),Rational.fromDecimal(ratatouille(ex2))))
|LTER(ex1,ex2)=>y(Rational.less(Rational.fromDecimal(ratatouille(ex1)),Rational.fromDecimal(ratatouille(ex2))) orelse Rational.equal(Rational.fromDecimal(ratatouille(ex1)),Rational.fromDecimal(ratatouille(ex2))))
|GTR(ex1,ex2)=>y2(Rational.less(Rational.fromDecimal(ratatouille(ex1)),Rational.fromDecimal(ratatouille(ex2))) orelse Rational.equal(Rational.fromDecimal(ratatouille(ex1)),Rational.fromDecimal(ratatouille(ex2))))
|GTER(ex1,ex2)=>y2(Rational.less(Rational.fromDecimal(ratatouille(ex1)),Rational.fromDecimal(ratatouille(ex2))))
end
fun evalexpression(b)=
let
open BigInt
in
case b of
EXP(ex)=> let
val value = evalexpression(ex)
in value
end
| IEXP(ex)=>
let
val value = intex(ex)
in value
end
| BEXP(ex)=>
let
val value = booo(ex)
in value
end
| REXP(ex)=>
let
val value = ratatouille(ex)
in value
end
| EQEXP(ex1,ex2)=>
let
open Rational;
val value = evalexpression(ex1);
val value2 = evalexpression(ex2);
in
if value = "true" andalso value2 = "true" then "true"
else if value = "false" andalso value2 = "false" then "true"
else if value = "true" andalso value2 = "false" then "false"
else if value = "false" andalso value2 = "true" then "false"
else y(Rational.equal(Rational.fromDecimal(value),Rational.fromDecimal(value2)))
end
| NEQEX(ex1,ex2)=>
let
open Rational;
val value = evalexpression(ex1);
val value2 = evalexpression(ex2);
in
if value = "true" andalso value2 = "true" then "false"
else if value = "false" andalso value2 = "false" then "false"
else if value = "true" andalso value2 = "true" then "true"
else if value = "false" andalso value2 = "true" then "true"
else y2(Rational.equal(Rational.fromDecimal(value),Rational.fromDecimal(value2)))
end
end
fun copyListPoly xs =
let
fun copyElem x = x
in
List.map copyElem xs
end
fun setvar(a,b)=
let
val value = evalexpression(b)
val new_dict = update_id(!globaldict,a,get_type(!globaldict,a),value)
in
globaldict := new_dict;
1
end
fun cmdhandle(x: CMD list)=
if length(x)=0 then 1
else
let
val cmd1 = hd(x);
fun ifthenelse(a,b,c)=
let
val value = evalexpression(a)
in
if value = "true" then cmdhandle(b)
else cmdhandle(c)
end
in
case cmd1 of
Call(a)=>
let
val blk = get_proceed(!procedlist,a);
val BLK(dec,cmd) = get_proceed(!procedlist,a);
(* val newglob = ref ( copyDict (!globaldict) ); *)
(* val new_stack = (newglob :: !stack ); *)
(* val _ = (stack := new_stack ); *)
(* val _ = (globaldict := !(hd( ! stack)) ); *)
val _ = dechandle(dec);
val _ = cmdhandle(cmd);
(* val _ = (stack := tl(!stack)); *)
(* val _ = (globaldict := !(hd( ! stack)) ); *)
in
cmdhandle(tl(x))
(* end *)
end
|SET(a,b)=>
let
val _ = setvar(a,b)
in
cmdhandle(tl(x))
end
|Read(a)=>
let
val _ = print(a^" : ")
val putin = TextIO.inputLine TextIO.stdIn;
val lenin = strip(valOf(putin))
val new_dict = update_id(!globaldict,a,get_type(!globaldict,a),lenin)
in
globaldict := new_dict;
cmdhandle(tl(x))
end
|Print(a)=>
let
val value = evalexpression(a)
val _ = (output := !output @ [value])
(* val _ = print(value^"\n") *)
in
cmdhandle(tl(x))
end
|ITE(a,b,c)=>
let
val _ = ifthenelse(a,b,c)
in
cmdhandle(tl(x))
end
|WH(a,b)=>
let
val value = evalexpression(a)
val _ = ifthenelse(a,b,[])
in
if value="true" then cmdhandle(x)
else cmdhandle(tl(x))
end
end
fun legoblocks(x : BLK)=
let
val BLK (dec,cmd) = x;
val _ = dechandle(dec);
val _ = cmdhandle(cmd);
in
1
end;
fun extract_nested(x : PDEF list)=
if length(x)=0 then 1
else
let
val PDEF(ty,st,blk)= hd(x)
val _ = extract_procs(blk)
in
extract_nested(tl(x))
end
and extract_procs (BLK (decs, cmds)) =
if List.length(decs)=0 then 0
else
let
val decl = hd(decs)
in
case decl of
PDEC(x) =>
let
val _ = (procedupdate(x))
val _ = extract_nested(x)
in
1
end
| _ => extract_procs(BLK(tl(decs),cmds))
end
fun proceeds(x : AST)=
let
val PROG block = x;
val _ = extract_procs(block);
in
1
end;
fun letsgo(x : AST)=
let
val PROG block = x;
val _ = proceeds(x);
val _ = legoblocks (block);
val result = output;
in
(* stack *)
(* () *)
result
end;
end;