1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-18 02:00:20 +02:00

whitespace changes

* module/language/elisp/bindings.scm:
* module/language/elisp/compile-tree-il.scm:
* module/language/elisp/lexer.scm:
* module/language/elisp/parser.scm:
* module/language/elisp/runtime.scm:
* module/language/elisp/runtime/function-slot.scm:
* module/language/elisp/runtime/macro-slot.scm: Ensure that all
  top-level forms and comments are separated by exactly one newline.
  Remove blank lines in most procedure bodies. Delete trailing
  whitespace.
This commit is contained in:
Brian Templeton 2010-06-07 16:37:24 -04:00
parent 802b47bdc6
commit 372b11fc73
8 changed files with 75 additions and 119 deletions

View file

@ -36,21 +36,18 @@
; with-dynamic-binding routines to associate symbols to different bindings ; with-dynamic-binding routines to associate symbols to different bindings
; over a dynamic extent. ; over a dynamic extent.
; Record type used to hold the data necessary. ; Record type used to hold the data necessary.
(define bindings-type (define bindings-type
(make-record-type 'bindings (make-record-type 'bindings
'(needed-globals lexical-bindings))) '(needed-globals lexical-bindings)))
; Construct an 'empty' instance of the bindings data structure to be used ; Construct an 'empty' instance of the bindings data structure to be used
; at the start of a fresh compilation. ; at the start of a fresh compilation.
(define (make-bindings) (define (make-bindings)
((record-constructor bindings-type) '() (make-hash-table))) ((record-constructor bindings-type) '() (make-hash-table)))
; Mark that a given symbol is needed as global in the specified slot-module. ; Mark that a given symbol is needed as global in the specified slot-module.
(define (mark-global-needed! bindings sym module) (define (mark-global-needed! bindings sym module)
@ -62,7 +59,6 @@
(new-needed (assoc-set! old-needed module new-in-module))) (new-needed (assoc-set! old-needed module new-in-module)))
((record-modifier bindings-type 'needed-globals) bindings new-needed))) ((record-modifier bindings-type 'needed-globals) bindings new-needed)))
; Cycle through all globals needed in order to generate the code for their ; Cycle through all globals needed in order to generate the code for their
; creation or some other analysis. ; creation or some other analysis.
@ -85,7 +81,6 @@
(cons (proc module (car sym-tail)) (cons (proc module (car sym-tail))
sym-result)))))))))) sym-result))))))))))
; Get the current lexical binding (gensym it should refer to in the current ; Get the current lexical binding (gensym it should refer to in the current
; scope) for a symbol or #f if it is dynamically bound. ; scope) for a symbol or #f if it is dynamically bound.
@ -96,7 +91,6 @@
(fluid-ref slot) (fluid-ref slot)
#f))) #f)))
; Establish a binding or mark a symbol as dynamically bound for the extent of ; Establish a binding or mark a symbol as dynamically bound for the extent of
; calling proc. ; calling proc.

View file

@ -6,12 +6,12 @@
;; it under the terms of the GNU General Public License as published by ;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option) ;; the Free Software Foundation; either version 3, or (at your option)
;; any later version. ;; any later version.
;; ;;
;; This program is distributed in the hope that it will be useful, ;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details. ;; GNU General Public License for more details.
;; ;;
;; You should have received a copy of the GNU General Public License ;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING. If not, write to ;; along with this program; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
@ -27,21 +27,22 @@
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
#:export (compile-tree-il)) #:export (compile-tree-il))
; Certain common parameters (like the bindings data structure or compiler ; Certain common parameters (like the bindings data structure or compiler
; options) are not always passed around but accessed using fluids to simulate ; options) are not always passed around but accessed using fluids to simulate
; dynamic binding (hey, this is about elisp). ; dynamic binding (hey, this is about elisp).
; The bindings data structure to keep track of symbol binding related data. ; The bindings data structure to keep track of symbol binding related data.
(define bindings-data (make-fluid)) (define bindings-data (make-fluid))
; Store for which symbols (or all/none) void checks are disabled. ; Store for which symbols (or all/none) void checks are disabled.
(define disable-void-check (make-fluid)) (define disable-void-check (make-fluid))
; Store which symbols (or all/none) should always be bound lexically, even ; Store which symbols (or all/none) should always be bound lexically, even
; with ordinary let and as lambda arguments. ; with ordinary let and as lambda arguments.
(define always-lexical (make-fluid))
(define always-lexical (make-fluid))
; Find the source properties of some parsed expression if there are any ; Find the source properties of some parsed expression if there are any
; associated with it. ; associated with it.
@ -52,20 +53,21 @@
(and (not (null? props)) (and (not (null? props))
props)))) props))))
; Values to use for Elisp's nil and t. ; Values to use for Elisp's nil and t.
(define (nil-value loc) (make-const loc (@ (language elisp runtime) nil-value))) (define (nil-value loc) (make-const loc (@ (language elisp runtime) nil-value)))
(define (t-value loc) (make-const loc (@ (language elisp runtime) t-value)))
(define (t-value loc) (make-const loc (@ (language elisp runtime) t-value)))
; Modules that contain the value and function slot bindings. ; Modules that contain the value and function slot bindings.
(define runtime '(language elisp runtime)) (define runtime '(language elisp runtime))
(define macro-slot '(language elisp runtime macro-slot))
(define value-slot (@ (language elisp runtime) value-slot-module))
(define function-slot (@ (language elisp runtime) function-slot-module))
(define macro-slot '(language elisp runtime macro-slot))
(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 ; The backquoting works the same as quasiquotes in Scheme, but the forms are
; named differently; to make easy adaptions, we define these predicates checking ; named differently; to make easy adaptions, we define these predicates checking
@ -80,13 +82,11 @@
(define (unquote-splicing? sym) (define (unquote-splicing? sym)
(and (symbol? sym) (eq? sym '\,@))) (and (symbol? sym) (eq? sym '\,@)))
; Build a call to a primitive procedure nicely. ; Build a call to a primitive procedure nicely.
(define (call-primitive loc sym . args) (define (call-primitive loc sym . args)
(make-application loc (make-primitive-ref loc sym) args)) (make-application loc (make-primitive-ref loc sym) args))
; Error reporting routine for syntax/compilation problems or build code for ; Error reporting routine for syntax/compilation problems or build code for
; a runtime-error output. ; a runtime-error output.
@ -97,7 +97,6 @@
(make-application loc (make-primitive-ref loc 'error) (make-application loc (make-primitive-ref loc 'error)
(cons (make-const loc msg) args))) (cons (make-const loc msg) args)))
; Generate code to ensure a global symbol is there for further use of a given ; Generate code to ensure a global symbol is there for further use of a given
; symbol. In general during the compilation, those needed are only tracked with ; symbol. In general during the compilation, those needed are only tracked with
; the bindings data structure. Afterwards, however, for all those needed ; the bindings data structure. Afterwards, however, for all those needed
@ -108,7 +107,6 @@
(list (make-const loc module) (list (make-const loc module)
(make-const loc sym)))) (make-const loc sym))))
; See if we should do a void-check for a given variable. That means, check ; See if we should do a void-check for a given variable. That means, check
; that this check is not disabled via the compiler options for this symbol. ; that this check is not disabled via the compiler options for this symbol.
; Disabling of void check is only done for the value-slot module! ; Disabling of void check is only done for the value-slot module!
@ -119,7 +117,6 @@
(and (not (eq? disabled 'all)) (and (not (eq? disabled 'all))
(not (memq sym disabled)))))) (not (memq sym disabled))))))
; Build a construct that establishes dynamic bindings for certain variables. ; Build a construct that establishes dynamic bindings for certain variables.
; We may want to choose between binding with fluids and with-fluids* and ; We may want to choose between binding with fluids and with-fluids* and
; using just ordinary module symbols and setting/reverting their values with ; using just ordinary module symbols and setting/reverting their values with
@ -135,7 +132,6 @@
(make-lambda loc '() (make-lambda loc '()
(make-lambda-case #f '() #f #f #f '() '() body #f)))) (make-lambda-case #f '() #f #f #f '() '() body #f))))
; Handle access to a variable (reference/setting) correctly depending on ; Handle access to a variable (reference/setting) correctly depending on
; whether it is currently lexically or dynamically bound. ; whether it is currently lexically or dynamically bound.
; lexical access is done only for references to the value-slot module! ; lexical access is done only for references to the value-slot module!
@ -146,7 +142,6 @@
(handle-lexical lexical) (handle-lexical lexical)
(handle-dynamic)))) (handle-dynamic))))
; Generate code to reference a variable. ; Generate code to reference a variable.
; For references in the value-slot module, we may want to generate a lexical ; For references in the value-slot module, we may want to generate a lexical
; reference instead if the variable has a lexical binding. ; reference instead if the variable has a lexical binding.
@ -160,7 +155,6 @@
(call-primitive loc 'fluid-ref (call-primitive loc 'fluid-ref
(make-module-ref loc module sym #t))))) (make-module-ref loc module sym #t)))))
; Reference a variable and error if the value is void. ; Reference a variable and error if the value is void.
(define (reference-with-check loc sym module) (define (reference-with-check loc sym module)
@ -175,7 +169,6 @@
(make-lexical-ref loc 'value var)))) (make-lexical-ref loc 'value var))))
(reference-variable loc sym module))) (reference-variable loc sym module)))
; Generate code to set a variable. ; Generate code to set a variable.
; Just as with reference-variable, in case of a reference to value-slot, ; Just as with reference-variable, in case of a reference to value-slot,
; we want to generate a lexical set when the variable has a lexical binding. ; we want to generate a lexical set when the variable has a lexical binding.
@ -190,7 +183,6 @@
(make-module-ref loc module sym #t) (make-module-ref loc module sym #t)
value)))) value))))
; Process the bindings part of a let or let* expression; that is, check for ; Process the bindings part of a let or let* expression; that is, check for
; correctness and bring it to the form ((sym1 . val1) (sym2 . val2) ...). ; correctness and bring it to the form ((sym1 . val1) (sym2 . val2) ...).
@ -206,7 +198,6 @@
(cons (car b) (cadr b)))))) (cons (car b) (cadr b))))))
bindings)) bindings))
; Split the let bindings into a list to be done lexically and one dynamically. ; Split the let bindings into a list to be done lexically and one dynamically.
; A symbol will be bound lexically if and only if: ; A symbol will be bound lexically if and only if:
; We're processing a lexical-let (i.e. module is 'lexical), OR ; We're processing a lexical-let (i.e. module is 'lexical), OR
@ -231,7 +222,6 @@
(iterate (cdr tail) (cons (car tail) lexical) dynamic) (iterate (cdr tail) (cons (car tail) lexical) dynamic)
(iterate (cdr tail) lexical (cons (car tail) dynamic)))))) (iterate (cdr tail) lexical (cons (car tail) dynamic))))))
; Compile let and let* expressions. The code here is used both for let/let* ; Compile let and let* expressions. The code here is used both for let/let*
; and flet/flet*, just with a different bindings module. ; and flet/flet*, just with a different bindings module.
; ;
@ -244,6 +234,7 @@
; among the bindings, we first do a let for all of them to evaluate all ; among the bindings, we first do a let for all of them to evaluate all
; values before any bindings take place, and then call let-dynamic for the ; values before any bindings take place, and then call let-dynamic for the
; variables to bind dynamically. ; variables to bind dynamically.
(define (generate-let loc module bindings body) (define (generate-let loc module bindings body)
(let ((bind (process-let-bindings loc bindings))) (let ((bind (process-let-bindings loc bindings)))
(call-with-values (call-with-values
@ -278,9 +269,9 @@
dynamic-syms) dynamic-syms)
(make-body))))))))))))) (make-body)))))))))))))
; Let* is compiled to a cascaded set of "small lets" for each binding in turn ; Let* is compiled to a cascaded set of "small lets" for each binding in turn
; so that each one already sees the preceding bindings. ; so that each one already sees the preceding bindings.
(define (generate-let* loc module bindings body) (define (generate-let* loc module bindings body)
(let ((bind (process-let-bindings loc bindings))) (let ((bind (process-let-bindings loc bindings)))
(begin (begin
@ -304,7 +295,6 @@
`(,(caar tail)) module `(,value) `(,(caar tail)) module `(,value)
(iterate (cdr tail)))))))))) (iterate (cdr tail))))))))))
; Split the argument list of a lambda expression into required, optional and ; Split the argument list of a lambda expression into required, optional and
; rest arguments and also check it is actually valid. ; rest arguments and also check it is actually valid.
; Additionally, we create a list of all "local variables" (that is, required, ; Additionally, we create a list of all "local variables" (that is, required,
@ -325,7 +315,6 @@
(lexical '()) (lexical '())
(dynamic '())) (dynamic '()))
(cond (cond
((null? tail) ((null? tail)
(let ((final-required (reverse required)) (let ((final-required (reverse required))
(final-optional (reverse optional)) (final-optional (reverse optional))
@ -333,11 +322,9 @@
(final-dynamic (reverse dynamic))) (final-dynamic (reverse dynamic)))
(values final-required final-optional #f (values final-required final-optional #f
final-lexical final-dynamic))) final-lexical final-dynamic)))
((and (eq? mode 'required) ((and (eq? mode 'required)
(eq? (car tail) '&optional)) (eq? (car tail) '&optional))
(iterate (cdr tail) 'optional required optional lexical dynamic)) (iterate (cdr tail) 'optional required optional lexical dynamic))
((eq? (car tail) '&rest) ((eq? (car tail) '&rest)
(if (or (null? (cdr tail)) (if (or (null? (cdr tail))
(not (null? (cddr tail)))) (not (null? (cddr tail))))
@ -354,7 +341,6 @@
(cons rest dynamic))))) (cons rest dynamic)))))
(values final-required final-optional rest (values final-required final-optional rest
final-lexical final-dynamic)))) final-lexical final-dynamic))))
(else (else
(if (not (symbol? (car tail))) (if (not (symbol? (car tail)))
(report-error loc "expected symbol in argument list, got" (car tail)) (report-error loc "expected symbol in argument list, got" (car tail))
@ -376,7 +362,6 @@
(else (else
(error "invalid mode in split-lambda-arguments" mode))))))))) (error "invalid mode in split-lambda-arguments" mode)))))))))
; Compile a lambda expression. Things get a little complicated because TreeIL ; Compile a lambda expression. Things get a little complicated because TreeIL
; does not allow optional arguments but only one rest argument, and also the ; does not allow optional arguments but only one rest argument, and also the
; rest argument should be nil instead of '() for no values given. Because of ; rest argument should be nil instead of '() for no values given. Because of
@ -486,6 +471,7 @@
; Build the code to handle setting of optional arguments that are present ; Build the code to handle setting of optional arguments that are present
; and updating the rest list. ; and updating the rest list.
(define (process-optionals loc optional rest-name rest-sym) (define (process-optionals loc optional rest-name rest-sym)
(let iterate ((tail optional)) (let iterate ((tail optional))
(if (null? tail) (if (null? tail)
@ -503,6 +489,7 @@
(iterate (cdr tail)))))))) (iterate (cdr tail))))))))
; This builds the code to set the rest variable to nil if it is empty. ; This builds the code to set the rest variable to nil if it is empty.
(define (process-rest loc rest rest-name rest-sym) (define (process-rest loc rest rest-name rest-sym)
(let ((rest-empty (call-primitive loc 'null? (let ((rest-empty (call-primitive loc 'null?
(make-lexical-ref loc rest-name rest-sym)))) (make-lexical-ref loc rest-name rest-sym))))
@ -518,7 +505,6 @@
(runtime-error loc "too many arguments and no rest argument"))) (runtime-error loc "too many arguments and no rest argument")))
(else (make-void loc))))) (else (make-void loc)))))
; Handle the common part of defconst and defvar, that is, checking for a correct ; 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 ; doc string and arguments as well as maybe in the future handling the docstring
; somehow. ; somehow.
@ -533,7 +519,6 @@
; TODO: Handle doc string if present. ; TODO: Handle doc string if present.
(else #t))) (else #t)))
; Handle macro bindings. ; Handle macro bindings.
(define (is-macro? sym) (define (is-macro? sym)
@ -550,7 +535,6 @@
(define (get-macro sym) (define (get-macro sym)
(module-ref (resolve-module macro-slot) sym)) (module-ref (resolve-module macro-slot) sym))
; See if a (backquoted) expression contains any unquotes. ; See if a (backquoted) expression contains any unquotes.
(define (contains-unquotes? expr) (define (contains-unquotes? expr)
@ -561,15 +545,15 @@
(contains-unquotes? (cdr expr)))) (contains-unquotes? (cdr expr))))
#f)) #f))
; Process a backquoted expression by building up the needed cons/append calls. ; 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 ; 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 ; 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 ; if it does not, but Scheme explicitly forbids it and this seems reasonable
; also for elisp. ; also for elisp.
(define (unquote-cell? expr) (define (unquote-cell? expr)
(and (list? expr) (= (length expr) 2) (unquote? (car expr)))) (and (list? expr) (= (length expr) 2) (unquote? (car expr))))
(define (unquote-splicing-cell? expr) (define (unquote-splicing-cell? expr)
(and (list? expr) (= (length expr) 2) (unquote-splicing? (car expr)))) (and (list? expr) (= (length expr) 2) (unquote-splicing? (car expr))))
@ -595,7 +579,6 @@
(report-error loc "non-pair expression contains unquotes" expr)) (report-error loc "non-pair expression contains unquotes" expr))
(make-const loc expr))) (make-const loc expr)))
; Temporarily update a list of symbols that are handled specially (disabled ; Temporarily update a list of symbols that are handled specially (disabled
; void check or always lexical) for compiling body. ; void check or always lexical) for compiling body.
; We need to handle special cases for already all / set to all and the like. ; We need to handle special cases for already all / set to all and the like.
@ -617,7 +600,6 @@
(with-fluids ((fluid new)) (with-fluids ((fluid new))
(make-body)))))) (make-body))))))
; Compile a symbol expression. This is a variable reference or maybe some ; Compile a symbol expression. This is a variable reference or maybe some
; special value like nil. ; special value like nil.
@ -627,12 +609,10 @@
((t) (t-value loc)) ((t) (t-value loc))
(else (reference-with-check loc sym value-slot)))) (else (reference-with-check loc sym value-slot))))
; Compile a pair-expression (that is, any structure-like construct). ; Compile a pair-expression (that is, any structure-like construct).
(define (compile-pair loc expr) (define (compile-pair loc expr)
(pmatch expr (pmatch expr
((progn . ,forms) ((progn . ,forms)
(make-sequence loc (map compile-expr forms))) (make-sequence loc (map compile-expr forms)))
@ -640,10 +620,12 @@
(make-conditional loc (compile-expr condition) (make-conditional loc (compile-expr condition)
(compile-expr ifclause) (compile-expr ifclause)
(nil-value loc))) (nil-value loc)))
((if ,condition ,ifclause ,elseclause) ((if ,condition ,ifclause ,elseclause)
(make-conditional loc (compile-expr condition) (make-conditional loc (compile-expr condition)
(compile-expr ifclause) (compile-expr ifclause)
(compile-expr elseclause))) (compile-expr elseclause)))
((if ,condition ,ifclause . ,elses) ((if ,condition ,ifclause . ,elses)
(make-conditional loc (compile-expr condition) (make-conditional loc (compile-expr condition)
(compile-expr ifclause) (compile-expr ifclause)
@ -659,6 +641,7 @@
(make-const loc sym))))) (make-const loc sym)))))
((defvar ,sym) (make-const loc sym)) ((defvar ,sym) (make-const loc sym))
((defvar ,sym ,value . ,doc) ((defvar ,sym ,value . ,doc)
(if (handle-var-def loc sym doc) (if (handle-var-def loc sym doc)
(make-sequence loc (make-sequence loc
@ -674,6 +657,7 @@
; Build a set form for possibly multiple values. The code is not formulated ; Build a set form for possibly multiple values. The code is not formulated
; tail recursive because it is clearer this way and large lists of symbol ; tail recursive because it is clearer this way and large lists of symbol
; expression pairs are very unlikely. ; expression pairs are very unlikely.
((setq . ,args) (guard (not (null? args))) ((setq . ,args) (guard (not (null? args)))
(make-sequence loc (make-sequence loc
(let iterate ((tail args)) (let iterate ((tail args))
@ -702,10 +686,12 @@
(not (null? bindings)) (not (null? bindings))
(not (null? body)))) (not (null? body))))
(generate-let loc value-slot bindings body)) (generate-let loc value-slot bindings body))
((lexical-let ,bindings . ,body) (guard (and (list? bindings) ((lexical-let ,bindings . ,body) (guard (and (list? bindings)
(not (null? bindings)) (not (null? bindings))
(not (null? body)))) (not (null? body))))
(generate-let loc 'lexical bindings body)) (generate-let loc 'lexical bindings body))
((flet ,bindings . ,body) (guard (and (list? bindings) ((flet ,bindings . ,body) (guard (and (list? bindings)
(not (null? bindings)) (not (null? bindings))
(not (null? body)))) (not (null? body))))
@ -715,10 +701,12 @@
(not (null? bindings)) (not (null? bindings))
(not (null? body)))) (not (null? body))))
(generate-let* loc value-slot bindings body)) (generate-let* loc value-slot bindings body))
((lexical-let* ,bindings . ,body) (guard (and (list? bindings) ((lexical-let* ,bindings . ,body) (guard (and (list? bindings)
(not (null? bindings)) (not (null? bindings))
(not (null? body)))) (not (null? body))))
(generate-let* loc 'lexical bindings body)) (generate-let* loc 'lexical bindings body))
((flet* ,bindings . ,body) (guard (and (list? bindings) ((flet* ,bindings . ,body) (guard (and (list? bindings)
(not (null? bindings)) (not (null? bindings))
(not (null? body)))) (not (null? body))))
@ -737,11 +725,13 @@
; elisp as a way to access data within ; elisp as a way to access data within
; the Guile universe. The module and symbol referenced are static values, ; the Guile universe. The module and symbol referenced are static values,
; just like (@ module symbol) does! ; just like (@ module symbol) does!
((guile-ref ,module ,sym) (guard (and (list? module) (symbol? sym))) ((guile-ref ,module ,sym) (guard (and (list? module) (symbol? sym)))
(make-module-ref loc module sym #t)) (make-module-ref loc module sym #t))
; guile-primitive allows to create primitive references, which are still ; guile-primitive allows to create primitive references, which are still
; a little faster. ; a little faster.
((guile-primitive ,sym) (guard (symbol? sym)) ((guile-primitive ,sym) (guard (symbol? sym))
(make-primitive-ref loc sym)) (make-primitive-ref loc sym))
@ -755,6 +745,7 @@
; ;
; As letrec is not directly accessible from elisp, while is implemented here ; As letrec is not directly accessible from elisp, while is implemented here
; instead of with a macro. ; instead of with a macro.
((while ,condition . ,body) ((while ,condition . ,body)
(let* ((itersym (gensym)) (let* ((itersym (gensym))
(compiled-body (map compile-expr body)) (compiled-body (map compile-expr body))
@ -775,14 +766,17 @@
; Either (lambda ...) or (function (lambda ...)) denotes a lambda-expression ; Either (lambda ...) or (function (lambda ...)) denotes a lambda-expression
; that should be compiled. ; that should be compiled.
((lambda ,args . ,body) ((lambda ,args . ,body)
(compile-lambda loc args body)) (compile-lambda loc args body))
((function (lambda ,args . ,body)) ((function (lambda ,args . ,body))
(compile-lambda loc args body)) (compile-lambda loc args body))
; Build a lambda and also assign it to the function cell of some symbol. ; Build a lambda and also assign it to the function cell of some symbol.
; This is no macro as we might want to honour the docstring at some time; ; This is no macro as we might want to honour the docstring at some time;
; just as with defvar/defconst. ; just as with defvar/defconst.
((defun ,name ,args . ,body) ((defun ,name ,args . ,body)
(if (not (symbol? name)) (if (not (symbol? name))
(report-error loc "expected symbol as function name" name) (report-error loc "expected symbol as function name" name)
@ -793,6 +787,7 @@
; Define a macro (this is done directly at compile-time!). ; Define a macro (this is done directly at compile-time!).
; FIXME: Recursive macros don't work! ; FIXME: Recursive macros don't work!
((defmacro ,name ,args . ,body) ((defmacro ,name ,args . ,body)
(if (not (symbol? name)) (if (not (symbol? name))
(report-error loc "expected symbol as macro name" name) (report-error loc "expected symbol as macro name" name)
@ -803,14 +798,17 @@
(make-const loc name)))) (make-const loc name))))
; XXX: Maybe we could implement backquotes in macros, too. ; XXX: Maybe we could implement backquotes in macros, too.
((,backq ,val) (guard (backquote? backq)) ((,backq ,val) (guard (backquote? backq))
(process-backquote loc val)) (process-backquote loc val))
; XXX: Why do we need 'quote here instead of quote? ; XXX: Why do we need 'quote here instead of quote?
(('quote ,val) (('quote ,val)
(make-const loc val)) (make-const loc val))
; Macro calls are simply expanded and recursively compiled. ; Macro calls are simply expanded and recursively compiled.
((,macro . ,args) (guard (and (symbol? macro) (is-macro? macro))) ((,macro . ,args) (guard (and (symbol? macro) (is-macro? macro)))
(let ((expander (get-macro macro))) (let ((expander (get-macro macro)))
(compile-expr (apply expander args)))) (compile-expr (apply expander args))))
@ -819,6 +817,7 @@
; take the function value of a symbol if it is one. It seems that functions ; take the function value of a symbol if it is one. It seems that functions
; in form of uncompiled lists are not supported in this syntax, so we don't ; in form of uncompiled lists are not supported in this syntax, so we don't
; have to care for them. ; have to care for them.
((,func . ,args) ((,func . ,args)
(make-application loc (make-application loc
(if (symbol? func) (if (symbol? func)
@ -829,7 +828,6 @@
(else (else
(report-error loc "unrecognized elisp" expr)))) (report-error loc "unrecognized elisp" expr))))
; Compile a single expression to TreeIL. ; Compile a single expression to TreeIL.
(define (compile-expr expr) (define (compile-expr expr)
@ -841,7 +839,6 @@
(compile-pair loc expr)) (compile-pair loc expr))
(else (make-const loc expr))))) (else (make-const loc expr)))))
; Process the compiler options. ; Process the compiler options.
; FIXME: Why is '(()) passed as options by the REPL? ; FIXME: Why is '(()) passed as options by the REPL?
@ -867,7 +864,6 @@
(report-error #f "Invalid value for #:always-lexical" value))) (report-error #f "Invalid value for #:always-lexical" value)))
(else (report-error #f "Invalid compiler option" key))))))) (else (report-error #f "Invalid compiler option" key)))))))
; Entry point for compilation to TreeIL. ; Entry point for compilation to TreeIL.
; This creates the bindings data structure, and after compiling the main ; This creates the bindings data structure, and after compiling the main
; expression we need to make sure all globals for symbols used during the ; expression we need to make sure all globals for symbols used during the

View file

@ -34,20 +34,17 @@
; TODO: #@count comments ; TODO: #@count comments
; Report an error from the lexer (that is, invalid input given). ; Report an error from the lexer (that is, invalid input given).
(define (lexer-error port msg . args) (define (lexer-error port msg . args)
(apply error msg args)) (apply error msg args))
; In a character, set a given bit. This is just some bit-wise or'ing on the ; In a character, set a given bit. This is just some bit-wise or'ing on the
; characters integer code and converting back to character. ; characters integer code and converting back to character.
(define (set-char-bit chr bit) (define (set-char-bit chr bit)
(logior chr (ash 1 bit))) (logior chr (ash 1 bit)))
; Check if a character equals some other. This is just like char=? except that ; Check if a character equals some other. This is just like char=? except that
; the tested one could be EOF in which case it simply isn't equal. ; the tested one could be EOF in which case it simply isn't equal.
@ -55,7 +52,6 @@
(and (not (eof-object? tested)) (and (not (eof-object? tested))
(char=? tested should-be))) (char=? tested should-be)))
; For a character (as integer code), find the real character it represents or ; For a character (as integer code), find the real character it represents or
; #\nul if out of range. This is used to work with Scheme character functions ; #\nul if out of range. This is used to work with Scheme character functions
; like char-numeric?. ; like char-numeric?.
@ -65,7 +61,6 @@
(integer->char chr) (integer->char chr)
#\nul)) #\nul))
; Return the control modified version of a character. This is not just setting ; Return the control modified version of a character. This is not just setting
; a modifier bit, because ASCII conrol characters must be handled as such, and ; a modifier bit, because ASCII conrol characters must be handled as such, and
; in elisp C-? is the delete character for historical reasons. ; in elisp C-? is the delete character for historical reasons.
@ -80,7 +75,6 @@
((#\@) 0) ((#\@) 0)
(else (set-char-bit chr 26)))))) (else (set-char-bit chr 26))))))
; Parse a charcode given in some base, basically octal or hexadecimal are ; Parse a charcode given in some base, basically octal or hexadecimal are
; needed. A requested number of digits can be given (#f means it does ; needed. A requested number of digits can be given (#f means it does
; not matter and arbitrary many are allowed), and additionally early ; not matter and arbitrary many are allowed), and additionally early
@ -113,7 +107,6 @@
(lexer-error port "invalid digit in escape-code" base cur)) (lexer-error port "invalid digit in escape-code" base cur))
(iterate (+ (* result base) value) (1+ procdigs))))))) (iterate (+ (* result base) value) (1+ procdigs)))))))
; Read a character and process escape-sequences when necessary. The special ; Read a character and process escape-sequences when necessary. The special
; in-string argument defines if this character is part of a string literal or ; in-string argument defines if this character is part of a string literal or
; a single character literal, the difference being that in strings the ; a single character literal, the difference being that in strings the
@ -129,13 +122,11 @@
(#\S . 25) (#\M . ,(if in-string 7 27)))) (#\S . 25) (#\M . ,(if in-string 7 27))))
(cur (read-char port))) (cur (read-char port)))
(if (char=? cur #\\) (if (char=? cur #\\)
; Handle an escape-sequence. ; Handle an escape-sequence.
(let* ((escaped (read-char port)) (let* ((escaped (read-char port))
(esc-code (assq-ref basic-escape-codes escaped)) (esc-code (assq-ref basic-escape-codes escaped))
(meta (assq-ref meta-bits escaped))) (meta (assq-ref meta-bits escaped)))
(cond (cond
; Meta-check must be before esc-code check because \s- must be ; Meta-check must be before esc-code check because \s- must be
; recognized as the super-meta modifier if a - follows. ; recognized as the super-meta modifier if a - follows.
; If not, it will be caught as \s -> space escape code. ; If not, it will be caught as \s -> space escape code.
@ -143,16 +134,13 @@
(if (not (char=? (read-char port) #\-)) (if (not (char=? (read-char port) #\-))
(error "expected - after control sequence")) (error "expected - after control sequence"))
(set-char-bit (get-character port in-string) meta)) (set-char-bit (get-character port in-string) meta))
; One of the basic control character escape names? ; One of the basic control character escape names?
(esc-code esc-code) (esc-code esc-code)
; Handle \ddd octal code if it is one. ; Handle \ddd octal code if it is one.
((and (char>=? escaped #\0) (char<? escaped #\8)) ((and (char>=? escaped #\0) (char<? escaped #\8))
(begin (begin
(unread-char escaped port) (unread-char escaped port)
(charcode-escape port 8 3 #t))) (charcode-escape port 8 3 #t)))
; Check for some escape-codes directly or otherwise ; Check for some escape-codes directly or otherwise
; use the escaped character literally. ; use the escaped character literally.
(else (else
@ -169,12 +157,10 @@
((#\u) (charcode-escape port 16 4 #f)) ((#\u) (charcode-escape port 16 4 #f))
((#\U) (charcode-escape port 16 8 #f)) ((#\U) (charcode-escape port 16 8 #f))
(else (char->integer escaped)))))) (else (char->integer escaped))))))
; No escape-sequence, just the literal character. ; No escape-sequence, just the literal character.
; But remember to get the code instead! ; But remember to get the code instead!
(char->integer cur)))) (char->integer cur))))
; Read a symbol or number from a port until something follows that marks the ; Read a symbol or number from a port until something follows that marks the
; start of a new token (like whitespace or parentheses). The data read is ; start of a new token (like whitespace or parentheses). The data read is
; returned as a string for further conversion to the correct type, but we also ; returned as a string for further conversion to the correct type, but we also
@ -184,11 +170,13 @@
; if it is possibly an integer or a float. ; if it is possibly an integer or a float.
(define integer-regex (make-regexp "^[+-]?[0-9]+\\.?$")) (define integer-regex (make-regexp "^[+-]?[0-9]+\\.?$"))
(define float-regex (define float-regex
(make-regexp "^[+-]?([0-9]+\\.?[0-9]*|[0-9]*\\.?[0-9]+)(e[+-]?[0-9]+)?$")) (make-regexp "^[+-]?([0-9]+\\.?[0-9]*|[0-9]*\\.?[0-9]+)(e[+-]?[0-9]+)?$"))
; A dot is also allowed literally, only a single dort alone is parsed as the ; A dot is also allowed literally, only a single dort alone is parsed as the
; 'dot' terminal for dotted lists. ; 'dot' terminal for dotted lists.
(define no-escape-punctuation (string->char-set "-+=*/_~!@$%^&:<>{}?.")) (define no-escape-punctuation (string->char-set "-+=*/_~!@$%^&:<>{}?."))
(define (get-symbol-or-number port) (define (get-symbol-or-number port)
@ -220,7 +208,6 @@
(unread-char c port) (unread-char c port)
(finish)))))) (finish))))))
; Parse a circular structure marker without the leading # (which was already ; Parse a circular structure marker without the leading # (which was already
; read and recognized), that is, a number as identifier and then either ; read and recognized), that is, a number as identifier and then either
; = or #. ; = or #.
@ -239,7 +226,6 @@
((#\#) `(circular-ref . ,id)) ((#\#) `(circular-ref . ,id))
((#\=) `(circular-def . ,id)) ((#\=) `(circular-def . ,id))
(else (lexer-error port "invalid circular marker character" type)))))) (else (lexer-error port "invalid circular marker character" type))))))
; Main lexer routine, which is given a port and does look for the next token. ; Main lexer routine, which is given a port and does look for the next token.
@ -257,23 +243,18 @@
; and actually point to the very character to be read. ; and actually point to the very character to be read.
(c (read-char port))) (c (read-char port)))
(cond (cond
; End of input must be specially marked to the parser. ; End of input must be specially marked to the parser.
((eof-object? c) '*eoi*) ((eof-object? c) '*eoi*)
; Whitespace, just skip it. ; Whitespace, just skip it.
((char-whitespace? c) (lex port)) ((char-whitespace? c) (lex port))
; The dot is only the one for dotted lists if followed by ; The dot is only the one for dotted lists if followed by
; whitespace. Otherwise it is considered part of a number of symbol. ; whitespace. Otherwise it is considered part of a number of symbol.
((and (char=? c #\.) ((and (char=? c #\.)
(char-whitespace? (peek-char port))) (char-whitespace? (peek-char port)))
(return 'dot #f)) (return 'dot #f))
; Continue checking for literal character values. ; Continue checking for literal character values.
(else (else
(case c (case c
; A line comment, skip until end-of-line is found. ; A line comment, skip until end-of-line is found.
((#\;) ((#\;)
(let iterate () (let iterate ()
@ -281,11 +262,9 @@
(if (or (eof-object? cur) (char=? cur #\newline)) (if (or (eof-object? cur) (char=? cur #\newline))
(lex port) (lex port)
(iterate))))) (iterate)))))
; A character literal. ; A character literal.
((#\?) ((#\?)
(return 'character (get-character port #f))) (return 'character (get-character port #f)))
; A literal string. This is mainly a sequence of characters just ; A literal string. This is mainly a sequence of characters just
; as in the character literals, the only difference is that escaped ; as in the character literals, the only difference is that escaped
; newline and space are to be completely ignored and that meta-escapes ; newline and space are to be completely ignored and that meta-escapes
@ -307,12 +286,10 @@
(iterate (cons (integer->char (get-character port #t)) (iterate (cons (integer->char (get-character port #t))
result-chars)))))) result-chars))))))
(else (iterate (cons cur result-chars))))))) (else (iterate (cons cur result-chars)))))))
; Circular markers (either reference or definition). ; Circular markers (either reference or definition).
((#\#) ((#\#)
(let ((mark (get-circular-marker port))) (let ((mark (get-circular-marker port)))
(return (car mark) (cdr mark)))) (return (car mark) (cdr mark))))
; Parentheses and other special-meaning single characters. ; Parentheses and other special-meaning single characters.
((#\() (return 'paren-open #f)) ((#\() (return 'paren-open #f))
((#\)) (return 'paren-close #f)) ((#\)) (return 'paren-close #f))
@ -320,7 +297,6 @@
((#\]) (return 'square-close #f)) ((#\]) (return 'square-close #f))
((#\') (return 'quote #f)) ((#\') (return 'quote #f))
((#\`) (return 'backquote #f)) ((#\`) (return 'backquote #f))
; Unquote and unquote-splicing. ; Unquote and unquote-splicing.
((#\,) ((#\,)
(if (is-char? (peek-char port) #\@) (if (is-char? (peek-char port) #\@)
@ -328,7 +304,6 @@
(error "expected @ in unquote-splicing") (error "expected @ in unquote-splicing")
(return 'unquote-splicing #f)) (return 'unquote-splicing #f))
(return 'unquote #f))) (return 'unquote #f)))
; Remaining are numbers and symbols. Process input until next ; Remaining are numbers and symbols. Process input until next
; whitespace is found, and see if it looks like a number ; whitespace is found, and see if it looks like a number
; (float/integer) or symbol and return accordingly. ; (float/integer) or symbol and return accordingly.
@ -369,7 +344,6 @@
num))) num)))
(else (error "wrong number/symbol type" type))))))))))) (else (error "wrong number/symbol type" type)))))))))))
; Build a lexer thunk for a port. This is the exported routine which can be ; Build a lexer thunk for a port. This is the exported routine which can be
; used to create a lexer for the parser to use. ; used to create a lexer for the parser to use.
@ -377,7 +351,6 @@
(lambda () (lambda ()
(lex port))) (lex port)))
; Build a special lexer that will only read enough for one expression and then ; Build a special lexer that will only read enough for one expression and then
; always return end-of-input. ; always return end-of-input.
; If we find one of the quotation stuff, one more expression is needed in any ; If we find one of the quotation stuff, one more expression is needed in any

