-
Notifications
You must be signed in to change notification settings - Fork 0
/
interpreter.bak
434 lines (363 loc) · 15.1 KB
/
interpreter.bak
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
; Jeff Eben
; Mammen Kurien
; Tristan Maidment
;hi
(load "functionParser.scm")
(load "state.scm")
(define interpreter
(lambda (l)
(clearVars)
(pushLayer) ; Initial layer
(display S) (newline)
(overallProgramWrapper (parser l) '())))
(define interpreterFxn
(lambda (l returnBreak)
(pushLayer)
(display S) (newline)
(call/cc
(lambda (returnBreak)
(overallProgramWrapper l returnBreak)))))
(define overallProgramWrapper
(lambda (l returnBreak)
(computeProgramContinuations l '() '() returnBreak '())
) ; will return value of return at this point
)
(define computeProgramContinuations
(lambda (l continue break returnBreak tryBreak)
(cond
((null? l) (void))
(else
(let ((computation (computeProgramLineContinuations (car l) continue break returnBreak tryBreak)))
(cond
((void? computation) (computeProgramContinuations (cdr l) continue break returnBreak tryBreak))
((global-scope?) computation)
;(else computation)))))))
(else (computeProgramContinuations (cdr l) continue break returnBreak tryBreak))))))))
(define computeProgramLineContinuations
(lambda (l continue break returnBreak tryBreak)
(cond
((eq? (car l) 'function) (saveFunction (cdr l) returnBreak))
((eq? (car l) 'funcall) (executeFunction (cdr l) returnBreak))
((eq? (car l) 'var) (executeVar (cdr l)))
((eq? (car l) '=) (executeEqual (cdr l)))
((eq? (car l) 'return) (executeReturn (cdr l) returnBreak)) ;only returnBreak needed, since a return breaks from whole function
((eq? (car l) 'if) (executeIf (cdr l) continue break returnBreak tryBreak)) ; Body could contain all possible call/cc vars
((eq? (car l) 'while) (executeWhile (cdr l) returnBreak tryBreak)) ; Body could contain all possible call/cc vars
((eq? (car l) 'begin) (computeProgramContinuations (cdr l) continue break returnBreak tryBreak))
((eq? (car l) 'continue)
(if (null? continue)
(error "You cannot continue when there is no loop")
(continue 'continueReturn))) ;Should return to program spot where continuation is formed if I did it correctly
((eq? (car l) 'break)
(if (null? break)
(error "You cannot break when there is no loop")
(break 'breakReturn)))
((eq? (car l) 'try) (executeTry (cdr l) continue break returnBreak tryBreak))
((eq? (car l) 'catch) (executeCatch (cdr l) continue break returnBreak tryBreak))
((eq? (car l) 'finally) (executeFinally (cdr l) continue break returnBreak tryBreak))
((eq? (car l) 'throw)
(if (eq? tryBreak '())
(error "You cannot throw an exception out of a try block")
((throw (cadr l))
(tryBreak 'tryReturn))))
(else
(if (eq? tryBreak '())
(error "You cannot throw an exception out of a try block")
(tryBreak 'tryReturn))) )))
;----------------------------------------------------------------------------------------
(define saveFunction
(lambda (l returnBreak)
(cond
((eq? (car l) 'main)
(defineFxn (car l) (cadr l) (caddr l) S)
(display S) (newline)
(interpreterFxn (caddr l) returnBreak))
(else (defineFxn (car l) (cadr l) (caddr l) S)
(display S) (newline)
)
)))
;defineFxn 'fxnName args body
;car = fxn name
;cadr = args
;caddr = fxn body
(define executeFunction
(lambda (l returnBreak)
(interpreterFxn (functionCreator (getFxn (car l) S) (cdr l)) returnBreak) ; input looks like (((args) (body)) (argValues))
))
;car = fxn name
;cdr = inputs
;Below is the format for getting the fxn
;(getFxn 'fxnName)
;returns
;(args body)
(define functionCreator
(lambda (fxnArgsBody fxnArgValues)
(let ((args (car fxnArgsBody)) (body (cadr fxnArgsBody))) ; abstract out args and body into individual lists
(functionCreatorHelper args body fxnArgValues)))) ; input looks like ((args) (body) (values))
;(define functionCreatorHelper
; (lambda (args body values)
; (list (list 'var (car args) (car values)) (car body)) ; executeOperator should be called on args (if args is something like (- a 1)) when ran by fxn
; )
; )
(define functionCreatorHelper
(lambda (args body values)
(append (append (cons (list 'var args values) '()) body) '((return))) ; appended return for case where there is no return
;(createList args values body)
)
)
;(define functionCreatorHelper2
; (lambda (arg body value)
; (cond
; ((eq? body '()) '())
;((eq? (car body) arg) (functionCreatorHelper2 arg (cons value (cdr body)) value))
;((atom? (car body))
; (cond
; ((eq? (car body) arg) (cons value (functionCreatorHelper2 arg (cdr body) value)))
;(else (functionCreatorHelper2 arg (cons (car body) (cdr body)) value)))))
; (else (cons (car body) (functionCreatorHelper2 arg (cdr body) value))))))))
;(else
(define executeVar
(lambda (l)
(if (not (atom? (car l))) (executeMultVars (car l) (executeComputeValues (cadr l))) ; If vars declared at beginning of fxn, calls executeMultVars
(if (null? (cdr l))
(addVar (car l) '() S)
(addVar (car l) (executeOperator (cadr l)) S)))
(display S) (newline)
))
(define executeMultVars
(lambda (vars values)
(cond
((and (null? vars) (null? values)) void)
((or (null? vars) (null? values)) (error "Wrong number of inputs" ))
((null? (car values))
(begin
(addVar (car vars) '() S)
(executeMultVars (cdr vars) (cdr values))))
(else
(begin
(addVar (car vars) (car values) S)
(executeMultVars (cdr vars) (cdr values)))))))
; Computes all values in value list to get rid of static State definition problem
(define executeComputeValues
(lambda (l)
(cond
((null? l) l)
(else (cons (executeOperator (car l)) (executeComputeValues (cdr l)))))))
(define executeEqual
(lambda (l)
(setVar (car l) (executeOperator (cadr l)) S)
(display S) (newline)
))
;atom? --> checks if atom
(define atom?
(lambda (x)
(and (not (pair? x)) (not (null? x)))))
;abstraction for ExecuteOperator and ExecuteReturn
(define element1 car)
(define second_element cadr )
(define rest_of_rest cddr )
(define third_element caddr )
; This helper function returns the value of some parse-tree arithmetic subexpression
; Could have numbers or variables that equal numbers
(define executeOperator
(lambda (l)
(cond
; If it's a straight up number
((number? l) l)
; If it's 'true'
((eq? l 'true) #t)
((eq? l 'false) #f)
; If it's a variable
; If none of the others, its a variable
((atom? l) (getVar l S))
; Number in a list (for fib)
;((number? (element1 l)) (element1 l)) ;----------------------23432942384238989234892348923489234898923489234892348923489
; Function call
((eq? (element1 l) 'funcall) (executeFunction (cdr l) '()))
; This allows working with AND's and OR's
((eq? (element1 l) '||) (or (executeOperator (second_element l)) (executeOperator (third_element l))))
((eq? (element1 l) '&&) (and (executeOperator (second_element l)) (executeOperator (third_element l))))
((eq? (element1 l) '!) (not (executeOperator (second_element l))))
; Allows working with inequalities
((eq? (element1 l) '>) (> (executeOperator (second_element l)) (executeOperator (third_element l))))
((eq? (element1 l) '>=) (>= (executeOperator (second_element l)) (executeOperator (third_element l))))
((eq? (element1 l) '<) (< (executeOperator (second_element l)) (executeOperator (third_element l))))
((eq? (element1 l) '<=) (<= (executeOperator (second_element l)) (executeOperator (third_element l))))
((eq? (element1 l) '==) (eq? (executeOperator (second_element l)) (executeOperator (third_element l))))
((eq? (element1 l) '!=) (not (eq? (executeOperator (second_element l)) (executeOperator (third_element l)))))
; If list isn't null, isn't conditional, and isn't and/or, it must start with operator (or variable)
((eq? (element1 l) '+) (+ (executeOperator (second_element l)) (executeOperator (third_element l))))
; Two cases: unary -, or subtraction
((eq? (element1 l) '-)
(if (null? (rest_of_rest l)) ;This case is when unary - is used
(- 0 (executeOperator (second_element l)))
(- (executeOperator (second_element l)) (executeOperator (third_element l))))) ; this is subtraction case
((eq? (element1 l) '*) (* (executeOperator (second_element l)) (executeOperator (third_element l))))
((eq? (element1 l) '/) (/ (executeOperator (second_element l)) (executeOperator (third_element l))))
((eq? (element1 l) '%) (modulo (executeOperator (second_element l)) (executeOperator (third_element l)))) )))
; Wrapper
(define executeReturn
(lambda (l returnBreak)
; Case when there is no return value in a fxn
(if (null? l) ((popLayer)
(returnBreak (void)))
(if (eq? (executeOperator (element1 l)) #t) ;covert #t to true
((popLayer)
(display S) (newline)
(returnBreak 'true))
(if (eq? (executeOperator (element1 l)) #f) ;convert #f to false
((popLayer)
(display S) (newline)
(returnBreak 'false))
((let ((result (executeOperator (element1 l))))
(popLayer)
(display S) (newline)
(returnBreak result))))))))
;Abstraction for ExecuteIf
(define element_1 car)
(define second_element cadr )
(define rest_of_rest cddr )
(define third_element caddr )
; {(conditional) (then-statement) (optional-else-statement)}
; If (car l) isn't equal to an operator, it must be one of the computeProgram cases
(define executeIf
(lambda (l continue break returnBreak tryBreak)
(cond
((eq? (executeOperator (element_1 l)) #t)
(pushLayer)
(display S) (newline)
(breakAbstraction (second_element l) continue break returnBreak tryBreak 'if))
((not (eq? (rest_of_rest l) '()))
(pushLayer)
(display S) (newline)
(breakAbstraction (third_element l) continue break returnBreak tryBreak 'if)))))
; Expression must either be some expression (executeOperator) or one of the 5 parse tree statements
(define executeIfThenStatement
(lambda (l continue break returnBreak tryBreak)
(computeProgramLineContinuations l continue break returnBreak tryBreak) ; used ComputeProgram in case it returns value.
))
; {(conditional) (body statement)}
; Create continuation before doing the whileThen, so that way if break is found, whole while loop is broken from
(define executeWhile
(lambda (l returnBreak tryBreak)
(breakAbstraction l '() '() returnBreak tryBreak 'whilebreak)
))
; Created for correct implementation of break continuation
(define executeWhileAfterBreak
(lambda (l break returnBreak tryBreak)
(cond
((eq? (executeOperator (car l)) #t) (executeWhileThen l break returnBreak tryBreak))
)))
; For continue, this should break out of continue block and just do the (executeWhile initialList) if continue is called
(define executeWhileThen;CallCC
(lambda (l break returnBreak tryBreak)
(pushLayer)
(display S) (newline)
(breakAbstraction l '() break returnBreak tryBreak 'whilecontinue)
))
(define executeTry
(lambda (l continue break returnBreak previousTryBreak)
(pushLayer)
(display S) (newline)
(breakAbstraction l continue break returnBreak previousTryBreak 'try)))
;Abstraction for ExecuteFinally
(define second_element cadr )
(define executeCatch
(lambda (l continue break returnBreak previousTryBreak)
(addVar (caar l) (getThrow) S)
(computeProgramContinuations (second_element l) continue break returnBreak previousTryBreak)
(popLayer)
(display S) (newline)
))
;Abstraction for ExecuteCatch
(define element_1 car)
(define executeFinally
(lambda (l continue break returnBreak previousTryBreak)
(computeProgramContinuations (element_1 l) continue break returnBreak previousTryBreak)
(popLayer)
(display S) (newline)
))
(define breakAbstraction
(lambda (l continue break returnBreak tryBreak type)
(cond
((eq? type 'whilebreak)
; Must use this to make sure theres not a double remove from continue and break
(cond
((eq? (call/cc
(lambda (break)
(executeWhileAfterBreak l break returnBreak tryBreak))) 'breakReturn)
(popLayer)
(display S) (newline)
)))
((eq? type 'whilecontinue)
(let ((l2 (cadr l)))
(call/cc
(lambda (continue)
(computeProgramLineContinuations l2 continue break returnBreak tryBreak)
))
(popLayer)
(display S) (newline)
(executeWhileAfterBreak l break returnBreak tryBreak)))
((eq? type 'if)
(letrec ((returnType (lambda (l continue break returnBreak tryBreak type)
(call/cc
(lambda (ifbreak)
(executeIfThenStatement l ifbreak ifbreak ifbreak ifbreak))))))
(let ((type (returnType l continue break returnBreak tryBreak type)))
(cond
((eq? type 'breakReturn)
(begin
(popLayer)
(display S) (newline)
(break 'breakReturn)))
((eq? type 'continueReturn)
(begin
(popLayer)
(display S) (newline)
(continue 'continueReturn)))
((eq? type 'tryReturn)
(let ((thrownVar (getThrow)))
(begin
(popLayer)
(display S) (newline)
(throw thrownVar)
(tryBreak 'tryReturn))))
((not (void? type))
(begin
(popLayer)
(display S) (newline)
(returnBreak type)))
(else
(popLayer)
(display S) (newline)
)))))
((eq? type 'try)
(call/cc
(lambda (tryBreak)
(computeProgramContinuations (car l) continue break returnBreak tryBreak)))
; Will be '() if nothing thrown
(let ((thrownVar (getThrow)))
; Get rid of current layer
(popLayer)
(display S) (newline)
(cond
; If catch exists
((not (null? (cadr l)))
(if (not (null? thrownVar))
(begin
(pushLayer)
(display S) (newline)
(throw thrownVar)
(computeProgramLineContinuations (cadr l) continue break returnBreak tryBreak)))
(cond
((not (null? (caddr l)))
(begin
(pushLayer)
(display S) (newline)
(computeProgramLineContinuations (caddr l) continue break returnBreak tryBreak)))))
((not (null? (caddr l)))
(begin
(pushLayer)
(display S) (newline)
(computeProgramLineContinuations (caddr l) continue break returnBreak tryBreak))))))
)))