mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 11:50:28 +02:00
reindent
* 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: * module/language/elisp/spec.scm: Reindent. Signed-off-by: Andy Wingo <wingo@pobox.com>
This commit is contained in:
parent
c983a199d8
commit
f4e5e4114d
8 changed files with 1030 additions and 808 deletions
|
@ -20,8 +20,10 @@
|
||||||
|
|
||||||
(define-module (language elisp bindings)
|
(define-module (language elisp bindings)
|
||||||
#:export (make-bindings
|
#:export (make-bindings
|
||||||
mark-global-needed! map-globals-needed
|
mark-global-needed!
|
||||||
with-lexical-bindings with-dynamic-bindings
|
map-globals-needed
|
||||||
|
with-lexical-bindings
|
||||||
|
with-dynamic-bindings
|
||||||
get-lexical-binding))
|
get-lexical-binding))
|
||||||
|
|
||||||
;;; This module defines routines to handle analysis of symbol bindings
|
;;; This module defines routines to handle analysis of symbol bindings
|
||||||
|
@ -40,8 +42,7 @@
|
||||||
;;; 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
|
;;; Construct an 'empty' instance of the bindings data structure to be
|
||||||
;;; used at the start of a fresh compilation.
|
;;; used at the start of a fresh compilation.
|
||||||
|
@ -53,19 +54,23 @@
|
||||||
;;; slot-module.
|
;;; slot-module.
|
||||||
|
|
||||||
(define (mark-global-needed! bindings sym module)
|
(define (mark-global-needed! bindings sym module)
|
||||||
(let* ((old-needed ((record-accessor bindings-type 'needed-globals) bindings))
|
(let* ((old-needed ((record-accessor bindings-type 'needed-globals)
|
||||||
|
bindings))
|
||||||
(old-in-module (or (assoc-ref old-needed module) '()))
|
(old-in-module (or (assoc-ref old-needed module) '()))
|
||||||
(new-in-module (if (memq sym old-in-module)
|
(new-in-module (if (memq sym old-in-module)
|
||||||
old-in-module
|
old-in-module
|
||||||
(cons sym old-in-module)))
|
(cons sym old-in-module)))
|
||||||
(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
|
;;; Cycle through all globals needed in order to generate the code for
|
||||||
;;; their creation or some other analysis.
|
;;; their creation or some other analysis.
|
||||||
|
|
||||||
(define (map-globals-needed bindings proc)
|
(define (map-globals-needed bindings proc)
|
||||||
(let ((needed ((record-accessor bindings-type 'needed-globals) bindings)))
|
(let ((needed ((record-accessor bindings-type 'needed-globals)
|
||||||
|
bindings)))
|
||||||
(let iterate-modules ((mod-tail needed)
|
(let iterate-modules ((mod-tail needed)
|
||||||
(mod-result '()))
|
(mod-result '()))
|
||||||
(if (null? mod-tail)
|
(if (null? mod-tail)
|
||||||
|
@ -87,7 +92,8 @@
|
||||||
;;; current scope) for a symbol or #f if it is dynamically bound.
|
;;; current scope) for a symbol or #f if it is dynamically bound.
|
||||||
|
|
||||||
(define (get-lexical-binding bindings sym)
|
(define (get-lexical-binding bindings sym)
|
||||||
(let* ((lex ((record-accessor bindings-type 'lexical-bindings) bindings))
|
(let* ((lex ((record-accessor bindings-type 'lexical-bindings)
|
||||||
|
bindings))
|
||||||
(slot (hash-ref lex sym #f)))
|
(slot (hash-ref lex sym #f)))
|
||||||
(if slot
|
(if slot
|
||||||
(fluid-ref slot)
|
(fluid-ref slot)
|
||||||
|
@ -100,14 +106,13 @@
|
||||||
(if (or (not (list? syms))
|
(if (or (not (list? syms))
|
||||||
(not (and-map symbol? syms)))
|
(not (and-map symbol? syms)))
|
||||||
(error "can't bind non-symbols" syms))
|
(error "can't bind non-symbols" syms))
|
||||||
(let ((lex ((record-accessor bindings-type 'lexical-bindings) bindings)))
|
(let ((lex ((record-accessor bindings-type 'lexical-bindings)
|
||||||
|
bindings)))
|
||||||
(for-each (lambda (sym)
|
(for-each (lambda (sym)
|
||||||
(if (not (hash-ref lex sym))
|
(if (not (hash-ref lex sym))
|
||||||
(hash-set! lex sym (make-fluid))))
|
(hash-set! lex sym (make-fluid))))
|
||||||
syms)
|
syms)
|
||||||
(with-fluids* (map (lambda (sym)
|
(with-fluids* (map (lambda (sym) (hash-ref lex sym)) syms)
|
||||||
(hash-ref lex sym))
|
|
||||||
syms)
|
|
||||||
targets
|
targets
|
||||||
proc)))
|
proc)))
|
||||||
|
|
||||||
|
@ -119,5 +124,6 @@
|
||||||
|
|
||||||
(define (with-dynamic-bindings bindings syms proc)
|
(define (with-dynamic-bindings bindings syms proc)
|
||||||
(with-symbol-bindings bindings
|
(with-symbol-bindings bindings
|
||||||
syms (map (lambda (el) #f) syms)
|
syms
|
||||||
|
(map (lambda (el) #f) syms)
|
||||||
proc))
|
proc))
|
||||||
|
|
|
@ -56,9 +56,11 @@
|
||||||
|
|
||||||
;;; 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.
|
||||||
|
|
||||||
|
@ -96,7 +98,8 @@
|
||||||
(apply error args))
|
(apply error args))
|
||||||
|
|
||||||
(define (runtime-error loc msg . args)
|
(define (runtime-error loc msg . args)
|
||||||
(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
|
;;; Generate code to ensure a global symbol is there for further use of
|
||||||
|
@ -106,7 +109,8 @@
|
||||||
;;; this routine.
|
;;; this routine.
|
||||||
|
|
||||||
(define (generate-ensure-global loc sym module)
|
(define (generate-ensure-global loc sym module)
|
||||||
(make-application loc (make-module-ref loc runtime 'ensure-fluid! #t)
|
(make-application loc
|
||||||
|
(make-module-ref loc runtime 'ensure-fluid! #t)
|
||||||
(list (make-const loc module)
|
(list (make-const loc module)
|
||||||
(make-const loc sym))))
|
(make-const loc sym))))
|
||||||
|
|
||||||
|
@ -127,13 +131,17 @@
|
||||||
;;; setting/reverting their values with a dynamic-wind.
|
;;; setting/reverting their values with a dynamic-wind.
|
||||||
|
|
||||||
(define (let-dynamic loc syms module vals body)
|
(define (let-dynamic loc syms module vals body)
|
||||||
(call-primitive loc 'with-fluids*
|
(call-primitive
|
||||||
(make-application loc (make-primitive-ref loc 'list)
|
loc
|
||||||
|
'with-fluids*
|
||||||
|
(make-application loc
|
||||||
|
(make-primitive-ref loc 'list)
|
||||||
(map (lambda (sym)
|
(map (lambda (sym)
|
||||||
(make-module-ref loc module sym #t))
|
(make-module-ref loc module sym #t))
|
||||||
syms))
|
syms))
|
||||||
(make-application loc (make-primitive-ref loc 'list) vals)
|
(make-application loc (make-primitive-ref loc 'list) vals)
|
||||||
(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
|
;;; Handle access to a variable (reference/setting) correctly depending
|
||||||
|
@ -151,12 +159,15 @@
|
||||||
;;; instead if the variable has a lexical binding.
|
;;; instead if the variable has a lexical binding.
|
||||||
|
|
||||||
(define (reference-variable loc sym module)
|
(define (reference-variable loc sym module)
|
||||||
(access-variable loc sym module
|
(access-variable
|
||||||
(lambda (lexical)
|
loc
|
||||||
(make-lexical-ref loc lexical lexical))
|
sym
|
||||||
|
module
|
||||||
|
(lambda (lexical) (make-lexical-ref loc lexical lexical))
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(mark-global-needed! (fluid-ref bindings-data) sym module)
|
(mark-global-needed! (fluid-ref bindings-data) sym module)
|
||||||
(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.
|
||||||
|
@ -164,9 +175,15 @@
|
||||||
(define (reference-with-check loc sym module)
|
(define (reference-with-check loc sym module)
|
||||||
(if (want-void-check? sym module)
|
(if (want-void-check? sym module)
|
||||||
(let ((var (gensym)))
|
(let ((var (gensym)))
|
||||||
(make-let loc '(value) `(,var) `(,(reference-variable loc sym module))
|
(make-let
|
||||||
(make-conditional loc
|
loc
|
||||||
(call-primitive loc 'eq?
|
'(value)
|
||||||
|
`(,var)
|
||||||
|
`(,(reference-variable loc sym module))
|
||||||
|
(make-conditional
|
||||||
|
loc
|
||||||
|
(call-primitive loc
|
||||||
|
'eq?
|
||||||
(make-module-ref loc runtime 'void #t)
|
(make-module-ref loc runtime 'void #t)
|
||||||
(make-lexical-ref loc 'value var))
|
(make-lexical-ref loc 'value var))
|
||||||
(runtime-error loc "variable is void:" (make-const loc sym))
|
(runtime-error loc "variable is void:" (make-const loc sym))
|
||||||
|
@ -178,12 +195,15 @@
|
||||||
;;; when the variable has a lexical binding.
|
;;; when the variable has a lexical binding.
|
||||||
|
|
||||||
(define (set-variable! loc sym module value)
|
(define (set-variable! loc sym module value)
|
||||||
(access-variable loc sym module
|
(access-variable
|
||||||
(lambda (lexical)
|
loc
|
||||||
(make-lexical-set loc lexical lexical value))
|
sym
|
||||||
|
module
|
||||||
|
(lambda (lexical) (make-lexical-set loc lexical lexical value))
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(mark-global-needed! (fluid-ref bindings-data) sym module)
|
(mark-global-needed! (fluid-ref bindings-data) sym module)
|
||||||
(call-primitive loc 'fluid-set!
|
(call-primitive loc
|
||||||
|
'fluid-set!
|
||||||
(make-module-ref loc module sym #t)
|
(make-module-ref loc module sym #t)
|
||||||
value))))
|
value))))
|
||||||
|
|
||||||
|
@ -192,12 +212,15 @@
|
||||||
;;; . val2) ...).
|
;;; . val2) ...).
|
||||||
|
|
||||||
(define (process-let-bindings loc bindings)
|
(define (process-let-bindings loc bindings)
|
||||||
(map (lambda (b)
|
(map
|
||||||
|
(lambda (b)
|
||||||
(if (symbol? b)
|
(if (symbol? b)
|
||||||
(cons b 'nil)
|
(cons b 'nil)
|
||||||
(if (or (not (list? b))
|
(if (or (not (list? b))
|
||||||
(not (= (length b) 2)))
|
(not (= (length b) 2)))
|
||||||
(report-error loc "expected symbol or list of 2 elements in let")
|
(report-error
|
||||||
|
loc
|
||||||
|
"expected symbol or list of 2 elements in let")
|
||||||
(if (not (symbol? (car b)))
|
(if (not (symbol? (car b)))
|
||||||
(report-error loc "expected symbol in let")
|
(report-error loc "expected symbol in let")
|
||||||
(cons (car b) (cadr b))))))
|
(cons (car b) (cadr b))))))
|
||||||
|
@ -243,15 +266,15 @@
|
||||||
(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
|
||||||
(lambda ()
|
(lambda () (split-let-bindings bind module))
|
||||||
(split-let-bindings bind module))
|
|
||||||
(lambda (lexical dynamic)
|
(lambda (lexical dynamic)
|
||||||
(for-each (lambda (sym)
|
(for-each (lambda (sym)
|
||||||
(mark-global-needed! (fluid-ref bindings-data) sym module))
|
(mark-global-needed! (fluid-ref bindings-data)
|
||||||
|
sym
|
||||||
|
module))
|
||||||
(map car dynamic))
|
(map car dynamic))
|
||||||
(let ((make-values (lambda (for)
|
(let ((make-values (lambda (for)
|
||||||
(map (lambda (el)
|
(map (lambda (el) (compile-expr (cdr el)))
|
||||||
(compile-expr (cdr el)))
|
|
||||||
for)))
|
for)))
|
||||||
(make-body (lambda ()
|
(make-body (lambda ()
|
||||||
(make-sequence loc (map compile-expr body)))))
|
(make-sequence loc (map compile-expr body)))))
|
||||||
|
@ -261,16 +284,26 @@
|
||||||
(let* ((lexical-syms (map (lambda (el) (gensym)) lexical))
|
(let* ((lexical-syms (map (lambda (el) (gensym)) lexical))
|
||||||
(dynamic-syms (map (lambda (el) (gensym)) dynamic))
|
(dynamic-syms (map (lambda (el) (gensym)) dynamic))
|
||||||
(all-syms (append lexical-syms dynamic-syms))
|
(all-syms (append lexical-syms dynamic-syms))
|
||||||
(vals (append (make-values lexical) (make-values dynamic))))
|
(vals (append (make-values lexical)
|
||||||
(make-let loc all-syms all-syms vals
|
(make-values dynamic))))
|
||||||
(with-lexical-bindings (fluid-ref bindings-data)
|
(make-let loc
|
||||||
|
all-syms
|
||||||
|
all-syms
|
||||||
|
vals
|
||||||
|
(with-lexical-bindings
|
||||||
|
(fluid-ref bindings-data)
|
||||||
(map car lexical) lexical-syms
|
(map car lexical) lexical-syms
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(if (null? dynamic)
|
(if (null? dynamic)
|
||||||
(make-body)
|
(make-body)
|
||||||
(let-dynamic loc (map car dynamic) module
|
(let-dynamic loc
|
||||||
(map (lambda (sym)
|
(map car dynamic)
|
||||||
(make-lexical-ref loc sym sym))
|
module
|
||||||
|
(map
|
||||||
|
(lambda (sym)
|
||||||
|
(make-lexical-ref loc
|
||||||
|
sym
|
||||||
|
sym))
|
||||||
dynamic-syms)
|
dynamic-syms)
|
||||||
(make-body)))))))))))))
|
(make-body)))))))))))))
|
||||||
|
|
||||||
|
@ -282,7 +315,9 @@
|
||||||
(begin
|
(begin
|
||||||
(for-each (lambda (sym)
|
(for-each (lambda (sym)
|
||||||
(if (not (bind-lexically? sym module))
|
(if (not (bind-lexically? sym module))
|
||||||
(mark-global-needed! (fluid-ref bindings-data) sym module)))
|
(mark-global-needed! (fluid-ref bindings-data)
|
||||||
|
sym
|
||||||
|
module)))
|
||||||
(map car bind))
|
(map car bind))
|
||||||
(let iterate ((tail bind))
|
(let iterate ((tail bind))
|
||||||
(if (null? tail)
|
(if (null? tail)
|
||||||
|
@ -291,13 +326,19 @@
|
||||||
(value (compile-expr (cdar tail))))
|
(value (compile-expr (cdar tail))))
|
||||||
(if (bind-lexically? sym module)
|
(if (bind-lexically? sym module)
|
||||||
(let ((target (gensym)))
|
(let ((target (gensym)))
|
||||||
(make-let loc `(,target) `(,target) `(,value)
|
(make-let loc
|
||||||
(with-lexical-bindings (fluid-ref bindings-data)
|
`(,target)
|
||||||
`(,sym) `(,target)
|
`(,target)
|
||||||
(lambda ()
|
`(,value)
|
||||||
(iterate (cdr tail))))))
|
(with-lexical-bindings
|
||||||
|
(fluid-ref bindings-data)
|
||||||
|
`(,sym)
|
||||||
|
`(,target)
|
||||||
|
(lambda () (iterate (cdr tail))))))
|
||||||
(let-dynamic loc
|
(let-dynamic loc
|
||||||
`(,(caar tail)) module `(,value)
|
`(,(caar tail))
|
||||||
|
module
|
||||||
|
`(,value)
|
||||||
(iterate (cdr tail))))))))))
|
(iterate (cdr tail))))))))))
|
||||||
|
|
||||||
;;; Split the argument list of a lambda expression into required,
|
;;; Split the argument list of a lambda expression into required,
|
||||||
|
@ -325,8 +366,11 @@
|
||||||
(final-optional (reverse optional))
|
(final-optional (reverse optional))
|
||||||
(final-lexical (reverse lexical))
|
(final-lexical (reverse lexical))
|
||||||
(final-dynamic (reverse dynamic)))
|
(final-dynamic (reverse dynamic)))
|
||||||
(values final-required final-optional #f
|
(values final-required
|
||||||
final-lexical final-dynamic)))
|
final-optional
|
||||||
|
#f
|
||||||
|
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))
|
||||||
|
@ -344,11 +388,16 @@
|
||||||
(final-dynamic (reverse (if rest-lexical
|
(final-dynamic (reverse (if rest-lexical
|
||||||
dynamic
|
dynamic
|
||||||
(cons rest dynamic)))))
|
(cons rest dynamic)))))
|
||||||
(values final-required final-optional rest
|
(values final-required
|
||||||
final-lexical final-dynamic))))
|
final-optional
|
||||||
|
rest
|
||||||
|
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))
|
||||||
(let* ((arg (car tail))
|
(let* ((arg (car tail))
|
||||||
(bind-lexical (bind-arg-lexical? arg))
|
(bind-lexical (bind-arg-lexical? arg))
|
||||||
(new-lexical (if bind-lexical
|
(new-lexical (if bind-lexical
|
||||||
|
@ -365,7 +414,8 @@
|
||||||
required (cons arg optional)
|
required (cons arg optional)
|
||||||
new-lexical new-dynamic))
|
new-lexical new-dynamic))
|
||||||
(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
|
;;; Compile a lambda expression. Things get a little complicated because
|
||||||
;;; TreeIL does not allow optional arguments but only one rest argument,
|
;;; TreeIL does not allow optional arguments but only one rest argument,
|
||||||
|
@ -423,55 +473,83 @@
|
||||||
(optional-sym (map make-sym lex-optionals))
|
(optional-sym (map make-sym lex-optionals))
|
||||||
(optional-lex-pairs (map cons lex-optionals optional-sym))
|
(optional-lex-pairs (map cons lex-optionals optional-sym))
|
||||||
(find-required-pairs (lambda (filter)
|
(find-required-pairs (lambda (filter)
|
||||||
(lset-intersection (lambda (name-sym el)
|
(lset-intersection
|
||||||
(eq? (car name-sym)
|
(lambda (name-sym el)
|
||||||
el))
|
(eq? (car name-sym) el))
|
||||||
required-pairs filter)))
|
required-pairs
|
||||||
|
filter)))
|
||||||
(required-lex-pairs (find-required-pairs lexical))
|
(required-lex-pairs (find-required-pairs lexical))
|
||||||
(rest-pair (if rest-lexical `((,rest . ,rest-sym)) '()))
|
(rest-pair (if rest-lexical `((,rest . ,rest-sym)) '()))
|
||||||
(all-lex-pairs (append required-lex-pairs optional-lex-pairs
|
(all-lex-pairs (append required-lex-pairs
|
||||||
|
optional-lex-pairs
|
||||||
rest-pair)))
|
rest-pair)))
|
||||||
(for-each (lambda (sym)
|
(for-each (lambda (sym)
|
||||||
(mark-global-needed! (fluid-ref bindings-data)
|
(mark-global-needed! (fluid-ref bindings-data)
|
||||||
sym value-slot))
|
sym
|
||||||
|
value-slot))
|
||||||
dynamic)
|
dynamic)
|
||||||
(with-dynamic-bindings (fluid-ref bindings-data) dynamic
|
(with-dynamic-bindings
|
||||||
|
(fluid-ref bindings-data)
|
||||||
|
dynamic
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(with-lexical-bindings (fluid-ref bindings-data)
|
(with-lexical-bindings
|
||||||
|
(fluid-ref bindings-data)
|
||||||
(map car all-lex-pairs)
|
(map car all-lex-pairs)
|
||||||
(map cdr all-lex-pairs)
|
(map cdr all-lex-pairs)
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(make-lambda loc '()
|
(make-lambda loc
|
||||||
|
'()
|
||||||
(make-lambda-case
|
(make-lambda-case
|
||||||
#f required #f
|
#f
|
||||||
|
required
|
||||||
|
#f
|
||||||
(if have-real-rest rest-name #f)
|
(if have-real-rest rest-name #f)
|
||||||
#f '()
|
#f
|
||||||
|
'()
|
||||||
(if have-real-rest
|
(if have-real-rest
|
||||||
(append required-sym (list rest-sym))
|
(append required-sym (list rest-sym))
|
||||||
required-sym)
|
required-sym)
|
||||||
(let* ((init-req (map (lambda (name-sym)
|
(let* ((init-req
|
||||||
(make-lexical-ref loc (car name-sym)
|
(map (lambda (name-sym)
|
||||||
|
(make-lexical-ref
|
||||||
|
loc
|
||||||
|
(car name-sym)
|
||||||
(cdr name-sym)))
|
(cdr name-sym)))
|
||||||
(find-required-pairs dynamic)))
|
(find-required-pairs dynamic)))
|
||||||
(init-nils (map (lambda (sym) (nil-value loc))
|
(init-nils
|
||||||
|
(map (lambda (sym) (nil-value loc))
|
||||||
(if rest-dynamic
|
(if rest-dynamic
|
||||||
`(,@dyn-optionals ,rest-sym)
|
`(,@dyn-optionals ,rest-sym)
|
||||||
dyn-optionals)))
|
dyn-optionals)))
|
||||||
(init (append init-req init-nils))
|
(init (append init-req init-nils))
|
||||||
(func-body (make-sequence loc
|
(func-body
|
||||||
`(,(process-optionals loc optional
|
(make-sequence
|
||||||
rest-name rest-sym)
|
loc
|
||||||
,(process-rest loc rest
|
`(,(process-optionals loc
|
||||||
rest-name rest-sym)
|
optional
|
||||||
|
rest-name
|
||||||
|
rest-sym)
|
||||||
|
,(process-rest loc
|
||||||
|
rest
|
||||||
|
rest-name
|
||||||
|
rest-sym)
|
||||||
,@(map compile-expr body))))
|
,@(map compile-expr body))))
|
||||||
(dynlet (let-dynamic loc dynamic value-slot
|
(dynlet (let-dynamic loc
|
||||||
init func-body))
|
dynamic
|
||||||
(full-body (if (null? dynamic) func-body dynlet)))
|
value-slot
|
||||||
|
init
|
||||||
|
func-body))
|
||||||
|
(full-body (if (null? dynamic)
|
||||||
|
func-body
|
||||||
|
dynlet)))
|
||||||
(if (null? optional-sym)
|
(if (null? optional-sym)
|
||||||
full-body
|
full-body
|
||||||
(make-let loc
|
(make-let loc
|
||||||
optional-sym optional-sym
|
optional-sym
|
||||||
(map (lambda (sym) (nil-value loc)) optional-sym)
|
optional-sym
|
||||||
|
(map (lambda (sym)
|
||||||
|
(nil-value loc))
|
||||||
|
optional-sym)
|
||||||
full-body)))
|
full-body)))
|
||||||
#f))))))))))
|
#f))))))))))
|
||||||
|
|
||||||
|
@ -482,33 +560,58 @@
|
||||||
(let iterate ((tail optional))
|
(let iterate ((tail optional))
|
||||||
(if (null? tail)
|
(if (null? tail)
|
||||||
(make-void loc)
|
(make-void loc)
|
||||||
(make-conditional loc
|
(make-conditional
|
||||||
(call-primitive loc 'null? (make-lexical-ref loc rest-name rest-sym))
|
loc
|
||||||
|
(call-primitive loc
|
||||||
|
'null?
|
||||||
|
(make-lexical-ref loc rest-name rest-sym))
|
||||||
(make-void loc)
|
(make-void loc)
|
||||||
(make-sequence loc
|
(make-sequence
|
||||||
(list (set-variable! loc (car tail) value-slot
|
loc
|
||||||
(call-primitive loc 'car
|
(list (set-variable! loc
|
||||||
(make-lexical-ref loc rest-name rest-sym)))
|
(car tail)
|
||||||
(make-lexical-set loc rest-name rest-sym
|
value-slot
|
||||||
(call-primitive loc 'cdr
|
(call-primitive loc
|
||||||
|
'car
|
||||||
|
(make-lexical-ref
|
||||||
|
loc
|
||||||
|
rest-name
|
||||||
|
rest-sym)))
|
||||||
|
(make-lexical-set
|
||||||
|
loc
|
||||||
|
rest-name
|
||||||
|
rest-sym
|
||||||
|
(call-primitive
|
||||||
|
loc
|
||||||
|
'cdr
|
||||||
(make-lexical-ref loc rest-name rest-sym)))
|
(make-lexical-ref loc rest-name rest-sym)))
|
||||||
(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
|
||||||
(make-lexical-ref loc rest-name rest-sym))))
|
'null?
|
||||||
|
(make-lexical-ref loc
|
||||||
|
rest-name
|
||||||
|
rest-sym))))
|
||||||
(cond
|
(cond
|
||||||
(rest
|
(rest
|
||||||
(make-conditional loc rest-empty
|
(make-conditional loc
|
||||||
|
rest-empty
|
||||||
(make-void loc)
|
(make-void loc)
|
||||||
(set-variable! loc rest value-slot
|
(set-variable! loc
|
||||||
(make-lexical-ref loc rest-name rest-sym))))
|
rest
|
||||||
|
value-slot
|
||||||
|
(make-lexical-ref loc
|
||||||
|
rest-name
|
||||||
|
rest-sym))))
|
||||||
((not (null? rest-sym))
|
((not (null? rest-sym))
|
||||||
(make-conditional loc rest-empty
|
(make-conditional loc rest-empty
|
||||||
(make-void loc)
|
(make-void loc)
|
||||||
(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
|
;;; Handle the common part of defconst and defvar, that is, checking for
|
||||||
|
@ -570,19 +673,26 @@
|
||||||
(compile-expr (cadr expr))
|
(compile-expr (cadr expr))
|
||||||
(let* ((head (car expr))
|
(let* ((head (car expr))
|
||||||
(processed-tail (process-backquote loc (cdr expr)))
|
(processed-tail (process-backquote loc (cdr expr)))
|
||||||
(head-is-list-2 (and (list? head) (= (length head) 2)))
|
(head-is-list-2 (and (list? head)
|
||||||
(head-unquote (and head-is-list-2 (unquote? (car head))))
|
(= (length head) 2)))
|
||||||
|
(head-unquote (and head-is-list-2
|
||||||
|
(unquote? (car head))))
|
||||||
(head-unquote-splicing (and head-is-list-2
|
(head-unquote-splicing (and head-is-list-2
|
||||||
(unquote-splicing? (car head)))))
|
(unquote-splicing?
|
||||||
|
(car head)))))
|
||||||
(if head-unquote-splicing
|
(if head-unquote-splicing
|
||||||
(call-primitive loc 'append
|
(call-primitive loc
|
||||||
(compile-expr (cadr head)) processed-tail)
|
'append
|
||||||
|
(compile-expr (cadr head))
|
||||||
|
processed-tail)
|
||||||
(call-primitive loc 'cons
|
(call-primitive loc 'cons
|
||||||
(if head-unquote
|
(if head-unquote
|
||||||
(compile-expr (cadr head))
|
(compile-expr (cadr head))
|
||||||
(process-backquote loc head))
|
(process-backquote loc head))
|
||||||
processed-tail))))
|
processed-tail))))
|
||||||
(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
|
;;; Temporarily update a list of symbols that are handled specially
|
||||||
|
@ -623,17 +733,20 @@
|
||||||
(make-sequence loc (map compile-expr forms)))
|
(make-sequence loc (map compile-expr forms)))
|
||||||
|
|
||||||
((if ,condition ,ifclause)
|
((if ,condition ,ifclause)
|
||||||
(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)
|
||||||
(make-sequence loc (map compile-expr elses))))
|
(make-sequence loc (map compile-expr elses))))
|
||||||
|
|
||||||
|
@ -644,20 +757,25 @@
|
||||||
((defconst ,sym ,value . ,doc)
|
((defconst ,sym ,value . ,doc)
|
||||||
(if (handle-var-def loc sym doc)
|
(if (handle-var-def loc sym doc)
|
||||||
(make-sequence loc
|
(make-sequence loc
|
||||||
(list (set-variable! loc sym value-slot (compile-expr value))
|
(list (set-variable! loc
|
||||||
|
sym
|
||||||
|
value-slot
|
||||||
|
(compile-expr value))
|
||||||
(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
|
||||||
(list (make-conditional loc
|
loc
|
||||||
(call-primitive loc 'eq?
|
(list (make-conditional
|
||||||
|
loc
|
||||||
|
(call-primitive loc
|
||||||
|
'eq?
|
||||||
(make-module-ref loc runtime 'void #t)
|
(make-module-ref loc runtime 'void #t)
|
||||||
(reference-variable loc sym value-slot))
|
(reference-variable loc sym value-slot))
|
||||||
(set-variable! loc sym value-slot
|
(set-variable! loc sym value-slot (compile-expr value))
|
||||||
(compile-expr value))
|
|
||||||
(make-void loc))
|
(make-void loc))
|
||||||
(make-const loc sym)))))
|
(make-const loc sym)))))
|
||||||
|
|
||||||
|
@ -666,22 +784,33 @@
|
||||||
;; large lists of symbol expression pairs are very unlikely.
|
;; large lists of symbol 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))
|
||||||
(let ((sym (car tail))
|
(let ((sym (car tail))
|
||||||
(tailtail (cdr tail)))
|
(tailtail (cdr tail)))
|
||||||
(if (not (symbol? sym))
|
(if (not (symbol? sym))
|
||||||
(report-error loc "expected symbol in setq")
|
(report-error loc "expected symbol in setq")
|
||||||
(if (null? tailtail)
|
(if (null? tailtail)
|
||||||
(report-error loc "missing value for symbol in setq" sym)
|
(report-error loc
|
||||||
|
"missing value for symbol in setq"
|
||||||
|
sym)
|
||||||
(let* ((val (compile-expr (car tailtail)))
|
(let* ((val (compile-expr (car tailtail)))
|
||||||
(op (set-variable! loc sym value-slot val)))
|
(op (set-variable! loc sym value-slot val)))
|
||||||
(if (null? (cdr tailtail))
|
(if (null? (cdr tailtail))
|
||||||
(let* ((temp (gensym))
|
(let* ((temp (gensym))
|
||||||
(ref (make-lexical-ref loc temp temp)))
|
(ref (make-lexical-ref loc temp temp)))
|
||||||
(list (make-let loc `(,temp) `(,temp) `(,val)
|
(list (make-let
|
||||||
(make-sequence loc
|
loc
|
||||||
(list (set-variable! loc sym value-slot ref)
|
`(,temp)
|
||||||
|
`(,temp)
|
||||||
|
`(,val)
|
||||||
|
(make-sequence
|
||||||
|
loc
|
||||||
|
(list (set-variable! loc
|
||||||
|
sym
|
||||||
|
value-slot
|
||||||
|
ref)
|
||||||
ref)))))
|
ref)))))
|
||||||
(cons (set-variable! loc sym value-slot val)
|
(cons (set-variable! loc sym value-slot val)
|
||||||
(iterate (cdr tailtail)))))))))))
|
(iterate (cdr tailtail)))))))))))
|
||||||
|
@ -759,7 +888,9 @@
|
||||||
(let* ((itersym (gensym))
|
(let* ((itersym (gensym))
|
||||||
(compiled-body (map compile-expr body))
|
(compiled-body (map compile-expr body))
|
||||||
(iter-call (make-application loc
|
(iter-call (make-application loc
|
||||||
(make-lexical-ref loc 'iterate itersym)
|
(make-lexical-ref loc
|
||||||
|
'iterate
|
||||||
|
itersym)
|
||||||
(list)))
|
(list)))
|
||||||
(full-body (make-sequence loc
|
(full-body (make-sequence loc
|
||||||
`(,@compiled-body ,iter-call)))
|
`(,@compiled-body ,iter-call)))
|
||||||
|
@ -767,10 +898,22 @@
|
||||||
(compile-expr condition)
|
(compile-expr condition)
|
||||||
full-body
|
full-body
|
||||||
(nil-value loc)))
|
(nil-value loc)))
|
||||||
(iter-thunk (make-lambda loc '()
|
(iter-thunk (make-lambda loc
|
||||||
(make-lambda-case #f '() #f #f #f '() '()
|
'()
|
||||||
lambda-body #f))))
|
(make-lambda-case #f
|
||||||
(make-letrec loc #f '(iterate) (list itersym) (list iter-thunk)
|
'()
|
||||||
|
#f
|
||||||
|
#f
|
||||||
|
#f
|
||||||
|
'()
|
||||||
|
'()
|
||||||
|
lambda-body
|
||||||
|
#f))))
|
||||||
|
(make-letrec loc
|
||||||
|
#f
|
||||||
|
'(iterate)
|
||||||
|
(list itersym)
|
||||||
|
(list iter-thunk)
|
||||||
iter-call)))
|
iter-call)))
|
||||||
|
|
||||||
;; Either (lambda ...) or (function (lambda ...)) denotes a
|
;; Either (lambda ...) or (function (lambda ...)) denotes a
|
||||||
|
@ -790,8 +933,12 @@
|
||||||
(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)
|
||||||
(make-sequence loc
|
(make-sequence loc
|
||||||
(list (set-variable! loc name function-slot
|
(list (set-variable! loc
|
||||||
(compile-lambda loc args body))
|
name
|
||||||
|
function-slot
|
||||||
|
(compile-lambda loc
|
||||||
|
args
|
||||||
|
body))
|
||||||
(make-const loc name)))))
|
(make-const loc name)))))
|
||||||
|
|
||||||
;; Define a macro (this is done directly at compile-time!). FIXME:
|
;; Define a macro (this is done directly at compile-time!). FIXME:
|
||||||
|
@ -866,12 +1013,18 @@
|
||||||
((#:disable-void-check)
|
((#:disable-void-check)
|
||||||
(if (valid-symbol-list-arg? value)
|
(if (valid-symbol-list-arg? value)
|
||||||
(fluid-set! disable-void-check value)
|
(fluid-set! disable-void-check value)
|
||||||
(report-error #f "Invalid value for #:disable-void-check" value)))
|
(report-error #f
|
||||||
|
"Invalid value for #:disable-void-check"
|
||||||
|
value)))
|
||||||
((#:always-lexical)
|
((#:always-lexical)
|
||||||
(if (valid-symbol-list-arg? value)
|
(if (valid-symbol-list-arg? value)
|
||||||
(fluid-set! always-lexical value)
|
(fluid-set! always-lexical value)
|
||||||
(report-error #f "Invalid value for #:always-lexical" value)))
|
(report-error #f
|
||||||
(else (report-error #f "Invalid compiler option" key)))))))
|
"Invalid value for #:always-lexical"
|
||||||
|
value)))
|
||||||
|
(else (report-error #f
|
||||||
|
"Invalid compiler option"
|
||||||
|
key)))))))
|
||||||
|
|
||||||
;;; Entry point for compilation to TreeIL. This creates the bindings
|
;;; Entry point for compilation to TreeIL. This creates the bindings
|
||||||
;;; data structure, and after compiling the main expression we need to
|
;;; data structure, and after compiling the main expression we need to
|
||||||
|
@ -887,7 +1040,8 @@
|
||||||
(let ((loc (location expr))
|
(let ((loc (location expr))
|
||||||
(compiled (compile-expr expr)))
|
(compiled (compile-expr expr)))
|
||||||
(make-sequence loc
|
(make-sequence loc
|
||||||
`(,@(map-globals-needed (fluid-ref bindings-data)
|
`(,@(map-globals-needed
|
||||||
|
(fluid-ref bindings-data)
|
||||||
(lambda (mod sym)
|
(lambda (mod sym)
|
||||||
(generate-ensure-global loc sym mod)))
|
(generate-ensure-global loc sym mod)))
|
||||||
,compiled))))
|
,compiled))))
|
||||||
|
|
|
@ -106,7 +106,10 @@
|
||||||
(begin
|
(begin
|
||||||
(unread-char cur port)
|
(unread-char cur port)
|
||||||
result)
|
result)
|
||||||
(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
|
;;; Read a character and process escape-sequences when necessary. The
|
||||||
|
@ -116,13 +119,23 @@
|
||||||
;;; characters.
|
;;; characters.
|
||||||
|
|
||||||
(define basic-escape-codes
|
(define basic-escape-codes
|
||||||
'((#\a . 7) (#\b . 8) (#\t . 9)
|
'((#\a . 7)
|
||||||
(#\n . 10) (#\v . 11) (#\f . 12) (#\r . 13)
|
(#\b . 8)
|
||||||
(#\e . 27) (#\s . 32) (#\d . 127)))
|
(#\t . 9)
|
||||||
|
(#\n . 10)
|
||||||
|
(#\v . 11)
|
||||||
|
(#\f . 12)
|
||||||
|
(#\r . 13)
|
||||||
|
(#\e . 27)
|
||||||
|
(#\s . 32)
|
||||||
|
(#\d . 127)))
|
||||||
|
|
||||||
(define (get-character port in-string)
|
(define (get-character port in-string)
|
||||||
(let ((meta-bits `((#\A . 22) (#\s . 23) (#\H . 24)
|
(let ((meta-bits `((#\A . 22)
|
||||||
(#\S . 25) (#\M . ,(if in-string 7 27))))
|
(#\s . 23)
|
||||||
|
(#\H . 24)
|
||||||
|
(#\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.
|
||||||
|
@ -160,8 +173,8 @@
|
||||||
((#\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
|
||||||
;; But remember to get the code instead!
|
;; to get the code instead!
|
||||||
(char->integer cur))))
|
(char->integer cur))))
|
||||||
|
|
||||||
;;; Read a symbol or number from a port until something follows that
|
;;; Read a symbol or number from a port until something follows that
|
||||||
|
@ -176,7 +189,8 @@
|
||||||
(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
|
;;; A dot is also allowed literally, only a single dort alone is parsed
|
||||||
;;; as the 'dot' terminal for dotted lists.
|
;;; as the 'dot' terminal for dotted lists.
|
||||||
|
@ -188,7 +202,8 @@
|
||||||
(had-escape #f))
|
(had-escape #f))
|
||||||
(let* ((c (read-char port))
|
(let* ((c (read-char port))
|
||||||
(finish (lambda ()
|
(finish (lambda ()
|
||||||
(let ((result (list->string (reverse result-chars))))
|
(let ((result (list->string
|
||||||
|
(reverse result-chars))))
|
||||||
(values
|
(values
|
||||||
(cond
|
(cond
|
||||||
((and (not had-escape)
|
((and (not had-escape)
|
||||||
|
@ -202,7 +217,8 @@
|
||||||
(need-no-escape? (lambda (c)
|
(need-no-escape? (lambda (c)
|
||||||
(or (char-numeric? c)
|
(or (char-numeric? c)
|
||||||
(char-alphabetic? c)
|
(char-alphabetic? c)
|
||||||
(char-set-contains? no-escape-punctuation
|
(char-set-contains?
|
||||||
|
no-escape-punctuation
|
||||||
c)))))
|
c)))))
|
||||||
(cond
|
(cond
|
||||||
((eof-object? c) (finish))
|
((eof-object? c) (finish))
|
||||||
|
@ -229,13 +245,17 @@
|
||||||
(case type
|
(case type
|
||||||
((#\#) `(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
|
;;; Main lexer routine, which is given a port and does look for the next
|
||||||
;;; token.
|
;;; token.
|
||||||
|
|
||||||
(define (lex port)
|
(define (lex port)
|
||||||
(let ((return (let ((file (if (file-port? port) (port-filename port) #f))
|
(let ((return (let ((file (if (file-port? port)
|
||||||
|
(port-filename port)
|
||||||
|
#f))
|
||||||
(line (1+ (port-line port)))
|
(line (1+ (port-line port)))
|
||||||
(column (1+ (port-column port))))
|
(column (1+ (port-column port))))
|
||||||
(lambda (token value)
|
(lambda (token value)
|
||||||
|
@ -289,7 +309,8 @@
|
||||||
(else
|
(else
|
||||||
(unread-char escaped port)
|
(unread-char escaped port)
|
||||||
(unread-char cur port)
|
(unread-char cur port)
|
||||||
(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).
|
||||||
|
@ -316,16 +337,15 @@
|
||||||
(else
|
(else
|
||||||
(unread-char c port)
|
(unread-char c port)
|
||||||
(call-with-values
|
(call-with-values
|
||||||
(lambda ()
|
(lambda () (get-symbol-or-number port))
|
||||||
(get-symbol-or-number port))
|
|
||||||
(lambda (type str)
|
(lambda (type str)
|
||||||
(case type
|
(case type
|
||||||
((symbol)
|
((symbol)
|
||||||
;; str could be empty if the first character is
|
;; str could be empty if the first character is already
|
||||||
;; already something not allowed in a symbol (and not
|
;; something not allowed in a symbol (and not escaped)!
|
||||||
;; escaped)! Take care about that, it is an error
|
;; Take care about that, it is an error because that
|
||||||
;; because that character should have been handled
|
;; character should have been handled elsewhere or is
|
||||||
;; elsewhere or is invalid in the input.
|
;; invalid in the input.
|
||||||
(if (zero? (string-length str))
|
(if (zero? (string-length str))
|
||||||
(begin
|
(begin
|
||||||
;; Take it out so the REPL might not get into an
|
;; Take it out so the REPL might not get into an
|
||||||
|
@ -335,10 +355,11 @@
|
||||||
(return 'symbol (string->symbol str))))
|
(return 'symbol (string->symbol str))))
|
||||||
((integer)
|
((integer)
|
||||||
;; In elisp, something like "1." is an integer, while
|
;; In elisp, something like "1." is an integer, while
|
||||||
;; string->number returns an inexact real. Thus we
|
;; string->number returns an inexact real. Thus we need
|
||||||
;; need a conversion here, but it should always
|
;; a conversion here, but it should always result in an
|
||||||
;; result in an integer!
|
;; integer!
|
||||||
(return 'integer
|
(return
|
||||||
|
'integer
|
||||||
(let ((num (inexact->exact (string->number str))))
|
(let ((num (inexact->exact (string->number str))))
|
||||||
(if (not (integer? num))
|
(if (not (integer? num))
|
||||||
(error "expected integer" str num))
|
(error "expected integer" str num))
|
||||||
|
@ -346,7 +367,9 @@
|
||||||
((float)
|
((float)
|
||||||
(return 'float (let ((num (string->number str)))
|
(return 'float (let ((num (string->number str)))
|
||||||
(if (exact? num)
|
(if (exact? num)
|
||||||
(error "expected inexact float" str num))
|
(error "expected inexact float"
|
||||||
|
str
|
||||||
|
num))
|
||||||
num)))
|
num)))
|
||||||
(else (error "wrong number/symbol type" type)))))))))))
|
(else (error "wrong number/symbol type" type)))))))))))
|
||||||
|
|
||||||
|
@ -354,8 +377,7 @@
|
||||||
;;; can be used to create a lexer for the parser to use.
|
;;; can be used to create a lexer for the parser to use.
|
||||||
|
|
||||||
(define (get-lexer port)
|
(define (get-lexer port)
|
||||||
(lambda ()
|
(lambda () (lex port)))
|
||||||
(lex port)))
|
|
||||||
|
|
||||||
;;; Build a special lexer that will only read enough for one expression
|
;;; Build a special lexer that will only read enough for one expression
|
||||||
;;; and then always return end-of-input. If we find one of the quotation
|
;;; and then always return end-of-input. If we find one of the quotation
|
||||||
|
|
|
@ -152,7 +152,8 @@
|
||||||
(error "got different token than peeked"))
|
(error "got different token than peeked"))
|
||||||
(let ((tail (get-list lex #f close-square)))
|
(let ((tail (get-list lex #f close-square)))
|
||||||
(if (not (= (length tail) 1))
|
(if (not (= (length tail) 1))
|
||||||
(parse-error next "expected exactly one element after dot"))
|
(parse-error next
|
||||||
|
"expected exactly one element after dot"))
|
||||||
(car tail))))
|
(car tail))))
|
||||||
(else
|
(else
|
||||||
;; Do both parses in exactly this sequence!
|
;; Do both parses in exactly this sequence!
|
||||||
|
@ -173,13 +174,16 @@
|
||||||
(type (car token))
|
(type (car token))
|
||||||
(return (lambda (result)
|
(return (lambda (result)
|
||||||
(if (pair? result)
|
(if (pair? result)
|
||||||
(set-source-properties! result (source-properties token)))
|
(set-source-properties!
|
||||||
|
result
|
||||||
|
(source-properties token)))
|
||||||
result)))
|
result)))
|
||||||
(case type
|
(case type
|
||||||
((integer float symbol character string)
|
((integer float symbol character string)
|
||||||
(return (cdr token)))
|
(return (cdr token)))
|
||||||
((quote backquote unquote unquote-splicing)
|
((quote backquote unquote unquote-splicing)
|
||||||
(return (list (assq-ref quotation-symbols type) (get-expression lex))))
|
(return (list (assq-ref quotation-symbols type)
|
||||||
|
(get-expression lex))))
|
||||||
((paren-open)
|
((paren-open)
|
||||||
(return (get-list lex #t #f)))
|
(return (get-list lex #t #f)))
|
||||||
((square-open)
|
((square-open)
|
||||||
|
|
|
@ -20,12 +20,17 @@
|
||||||
|
|
||||||
(define-module (language elisp runtime)
|
(define-module (language elisp runtime)
|
||||||
#:export (void
|
#:export (void
|
||||||
nil-value t-value
|
nil-value
|
||||||
value-slot-module function-slot-module
|
t-value
|
||||||
|
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.
|
||||||
|
|
|
@ -28,65 +28,82 @@
|
||||||
|
|
||||||
;;; Equivalence and equalness predicates.
|
;;; Equivalence and equalness predicates.
|
||||||
|
|
||||||
(built-in-func eq (lambda (a b)
|
(built-in-func eq
|
||||||
|
(lambda (a b)
|
||||||
(elisp-bool (eq? a b))))
|
(elisp-bool (eq? a b))))
|
||||||
|
|
||||||
(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)
|
||||||
(elisp-bool (and (real? num)
|
(elisp-bool (and (real? num)
|
||||||
(or (inexact? num)
|
(or (inexact? num)
|
||||||
(prim not (integer? num)))))))
|
(prim not (integer? num)))))))
|
||||||
|
|
||||||
(built-in-func integerp (lambda (num)
|
(built-in-func integerp
|
||||||
|
(lambda (num)
|
||||||
(elisp-bool (and (exact? num)
|
(elisp-bool (and (exact? num)
|
||||||
(integer? num)))))
|
(integer? num)))))
|
||||||
|
|
||||||
(built-in-func numberp (lambda (num)
|
(built-in-func numberp
|
||||||
|
(lambda (num)
|
||||||
(elisp-bool (real? num))))
|
(elisp-bool (real? num))))
|
||||||
|
|
||||||
(built-in-func wholenump (lambda (num)
|
(built-in-func wholenump
|
||||||
|
(lambda (num)
|
||||||
(elisp-bool (and (exact? num)
|
(elisp-bool (and (exact? num)
|
||||||
(integer? num)
|
(integer? num)
|
||||||
(prim >= num 0)))))
|
(prim >= num 0)))))
|
||||||
|
|
||||||
(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)
|
||||||
(if (exact? num)
|
(if (exact? num)
|
||||||
(exact->inexact num)
|
(exact->inexact num)
|
||||||
num)))
|
num)))
|
||||||
|
@ -229,14 +246,19 @@
|
||||||
(else
|
(else
|
||||||
(let iterate ((i (prim +
|
(let iterate ((i (prim +
|
||||||
from
|
from
|
||||||
(prim * sep
|
(prim *
|
||||||
|
sep
|
||||||
(prim quotient
|
(prim quotient
|
||||||
(prim abs (prim - to from))
|
(prim abs
|
||||||
|
(prim -
|
||||||
|
to
|
||||||
|
from))
|
||||||
(prim abs sep)))))
|
(prim abs sep)))))
|
||||||
(result '()))
|
(result '()))
|
||||||
(if (prim = i from)
|
(if (prim = i from)
|
||||||
(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.
|
||||||
|
|
||||||
|
@ -281,12 +303,16 @@
|
||||||
(built-in-func boundp
|
(built-in-func boundp
|
||||||
(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
|
;;; Function calls. These must take care of special cases, like using
|
||||||
;;; symbols or raw lambda-lists as functions!
|
;;; symbols or raw lambda-lists as functions!
|
||||||
|
@ -295,13 +321,15 @@
|
||||||
(lambda (func . args)
|
(lambda (func . args)
|
||||||
(let ((real-func (cond
|
(let ((real-func (cond
|
||||||
((symbol? func)
|
((symbol? func)
|
||||||
(reference-variable-with-check function-slot-module
|
(reference-variable-with-check
|
||||||
|
function-slot-module
|
||||||
func))
|
func))
|
||||||
((list? func)
|
((list? func)
|
||||||
(if (and (prim not (null? func))
|
(if (and (prim not (null? func))
|
||||||
(eq? (prim car func) 'lambda))
|
(eq? (prim car func) 'lambda))
|
||||||
(compile func #:from 'elisp #:to 'value)
|
(compile func #:from 'elisp #:to 'value)
|
||||||
(runtime-error "list is not a function" func)))
|
(runtime-error "list is not a function"
|
||||||
|
func)))
|
||||||
(else func))))
|
(else func))))
|
||||||
(prim apply (@ (guile) apply) real-func args))))
|
(prim apply (@ (guile) apply) real-func args))))
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,8 @@
|
||||||
|
|
||||||
(built-in-macro dotimes
|
(built-in-macro dotimes
|
||||||
(lambda (args . body)
|
(lambda (args . body)
|
||||||
(if (prim or (not (list? args))
|
(if (prim or
|
||||||
|
(not (list? args))
|
||||||
(< (length args) 2)
|
(< (length args) 2)
|
||||||
(> (length args) 3))
|
(> (length args) 3))
|
||||||
(macro-error "invalid dotimes arguments" args)
|
(macro-error "invalid dotimes arguments" args)
|
||||||
|
@ -131,7 +132,8 @@
|
||||||
|
|
||||||
(built-in-macro dolist
|
(built-in-macro dolist
|
||||||
(lambda (args . body)
|
(lambda (args . body)
|
||||||
(if (prim or (not (list? args))
|
(if (prim or
|
||||||
|
(not (list? args))
|
||||||
(< (length args) 2)
|
(< (length args) 2)
|
||||||
(> (length args) 3))
|
(> (length args) 3))
|
||||||
(macro-error "invalid dolist arguments" args)
|
(macro-error "invalid dolist arguments" args)
|
||||||
|
@ -175,7 +177,8 @@
|
||||||
(elisp-key (gensym))
|
(elisp-key (gensym))
|
||||||
(value (gensym))
|
(value (gensym))
|
||||||
(arglist `(,dummy-key ,elisp-key ,value)))
|
(arglist `(,dummy-key ,elisp-key ,value)))
|
||||||
`(with-always-lexical ,arglist
|
`(with-always-lexical
|
||||||
|
,arglist
|
||||||
(lambda ,arglist
|
(lambda ,arglist
|
||||||
(if (eq ,elisp-key ,tagsym)
|
(if (eq ,elisp-key ,tagsym)
|
||||||
,value
|
,value
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue