123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814 |
- ;;; Guile Emacs Lisp
- ;; Copyright (C) 2009-2011, 2013, 2018 Free Software Foundation, Inc.
- ;; This program is free software; you can redistribute it and/or modify
- ;; it under the terms of the GNU General Public License as published by
- ;; the Free Software Foundation; either version 3, or (at your option)
- ;; any later version.
- ;;
- ;; This program is distributed in the hope that it will be useful,
- ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ;; GNU General Public License for more details.
- ;;
- ;; You should have received a copy of the GNU General Public License
- ;; along with this program; see the file COPYING. If not, write to
- ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- ;; Boston, MA 02111-1307, USA.
- ;;; Code:
- (define-module (language elisp compile-tree-il)
- #:use-module (language elisp bindings)
- #:use-module (language elisp runtime)
- #:use-module (language tree-il)
- #:use-module (system base pmatch)
- #:use-module (system base compile)
- #:use-module (system base target)
- #:use-module (srfi srfi-1)
- #:use-module (srfi srfi-8)
- #:use-module (srfi srfi-11)
- #:use-module (srfi srfi-26)
- #:export (compile-tree-il
- compile-progn
- compile-eval-when-compile
- compile-if
- compile-defconst
- compile-defvar
- compile-setq
- compile-let
- compile-flet
- compile-labels
- compile-let*
- compile-guile-ref
- compile-guile-primitive
- compile-function
- compile-defmacro
- compile-defun
- #{compile-`}#
- compile-quote
- compile-%funcall
- compile-%set-lexical-binding-mode))
- ;;; Certain common parameters (like the bindings data structure or
- ;;; compiler options) are not always passed around but accessed using
- ;;; fluids to simulate dynamic binding (hey, this is about elisp).
- ;;; The bindings data structure to keep track of symbol binding related
- ;;; data.
- (define bindings-data (make-fluid))
- (define lexical-binding (make-fluid))
- ;;; Find the source properties of some parsed expression if there are
- ;;; any associated with it.
- (define (location x)
- (and (pair? x)
- (let ((props (source-properties x)))
- (and (not (null? props))
- props))))
- ;;; Values to use for Elisp's nil and t.
- (define (nil-value loc)
- (make-const loc (@ (language elisp runtime) nil-value)))
- (define (t-value loc)
- (make-const loc (@ (language elisp runtime) t-value)))
- ;;; Modules that contain the value and function slot bindings.
- (define runtime '(language elisp runtime))
- (define value-slot (@ (language elisp runtime) value-slot-module))
- (define function-slot (@ (language elisp runtime) function-slot-module))
- ;;; The backquoting works the same as quasiquotes in Scheme, but the
- ;;; forms are named differently; to make easy adaptions, we define these
- ;;; predicates checking for a symbol being the car of an
- ;;; unquote/unquote-splicing/backquote form.
- (define (unquote? sym)
- (and (symbol? sym) (eq? sym '#{,}#)))
- (define (unquote-splicing? sym)
- (and (symbol? sym) (eq? sym '#{,@}#)))
- ;;; Build a call to a primitive procedure nicely.
- (define (call-primitive loc sym . args)
- (make-primcall loc sym args))
- ;;; Error reporting routine for syntax/compilation problems or build
- ;;; code for a runtime-error output.
- (define (report-error loc . args)
- (apply error args))
- (define (access-variable loc symbol handle-lexical handle-dynamic)
- (cond
- ((get-lexical-binding (fluid-ref bindings-data) symbol)
- => handle-lexical)
- (else
- (handle-dynamic))))
- (define (reference-variable loc symbol)
- (access-variable
- loc
- symbol
- (lambda (lexical)
- (make-lexical-ref loc lexical lexical))
- (lambda ()
- (call-primitive loc
- 'fluid-ref
- (make-module-ref loc value-slot symbol #t)))))
- (define (global? module symbol)
- (module-variable module symbol))
- (define (ensure-globals! loc names body)
- (if (and (every (cut global? (resolve-module value-slot) <>) names)
- (every symbol-interned? names))
- body
- (list->seq
- loc
- `(,@(map
- (lambda (name)
- (ensure-fluid! value-slot name)
- (make-call loc
- (make-module-ref loc runtime 'ensure-fluid! #t)
- (list (make-const loc value-slot)
- (make-const loc name))))
- names)
- ,body))))
- (define (set-variable! loc symbol value)
- (access-variable
- loc
- symbol
- (lambda (lexical)
- (make-lexical-set loc lexical lexical value))
- (lambda ()
- (ensure-globals!
- loc
- (list symbol)
- (call-primitive loc
- 'fluid-set!
- (make-module-ref loc value-slot symbol #t)
- value)))))
- (define (access-function loc symbol handle-lexical handle-global)
- (cond
- ((get-function-binding (fluid-ref bindings-data) symbol)
- => handle-lexical)
- (else
- (handle-global))))
- (define (reference-function loc symbol)
- (access-function
- loc
- symbol
- (lambda (gensym) (make-lexical-ref loc symbol gensym))
- (lambda () (make-module-ref loc function-slot symbol #t))))
- (define (set-function! loc symbol value)
- (access-function
- loc
- symbol
- (lambda (gensym) (make-lexical-set loc symbol gensym value))
- (lambda ()
- (make-call
- loc
- (make-module-ref loc runtime 'set-symbol-function! #t)
- (list (make-const loc symbol) value)))))
- (define (bind-lexically? sym module decls)
- (or (eq? module function-slot)
- (let ((decl (assq-ref decls sym)))
- (and (equal? module value-slot)
- (or
- (eq? decl 'lexical)
- (and
- (fluid-ref lexical-binding)
- (not (global? (resolve-module module) sym))))))))
- (define (parse-let-binding loc binding)
- (pmatch binding
- ((unquote var)
- (guard (symbol? var))
- (cons var #nil))
- ((,var)
- (guard (symbol? var))
- (cons var #nil))
- ((,var ,val)
- (guard (symbol? var))
- (cons var val))
- (else
- (report-error loc "malformed variable binding" binding))))
- (define (parse-flet-binding loc binding)
- (pmatch binding
- ((,var ,args . ,body)
- (guard (symbol? var))
- (cons var `(function (lambda ,args ,@body))))
- (else
- (report-error loc "malformed function binding" binding))))
- (define (parse-declaration expr)
- (pmatch expr
- ((lexical . ,vars)
- (map (cut cons <> 'lexical) vars))
- (else
- '())))
- (define (parse-body-1 body lambda?)
- (let loop ((lst body)
- (decls '())
- (intspec #f)
- (doc #f))
- (pmatch lst
- (((declare . ,x) . ,tail)
- (loop tail (append-reverse x decls) intspec doc))
- (((interactive . ,x) . ,tail)
- (guard lambda? (not intspec))
- (loop tail decls x doc))
- ((,x . ,tail)
- (guard lambda? (string? x) (not doc) (not (null? tail)))
- (loop tail decls intspec x))
- (else
- (values (append-map parse-declaration decls)
- intspec
- doc
- lst)))))
- (define (parse-lambda-body body)
- (parse-body-1 body #t))
- (define (parse-body body)
- (receive (decls intspec doc body) (parse-body-1 body #f)
- (values decls body)))
- ;;; Partition the argument list of a lambda expression into required,
- ;;; optional and rest arguments.
- (define (parse-lambda-list lst)
- (define (%match lst null optional rest symbol)
- (pmatch lst
- (() (null))
- (nil (null))
- ((&optional . ,tail) (optional tail))
- ((&rest . ,tail) (rest tail))
- ((,arg . ,tail) (guard (symbol? arg)) (symbol arg tail))
- (else (fail))))
- (define (return rreq ropt rest)
- (values #t (reverse rreq) (reverse ropt) rest))
- (define (fail)
- (values #f #f #f #f))
- (define (parse-req lst rreq)
- (%match lst
- (lambda () (return rreq '() #f))
- (lambda (tail) (parse-opt tail rreq '()))
- (lambda (tail) (parse-rest tail rreq '()))
- (lambda (arg tail) (parse-req tail (cons arg rreq)))))
- (define (parse-opt lst rreq ropt)
- (%match lst
- (lambda () (return rreq ropt #f))
- (lambda (tail) (fail))
- (lambda (tail) (parse-rest tail rreq ropt))
- (lambda (arg tail) (parse-opt tail rreq (cons arg ropt)))))
- (define (parse-rest lst rreq ropt)
- (%match lst
- (lambda () (fail))
- (lambda (tail) (fail))
- (lambda (tail) (fail))
- (lambda (arg tail) (parse-post-rest tail rreq ropt arg))))
- (define (parse-post-rest lst rreq ropt rest)
- (%match lst
- (lambda () (return rreq ropt rest))
- (lambda () (fail))
- (lambda () (fail))
- (lambda (arg tail) (fail))))
- (parse-req lst '()))
- (define (make-simple-lambda loc meta req opt init rest vars body)
- (make-lambda loc
- meta
- (make-lambda-case #f req opt rest #f init vars body #f)))
- (define (make-dynlet src fluids vals body)
- (let ((f (map (lambda (x) (gensym "fluid ")) fluids))
- (v (map (lambda (x) (gensym "valud ")) vals)))
- (make-let src (map (lambda (_) 'fluid) fluids) f fluids
- (make-let src (map (lambda (_) 'val) vals) v vals
- (let lp ((f f) (v v))
- (if (null? f)
- body
- (make-primcall
- src 'with-fluid*
- (list (make-lexical-ref #f 'fluid (car f))
- (make-lexical-ref #f 'val (car v))
- (make-lambda
- src '()
- (make-lambda-case
- src '() #f #f #f '() '()
- (lp (cdr f) (cdr v))
- #f))))))))))
- (define (compile-lambda loc meta args body)
- (receive (valid? req-ids opt-ids rest-id)
- (parse-lambda-list args)
- (if valid?
- (let* ((all-ids (append req-ids
- opt-ids
- (or (and=> rest-id list) '())))
- (all-vars (map (lambda (ignore) (gensym)) all-ids)))
- (let*-values (((decls intspec doc forms)
- (parse-lambda-body body))
- ((lexical dynamic)
- (partition
- (compose (cut bind-lexically? <> value-slot decls)
- car)
- (map list all-ids all-vars)))
- ((lexical-ids lexical-vars) (unzip2 lexical))
- ((dynamic-ids dynamic-vars) (unzip2 dynamic)))
- (with-dynamic-bindings
- (fluid-ref bindings-data)
- dynamic-ids
- (lambda ()
- (with-lexical-bindings
- (fluid-ref bindings-data)
- lexical-ids
- lexical-vars
- (lambda ()
- (ensure-globals!
- loc
- dynamic-ids
- (let* ((tree-il
- (compile-expr
- (if rest-id
- `(let ((,rest-id (if ,rest-id
- ,rest-id
- nil)))
- ,@forms)
- `(progn ,@forms))))
- (full-body
- (if (null? dynamic)
- tree-il
- (make-dynlet
- loc
- (map (cut make-module-ref loc value-slot <> #t)
- dynamic-ids)
- (map (cut make-lexical-ref loc <> <>)
- dynamic-ids
- dynamic-vars)
- tree-il))))
- (make-simple-lambda loc
- meta
- req-ids
- opt-ids
- (map (const (nil-value loc))
- opt-ids)
- rest-id
- all-vars
- full-body)))))))))
- (report-error "invalid function" `(lambda ,args ,@body)))))
- ;;; Handle the common part of defconst and defvar, that is, checking for
- ;;; a correct doc string and arguments as well as maybe in the future
- ;;; handling the docstring somehow.
- (define (handle-var-def loc sym doc)
- (cond
- ((not (symbol? sym)) (report-error loc "expected symbol, got" sym))
- ((> (length doc) 1) (report-error loc "too many arguments to defvar"))
- ((and (not (null? doc)) (not (string? (car doc))))
- (report-error loc "expected string as third argument of defvar, got"
- (car doc)))
- ;; TODO: Handle doc string if present.
- (else #t)))
- ;;; Handle macro and special operator bindings.
- (define (find-operator name type)
- (and
- (symbol? name)
- (module-defined? (resolve-interface function-slot) name)
- (let ((op (module-ref (resolve-module function-slot) name)))
- (if (and (pair? op) (eq? (car op) type))
- (cdr op)
- #f))))
- ;;; See if a (backquoted) expression contains any unquotes.
- (define (contains-unquotes? expr)
- (if (pair? expr)
- (if (or (unquote? (car expr)) (unquote-splicing? (car expr)))
- #t
- (or (contains-unquotes? (car expr))
- (contains-unquotes? (cdr expr))))
- #f))
- ;;; Process a backquoted expression by building up the needed
- ;;; cons/append calls. For splicing, it is assumed that the expression
- ;;; spliced in evaluates to a list. The emacs manual does not really
- ;;; state either it has to or what to do if it does not, but Scheme
- ;;; explicitly forbids it and this seems reasonable also for elisp.
- (define (unquote-cell? expr)
- (and (list? expr) (= (length expr) 2) (unquote? (car expr))))
- (define (unquote-splicing-cell? expr)
- (and (list? expr) (= (length expr) 2) (unquote-splicing? (car expr))))
- (define (process-backquote loc expr)
- (if (contains-unquotes? expr)
- (if (pair? expr)
- (if (or (unquote-cell? expr) (unquote-splicing-cell? expr))
- (compile-expr (cadr expr))
- (let* ((head (car expr))
- (processed-tail (process-backquote loc (cdr expr)))
- (head-is-list-2 (and (list? head)
- (= (length head) 2)))
- (head-unquote (and head-is-list-2
- (unquote? (car head))))
- (head-unquote-splicing (and head-is-list-2
- (unquote-splicing?
- (car head)))))
- (if head-unquote-splicing
- (call-primitive loc
- 'append
- (compile-expr (cadr head))
- processed-tail)
- (call-primitive loc 'cons
- (if head-unquote
- (compile-expr (cadr head))
- (process-backquote loc head))
- processed-tail))))
- (report-error loc
- "non-pair expression contains unquotes"
- expr))
- (make-const loc expr)))
- ;;; Special operators
- (defspecial progn (loc args)
- (list->seq loc
- (if (null? args)
- (list (nil-value loc))
- (map compile-expr args))))
- (defspecial eval-when-compile (loc args)
- (make-const loc (with-native-target
- (lambda ()
- (compile `(progn ,@args) #:from 'elisp #:to 'value)))))
- (defspecial if (loc args)
- (pmatch args
- ((,cond ,then . ,else)
- (make-conditional
- loc
- (call-primitive loc 'not
- (call-primitive loc 'nil? (compile-expr cond)))
- (compile-expr then)
- (compile-expr `(progn ,@else))))))
- (defspecial defconst (loc args)
- (pmatch args
- ((,sym ,value . ,doc)
- (if (handle-var-def loc sym doc)
- (make-seq loc
- (set-variable! loc sym (compile-expr value))
- (make-const loc sym))))))
- (defspecial defvar (loc args)
- (pmatch args
- ((,sym) (make-const loc sym))
- ((,sym ,value . ,doc)
- (if (handle-var-def loc sym doc)
- (make-seq
- loc
- (make-conditional
- loc
- (make-conditional
- loc
- (call-primitive
- loc
- 'module-bound?
- (call-primitive loc
- 'resolve-interface
- (make-const loc value-slot))
- (make-const loc sym))
- (call-primitive loc
- 'fluid-bound?
- (make-module-ref loc value-slot sym #t))
- (make-const loc #f))
- (make-void loc)
- (set-variable! loc sym (compile-expr value)))
- (make-const loc sym))))))
- (defspecial setq (loc args)
- (define (car* x) (if (null? x) '() (car x)))
- (define (cdr* x) (if (null? x) '() (cdr x)))
- (define (cadr* x) (car* (cdr* x)))
- (define (cddr* x) (cdr* (cdr* x)))
- (list->seq
- loc
- (let loop ((args args) (last (nil-value loc)))
- (if (null? args)
- (list last)
- (let ((sym (car args))
- (val (compile-expr (cadr* args))))
- (if (not (symbol? sym))
- (report-error loc "expected symbol in setq")
- (cons
- (set-variable! loc sym val)
- (loop (cddr* args)
- (reference-variable loc sym)))))))))
-
- (defspecial let (loc args)
- (pmatch args
- ((,varlist . ,body)
- (let ((bindings (map (cut parse-let-binding loc <>) varlist)))
- (receive (decls forms) (parse-body body)
- (receive (lexical dynamic)
- (partition
- (compose (cut bind-lexically? <> value-slot decls)
- car)
- bindings)
- (let ((make-values (lambda (for)
- (map (lambda (el) (compile-expr (cdr el)))
- for)))
- (make-body (lambda () (compile-expr `(progn ,@forms)))))
- (ensure-globals!
- loc
- (map car dynamic)
- (if (null? lexical)
- (make-dynlet loc
- (map (compose (cut make-module-ref
- loc
- value-slot
- <>
- #t)
- car)
- dynamic)
- (map (compose compile-expr cdr)
- dynamic)
- (make-body))
- (let* ((lexical-syms (map (lambda (el) (gensym)) lexical))
- (dynamic-syms (map (lambda (el) (gensym)) dynamic))
- (all-syms (append lexical-syms dynamic-syms))
- (vals (append (make-values lexical)
- (make-values dynamic))))
- (make-let loc
- all-syms
- all-syms
- vals
- (with-lexical-bindings
- (fluid-ref bindings-data)
- (map car lexical)
- lexical-syms
- (lambda ()
- (if (null? dynamic)
- (make-body)
- (make-dynlet loc
- (map
- (compose
- (cut make-module-ref
- loc
- value-slot
- <>
- #t)
- car)
- dynamic)
- (map
- (lambda (sym)
- (make-lexical-ref
- loc
- sym
- sym))
- dynamic-syms)
- (make-body))))))))))))))))
- (defspecial let* (loc args)
- (pmatch args
- ((,varlist . ,body)
- (let ((bindings (map (cut parse-let-binding loc <>) varlist)))
- (receive (decls forms) (parse-body body)
- (let iterate ((tail bindings))
- (if (null? tail)
- (compile-expr `(progn ,@forms))
- (let ((sym (caar tail))
- (value (compile-expr (cdar tail))))
- (if (bind-lexically? sym value-slot decls)
- (let ((target (gensym)))
- (make-let loc
- `(,target)
- `(,target)
- `(,value)
- (with-lexical-bindings
- (fluid-ref bindings-data)
- `(,sym)
- `(,target)
- (lambda () (iterate (cdr tail))))))
- (ensure-globals!
- loc
- (list sym)
- (make-dynlet loc
- (list (make-module-ref loc value-slot sym #t))
- (list value)
- (iterate (cdr tail)))))))))))))
- (defspecial flet (loc args)
- (pmatch args
- ((,bindings . ,body)
- (let ((names+vals (map (cut parse-flet-binding loc <>) bindings)))
- (receive (decls forms) (parse-body body)
- (let ((names (map car names+vals))
- (vals (map cdr names+vals))
- (gensyms (map (lambda (x) (gensym)) names+vals)))
- (with-function-bindings
- (fluid-ref bindings-data)
- names
- gensyms
- (lambda ()
- (make-let loc
- names
- gensyms
- (map compile-expr vals)
- (compile-expr `(progn ,@forms)))))))))))
- (defspecial labels (loc args)
- (pmatch args
- ((,bindings . ,body)
- (let ((names+vals (map (cut parse-flet-binding loc <>) bindings)))
- (receive (decls forms) (parse-body body)
- (let ((names (map car names+vals))
- (vals (map cdr names+vals))
- (gensyms (map (lambda (x) (gensym)) names+vals)))
- (with-function-bindings
- (fluid-ref bindings-data)
- names
- gensyms
- (lambda ()
- (make-letrec #f
- loc
- names
- gensyms
- (map compile-expr vals)
- (compile-expr `(progn ,@forms)))))))))))
- ;;; guile-ref allows building TreeIL's module references from within
- ;;; elisp as a way to access data within the Guile universe. The module
- ;;; and symbol referenced are static values, just like (@ module symbol)
- ;;; does!
- (defspecial guile-ref (loc args)
- (pmatch args
- ((,module ,sym) (guard (and (list? module) (symbol? sym)))
- (make-module-ref loc module sym #t))))
- ;;; guile-primitive allows to create primitive references, which are
- ;;; still a little faster.
- (defspecial guile-primitive (loc args)
- (pmatch args
- ((,sym)
- (make-primitive-ref loc sym))))
- (defspecial function (loc args)
- (pmatch args
- (((lambda ,args . ,body))
- (compile-lambda loc '() args body))
- ((,sym) (guard (symbol? sym))
- (reference-function loc sym))))
- (defspecial defmacro (loc args)
- (pmatch args
- ((,name ,args . ,body)
- (if (not (symbol? name))
- (report-error loc "expected symbol as macro name" name)
- (let* ((tree-il
- (make-seq
- loc
- (set-function!
- loc
- name
- (make-call
- loc
- (make-module-ref loc '(guile) 'cons #t)
- (list (make-const loc 'macro)
- (compile-lambda loc
- `((name . ,name))
- args
- body))))
- (make-const loc name))))
- (with-native-target
- (lambda ()
- (compile tree-il #:from 'tree-il #:to 'value)))
- tree-il)))))
- (defspecial defun (loc args)
- (pmatch args
- ((,name ,args . ,body)
- (if (not (symbol? name))
- (report-error loc "expected symbol as function name" name)
- (make-seq loc
- (set-function! loc
- name
- (compile-lambda loc
- `((name . ,name))
- args
- body))
- (make-const loc name))))))
- (defspecial #{`}# (loc args)
- (pmatch args
- ((,val)
- (process-backquote loc val))))
- (defspecial quote (loc args)
- (pmatch args
- ((,val)
- (make-const loc val))))
- (defspecial %funcall (loc args)
- (pmatch args
- ((,function . ,arguments)
- (make-call loc
- (compile-expr function)
- (map compile-expr arguments)))))
- (defspecial %set-lexical-binding-mode (loc args)
- (pmatch args
- ((,val)
- (fluid-set! lexical-binding val)
- (make-void loc))))
- ;;; Compile a compound expression to Tree-IL.
- (define (compile-pair loc expr)
- (let ((operator (car expr))
- (arguments (cdr expr)))
- (cond
- ((find-operator operator 'special-operator)
- => (lambda (special-operator-function)
- (special-operator-function loc arguments)))
- ((find-operator operator 'macro)
- => (lambda (macro-function)
- (compile-expr (apply macro-function arguments))))
- (else
- (compile-expr `(%funcall (function ,operator) ,@arguments))))))
- ;;; Compile a symbol expression. This is a variable reference or maybe
- ;;; some special value like nil.
- (define (compile-symbol loc sym)
- (case sym
- ((nil) (nil-value loc))
- ((t) (t-value loc))
- (else (reference-variable loc sym))))
- ;;; Compile a single expression to TreeIL.
- (define (compile-expr expr)
- (let ((loc (location expr)))
- (cond
- ((symbol? expr)
- (compile-symbol loc expr))
- ((pair? expr)
- (compile-pair loc expr))
- (else (make-const loc expr)))))
- ;;; Process the compiler options.
- ;;; FIXME: Why is '(()) passed as options by the REPL?
- (define (valid-symbol-list-arg? value)
- (or (eq? value 'all)
- (and (list? value) (and-map symbol? value))))
- (define (process-options! opt)
- (if (and (not (null? opt))
- (not (equal? opt '(()))))
- (if (null? (cdr opt))
- (report-error #f "Invalid compiler options" opt)
- (let ((key (car opt))
- (value (cadr opt)))
- (case key
- ((#:warnings #:to-file?) ; ignore
- #f)
- (else (report-error #f
- "Invalid compiler option"
- key)))))))
- (define (compile-tree-il expr env opts)
- (values
- (with-fluids ((bindings-data (make-bindings)))
- (process-options! opts)
- (compile-expr expr))
- env
- env))
|