View file

@ -28,14 +28,12 @@
; lexer ((text parse-lalr) seems not to allow access to the original lexer ; lexer ((text parse-lalr) seems not to allow access to the original lexer
; token-pair) and is easy enough anyways. ; token-pair) and is easy enough anyways.
; Report a parse error. The first argument is some current lexer token ; Report a parse error. The first argument is some current lexer token
; where source information is available should it be useful. ; where source information is available should it be useful.
(define (parse-error token msg . args) (define (parse-error token msg . args)
(apply error msg args)) (apply error msg args))
; For parsing circular structures, we keep track of definitions in a ; For parsing circular structures, we keep track of definitions in a
; hash-map that maps the id's to their values. ; hash-map that maps the id's to their values.
; When defining a new id, though, we immediatly fill the slot with a promise ; When defining a new id, though, we immediatly fill the slot with a promise
@ -64,6 +62,7 @@
; Returned is a closure that, when invoked, will set the final value. ; Returned is a closure that, when invoked, will set the final value.
; This means both the variable the promise will return and the hash-table ; This means both the variable the promise will return and the hash-table
; slot so we don't generate promises any longer. ; slot so we don't generate promises any longer.
(define (circular-define! token) (define (circular-define! token)
(if (not (eq? (car token) 'circular-def)) (if (not (eq? (car token) 'circular-def))
(error "invalid token for circular-define!" token)) (error "invalid token for circular-define!" token))
@ -80,6 +79,7 @@
; this may lead to infinite recursion with a circular structure, and ; this may lead to infinite recursion with a circular structure, and
; additionally this value was already processed when it was defined. ; additionally this value was already processed when it was defined.
; All deep data structures that can be parsed must be handled here! ; All deep data structures that can be parsed must be handled here!
(define (force-promises! data) (define (force-promises! data)
(cond (cond
((pair? data) ((pair? data)
@ -102,7 +102,6 @@
; Else nothing needs to be done. ; Else nothing needs to be done.
)) ))
; We need peek-functionality for the next lexer token, this is done with some ; We need peek-functionality for the next lexer token, this is done with some
; single token look-ahead storage. This is handled by a closure which allows ; single token look-ahead storage. This is handled by a closure which allows
; getting or peeking the next token. ; getting or peeking the next token.
@ -128,7 +127,6 @@
result)) result))
(else (error "invalid lexer-buffer action" action)))))))) (else (error "invalid lexer-buffer action" action))))))))
; Get the contents of a list, where the opening parentheses has already been ; Get the contents of a list, where the opening parentheses has already been
; found. The same code is used for vectors and lists, where lists allow the ; found. The same code is used for vectors and lists, where lists allow the
; dotted tail syntax and vectors not; additionally, the closing parenthesis ; dotted tail syntax and vectors not; additionally, the closing parenthesis
@ -159,8 +157,6 @@
(tail (get-list lex allow-dot close-square))) (tail (get-list lex allow-dot close-square)))
(cons head tail)))))) (cons head tail))))))
; Parse a single expression from a lexer-buffer. This is the main routine in ; Parse a single expression from a lexer-buffer. This is the main routine in
; our recursive-descent parser. ; our recursive-descent parser.
@ -197,7 +193,6 @@
(else (else
(parse-error token "expected expression, got" token))))) (parse-error token "expected expression, got" token)))))
; Define the reader function based on this; build a lexer, a lexer-buffer, ; Define the reader function based on this; build a lexer, a lexer-buffer,
; and then parse a single expression to return. ; and then parse a single expression to return.
; We also define a circular-definitions data structure to use. ; We also define a circular-definitions data structure to use.

View file

@ -22,36 +22,31 @@
#:export (void #:export (void
nil-value t-value nil-value t-value
value-slot-module function-slot-module value-slot-module function-slot-module
elisp-bool elisp-bool
ensure-fluid! reference-variable reference-variable-with-check ensure-fluid! reference-variable reference-variable-with-check
set-variable! set-variable!
runtime-error macro-error) runtime-error macro-error)
#:export-syntax (built-in-func built-in-macro prim)) #:export-syntax (built-in-func built-in-macro prim))
; This module provides runtime support for the Elisp front-end. ; This module provides runtime support for the Elisp front-end.
; The reserved value to mean (when eq?) void. ; The reserved value to mean (when eq?) void.
(define void (list 42)) (define void (list 42))
; Values for t and nil. (FIXME remove this abstraction) ; Values for t and nil. (FIXME remove this abstraction)
(define nil-value #nil) (define nil-value #nil)
(define t-value #t)
(define t-value #t)
; Modules for the binding slots. ; Modules for the binding slots.
; Note: Naming those value-slot and/or function-slot clashes with the ; Note: Naming those value-slot and/or function-slot clashes with the
; submodules of these names! ; submodules of these names!
(define value-slot-module '(language elisp runtime value-slot)) (define value-slot-module '(language elisp runtime value-slot))
(define function-slot-module '(language elisp runtime function-slot))
(define function-slot-module '(language elisp runtime function-slot))
; Report an error during macro compilation, that means some special compilation ; Report an error during macro compilation, that means some special compilation
; (syntax) error; or report a simple runtime-error from a built-in function. ; (syntax) error; or report a simple runtime-error from a built-in function.
@ -61,7 +56,6 @@
(define runtime-error macro-error) (define runtime-error macro-error)
; Convert a scheme boolean to Elisp. ; Convert a scheme boolean to Elisp.
(define (elisp-bool b) (define (elisp-bool b)
@ -69,7 +63,6 @@
t-value t-value
nil-value)) nil-value))
; Routines for access to elisp dynamically bound symbols. ; Routines for access to elisp dynamically bound symbols.
; This is used for runtime access using functions like symbol-value or set, ; This is used for runtime access using functions like symbol-value or set,
; where the symbol accessed might not be known at compile-time. ; where the symbol accessed might not be known at compile-time.
@ -101,7 +94,6 @@
(fluid-set! (module-ref resolved sym) value) (fluid-set! (module-ref resolved sym) value)
value)) value))
; Define a predefined function or predefined macro for use in the function-slot ; Define a predefined function or predefined macro for use in the function-slot
; and macro-slot modules, respectively. ; and macro-slot modules, respectively.
@ -117,7 +109,6 @@
((_ name value) ((_ name value)
(define-public name value)))) (define-public name value))))
; Call a guile-primitive that may be rebound for elisp and thus needs absolute ; Call a guile-primitive that may be rebound for elisp and thus needs absolute
; addressing. ; addressing.

