mirror of
https://github.com/justinethier/cyclone.git
synced 2025-05-19 05:39:17 +02:00
137 lines
4.8 KiB
Scheme
137 lines
4.8 KiB
Scheme
;; A temporary testbed file
|
|
(import (scheme base)
|
|
(scheme eval)
|
|
;(scheme file)
|
|
;(scheme read)
|
|
(scheme write)
|
|
(scheme cyclone common)
|
|
(scheme cyclone util)
|
|
;(scheme cyclone cgen)
|
|
(scheme cyclone transforms)
|
|
(scheme cyclone macros)
|
|
;(scheme cyclone libraries)
|
|
)
|
|
|
|
;(define input-program '(lambda (x) (begin (+ x x) 1 2 3)))
|
|
(define input-program
|
|
'((lambda ()
|
|
(define-syntax test
|
|
(er-macro-transformer
|
|
(lambda (expr rename compare)
|
|
`(begin ,(if (cadr expr) '(test #f) 1) (define tmp #t) 3))))
|
|
(test #t)
|
|
(test #f)
|
|
(write tmp)
|
|
)))
|
|
|
|
;; Load macros for expansion phase
|
|
(let ((macros (filter
|
|
(lambda (v)
|
|
(macro? (Cyc-get-cvar (cdr v))))
|
|
(Cyc-global-vars))))
|
|
(set! *defined-macros*
|
|
(append
|
|
macros
|
|
*defined-macros*)))
|
|
(macro:load-env! *defined-macros* (create-environment '() '()))
|
|
|
|
;; Expand macros
|
|
(set! input-program (my-expand input-program (macro:get-env)))
|
|
(write "---------------- after macro expansion:")
|
|
(write input-program) ;pretty-print
|
|
|
|
;; Expand lambda body here so we can splice in any begin's
|
|
(define (expand-body result exp env)
|
|
(cond
|
|
((null? exp) (reverse result))
|
|
;; Splice in begin contents and keep expanding body
|
|
((begin? (car exp))
|
|
(let* ((expr (car exp))
|
|
(begin-exprs (begin->exps expr)))
|
|
(expand-body
|
|
result
|
|
(append begin-exprs (cdr exp))
|
|
env)))
|
|
(else
|
|
(let ((macro #f))
|
|
(when (and (app? (car exp))
|
|
(symbol? (caar exp)))
|
|
(set! macro (env:lookup (caar exp) env #f)))
|
|
(if (tagged-list? 'macro macro)
|
|
;; Expand macro here so we can catch begins in the expanded code,
|
|
;; including nested begins
|
|
(let ((expanded (macro:expand (car exp) macro env)))
|
|
;; Call with expanded macro in case we need to expand again
|
|
(expand-body
|
|
result
|
|
(cons expanded (cdr exp))
|
|
env))
|
|
;; No macro, use main expand function to process
|
|
(expand-body
|
|
(cons
|
|
(inner-expand (car exp) env)
|
|
result)
|
|
(cdr exp)
|
|
env))))))
|
|
|
|
(define (my-expand exp env)
|
|
(inner-expand exp env))
|
|
|
|
;; TODO: need to be able to splice expanded begins somehow.
|
|
;; maybe pass built up exp list to it and splice the begin into that before
|
|
;; continuing expansion
|
|
(define (inner-expand exp env) ; body?)
|
|
(cond
|
|
((const? exp) exp)
|
|
((prim? exp) exp)
|
|
((ref? exp) exp)
|
|
((quote? exp) exp)
|
|
;; TODO: need a way of taking a begin here and splicing its contents
|
|
;; into the body
|
|
((lambda? exp) `(lambda ,(lambda->formals exp)
|
|
,@(expand-body '() (lambda->exp exp) env)
|
|
;,@(map
|
|
; ;; TODO: use extend env here?
|
|
; (lambda (expr) (my-expand expr env))
|
|
; (lambda->exp exp))
|
|
))
|
|
((define? exp) (if (define-lambda? exp)
|
|
(inner-expand (define->lambda exp) env)
|
|
`(define ,(inner-expand (define->var exp) env)
|
|
,@(inner-expand (define->exp exp) env))))
|
|
((set!? exp) `(set! ,(inner-expand (set!->var exp) env)
|
|
,(inner-expand (set!->exp exp) env)))
|
|
((if? exp) `(if ,(inner-expand (if->condition exp) env)
|
|
,(inner-expand (if->then exp) env)
|
|
,(if (if-else? exp)
|
|
(inner-expand (if->else exp) env)
|
|
;; Insert default value for missing else clause
|
|
;; FUTURE: append the empty (unprinted) value
|
|
;; instead of #f
|
|
#f)))
|
|
((app? exp)
|
|
(cond
|
|
((define-syntax? exp)
|
|
(let* ((name (cadr exp))
|
|
(trans (caddr exp))
|
|
(body (cadr trans)))
|
|
(set! *defined-macros* (cons (cons name body) *defined-macros*))
|
|
(macro:add! name body)
|
|
(env:define-variable! name (list 'macro body) env)
|
|
`(define ,name ,(expand body env))))
|
|
((symbol? (car exp))
|
|
(let ((val (env:lookup (car exp) env #f)))
|
|
(if (tagged-list? 'macro val)
|
|
(inner-expand ; Could expand into another macro
|
|
(macro:expand exp val env)
|
|
env)
|
|
(map
|
|
(lambda (expr) (inner-expand expr env))
|
|
exp))))
|
|
|
|
(else
|
|
(map
|
|
(lambda (expr) (inner-expand expr env))
|
|
exp))))
|
|
(else
|
|
(error "unknown exp: " exp))))
|