3 (define (form? keyword source)
5 (eq? (car source) keyword)))
7 (define (expect-form keyword source)
8 (if (not (form? keyword source))
9 (error "expected" keyword source)))
11 (define (get-id source)
12 (expect-form 'six.identifier source)
15 (define (define-variable source cte cont)
16 (let* ((id (get-id (cadr source)))
18 (dims (cadddr source))
19 (val (car (cddddr source))))
21 ;; variables which, when found in programs, have special meanings
22 ;; when any of these are encountered, its associated thunk is
24 (define special-variables
26 (cons 'SIXPIC_MEMORY_DIVIDE
28 (set! memory-divide (cadr val)) ; must be a literal
29 (expression val cte (lambda (ast cte)
30 (def (list ast) cte)))))
31 (cons 'SIXPIC_FSR0 ; these 3 must be int16
32 (lambda () ;; TODO this code repetition is ugly, but factoring it out did not work
37 (list ast) id '() 'int16
38 (new-value (list (get-register FSR0L)
39 (get-register FSR0H)))
42 (cte-extend cte (list new-var))))))))
49 (list ast) id '() 'int16
50 (new-value (list (get-register FSR1L)
51 (get-register FSR1H)))
54 (cte-extend cte (list new-var))))))))
61 (list ast) id '() 'int16
62 (new-value (list (get-register FSR2L)
63 (get-register FSR2H)))
66 (cte-extend cte (list new-var))))))))))
69 (define (def asts cte)
73 (new-def-variable asts id '() type value '()))
75 (cte-extend cte (list ast))))
78 ;; if it's a special variable, call its associated thunk instead
79 (let ((target (assq id special-variables)))
83 (expression val cte (lambda (ast cte) (def (list ast) cte)))
86 (define (define-procedure source cte cont)
87 (let* ((id (get-id (cadr source)))
88 (proc (caddr source)))
89 (expect-form 'six.procedure proc)
98 (new-def-variable '() (get-id (car x)) '() type value '())))
102 (expect-form 'six.procedure-body body)
106 (new-def-procedure '() id '() type value params))
108 (cte-extend cte (list ast))))
109 (multi-link-parent! params ast)
111 (cte-extend cte params)
112 (lambda (body-ast body-cte)
113 (ast-subasts-set! ast (list body-ast))
114 (link-parent! body-ast ast)
118 (define (block source cte cont)
119 (define (b source cte cont)
122 (let ((head (car source))
124 (if (or (form? 'six.label head) ; we complete the block with a list of named blocks
125 (form? 'six.case head))
126 (named-block-list source
128 cont) ; will return a list of named blocks
135 (cont (cons ast asts)
140 (cont (new-block asts)
143 ;; returns a list of the named blocks (implicit blocks delimited by labels) present in the given tree
144 ;; useful for switch and goto
145 (define (named-block-list source cte cont)
146 (define (b source cte cont name body-so-far)
148 (cont (list (new-named-block name body-so-far)) ; last block
150 (let ((curr (car source)))
151 (if (or (form? 'six.label curr) ; we reached another named block
152 (form? 'six.case curr))
153 (named-block-list source
155 (lambda (named-blocks cte)
156 (cont (cons (new-named-block name body-so-far)
166 (append body-so-far (list ast)))))))))
174 (if (form? 'six.case (car source)) ; the label is a case
175 (literal (cadar source)
178 (new-cont (list 'case (literal-val name)) cte)))
179 (new-cont (cadar source) cte)))) ; ordinary label
181 (define (statement source cte cont)
182 (cond ((form? 'six.define-variable source)
183 (define-variable source cte cont))
184 ((form? 'six.if source)
185 (if (null? (cdddr source))
186 (if1 source cte cont)
187 (if2 source cte cont)))
188 ((form? 'six.switch source)
189 (switch source cte cont))
190 ((form? 'six.while source)
191 (while source cte cont))
192 ((form? 'six.do-while source)
193 (do-while source cte cont))
194 ((form? 'six.for source)
195 (for source cte cont))
196 ((form? 'six.return source)
197 (return source cte cont))
198 ((form? 'six.break source)
199 (break source cte cont))
200 ((form? 'six.continue source)
201 (continue source cte cont))
202 ((form? 'six.goto source)
203 (goto source cte cont))
204 ((form? 'six.compound source)
205 (block source cte cont))
207 (expression source cte cont))))
209 (define (return source cte cont)
211 (define (ret asts cte)
212 (cont (new-return asts)
215 (if (null? (cdr source))
217 (expression (cadr source)
220 (ret (list ast) cte)))))
222 (define (break source cte cont)
226 (define (continue source cte cont)
230 (define (goto source cte cont)
231 (cont (new-goto (cadadr source)) ; label
234 (define (if1 source cte cont)
235 (expression (cadr source)
238 (statement (caddr source)
241 (cont (new-if (list ast1 ast2))
244 (define (if2 source cte cont)
245 (expression (cadr source)
248 (statement (caddr source)
251 (statement (cadddr source)
254 (cont (new-if (list ast1 ast2 ast3))
257 (define (switch source cte cont)
258 (expression (cadr source)
260 (lambda (ast1 cte) ; we matched the paren expr
261 (expect-form 'six.compound (caddr source))
262 (block (caddr source)
265 (cont (new-switch (cons ast1 (ast-subasts ast2))) ; we only need the contents of the generated block, which would be a named block list
268 (define (while source cte cont)
269 (expression (cadr source)
272 (statement (caddr source)
275 (cont (new-while (list ast1 ast2))
278 (define (do-while source cte cont)
279 (statement (cadr source)
282 (expression (caddr source)
285 (cont (new-do-while (list ast1 ast2))
288 (define (for source cte cont)
290 (define (opt-expr source cte cont)
292 (expression source cte cont)
295 (statement (cadr source)
298 (opt-expr (caddr source)
301 (opt-expr (cadddr source)
304 (statement (car (cddddr source))
310 (new-literal 'int 1))
316 (define (expression source cte cont)
317 (cond ((form? 'six.literal source)
318 (literal source cte cont))
319 ((form? 'six.identifier source)
320 (ref source cte cont))
321 ((form? 'six.index source)
322 (array-ref source cte cont)) ;; TODO make an operation
323 ((form? 'six.call source)
324 (call source cte cont))
328 (operation op source cte cont)))
330 (error "expected expression" source))))
332 (define (operation op source cte cont)
334 (expression (cadr source)
338 (new-oper (list ast1) #f op)))
339 (expr-type-set! ast ((op-type-rule op) ast))
340 (cont ((op-constant-fold op) ast)
342 (expression (cadr source)
345 (expression (caddr source)
349 (new-oper (list ast1 ast2) #f op)))
350 (expr-type-set! ast ((op-type-rule op) ast))
351 (cont ((op-constant-fold op) ast)
354 (define (call source cte cont)
355 (let* ((id (get-id (cadr source)))
356 (binding (cte-lookup cte id)))
357 (if (def-procedure? binding)
358 (expressions (cddr source)
361 (cont (new-call args (def-procedure-type binding) binding)
363 (error "expected procedure" source))))
365 (define (expressions source cte cont)
366 (cond ((null? source)
370 (let ((head (car source))
378 (cont (cons ast asts)
381 (define (literal source cte cont)
382 (let ((n (cadr source)))
383 (cont (new-literal (cond ((and (>= n 0) (< n 256))
385 ((and (>= n 0) (< n 65536))
392 (define (ref source cte cont)
393 (let* ((id (cadr source))
394 (binding (cte-lookup cte id)))
395 (if (def-variable? binding)
396 (cont (new-ref (def-variable-type binding) binding)
398 (error "expected variable" source))))
400 (define (array-ref source cte cont)
401 (let* ((id (cadr source))
402 (index (caddr source)))
409 (cont (new-array-ref ast1 ast2)
412 (define (toplevel source cte cont) ;; TODO have an implicit main
413 (cond ((form? 'six.define-variable source)
414 (define-variable source cte cont))
415 ((form? 'six.define-procedure source)
416 (define-procedure source cte cont))
418 (statement source cte cont))))
420 (define (program source cte cont)
422 (define (p source cte cont)
423 (cond ((null? source)
427 (let ((head (car source))
435 (cont (cons ast asts)
441 (cont (new-program asts)