switching to scheme #t, #f, and () values
porting code to sort out which NILs are false and which are
empty lists
switching to scheme-style special forms. however you feel about
scheme names vs. CL names, using both is silly.
mostly switching to scheme predicate names, with compatibility
aliases for now. adding set-constant! to make this efficient.
adding null?, eqv?, assq, assv, assoc, memq, memv, member
adding 2-argument form of if
allowing else as final cond condition
looking for init file in same directory as executable, so flisp
can be started from anywhere
renaming T to FL_T, since exporting a 1-character symbol is
not very nice
adding opaque type boilerplate example file
adding correctness checking for the pattern-lambda benchmark
bugfix in int2str
2009-01-28 20:04:23 -05:00
|
|
|
; -*- scheme -*-
|
2008-07-14 20:11:04 -04:00
|
|
|
(load "match.lsp")
|
|
|
|
(load "asttools.lsp")
|
2008-06-30 21:54:22 -04:00
|
|
|
|
|
|
|
(define missing-arg-tag '*r-missing*)
|
|
|
|
|
|
|
|
; tree inspection utils
|
|
|
|
|
|
|
|
(define (assigned-var e)
|
2009-01-31 20:53:58 -05:00
|
|
|
(and (pair? e)
|
2008-06-30 21:54:22 -04:00
|
|
|
(or (eq (car e) '<-) (eq (car e) 'ref=))
|
2009-01-31 20:53:58 -05:00
|
|
|
(symbol? (cadr e))
|
2008-06-30 21:54:22 -04:00
|
|
|
(cadr e)))
|
|
|
|
|
|
|
|
(define (func-argnames f)
|
|
|
|
(let ((argl (cadr f)))
|
|
|
|
(if (eq argl '*r-null*) ()
|
|
|
|
(map cadr argl))))
|
|
|
|
|
|
|
|
; transformations
|
|
|
|
|
switching to scheme #t, #f, and () values
porting code to sort out which NILs are false and which are
empty lists
switching to scheme-style special forms. however you feel about
scheme names vs. CL names, using both is silly.
mostly switching to scheme predicate names, with compatibility
aliases for now. adding set-constant! to make this efficient.
adding null?, eqv?, assq, assv, assoc, memq, memv, member
adding 2-argument form of if
allowing else as final cond condition
looking for init file in same directory as executable, so flisp
can be started from anywhere
renaming T to FL_T, since exporting a 1-character symbol is
not very nice
adding opaque type boilerplate example file
adding correctness checking for the pattern-lambda benchmark
bugfix in int2str
2009-01-28 20:04:23 -05:00
|
|
|
(let ((ctr 0))
|
|
|
|
(define (r-gensym) (prog1 (intern (string "%r:" ctr))
|
|
|
|
(set! ctr (+ ctr 1)))))
|
|
|
|
|
2008-06-30 21:54:22 -04:00
|
|
|
(define (dollarsign-transform e)
|
|
|
|
(pattern-expand
|
|
|
|
(pattern-lambda ($ lhs name)
|
2009-01-31 20:53:58 -05:00
|
|
|
(let* ((g (if (not (pair? lhs)) lhs (r-gensym)))
|
|
|
|
(n (if (symbol? name)
|
2008-06-30 21:54:22 -04:00
|
|
|
name ;(symbol->string name)
|
|
|
|
name))
|
|
|
|
(expr `(r-call
|
|
|
|
r-aref ,g (index-in-strlist ,n (r-call attr ,g "names")))))
|
2009-01-31 20:53:58 -05:00
|
|
|
(if (not (pair? lhs))
|
2008-06-30 21:54:22 -04:00
|
|
|
expr
|
|
|
|
`(r-block (ref= ,g ,lhs) ,expr))))
|
|
|
|
e))
|
|
|
|
|
|
|
|
; lower r expressions of the form f(lhs,...) <- rhs
|
|
|
|
; TODO: if there are any special forms that can be f in this expression,
|
|
|
|
; they need to be handled separately. For example a$b can be lowered
|
|
|
|
; to an index assignment (by dollarsign-transform), after which
|
|
|
|
; this transform applies. I don't think there are any others though.
|
|
|
|
(define (fancy-assignment-transform e)
|
|
|
|
(pattern-expand
|
|
|
|
(pattern-lambda (-$ (<- (r-call f lhs ...) rhs)
|
|
|
|
(<<- (r-call f lhs ...) rhs))
|
2009-01-31 20:53:58 -05:00
|
|
|
(let ((g (if (pair? rhs) (r-gensym) rhs))
|
2008-06-30 21:54:22 -04:00
|
|
|
(op (car __)))
|
2009-01-31 20:53:58 -05:00
|
|
|
`(r-block ,@(if (pair? rhs) `((ref= ,g ,rhs)) ())
|
2008-06-30 21:54:22 -04:00
|
|
|
(,op ,lhs (r-call ,(symconcat f '<-) ,@(cddr (cadr __)) ,g))
|
|
|
|
,g)))
|
|
|
|
e))
|
|
|
|
|
|
|
|
; map an arglist with default values to appropriate init code
|
|
|
|
; function(x=blah) { ... } gets
|
|
|
|
; if (missing(x)) x = blah
|
|
|
|
; added to its body
|
|
|
|
(define (gen-default-inits arglist)
|
|
|
|
(map (lambda (arg)
|
|
|
|
(let ((name (cadr arg))
|
|
|
|
(default (caddr arg)))
|
|
|
|
`(when (missing ,name)
|
|
|
|
(<- ,name ,default))))
|
|
|
|
(filter (lambda (arg) (not (eq (caddr arg) missing-arg-tag))) arglist)))
|
|
|
|
|
|
|
|
; convert r function expressions to lambda
|
|
|
|
(define (normalize-r-functions e)
|
|
|
|
(maptree-post (lambda (n)
|
2009-01-31 20:53:58 -05:00
|
|
|
(if (and (pair? n) (eq (car n) 'function))
|
2008-06-30 21:54:22 -04:00
|
|
|
`(lambda ,(func-argnames n)
|
|
|
|
(r-block ,@(gen-default-inits (cadr n))
|
2009-01-31 20:53:58 -05:00
|
|
|
,@(if (and (pair? (caddr n))
|
2008-06-30 21:54:22 -04:00
|
|
|
(eq (car (caddr n)) 'r-block))
|
|
|
|
(cdr (caddr n))
|
|
|
|
(list (caddr n)))))
|
|
|
|
n))
|
|
|
|
e))
|
|
|
|
|
|
|
|
(define (find-assigned-vars n)
|
|
|
|
(let ((vars ()))
|
|
|
|
(maptree-pre (lambda (s)
|
2009-01-31 20:53:58 -05:00
|
|
|
(if (not (pair? s)) s
|
switching to scheme #t, #f, and () values
porting code to sort out which NILs are false and which are
empty lists
switching to scheme-style special forms. however you feel about
scheme names vs. CL names, using both is silly.
mostly switching to scheme predicate names, with compatibility
aliases for now. adding set-constant! to make this efficient.
adding null?, eqv?, assq, assv, assoc, memq, memv, member
adding 2-argument form of if
allowing else as final cond condition
looking for init file in same directory as executable, so flisp
can be started from anywhere
renaming T to FL_T, since exporting a 1-character symbol is
not very nice
adding opaque type boilerplate example file
adding correctness checking for the pattern-lambda benchmark
bugfix in int2str
2009-01-28 20:04:23 -05:00
|
|
|
(cond ((eq (car s) 'lambda) ())
|
2008-06-30 21:54:22 -04:00
|
|
|
((eq (car s) '<-)
|
switching to scheme #t, #f, and () values
porting code to sort out which NILs are false and which are
empty lists
switching to scheme-style special forms. however you feel about
scheme names vs. CL names, using both is silly.
mostly switching to scheme predicate names, with compatibility
aliases for now. adding set-constant! to make this efficient.
adding null?, eqv?, assq, assv, assoc, memq, memv, member
adding 2-argument form of if
allowing else as final cond condition
looking for init file in same directory as executable, so flisp
can be started from anywhere
renaming T to FL_T, since exporting a 1-character symbol is
not very nice
adding opaque type boilerplate example file
adding correctness checking for the pattern-lambda benchmark
bugfix in int2str
2009-01-28 20:04:23 -05:00
|
|
|
(set! vars (list-adjoin (cadr s) vars))
|
2008-06-30 21:54:22 -04:00
|
|
|
(cddr s))
|
2009-01-31 20:53:58 -05:00
|
|
|
(#t s))))
|
2008-06-30 21:54:22 -04:00
|
|
|
n)
|
|
|
|
vars))
|
|
|
|
|
|
|
|
; introduce let based on assignment statements
|
|
|
|
(define (letbind-locals e)
|
|
|
|
(maptree-post (lambda (n)
|
2009-01-31 20:53:58 -05:00
|
|
|
(if (and (pair? n) (eq (car n) 'lambda))
|
2008-06-30 21:54:22 -04:00
|
|
|
(let ((vars (find-assigned-vars (cddr n))))
|
|
|
|
`(lambda ,(cadr n) (let ,(map (lambda (v) (list v ()))
|
|
|
|
vars)
|
|
|
|
,@(cddr n))))
|
|
|
|
n))
|
|
|
|
e))
|
|
|
|
|
|
|
|
(define (compile-ish e)
|
|
|
|
(letbind-locals
|
|
|
|
(normalize-r-functions
|
|
|
|
(fancy-assignment-transform
|
|
|
|
(dollarsign-transform
|
|
|
|
(flatten-all-op && (flatten-all-op \|\| e)))))))
|