Starting The Translator
So I started the translator this week.
I haven't gotten very far (given break and being sick).
Here is the skeleton thus far:
#lang racket
#|
tree-transform.rkt
Logan Davis
Description:
An in-progress transcompiler to turn a <new languages name>
AST into an Arduino-C AST to be unpacked.
To Use:
Import into another racket file and call (tree-transform)
on a syntax->datum list of the <new language>s AST.
11/28/16 | Racket 6.6 | MIT License
|#
; Verifies that a mutable tag is present in a let-statement
(define mutable-tag?
(lambda (let-statement)
(define result (filter (lambda (x) (equal? (first x) 'mutable-tag))
(rest let-statement)))
(if (equal? (length result) 1) #t #f)))
; Handles a 'program branch of an AST
(define program-tag-handler
(lambda (datum)
(let ([content (rest datum)]
[new_program '(program)])
(for ([item content])
(set! new_program (append new_program (list (tree-transform item)))))
new_program)))
; Handles a 'let-statement branch of an AST
(define let-tag-handler
;;; add section for mutable lets
(lambda (datum)
(let ([mutable? (mutable-tag? datum)])
(if mutable?
'()
(append (list 'declaration)
(list (list 'type (letType-handler (fifth datum)))) ;;type
(list (third datum)) ;; id
(list (sixth datum)) ;; equal symbol
(list (seventh datum)) ;;value
(list (eighth datum))))))) ;; delimiter
; Translates types from original-AST to target AST.
(define letType-handler
;;; TODO: add multi-dimensional array type handling.
(lambda (datum)
(cond [(equal? (second datum) "array")
(string-append (fourth datum) "[]")]
[else (second datum)])))
; Takes some syntax->datum list of original AST and returns translated AST
(define tree-transform
(lambda (datum)
(define tag (first datum))
(cond
;;;----------------TOP LEVEL PROGRAM-----------------------;;;
[(equal? tag 'program)
(program-tag-handler datum)]
;;;----------------LET STATEMENT---------------------------;;;
[(equal? tag 'let-statement)
(let-tag-handler datum)])))
(provide (all-defined-out))
When I call it on this sample AST:
(tree-transform '(program
(let-statement
(let "let")
(id "list_of_pins")
(colon ":")
(type "array" (lSqBrac "[") "int" (rSqBrac "]"))
(eq "=")
(lit
(array
(lSqBrac "[")
(lit (int "1"))
(comma ",")
(lit (int "2"))
(comma ",")
(lit (int "3"))
(comma ",")
(lit (int "4"))
(comma ",")
(lit (int "5"))
(rSqBrac "]")))
(delimit ";"))
(let-statement
(let "let")
(id "on")
(colon ":")
(type "int")
(eq "=")
(expr
(term (factor (lit (int "7"))) (mult "*") (factor (lit (int "8"))))
(sub "-")
(term (factor (lit (int "5")))))
(delimit ";"))))
It produces:
'(program
(declaration
(type "int[]")
(id "list_of_pins")
(eq "=")
(lit
(array
(lSqBrac "[")
(lit (int "1"))
(comma ",")
(lit (int "2"))
(comma ",")
(lit (int "3"))
(comma ",")
(lit (int "4"))
(comma ",")
(lit (int "5"))
(rSqBrac "]")))
(delimit ";"))
(declaration
(type "int")
(id "on")
(eq "=")
(expr (term (factor (lit (int "7"))) (mult "*") (factor (lit (int "8")))) (sub "-") (term (factor (lit (int "5")))))
(delimit ";")))
It looks pretty good other than the fact that I have no way to handles
multi-dimensional arrays yet and I don't change "[]" surrounding the
array-literal to the correct "{}". But those are minor fixes.
It should just be a process of chipping away at different cases of nesting now.
I will have to add a few words to the BNF-spec (like "return"), but other than that
it seems pretty straight forward.