View file

@ -25,7 +25,6 @@
; This module contains the function-slots of elisp symbols. Elisp built-in ; This module contains the function-slots of elisp symbols. Elisp built-in
; functions are implemented as predefined function bindings here. ; functions are implemented as predefined function bindings here.
; Equivalence and equalness predicates. ; Equivalence and equalness predicates.
(built-in-func eq (lambda (a b) (built-in-func eq (lambda (a b)
@ -34,7 +33,6 @@
(built-in-func equal (lambda (a b) (built-in-func equal (lambda (a b)
(elisp-bool (equal? a b)))) (elisp-bool (equal? a b))))
; Number predicates. ; Number predicates.
(built-in-func floatp (lambda (num) (built-in-func floatp (lambda (num)
@ -57,31 +55,34 @@
(built-in-func zerop (lambda (num) (built-in-func zerop (lambda (num)
(elisp-bool (prim = num 0)))) (elisp-bool (prim = num 0))))
; Number comparisons. ; Number comparisons.
(built-in-func = (lambda (num1 num2) (built-in-func = (lambda (num1 num2)
(elisp-bool (prim = num1 num2)))) (elisp-bool (prim = num1 num2))))
(built-in-func /= (lambda (num1 num2) (built-in-func /= (lambda (num1 num2)
(elisp-bool (prim not (prim = num1 num2))))) (elisp-bool (prim not (prim = num1 num2)))))
(built-in-func < (lambda (num1 num2) (built-in-func < (lambda (num1 num2)
(elisp-bool (prim < num1 num2)))) (elisp-bool (prim < num1 num2))))
(built-in-func <= (lambda (num1 num2) (built-in-func <= (lambda (num1 num2)
(elisp-bool (prim <= num1 num2)))) (elisp-bool (prim <= num1 num2))))
(built-in-func > (lambda (num1 num2) (built-in-func > (lambda (num1 num2)
(elisp-bool (prim > num1 num2)))) (elisp-bool (prim > num1 num2))))
(built-in-func >= (lambda (num1 num2) (built-in-func >= (lambda (num1 num2)
(elisp-bool (prim >= num1 num2)))) (elisp-bool (prim >= num1 num2))))
(built-in-func max (lambda (. nums) (built-in-func max (lambda (. nums)
(prim apply (@ (guile) max) nums))) (prim apply (@ (guile) max) nums)))
(built-in-func min (lambda (. nums) (built-in-func min (lambda (. nums)
(prim apply (@ (guile) min) nums))) (prim apply (@ (guile) min) nums)))
(built-in-func abs (@ (guile) abs)) (built-in-func abs (@ (guile) abs))
; Number conversion. ; Number conversion.
(built-in-func float (lambda (num) (built-in-func float (lambda (num)
@ -91,32 +92,38 @@
; TODO: truncate, floor, ceiling, round. ; TODO: truncate, floor, ceiling, round.
; Arithmetic functions. ; Arithmetic functions.
(built-in-func 1+ (@ (guile) 1+)) (built-in-func 1+ (@ (guile) 1+))
(built-in-func 1- (@ (guile) 1-)) (built-in-func 1- (@ (guile) 1-))
(built-in-func + (@ (guile) +)) (built-in-func + (@ (guile) +))
(built-in-func - (@ (guile) -)) (built-in-func - (@ (guile) -))
(built-in-func * (@ (guile) *)) (built-in-func * (@ (guile) *))
(built-in-func % (@ (guile) modulo)) (built-in-func % (@ (guile) modulo))
; TODO: / with correct integer/real behaviour, mod (for floating-piont values). ; TODO: / with correct integer/real behaviour, mod (for floating-piont values).
; Floating-point rounding operations. ; Floating-point rounding operations.
(built-in-func ffloor (@ (guile) floor)) (built-in-func ffloor (@ (guile) floor))
(built-in-func fceiling (@ (guile) ceiling))
(built-in-func ftruncate (@ (guile) truncate))
(built-in-func fround (@ (guile) round))
(built-in-func fceiling (@ (guile) ceiling))
(built-in-func ftruncate (@ (guile) truncate))
(built-in-func fround (@ (guile) round))
; List predicates. ; List predicates.
(built-in-func consp (built-in-func consp
(lambda (el) (lambda (el)
(elisp-bool (pair? el)))) (elisp-bool (pair? el))))
(built-in-func atomp (built-in-func atomp
(lambda (el) (lambda (el)
(elisp-bool (prim not (pair? el))))) (elisp-bool (prim not (pair? el)))))
@ -124,6 +131,7 @@
(built-in-func listp (built-in-func listp
(lambda (el) (lambda (el)
(elisp-bool (or (pair? el) (null? el))))) (elisp-bool (or (pair? el) (null? el)))))
(built-in-func nlistp (built-in-func nlistp
(lambda (el) (lambda (el)
(elisp-bool (and (prim not (pair? el)) (elisp-bool (and (prim not (pair? el))
@ -133,7 +141,6 @@
(lambda (el) (lambda (el)
(elisp-bool (null? el)))) (elisp-bool (null? el))))
; Accessing list elements. ; Accessing list elements.
(built-in-func car (built-in-func car
@ -141,6 +148,7 @@
(if (null? el) (if (null? el)
nil-value nil-value
(prim car el)))) (prim car el))))
(built-in-func cdr (built-in-func cdr
(lambda (el) (lambda (el)
(if (null? el) (if (null? el)
@ -152,6 +160,7 @@
(if (pair? el) (if (pair? el)
(prim car el) (prim car el)
nil-value))) nil-value)))
(built-in-func cdr-safe (built-in-func cdr-safe
(lambda (el) (lambda (el)
(if (pair? el) (if (pair? el)
@ -168,6 +177,7 @@
((null? tail) nil-value) ((null? tail) nil-value)
((zero? i) (prim car tail)) ((zero? i) (prim car tail))
(else (iterate (prim 1- i) (prim cdr tail)))))))) (else (iterate (prim 1- i) (prim cdr tail))))))))
(built-in-func nthcdr (built-in-func nthcdr
(lambda (n lst) (lambda (n lst)
(if (negative? n) (if (negative? n)
@ -181,17 +191,20 @@
(built-in-func length (@ (guile) length)) (built-in-func length (@ (guile) length))
; Building lists. ; Building lists.
(built-in-func cons (@ (guile) cons)) (built-in-func cons (@ (guile) cons))
(built-in-func list (@ (guile) list)) (built-in-func list (@ (guile) list))
(built-in-func make-list (built-in-func make-list
(lambda (len obj) (lambda (len obj)
(prim make-list len obj))) (prim make-list len obj)))
(built-in-func append (@ (guile) append)) (built-in-func append (@ (guile) append))
(built-in-func reverse (@ (guile) reverse)) (built-in-func reverse (@ (guile) reverse))
(built-in-func copy-tree (@ (guile) copy-tree)) (built-in-func copy-tree (@ (guile) copy-tree))
(built-in-func number-sequence (built-in-func number-sequence
@ -223,7 +236,6 @@
(prim cons i result) (prim cons i result)
(iterate (prim - i sep) (prim cons i result))))))))))) (iterate (prim - i sep) (prim cons i result)))))))))))
; Changing lists. ; Changing lists.
(built-in-func setcar (built-in-func setcar
@ -236,12 +248,12 @@
(prim set-cdr! cell val) (prim set-cdr! cell val)
val)) val))
; Accessing symbol bindings for symbols known only at runtime. ; Accessing symbol bindings for symbols known only at runtime.
(built-in-func symbol-value (built-in-func symbol-value
(lambda (sym) (lambda (sym)
(reference-variable-with-check value-slot-module sym))) (reference-variable-with-check value-slot-module sym)))
(built-in-func symbol-function (built-in-func symbol-function
(lambda (sym) (lambda (sym)
(reference-variable-with-check function-slot-module sym))) (reference-variable-with-check function-slot-module sym)))
@ -249,6 +261,7 @@
(built-in-func set (built-in-func set
(lambda (sym value) (lambda (sym value)
(set-variable! value-slot-module sym value))) (set-variable! value-slot-module sym value)))
(built-in-func fset (built-in-func fset
(lambda (sym value) (lambda (sym value)
(set-variable! function-slot-module sym value))) (set-variable! function-slot-module sym value)))
@ -257,6 +270,7 @@
(lambda (sym) (lambda (sym)
(set-variable! value-slot-module sym void) (set-variable! value-slot-module sym void)
sym)) sym))
(built-in-func fmakunbound (built-in-func fmakunbound
(lambda (sym) (lambda (sym)
(set-variable! function-slot-module sym void) (set-variable! function-slot-module sym void)
@ -266,12 +280,12 @@
(lambda (sym) (lambda (sym)
(elisp-bool (prim not (elisp-bool (prim not
(eq? void (reference-variable value-slot-module sym)))))) (eq? void (reference-variable value-slot-module sym))))))
(built-in-func fboundp (built-in-func fboundp
(lambda (sym) (lambda (sym)
(elisp-bool (prim not (elisp-bool (prim not
(eq? void (reference-variable function-slot-module sym)))))) (eq? void (reference-variable function-slot-module sym))))))
; Function calls. These must take care of special cases, like using symbols ; Function calls. These must take care of special cases, like using symbols
; or raw lambda-lists as functions! ; or raw lambda-lists as functions!
@ -294,14 +308,12 @@
(lambda (func . args) (lambda (func . args)
(myapply func args)))) (myapply func args))))
; Throw can be implemented as built-in function. ; Throw can be implemented as built-in function.
(built-in-func throw (built-in-func throw
(lambda (tag value) (lambda (tag value)
(prim throw 'elisp-exception tag value))) (prim throw 'elisp-exception tag value)))
; Miscellaneous. ; Miscellaneous.
(built-in-func not (built-in-func not

View file

@ -26,7 +26,6 @@
; course, so not really in runtime. But I think it fits well to the others ; course, so not really in runtime. But I think it fits well to the others
; here. ; here.
; The prog1 and prog2 constructs can easily be defined as macros using progn ; The prog1 and prog2 constructs can easily be defined as macros using progn
; and some lexical-let's to save the intermediate value to return at the end. ; and some lexical-let's to save the intermediate value to return at the end.
@ -42,7 +41,6 @@
(lambda (form1 form2 . rest) (lambda (form1 form2 . rest)
`(progn ,form1 (prog1 ,form2 ,@rest)))) `(progn ,form1 (prog1 ,form2 ,@rest))))
; Define the conditionals when and unless as macros. ; Define the conditionals when and unless as macros.
(built-in-macro when (built-in-macro when
@ -53,7 +51,6 @@
(lambda (condition . elses) (lambda (condition . elses)
`(if ,condition nil (progn ,@elses)))) `(if ,condition nil (progn ,@elses))))
; Impement the cond form as nested if's. A special case is a (condition) ; Impement the cond form as nested if's. A special case is a (condition)
; subform, in which case we need to return the condition itself if it is true ; subform, in which case we need to return the condition itself if it is true
; and thus save it in a local variable before testing it. ; and thus save it in a local variable before testing it.
@ -80,7 +77,6 @@
(progn ,@(cdr cur)) (progn ,@(cdr cur))
,rest)))))))) ,rest))))))))
; The and and or forms can also be easily defined with macros. ; The and and or forms can also be easily defined with macros.
(built-in-macro and (built-in-macro and
@ -111,7 +107,6 @@
,var ,var
,(iterate (car tail) (cdr tail))))))))))) ,(iterate (car tail) (cdr tail)))))))))))
; Define the dotimes and dolist iteration macros. ; Define the dotimes and dolist iteration macros.
(built-in-macro dotimes (built-in-macro dotimes
@ -155,7 +150,6 @@
(list (caddr args)) (list (caddr args))
'()))))))))) '())))))))))
; Exception handling. unwind-protect and catch are implemented as macros (throw ; Exception handling. unwind-protect and catch are implemented as macros (throw
; is a built-in function). ; is a built-in function).
@ -165,6 +159,7 @@
; for matches using eq (eq?). We handle this by using always #t as key ; for matches using eq (eq?). We handle this by using always #t as key
; for the Guile primitives and check for matches inside the handler; if ; for the Guile primitives and check for matches inside the handler; if
; the elisp keys are not eq?, we rethrow the exception. ; the elisp keys are not eq?, we rethrow the exception.
(built-in-macro catch (built-in-macro catch
(lambda (tag . body) (lambda (tag . body)
(if (null? body) (if (null? body)
@ -185,8 +180,9 @@
((guile-primitive throw) ,dummy-key ,elisp-key ((guile-primitive throw) ,dummy-key ,elisp-key
,value)))))))))) ,value))))))))))
; unwind-protect is just some weaker construct as dynamic-wind, so ; unwind-protect is just some weaker construct as dynamic-wind, so
; straight-forward to implement. ; straight-forward to implement.
(built-in-macro unwind-protect (built-in-macro unwind-protect
(lambda (body . clean-ups) (lambda (body . clean-ups)
(if (null? clean-ups) (if (null? clean-ups)
@ -196,7 +192,6 @@
(lambda () ,body) (lambda () ,body)
(lambda () ,@clean-ups)))) (lambda () ,@clean-ups))))
; Pop off the first element from a list or push one to it. ; Pop off the first element from a list or push one to it.
(built-in-macro pop (built-in-macro pop

View file

@ -6,12 +6,12 @@
;;;; modify it under the terms of the GNU Lesser General Public ;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either ;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version. ;;;; version 3 of the License, or (at your option) any later version.
;;;; ;;;;
;;;; This library is distributed in the hope that it will be useful, ;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;;; Lesser General Public License for more details. ;;;; Lesser General Public License for more details.
;;;; ;;;;
;;;; You should have received a copy of the GNU Lesser General Public ;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software ;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA