mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-14 01:30:19 +02:00
elisp updates
(Best-ability ChangeLog annotation added by Christine Lemmer-Webber.) * module/language/elisp/bindings.scm (get-lexical-binding) (get-function-binding): Use cadr instead of fluid-ref on slot. (with-fluids**): New procedure. (with-symbol-bindings, with-function-bindings): Use with-fluids**. Also stop using "make-fluid", use "(list #f #f)" instead as default lexical-bindings hashtable value. (with-lexical-bindings): Drop the error checking for invalid targets. * module/language/elisp/boot.el (defun, save-excursion) (save-current-buffer, save-restriction, track-mouse, setq-default) (catch, condition-case): New macros. (omega, eval, gensym, interactive, autoload-do-load, fset, prin1) (backtrace-frame, backtrace, %set-eager-macroexpansion-mode): New functions. (null, consp, listp, car, cdr, make-symbol, signal): Wrap in eval-and-compile. (prog1, cond, or, while): Update to make use of gensym. (unwind-protect): Switch from funcall to %funcall. (%functionp): Rename from functionp. (%indirect-function): Update to use %functionp instead of functionp. Add check for if object is null, signaling void-function. Instead of calling symbol-function directly, call via %funcall from the module "(language elisp runtime)". (fset): Significant additions and refactoring. (gload): Renamed from fload. (defvaralias, nthcdr, nth, eq): Move functions to a different location. (eq): Also stop using null. (dolist): Remove quasiquoting, build list manually. (random): Fix indentation. (progn, eval-when-compile, if, defconst, defvar, setq, let, flet) (labels, let*, function, defmacro, quote): Protect as special operators by raising error if invoked as a function. * module/language/elisp/compile-tree-il.scm: Import "(ice-9 format)". Export compile-%function. (lexical-binding, handle-var-def, defun, valid-symbol-list-arg?) (process-options!): Remove. (reference-variable): Adjust functions passed to access-variable. (global?): Drop module parameter, use value-slot instead. (ensure-globals!, set-variable!, parse-body-1, parse-lambda-list) (compile-lambda, defconst, defvar, let, let*, compile-pair): Refactor. (reference-function): Use '(elisp-functions) instead of function-slot. (bind-lexically?): Drop module parameter, simplify. (make-dynlet): Switch from using make-primcall to make-call. (find-operator): Switch from using resolve-interface/resolve-module to using function-slot. (if, defconst, defvar, let, let*, flet, labels, guile-ref) (guile-private-ref, guile-primitive, defmacro, `, quote, %funcall) (%set-lexical-binding-mode): Add error checking. (setq): Pass in args to report-error. (function): Simplified, now calling %function. (%function): New function, based on prior "function". Refactor, including adding support for matching against a closure. (%set-lexical-binding-mode): Switch from using fluid-set! to set-lexical-binding-mode. (special-operators): New variable. Build from following for-each statement. (compile-tree-il): Drop call to "process-options!" * module/language/elisp/lexer.scm: Import "(language elisp runtime)". (lex): Switch from using "list->string" to "make-lisp-string". * module/language/elisp/runtime.scm: Use modules "(ice-9 format)", "(system base compile)". Remove from export list list, removing ensure-fluid!, symbol-fluid!, set-symbol-fluid!. Add to export list ensure-dynamic!, symbol-name, symbol-plist, set-symbol-plist!, bind-symbol, symbol-desc, proclaim-symbol! special? emacs! unbound, lexical-binding?, set-lexical-binding-mode, log!, eval-elisp, local-eval-elisp, make-lisp-string, lisp-string? (make-list-string, lisp-string?) New function aliases. (value-slot-module, function-slot-module): Adjust module resolution. (nil_, t_): New variables. (ensure-fluid!, symbol-fluid, set-symbol-fluid!): Removed. (lexical-binding, unbound): New variables. (lexical-binding?, set-lexical-binding-mode, unbound, dynamic?) (make-dynamic, dynamic-ref, dynamic-set!, dynamic-unset!) (dynamic-bound?, dynamic-bind, ensure-present!, ensure-desc!) (schemify, symbol-name, symbol-desc, ensure-dynamic!, symbol-dynamic) (set-symbol-plist!, special?, proclaim-special!, emacs!, eval-elisp) (make-string): New procedures. (symbol-value): Use dynamic-ref! instead of fluid-ref!. (set-symbol-value!): Use dynamic-set! instead of fluid-set!. (symbol-function, set-symbol-function!, symbol-bound?) (symbol-fbound?, makunbound!, fmakunbound!): Refactor, including adjusting how module resolution is being done. * module/language/elisp/spec.scm: Import module "(system vm vm)". Setup elisp-symbols, elisp-functions, elisp-plists. Use "set-default-vm-engine!" and "set-vm-engine!" to be set to 'debug. (elisp): Comment out joiner.
This commit is contained in:
parent
ad3d498d31
commit
cf5e02f1a6
6 changed files with 582 additions and 276 deletions
|
@ -61,12 +61,22 @@
|
||||||
(let* ((lex (lexical-bindings bindings))
|
(let* ((lex (lexical-bindings bindings))
|
||||||
(slot (hash-ref lex sym #f)))
|
(slot (hash-ref lex sym #f)))
|
||||||
(if slot
|
(if slot
|
||||||
(fluid-ref slot)
|
(cadr slot)
|
||||||
#f)))
|
#f)))
|
||||||
|
|
||||||
(define (get-function-binding bindings symbol)
|
(define (get-function-binding bindings symbol)
|
||||||
(and=> (hash-ref (function-bindings bindings) symbol)
|
(and=> (hash-ref (function-bindings bindings) symbol)
|
||||||
fluid-ref))
|
cadr))
|
||||||
|
|
||||||
|
(define (with-fluids** fls vals proc)
|
||||||
|
(dynamic-wind
|
||||||
|
(lambda ()
|
||||||
|
(for-each (lambda (f v) (set-cdr! f (cons v (cdr f))))
|
||||||
|
fls vals))
|
||||||
|
proc
|
||||||
|
(lambda ()
|
||||||
|
(for-each (lambda (f) (set-cdr! f (cdr (cdr f))))
|
||||||
|
fls))))
|
||||||
|
|
||||||
;;; Establish a binding or mark a symbol as dynamically bound for the
|
;;; Establish a binding or mark a symbol as dynamically bound for the
|
||||||
;;; extent of calling proc.
|
;;; extent of calling proc.
|
||||||
|
@ -78,17 +88,14 @@
|
||||||
(let ((lex (lexical-bindings bindings)))
|
(let ((lex (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 (list #f #f))))
|
||||||
syms)
|
syms)
|
||||||
(with-fluids* (map (lambda (sym) (hash-ref lex sym)) syms)
|
(with-fluids** (map (lambda (sym) (hash-ref lex sym)) syms)
|
||||||
targets
|
targets
|
||||||
proc)))
|
proc)))
|
||||||
|
|
||||||
(define (with-lexical-bindings bindings syms targets proc)
|
(define (with-lexical-bindings bindings syms targets proc)
|
||||||
(if (or (not (list? targets))
|
(with-symbol-bindings bindings syms targets proc))
|
||||||
(not (and-map symbol? targets)))
|
|
||||||
(error "invalid targets for lexical binding" targets)
|
|
||||||
(with-symbol-bindings bindings syms targets proc)))
|
|
||||||
|
|
||||||
(define (with-dynamic-bindings bindings syms proc)
|
(define (with-dynamic-bindings bindings syms proc)
|
||||||
(with-symbol-bindings bindings
|
(with-symbol-bindings bindings
|
||||||
|
@ -100,8 +107,8 @@
|
||||||
(let ((fb (function-bindings bindings)))
|
(let ((fb (function-bindings bindings)))
|
||||||
(for-each (lambda (symbol)
|
(for-each (lambda (symbol)
|
||||||
(if (not (hash-ref fb symbol))
|
(if (not (hash-ref fb symbol))
|
||||||
(hash-set! fb symbol (make-fluid))))
|
(hash-set! fb symbol (list #f #f))))
|
||||||
symbols)
|
symbols)
|
||||||
(with-fluids* (map (cut hash-ref fb <>) symbols)
|
(with-fluids** (map (cut hash-ref fb <>) symbols)
|
||||||
gensyms
|
gensyms
|
||||||
thunk)))
|
thunk)))
|
||||||
|
|
|
@ -22,11 +22,26 @@
|
||||||
(defmacro @ (module symbol)
|
(defmacro @ (module symbol)
|
||||||
`(guile-ref ,module ,symbol))
|
`(guile-ref ,module ,symbol))
|
||||||
|
|
||||||
|
(defmacro defun (name args &rest body)
|
||||||
|
`(let ((proc (function (lambda ,args ,@body))))
|
||||||
|
(%funcall (@ (language elisp runtime) set-symbol-function!)
|
||||||
|
',name
|
||||||
|
proc)
|
||||||
|
(%funcall (@ (guile) set-procedure-property!)
|
||||||
|
proc 'name ',name)
|
||||||
|
',name))
|
||||||
|
|
||||||
|
(defun omega () (omega))
|
||||||
|
|
||||||
(defmacro eval-and-compile (&rest body)
|
(defmacro eval-and-compile (&rest body)
|
||||||
`(progn
|
`(progn
|
||||||
(eval-when-compile ,@body)
|
(eval-when-compile ,@body)
|
||||||
(progn ,@body)))
|
(progn ,@body)))
|
||||||
|
|
||||||
|
(eval-and-compile
|
||||||
|
(defun eval (form)
|
||||||
|
(%funcall (@ (language elisp runtime) eval-elisp) form)))
|
||||||
|
|
||||||
(eval-and-compile
|
(eval-and-compile
|
||||||
(defun null (object)
|
(defun null (object)
|
||||||
(if object nil t))
|
(if object nil t))
|
||||||
|
@ -40,6 +55,8 @@
|
||||||
(if list (%funcall (@ (guile) cdr) list) nil))
|
(if list (%funcall (@ (guile) cdr) list) nil))
|
||||||
(defun make-symbol (name)
|
(defun make-symbol (name)
|
||||||
(%funcall (@ (guile) make-symbol) name))
|
(%funcall (@ (guile) make-symbol) name))
|
||||||
|
(defun gensym ()
|
||||||
|
(%funcall (@ (guile) gensym)))
|
||||||
(defun signal (error-symbol data)
|
(defun signal (error-symbol data)
|
||||||
(%funcall (@ (guile) throw) 'elisp-condition error-symbol data)))
|
(%funcall (@ (guile) throw) 'elisp-condition error-symbol data)))
|
||||||
|
|
||||||
|
@ -47,12 +64,15 @@
|
||||||
`#'(lambda ,@cdr))
|
`#'(lambda ,@cdr))
|
||||||
|
|
||||||
(defmacro prog1 (first &rest body)
|
(defmacro prog1 (first &rest body)
|
||||||
(let ((temp (make-symbol "prog1-temp")))
|
(let ((temp (gensym)))
|
||||||
`(let ((,temp ,first))
|
`(let ((,temp ,first))
|
||||||
(declare (lexical ,temp))
|
(declare (lexical ,temp))
|
||||||
,@body
|
,@body
|
||||||
,temp)))
|
,temp)))
|
||||||
|
|
||||||
|
(defun interactive (&optional arg)
|
||||||
|
nil)
|
||||||
|
|
||||||
(defmacro prog2 (form1 form2 &rest body)
|
(defmacro prog2 (form1 form2 &rest body)
|
||||||
`(progn ,form1 (prog1 ,form2 ,@body)))
|
`(progn ,form1 (prog1 ,form2 ,@body)))
|
||||||
|
|
||||||
|
@ -65,7 +85,7 @@
|
||||||
(let ((condition (car first))
|
(let ((condition (car first))
|
||||||
(body (cdr first)))
|
(body (cdr first)))
|
||||||
(if (null body)
|
(if (null body)
|
||||||
(let ((temp (make-symbol "cond-temp")))
|
(let ((temp (gensym)))
|
||||||
`(let ((,temp ,condition))
|
`(let ((,temp ,condition))
|
||||||
(declare (lexical ,temp))
|
(declare (lexical ,temp))
|
||||||
(if ,temp
|
(if ,temp
|
||||||
|
@ -86,7 +106,7 @@
|
||||||
(defmacro or (&rest conditions)
|
(defmacro or (&rest conditions)
|
||||||
(cond ((null conditions) nil)
|
(cond ((null conditions) nil)
|
||||||
((null (cdr conditions)) (car conditions))
|
((null (cdr conditions)) (car conditions))
|
||||||
(t (let ((temp (make-symbol "or-temp")))
|
(t (let ((temp (gensym)))
|
||||||
`(let ((,temp ,(car conditions)))
|
`(let ((,temp ,(car conditions)))
|
||||||
(declare (lexical ,temp))
|
(declare (lexical ,temp))
|
||||||
(if ,temp
|
(if ,temp
|
||||||
|
@ -118,7 +138,7 @@
|
||||||
(loop bindings '())))
|
(loop bindings '())))
|
||||||
|
|
||||||
(defmacro while (test &rest body)
|
(defmacro while (test &rest body)
|
||||||
(let ((loop (make-symbol "loop")))
|
(let ((loop (gensym)))
|
||||||
`(labels ((,loop ()
|
`(labels ((,loop ()
|
||||||
(if ,test
|
(if ,test
|
||||||
(progn ,@body (,loop))
|
(progn ,@body (,loop))
|
||||||
|
@ -126,10 +146,10 @@
|
||||||
(,loop))))
|
(,loop))))
|
||||||
|
|
||||||
(defmacro unwind-protect (bodyform &rest unwindforms)
|
(defmacro unwind-protect (bodyform &rest unwindforms)
|
||||||
`(funcall (@ (guile) dynamic-wind)
|
`(%funcall (@ (guile) dynamic-wind)
|
||||||
#'(lambda () nil)
|
#'(lambda () nil)
|
||||||
#'(lambda () ,bodyform)
|
#'(lambda () ,bodyform)
|
||||||
#'(lambda () ,@unwindforms)))
|
#'(lambda () ,@unwindforms)))
|
||||||
|
|
||||||
(defmacro when (cond &rest body)
|
(defmacro when (cond &rest body)
|
||||||
`(if ,cond
|
`(if ,cond
|
||||||
|
@ -142,7 +162,7 @@
|
||||||
(defun symbolp (object)
|
(defun symbolp (object)
|
||||||
(%funcall (@ (guile) symbol?) object))
|
(%funcall (@ (guile) symbol?) object))
|
||||||
|
|
||||||
(defun functionp (object)
|
(defun %functionp (object)
|
||||||
(%funcall (@ (guile) procedure?) object))
|
(%funcall (@ (guile) procedure?) object))
|
||||||
|
|
||||||
(defun symbol-function (symbol)
|
(defun symbol-function (symbol)
|
||||||
|
@ -162,10 +182,13 @@
|
||||||
|
|
||||||
(defun %indirect-function (object)
|
(defun %indirect-function (object)
|
||||||
(cond
|
(cond
|
||||||
((functionp object)
|
((%functionp object)
|
||||||
object)
|
object)
|
||||||
|
((null object)
|
||||||
|
(signal 'void-function nil))
|
||||||
((symbolp object) ;++ cycle detection
|
((symbolp object) ;++ cycle detection
|
||||||
(%indirect-function (symbol-function object)))
|
(%indirect-function
|
||||||
|
(%funcall (@ (language elisp runtime) symbol-function) object)))
|
||||||
((listp object)
|
((listp object)
|
||||||
(eval `(function ,object)))
|
(eval `(function ,object)))
|
||||||
(t
|
(t
|
||||||
|
@ -182,17 +205,67 @@
|
||||||
(%indirect-function function)
|
(%indirect-function function)
|
||||||
arguments))
|
arguments))
|
||||||
|
|
||||||
|
(defun autoload-do-load (fundef &optional funname macro-only)
|
||||||
|
(and (load (cadr fundef))
|
||||||
|
(%indirect-function funname)))
|
||||||
|
|
||||||
(defun fset (symbol definition)
|
(defun fset (symbol definition)
|
||||||
(funcall (@ (language elisp runtime) set-symbol-function!)
|
(funcall (@ (language elisp runtime) set-symbol-function!)
|
||||||
symbol
|
symbol
|
||||||
(if (functionp definition)
|
definition))
|
||||||
definition
|
|
||||||
|
(defun eq (obj1 obj2)
|
||||||
|
(if obj1
|
||||||
|
(%funcall (@ (guile) eq?) obj1 obj2)
|
||||||
|
(if obj2 nil t)))
|
||||||
|
|
||||||
|
(defun nthcdr (n list)
|
||||||
|
(let ((i 0))
|
||||||
|
(while (< i n)
|
||||||
|
(setq list (cdr list)
|
||||||
|
i (+ i 1)))
|
||||||
|
list))
|
||||||
|
|
||||||
|
(defun nth (n list)
|
||||||
|
(car (nthcdr n list)))
|
||||||
|
|
||||||
|
(defun fset (symbol definition)
|
||||||
|
(funcall (@ (language elisp runtime) set-symbol-function!)
|
||||||
|
symbol
|
||||||
|
(cond
|
||||||
|
((%funcall (@ (guile) procedure?) definition)
|
||||||
|
definition)
|
||||||
|
((and (consp definition)
|
||||||
|
(eq (car definition) 'macro))
|
||||||
|
(if (%funcall (@ (guile) procedure?) (cdr definition))
|
||||||
|
definition
|
||||||
|
(cons 'macro
|
||||||
|
(funcall (@ (language elisp falias) make-falias)
|
||||||
|
(function
|
||||||
|
(lambda (&rest args) (apply (cdr definition) args)))
|
||||||
|
(cdr definition)))))
|
||||||
|
((and (consp definition)
|
||||||
|
(eq (car definition) 'autoload))
|
||||||
|
(if (or (eq (nth 4 definition) 'macro)
|
||||||
|
(eq (nth 4 definition) t))
|
||||||
|
(cons 'macro
|
||||||
|
(funcall
|
||||||
|
(@ (language elisp falias) make-falias)
|
||||||
|
(function (lambda (&rest args)
|
||||||
|
(apply (cdr (autoload-do-load definition symbol nil)) args)))
|
||||||
|
definition))
|
||||||
|
(funcall
|
||||||
|
(@ (language elisp falias) make-falias)
|
||||||
|
(function (lambda (&rest args)
|
||||||
|
(apply (autoload-do-load definition symbol nil) args)))
|
||||||
|
definition)))
|
||||||
|
(t
|
||||||
(funcall (@ (language elisp falias) make-falias)
|
(funcall (@ (language elisp falias) make-falias)
|
||||||
#'(lambda (&rest args) (apply definition args))
|
(function (lambda (&rest args) (apply definition args)))
|
||||||
definition)))
|
definition))))
|
||||||
definition)
|
definition)
|
||||||
|
|
||||||
(defun load (file)
|
(defun gload (file)
|
||||||
(funcall (@ (system base compile) compile-file)
|
(funcall (@ (system base compile) compile-file)
|
||||||
file
|
file
|
||||||
(funcall (@ (guile) symbol->keyword) 'from)
|
(funcall (@ (guile) symbol->keyword) 'from)
|
||||||
|
@ -203,11 +276,6 @@
|
||||||
|
|
||||||
;;; Equality predicates
|
;;; Equality predicates
|
||||||
|
|
||||||
(defun eq (obj1 obj2)
|
|
||||||
(if obj1
|
|
||||||
(funcall (@ (guile) eq?) obj1 obj2)
|
|
||||||
(null obj2)))
|
|
||||||
|
|
||||||
(defun eql (obj1 obj2)
|
(defun eql (obj1 obj2)
|
||||||
(if obj1
|
(if obj1
|
||||||
(funcall (@ (guile) eqv?) obj1 obj2)
|
(funcall (@ (guile) eqv?) obj1 obj2)
|
||||||
|
@ -231,13 +299,13 @@
|
||||||
(fset 'fboundp (@ (language elisp runtime) symbol-fbound?))
|
(fset 'fboundp (@ (language elisp runtime) symbol-fbound?))
|
||||||
(fset 'intern (@ (guile) string->symbol))
|
(fset 'intern (@ (guile) string->symbol))
|
||||||
|
|
||||||
(defun defvaralias (new-alias base-variable &optional docstring)
|
;(defun defvaralias (new-alias base-variable &optional docstring)
|
||||||
(let ((fluid (funcall (@ (language elisp runtime) symbol-fluid)
|
; (let ((fluid (funcall (@ (language elisp runtime) symbol-fluid)
|
||||||
base-variable)))
|
; base-variable)))
|
||||||
(funcall (@ (language elisp runtime) set-symbol-fluid!)
|
; (funcall (@ (language elisp runtime) set-symbol-fluid!)
|
||||||
new-alias
|
; new-alias
|
||||||
fluid)
|
; fluid)
|
||||||
base-variable))
|
; base-variable))
|
||||||
|
|
||||||
;;; Numerical type predicates
|
;;; Numerical type predicates
|
||||||
|
|
||||||
|
@ -344,16 +412,6 @@
|
||||||
newcdr)
|
newcdr)
|
||||||
(signal 'wrong-type-argument `(consp ,cell))))
|
(signal 'wrong-type-argument `(consp ,cell))))
|
||||||
|
|
||||||
(defun nthcdr (n list)
|
|
||||||
(let ((i 0))
|
|
||||||
(while (< i n)
|
|
||||||
(setq list (cdr list)
|
|
||||||
i (+ i 1)))
|
|
||||||
list))
|
|
||||||
|
|
||||||
(defun nth (n list)
|
|
||||||
(car (nthcdr n list)))
|
|
||||||
|
|
||||||
(defun %member (elt list test)
|
(defun %member (elt list test)
|
||||||
(cond
|
(cond
|
||||||
((null list) nil)
|
((null list) nil)
|
||||||
|
@ -400,10 +458,11 @@
|
||||||
|
|
||||||
(defmacro dolist (spec &rest body)
|
(defmacro dolist (spec &rest body)
|
||||||
(apply #'(lambda (var list &optional result)
|
(apply #'(lambda (var list &optional result)
|
||||||
`(mapc #'(lambda (,var)
|
(list 'progn
|
||||||
,@body
|
(list 'mapc
|
||||||
,result)
|
(cons 'lambda (cons (list var) body))
|
||||||
,list))
|
list)
|
||||||
|
result))
|
||||||
spec))
|
spec))
|
||||||
|
|
||||||
;;; Strings
|
;;; Strings
|
||||||
|
@ -582,6 +641,9 @@
|
||||||
(defun print (object)
|
(defun print (object)
|
||||||
(funcall (@ (guile) write) object))
|
(funcall (@ (guile) write) object))
|
||||||
|
|
||||||
|
(defun prin1 (object)
|
||||||
|
(funcall (@ (guile) write) object))
|
||||||
|
|
||||||
(defun terpri ()
|
(defun terpri ()
|
||||||
(funcall (@ (guile) newline)))
|
(funcall (@ (guile) newline)))
|
||||||
|
|
||||||
|
@ -607,11 +669,90 @@
|
||||||
(@ (guile) *random-state*)))
|
(@ (guile) *random-state*)))
|
||||||
|
|
||||||
(defun random (&optional limit)
|
(defun random (&optional limit)
|
||||||
(if (eq limit t)
|
(if (eq limit t)
|
||||||
(setq %random-state
|
(setq %random-state
|
||||||
(funcall (@ (guile) random-state-from-platform))))
|
(funcall (@ (guile) random-state-from-platform))))
|
||||||
(funcall (@ (guile) random)
|
(funcall (@ (guile) random)
|
||||||
(if (wholenump limit)
|
(if (wholenump limit)
|
||||||
limit
|
limit
|
||||||
(@ (guile) most-positive-fixnum))
|
(@ (guile) most-positive-fixnum))
|
||||||
%random-state))
|
%random-state))
|
||||||
|
|
||||||
|
(defmacro save-excursion (&rest body)
|
||||||
|
`(call-with-save-excursion #'(lambda () ,@body)))
|
||||||
|
|
||||||
|
(defmacro save-current-buffer (&rest body)
|
||||||
|
`(call-with-save-current-buffer #'(lambda () ,@body)))
|
||||||
|
|
||||||
|
(defmacro save-restriction (&rest body)
|
||||||
|
`(call-with-save-restriction #'(lambda () ,@body)))
|
||||||
|
|
||||||
|
(defmacro track-mouse (&rest body)
|
||||||
|
`(call-with-track-mouse #'(lambda () ,@body)))
|
||||||
|
|
||||||
|
(defmacro setq-default (var value &rest args)
|
||||||
|
`(progn (set-default ',var ,value)
|
||||||
|
,(if (null args)
|
||||||
|
var
|
||||||
|
`(setq-default ,@args))))
|
||||||
|
|
||||||
|
(defmacro catch (tag &rest body)
|
||||||
|
`(call-with-catch ,tag #'(lambda () ,@body)))
|
||||||
|
|
||||||
|
(defmacro condition-case (var bodyform &rest args)
|
||||||
|
(if (consp args)
|
||||||
|
(let* ((handler (car args))
|
||||||
|
(handlers (cdr args))
|
||||||
|
(handler-conditions (car handler))
|
||||||
|
(handler-body (cdr handler)))
|
||||||
|
`(call-with-handler ',var
|
||||||
|
',handler-conditions
|
||||||
|
#'(lambda () ,@handler-body)
|
||||||
|
#'(lambda ()
|
||||||
|
(condition-case ,var
|
||||||
|
,bodyform
|
||||||
|
,@handlers))))
|
||||||
|
bodyform))
|
||||||
|
|
||||||
|
(defun backtrace-frame (nframes)
|
||||||
|
(let* ((stack (funcall (@ (guile) make-stack) t))
|
||||||
|
(frame (stack-ref stack nframes))
|
||||||
|
(proc (funcall (@ (guile) frame-procedure) frame))
|
||||||
|
(pname (or (and (%functionp proc)
|
||||||
|
(funcall (@ (guile) procedure-name) proc))
|
||||||
|
proc))
|
||||||
|
(args (funcall (@ (guile) frame-arguments) frame)))
|
||||||
|
(cons t (cons pname args))))
|
||||||
|
|
||||||
|
(defun backtrace ()
|
||||||
|
(interactive)
|
||||||
|
(let* ((stack (funcall (@ (guile) make-stack) t))
|
||||||
|
(frame (funcall (@ (guile) stack-ref) stack 1))
|
||||||
|
(space (funcall (@ (guile) integer->char) 32)))
|
||||||
|
(while frame
|
||||||
|
(princ (string 32 32))
|
||||||
|
(let ((proc (funcall (@ (guile) frame-procedure) frame)))
|
||||||
|
(prin1 (or (and (%functionp proc)
|
||||||
|
(funcall (@ (guile) procedure-name) proc))
|
||||||
|
proc)))
|
||||||
|
(prin1 (funcall (@ (guile) frame-arguments) frame))
|
||||||
|
(terpri)
|
||||||
|
(setq frame (funcall (@ (guile) frame-previous) frame)))
|
||||||
|
nil))
|
||||||
|
|
||||||
|
(defun %set-eager-macroexpansion-mode (ignore)
|
||||||
|
nil)
|
||||||
|
|
||||||
|
(defun progn (&rest args) (error "Special operator"))
|
||||||
|
(defun eval-when-compile (&rest args) (error "Special operator"))
|
||||||
|
(defun if (&rest args) (error "Special operator"))
|
||||||
|
(defun defconst (&rest args) (error "Special operator"))
|
||||||
|
(defun defvar (&rest args) (error "Special operator"))
|
||||||
|
(defun setq (&rest args) (error "Special operator"))
|
||||||
|
(defun let (&rest args) (error "Special operator"))
|
||||||
|
(defun flet (&rest args) (error "Special operator"))
|
||||||
|
(defun labels (&rest args) (error "Special operator"))
|
||||||
|
(defun let* (&rest args) (error "Special operator"))
|
||||||
|
(defun function (&rest args) (error "Special operator"))
|
||||||
|
(defun defmacro (&rest args) (error "Special operator"))
|
||||||
|
(defun quote (&rest args) (error "Special operator"))
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#:use-module (srfi srfi-8)
|
#:use-module (srfi srfi-8)
|
||||||
#:use-module (srfi srfi-11)
|
#:use-module (srfi srfi-11)
|
||||||
#:use-module (srfi srfi-26)
|
#:use-module (srfi srfi-26)
|
||||||
|
#:use-module (ice-9 format)
|
||||||
#:export (compile-tree-il
|
#:export (compile-tree-il
|
||||||
compile-progn
|
compile-progn
|
||||||
compile-eval-when-compile
|
compile-eval-when-compile
|
||||||
|
@ -44,6 +45,7 @@
|
||||||
compile-guile-ref
|
compile-guile-ref
|
||||||
compile-guile-private-ref
|
compile-guile-private-ref
|
||||||
compile-guile-primitive
|
compile-guile-primitive
|
||||||
|
compile-%function
|
||||||
compile-function
|
compile-function
|
||||||
compile-defmacro
|
compile-defmacro
|
||||||
compile-defun
|
compile-defun
|
||||||
|
@ -61,8 +63,6 @@
|
||||||
|
|
||||||
(define bindings-data (make-fluid))
|
(define bindings-data (make-fluid))
|
||||||
|
|
||||||
(define lexical-binding (make-fluid))
|
|
||||||
|
|
||||||
;;; Find the source properties of some parsed expression if there are
|
;;; Find the source properties of some parsed expression if there are
|
||||||
;;; any associated with it.
|
;;; any associated with it.
|
||||||
|
|
||||||
|
@ -122,28 +122,29 @@
|
||||||
loc
|
loc
|
||||||
symbol
|
symbol
|
||||||
(lambda (lexical)
|
(lambda (lexical)
|
||||||
(make-lexical-ref loc lexical lexical))
|
(if (symbol? lexical)
|
||||||
|
(make-lexical-ref loc symbol lexical)
|
||||||
|
(make-call loc lexical '())))
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(call-primitive loc
|
(make-call loc
|
||||||
'fluid-ref
|
(make-module-ref loc runtime 'symbol-value #t)
|
||||||
(make-module-ref loc value-slot symbol #t)))))
|
(list (make-const loc symbol))))))
|
||||||
|
|
||||||
(define (global? module symbol)
|
(define (global? symbol)
|
||||||
(module-variable module symbol))
|
(module-variable value-slot symbol))
|
||||||
|
|
||||||
(define (ensure-globals! loc names body)
|
(define (ensure-globals! loc names body)
|
||||||
(if (and (every (cut global? (resolve-module value-slot) <>) names)
|
(if (and (every global? names)
|
||||||
(every symbol-interned? names))
|
(every symbol-interned? names))
|
||||||
body
|
body
|
||||||
(list->seq
|
(list->seq
|
||||||
loc
|
loc
|
||||||
`(,@(map
|
`(,@(map
|
||||||
(lambda (name)
|
(lambda (name)
|
||||||
(ensure-fluid! value-slot name)
|
(symbol-desc name)
|
||||||
(make-call loc
|
(make-call loc
|
||||||
(make-module-ref loc runtime 'ensure-fluid! #t)
|
(make-module-ref loc runtime 'symbol-desc #t)
|
||||||
(list (make-const loc value-slot)
|
(list (make-const loc name))))
|
||||||
(make-const loc name))))
|
|
||||||
names)
|
names)
|
||||||
,body))))
|
,body))))
|
||||||
|
|
||||||
|
@ -152,15 +153,17 @@
|
||||||
loc
|
loc
|
||||||
symbol
|
symbol
|
||||||
(lambda (lexical)
|
(lambda (lexical)
|
||||||
(make-lexical-set loc lexical lexical value))
|
(if (symbol? lexical)
|
||||||
|
(make-lexical-set loc symbol lexical value)
|
||||||
|
(make-call loc lexical (list value))))
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(ensure-globals!
|
(ensure-globals!
|
||||||
loc
|
loc
|
||||||
(list symbol)
|
(list symbol)
|
||||||
(call-primitive loc
|
(make-call loc
|
||||||
'fluid-set!
|
(make-module-ref loc runtime 'set-symbol-value! #t)
|
||||||
(make-module-ref loc value-slot symbol #t)
|
(list (make-const loc symbol)
|
||||||
value)))))
|
value))))))
|
||||||
|
|
||||||
(define (access-function loc symbol handle-lexical handle-global)
|
(define (access-function loc symbol handle-lexical handle-global)
|
||||||
(cond
|
(cond
|
||||||
|
@ -174,7 +177,8 @@
|
||||||
loc
|
loc
|
||||||
symbol
|
symbol
|
||||||
(lambda (gensym) (make-lexical-ref loc symbol gensym))
|
(lambda (gensym) (make-lexical-ref loc symbol gensym))
|
||||||
(lambda () (make-module-ref loc function-slot symbol #t))))
|
(lambda ()
|
||||||
|
(make-module-ref loc '(elisp-functions) symbol #t))))
|
||||||
|
|
||||||
(define (set-function! loc symbol value)
|
(define (set-function! loc symbol value)
|
||||||
(access-function
|
(access-function
|
||||||
|
@ -187,15 +191,12 @@
|
||||||
(make-module-ref loc runtime 'set-symbol-function! #t)
|
(make-module-ref loc runtime 'set-symbol-function! #t)
|
||||||
(list (make-const loc symbol) value)))))
|
(list (make-const loc symbol) value)))))
|
||||||
|
|
||||||
(define (bind-lexically? sym module decls)
|
(define (bind-lexically? sym decls)
|
||||||
(or (eq? module function-slot)
|
(let ((decl (assq-ref decls sym)))
|
||||||
(let ((decl (assq-ref decls sym)))
|
(or (eq? decl 'lexical)
|
||||||
(and (equal? module value-slot)
|
(and
|
||||||
(or
|
(lexical-binding?)
|
||||||
(eq? decl 'lexical)
|
(not (special? sym))))))
|
||||||
(and
|
|
||||||
(fluid-ref lexical-binding)
|
|
||||||
(not (global? (resolve-module module) sym))))))))
|
|
||||||
|
|
||||||
(define (parse-let-binding loc binding)
|
(define (parse-let-binding loc binding)
|
||||||
(pmatch binding
|
(pmatch binding
|
||||||
|
@ -234,11 +235,14 @@
|
||||||
(pmatch lst
|
(pmatch lst
|
||||||
(((declare . ,x) . ,tail)
|
(((declare . ,x) . ,tail)
|
||||||
(loop tail (append-reverse x decls) intspec doc))
|
(loop tail (append-reverse x decls) intspec doc))
|
||||||
(((interactive . ,x) . ,tail)
|
(((interactive) . ,tail)
|
||||||
(guard lambda? (not intspec))
|
(guard lambda? (not intspec))
|
||||||
(loop tail decls x doc))
|
(loop tail decls (cons 'interactive-form #nil) doc))
|
||||||
|
(((interactive ,x) . ,tail)
|
||||||
|
(guard lambda? (not intspec))
|
||||||
|
(loop tail decls (cons 'interactive-form x) doc))
|
||||||
((,x . ,tail)
|
((,x . ,tail)
|
||||||
(guard lambda? (string? x) (not doc) (not (null? tail)))
|
(guard lambda? (or (string? x) (lisp-string? x)) (not doc) (not (null? tail)))
|
||||||
(loop tail decls intspec x))
|
(loop tail decls intspec x))
|
||||||
(else
|
(else
|
||||||
(values (append-map parse-declaration decls)
|
(values (append-map parse-declaration decls)
|
||||||
|
@ -257,13 +261,14 @@
|
||||||
;;; optional and rest arguments.
|
;;; optional and rest arguments.
|
||||||
|
|
||||||
(define (parse-lambda-list lst)
|
(define (parse-lambda-list lst)
|
||||||
(define (%match lst null optional rest symbol)
|
(define (%match lst null optional rest symbol list*)
|
||||||
(pmatch lst
|
(pmatch lst
|
||||||
(() (null))
|
(() (null))
|
||||||
(nil (null))
|
(nil (null))
|
||||||
((&optional . ,tail) (optional tail))
|
((&optional . ,tail) (optional tail))
|
||||||
((&rest . ,tail) (rest tail))
|
((&rest . ,tail) (rest tail))
|
||||||
((,arg . ,tail) (guard (symbol? arg)) (symbol arg tail))
|
((,arg . ,tail) (guard (symbol? arg)) (symbol arg tail))
|
||||||
|
((,arg . ,tail) (guard (list? arg)) (list* arg tail))
|
||||||
(else (fail))))
|
(else (fail))))
|
||||||
(define (return rreq ropt rest)
|
(define (return rreq ropt rest)
|
||||||
(values #t (reverse rreq) (reverse ropt) rest))
|
(values #t (reverse rreq) (reverse ropt) rest))
|
||||||
|
@ -274,24 +279,28 @@
|
||||||
(lambda () (return rreq '() #f))
|
(lambda () (return rreq '() #f))
|
||||||
(lambda (tail) (parse-opt tail rreq '()))
|
(lambda (tail) (parse-opt tail rreq '()))
|
||||||
(lambda (tail) (parse-rest tail rreq '()))
|
(lambda (tail) (parse-rest tail rreq '()))
|
||||||
(lambda (arg tail) (parse-req tail (cons arg rreq)))))
|
(lambda (arg tail) (parse-req tail (cons arg rreq)))
|
||||||
|
(lambda (arg tail) (fail))))
|
||||||
(define (parse-opt lst rreq ropt)
|
(define (parse-opt lst rreq ropt)
|
||||||
(%match lst
|
(%match lst
|
||||||
(lambda () (return rreq ropt #f))
|
(lambda () (return rreq ropt #f))
|
||||||
(lambda (tail) (fail))
|
(lambda (tail) (fail))
|
||||||
(lambda (tail) (parse-rest tail rreq ropt))
|
(lambda (tail) (parse-rest tail rreq ropt))
|
||||||
|
(lambda (arg tail) (parse-opt tail rreq (cons (list arg) ropt)))
|
||||||
(lambda (arg tail) (parse-opt tail rreq (cons arg ropt)))))
|
(lambda (arg tail) (parse-opt tail rreq (cons arg ropt)))))
|
||||||
(define (parse-rest lst rreq ropt)
|
(define (parse-rest lst rreq ropt)
|
||||||
(%match lst
|
(%match lst
|
||||||
(lambda () (fail))
|
(lambda () (fail))
|
||||||
(lambda (tail) (fail))
|
(lambda (tail) (fail))
|
||||||
(lambda (tail) (fail))
|
(lambda (tail) (fail))
|
||||||
(lambda (arg tail) (parse-post-rest tail rreq ropt arg))))
|
(lambda (arg tail) (parse-post-rest tail rreq ropt arg))
|
||||||
|
(lambda (arg tail) (fail))))
|
||||||
(define (parse-post-rest lst rreq ropt rest)
|
(define (parse-post-rest lst rreq ropt rest)
|
||||||
(%match lst
|
(%match lst
|
||||||
(lambda () (return rreq ropt rest))
|
(lambda () (return rreq ropt rest))
|
||||||
(lambda () (fail))
|
(lambda () (fail))
|
||||||
(lambda () (fail))
|
(lambda () (fail))
|
||||||
|
(lambda (arg tail) (fail))
|
||||||
(lambda (arg tail) (fail))))
|
(lambda (arg tail) (fail))))
|
||||||
(parse-req lst '()))
|
(parse-req lst '()))
|
||||||
|
|
||||||
|
@ -308,30 +317,30 @@
|
||||||
(let lp ((f f) (v v))
|
(let lp ((f f) (v v))
|
||||||
(if (null? f)
|
(if (null? f)
|
||||||
body
|
body
|
||||||
(make-primcall
|
(make-call src
|
||||||
src 'with-fluid*
|
(make-module-ref src runtime 'bind-symbol #t)
|
||||||
(list (make-lexical-ref #f 'fluid (car f))
|
(list (make-lexical-ref #f 'fluid (car f))
|
||||||
(make-lexical-ref #f 'val (car v))
|
(make-lexical-ref #f 'val (car v))
|
||||||
(make-lambda
|
(make-lambda
|
||||||
src '()
|
src '()
|
||||||
(make-lambda-case
|
(make-lambda-case
|
||||||
src '() #f #f #f '() '()
|
src '() #f #f #f '() '()
|
||||||
(lp (cdr f) (cdr v))
|
(lp (cdr f) (cdr v))
|
||||||
#f))))))))))
|
#f))))))))))
|
||||||
|
|
||||||
(define (compile-lambda loc meta args body)
|
(define (compile-lambda loc meta args body)
|
||||||
(receive (valid? req-ids opt-ids rest-id)
|
(receive (valid? req-ids opts rest-id)
|
||||||
(parse-lambda-list args)
|
(parse-lambda-list args)
|
||||||
(if valid?
|
(if valid?
|
||||||
(let* ((all-ids (append req-ids
|
(let* ((all-ids (append req-ids
|
||||||
opt-ids
|
(and opts (map car opts))
|
||||||
(or (and=> rest-id list) '())))
|
(or (and=> rest-id list) '())))
|
||||||
(all-vars (map (lambda (ignore) (gensym)) all-ids)))
|
(all-vars (map (lambda (ignore) (gensym)) all-ids)))
|
||||||
(let*-values (((decls intspec doc forms)
|
(let*-values (((decls intspec doc forms)
|
||||||
(parse-lambda-body body))
|
(parse-lambda-body body))
|
||||||
((lexical dynamic)
|
((lexical dynamic)
|
||||||
(partition
|
(partition
|
||||||
(compose (cut bind-lexically? <> value-slot decls)
|
(compose (cut bind-lexically? <> decls)
|
||||||
car)
|
car)
|
||||||
(map list all-ids all-vars)))
|
(map list all-ids all-vars)))
|
||||||
((lexical-ids lexical-vars) (unzip2 lexical))
|
((lexical-ids lexical-vars) (unzip2 lexical))
|
||||||
|
@ -361,50 +370,42 @@
|
||||||
tree-il
|
tree-il
|
||||||
(make-dynlet
|
(make-dynlet
|
||||||
loc
|
loc
|
||||||
(map (cut make-module-ref loc value-slot <> #t)
|
(map (cut make-const loc <>) dynamic-ids)
|
||||||
dynamic-ids)
|
|
||||||
(map (cut make-lexical-ref loc <> <>)
|
(map (cut make-lexical-ref loc <> <>)
|
||||||
dynamic-ids
|
dynamic-ids
|
||||||
dynamic-vars)
|
dynamic-vars)
|
||||||
tree-il))))
|
tree-il))))
|
||||||
(make-simple-lambda loc
|
(make-simple-lambda loc
|
||||||
meta
|
(append (if intspec
|
||||||
|
(list intspec)
|
||||||
|
'())
|
||||||
|
(if doc
|
||||||
|
(list (cons 'emacs-documentation doc))
|
||||||
|
'())
|
||||||
|
meta)
|
||||||
req-ids
|
req-ids
|
||||||
opt-ids
|
(map car opts)
|
||||||
(map (const (nil-value loc))
|
(map (lambda (x)
|
||||||
opt-ids)
|
(if (pair? (cdr x))
|
||||||
|
(compile-expr (car (cdr x)))
|
||||||
|
(make-const loc #nil)))
|
||||||
|
opts)
|
||||||
rest-id
|
rest-id
|
||||||
all-vars
|
all-vars
|
||||||
full-body)))))))))
|
full-body)))))))))
|
||||||
(report-error "invalid function" `(lambda ,args ,@body)))))
|
(report-error "invalid function" `(lambda ,args ,@body)))))
|
||||||
|
|
||||||
;;; Handle the common part of defconst and defvar, that is, checking for
|
|
||||||
;;; a correct doc string and arguments as well as maybe in the future
|
|
||||||
;;; handling the docstring somehow.
|
|
||||||
|
|
||||||
(define (handle-var-def loc sym doc)
|
|
||||||
(cond
|
|
||||||
((not (symbol? sym)) (report-error loc "expected symbol, got" sym))
|
|
||||||
((> (length doc) 1) (report-error loc "too many arguments to defvar"))
|
|
||||||
((and (not (null? doc)) (not (string? (car doc))))
|
|
||||||
(report-error loc "expected string as third argument of defvar, got"
|
|
||||||
(car doc)))
|
|
||||||
;; TODO: Handle doc string if present.
|
|
||||||
(else #t)))
|
|
||||||
|
|
||||||
;;; Handle macro and special operator bindings.
|
;;; Handle macro and special operator bindings.
|
||||||
|
|
||||||
(define (find-operator name type)
|
(define (find-operator name type)
|
||||||
(and
|
(and
|
||||||
(symbol? name)
|
(symbol? name)
|
||||||
(module-defined? (resolve-interface function-slot) name)
|
(module-defined? function-slot name)
|
||||||
(let ((op (module-ref (resolve-module function-slot) name)))
|
(let ((op (module-ref function-slot name)))
|
||||||
(if (and (pair? op) (eq? (car op) type))
|
(if (and (pair? op) (eq? (car op) type))
|
||||||
(cdr op)
|
(cdr op)
|
||||||
#f))))
|
#f))))
|
||||||
|
|
||||||
;;; See if a (backquoted) expression contains any unquotes.
|
|
||||||
|
|
||||||
(define (contains-unquotes? expr)
|
(define (contains-unquotes? expr)
|
||||||
(if (pair? expr)
|
(if (pair? expr)
|
||||||
(if (or (unquote? (car expr)) (unquote-splicing? (car expr)))
|
(if (or (unquote? (car expr)) (unquote-splicing? (car expr)))
|
||||||
|
@ -475,41 +476,47 @@
|
||||||
(call-primitive loc 'not
|
(call-primitive loc 'not
|
||||||
(call-primitive loc 'nil? (compile-expr cond)))
|
(call-primitive loc 'nil? (compile-expr cond)))
|
||||||
(compile-expr then)
|
(compile-expr then)
|
||||||
(compile-expr `(progn ,@else))))))
|
(compile-expr `(progn ,@else))))
|
||||||
|
(else (report-error loc "Bad if" args))))
|
||||||
|
|
||||||
(defspecial defconst (loc args)
|
(defspecial defconst (loc args)
|
||||||
(pmatch args
|
(pmatch args
|
||||||
((,sym ,value . ,doc)
|
((,sym ,value . ,doc)
|
||||||
(if (handle-var-def loc sym doc)
|
(make-seq
|
||||||
(make-seq loc
|
loc
|
||||||
(set-variable! loc sym (compile-expr value))
|
(make-call loc
|
||||||
(make-const loc sym))))))
|
(make-module-ref loc runtime 'proclaim-special! #t)
|
||||||
|
(list (make-const loc sym)))
|
||||||
|
(make-seq loc
|
||||||
|
(set-variable! loc sym (compile-expr value))
|
||||||
|
(make-const loc sym))))
|
||||||
|
(else (report-error loc "Bad defconst" args))))
|
||||||
|
|
||||||
(defspecial defvar (loc args)
|
(defspecial defvar (loc args)
|
||||||
(pmatch args
|
(pmatch args
|
||||||
((,sym) (make-const loc sym))
|
((,sym)
|
||||||
|
(make-seq loc
|
||||||
|
(make-call loc
|
||||||
|
(make-module-ref loc runtime 'proclaim-special! #t)
|
||||||
|
(list (make-const loc sym)))
|
||||||
|
(make-const loc sym)))
|
||||||
((,sym ,value . ,doc)
|
((,sym ,value . ,doc)
|
||||||
(if (handle-var-def loc sym doc)
|
(make-seq
|
||||||
(make-seq
|
loc
|
||||||
loc
|
(make-call loc
|
||||||
(make-conditional
|
(make-module-ref loc runtime 'proclaim-special! #t)
|
||||||
loc
|
(list (make-const loc sym)))
|
||||||
(make-conditional
|
(make-seq
|
||||||
loc
|
loc
|
||||||
(call-primitive
|
(make-conditional
|
||||||
loc
|
loc
|
||||||
'module-bound?
|
(make-call loc
|
||||||
(call-primitive loc
|
(make-module-ref loc runtime 'symbol-bound? #t)
|
||||||
'resolve-interface
|
(list (make-const loc sym)))
|
||||||
(make-const loc value-slot))
|
(make-void loc)
|
||||||
(make-const loc sym))
|
(set-variable! loc sym (compile-expr value)))
|
||||||
(call-primitive loc
|
(make-const loc sym))))
|
||||||
'fluid-bound?
|
(else (report-error loc "Bad defvar" args))))
|
||||||
(make-module-ref loc value-slot sym #t))
|
|
||||||
(make-const loc #f))
|
|
||||||
(make-void loc)
|
|
||||||
(set-variable! loc sym (compile-expr value)))
|
|
||||||
(make-const loc sym))))))
|
|
||||||
|
|
||||||
(defspecial setq (loc args)
|
(defspecial setq (loc args)
|
||||||
(define (car* x) (if (null? x) '() (car x)))
|
(define (car* x) (if (null? x) '() (car x)))
|
||||||
|
@ -524,7 +531,7 @@
|
||||||
(let ((sym (car args))
|
(let ((sym (car args))
|
||||||
(val (compile-expr (cadr* args))))
|
(val (compile-expr (cadr* args))))
|
||||||
(if (not (symbol? sym))
|
(if (not (symbol? sym))
|
||||||
(report-error loc "expected symbol in setq")
|
(report-error loc "expected symbol in setq" args)
|
||||||
(cons
|
(cons
|
||||||
(set-variable! loc sym val)
|
(set-variable! loc sym val)
|
||||||
(loop (cddr* args)
|
(loop (cddr* args)
|
||||||
|
@ -537,7 +544,7 @@
|
||||||
(receive (decls forms) (parse-body body)
|
(receive (decls forms) (parse-body body)
|
||||||
(receive (lexical dynamic)
|
(receive (lexical dynamic)
|
||||||
(partition
|
(partition
|
||||||
(compose (cut bind-lexically? <> value-slot decls)
|
(compose (cut bind-lexically? <> decls)
|
||||||
car)
|
car)
|
||||||
bindings)
|
bindings)
|
||||||
(let ((make-values (lambda (for)
|
(let ((make-values (lambda (for)
|
||||||
|
@ -549,12 +556,7 @@
|
||||||
(map car dynamic)
|
(map car dynamic)
|
||||||
(if (null? lexical)
|
(if (null? lexical)
|
||||||
(make-dynlet loc
|
(make-dynlet loc
|
||||||
(map (compose (cut make-module-ref
|
(map (compose (cut make-const loc <>) car)
|
||||||
loc
|
|
||||||
value-slot
|
|
||||||
<>
|
|
||||||
#t)
|
|
||||||
car)
|
|
||||||
dynamic)
|
dynamic)
|
||||||
(map (compose compile-expr cdr)
|
(map (compose compile-expr cdr)
|
||||||
dynamic)
|
dynamic)
|
||||||
|
@ -577,13 +579,10 @@
|
||||||
(make-body)
|
(make-body)
|
||||||
(make-dynlet loc
|
(make-dynlet loc
|
||||||
(map
|
(map
|
||||||
(compose
|
(compose (cut make-const
|
||||||
(cut make-module-ref
|
loc
|
||||||
loc
|
<>)
|
||||||
value-slot
|
car)
|
||||||
<>
|
|
||||||
#t)
|
|
||||||
car)
|
|
||||||
dynamic)
|
dynamic)
|
||||||
(map
|
(map
|
||||||
(lambda (sym)
|
(lambda (sym)
|
||||||
|
@ -592,7 +591,8 @@
|
||||||
sym
|
sym
|
||||||
sym))
|
sym))
|
||||||
dynamic-syms)
|
dynamic-syms)
|
||||||
(make-body))))))))))))))))
|
(make-body))))))))))))))
|
||||||
|
(else (report-error loc "bad let args"))))
|
||||||
|
|
||||||
(defspecial let* (loc args)
|
(defspecial let* (loc args)
|
||||||
(pmatch args
|
(pmatch args
|
||||||
|
@ -604,7 +604,7 @@
|
||||||
(compile-expr `(progn ,@forms))
|
(compile-expr `(progn ,@forms))
|
||||||
(let ((sym (caar tail))
|
(let ((sym (caar tail))
|
||||||
(value (compile-expr (cdar tail))))
|
(value (compile-expr (cdar tail))))
|
||||||
(if (bind-lexically? sym value-slot decls)
|
(if (bind-lexically? sym decls)
|
||||||
(let ((target (gensym)))
|
(let ((target (gensym)))
|
||||||
(make-let loc
|
(make-let loc
|
||||||
`(,target)
|
`(,target)
|
||||||
|
@ -619,9 +619,10 @@
|
||||||
loc
|
loc
|
||||||
(list sym)
|
(list sym)
|
||||||
(make-dynlet loc
|
(make-dynlet loc
|
||||||
(list (make-module-ref loc value-slot sym #t))
|
(list (make-const loc sym))
|
||||||
(list value)
|
(list value)
|
||||||
(iterate (cdr tail)))))))))))))
|
(iterate (cdr tail)))))))))))
|
||||||
|
(else (report-error loc "Bad let*" args))))
|
||||||
|
|
||||||
(defspecial flet (loc args)
|
(defspecial flet (loc args)
|
||||||
(pmatch args
|
(pmatch args
|
||||||
|
@ -640,7 +641,8 @@
|
||||||
names
|
names
|
||||||
gensyms
|
gensyms
|
||||||
(map compile-expr vals)
|
(map compile-expr vals)
|
||||||
(compile-expr `(progn ,@forms)))))))))))
|
(compile-expr `(progn ,@forms)))))))))
|
||||||
|
(else (report-error loc "bad flet" args))))
|
||||||
|
|
||||||
(defspecial labels (loc args)
|
(defspecial labels (loc args)
|
||||||
(pmatch args
|
(pmatch args
|
||||||
|
@ -660,7 +662,8 @@
|
||||||
names
|
names
|
||||||
gensyms
|
gensyms
|
||||||
(map compile-expr vals)
|
(map compile-expr vals)
|
||||||
(compile-expr `(progn ,@forms)))))))))))
|
(compile-expr `(progn ,@forms)))))))))
|
||||||
|
(else (report-error loc "bad labels" args))))
|
||||||
|
|
||||||
;;; guile-ref allows building TreeIL's module references from within
|
;;; guile-ref allows building TreeIL's module references from within
|
||||||
;;; elisp as a way to access data within the Guile universe. The module
|
;;; elisp as a way to access data within the Guile universe. The module
|
||||||
|
@ -670,12 +673,14 @@
|
||||||
(defspecial guile-ref (loc args)
|
(defspecial guile-ref (loc args)
|
||||||
(pmatch args
|
(pmatch args
|
||||||
((,module ,sym) (guard (and (list? module) (symbol? sym)))
|
((,module ,sym) (guard (and (list? module) (symbol? sym)))
|
||||||
(make-module-ref loc module sym #t))))
|
(make-module-ref loc module sym #t))
|
||||||
|
(else (report-error loc "bad guile-ref" args))))
|
||||||
|
|
||||||
(defspecial guile-private-ref (loc args)
|
(defspecial guile-private-ref (loc args)
|
||||||
(pmatch args
|
(pmatch args
|
||||||
((,module ,sym) (guard (and (list? module) (symbol? sym)))
|
((,module ,sym) (guard (and (list? module) (symbol? sym)))
|
||||||
(make-module-ref loc module sym #f))))
|
(make-module-ref loc module sym #f))
|
||||||
|
(else (report-error loc "bad guile-private-ref" args))))
|
||||||
|
|
||||||
;;; guile-primitive allows to create primitive references, which are
|
;;; guile-primitive allows to create primitive references, which are
|
||||||
;;; still a little faster.
|
;;; still a little faster.
|
||||||
|
@ -683,14 +688,46 @@
|
||||||
(defspecial guile-primitive (loc args)
|
(defspecial guile-primitive (loc args)
|
||||||
(pmatch args
|
(pmatch args
|
||||||
((,sym)
|
((,sym)
|
||||||
(make-primitive-ref loc sym))))
|
(make-primitive-ref loc sym))
|
||||||
|
(else (report-error loc "bad guile-primitive" args))))
|
||||||
|
|
||||||
(defspecial function (loc args)
|
(defspecial %function (loc args)
|
||||||
(pmatch args
|
(pmatch args
|
||||||
(((lambda ,args . ,body))
|
(((lambda ,args . ,body))
|
||||||
(compile-lambda loc '() args body))
|
(compile-lambda loc '() args body))
|
||||||
|
(((closure ,env ,args . ,body))
|
||||||
|
(let ((bindings (map (lambda (x) (list (car x) (cdr x)))
|
||||||
|
(filter pair? env))))
|
||||||
|
(compile-expr
|
||||||
|
(let ((form `(let ,bindings
|
||||||
|
(declare ,@(map (lambda (x) (list 'lexical x))
|
||||||
|
bindings))
|
||||||
|
(function (lambda ,args
|
||||||
|
(declare
|
||||||
|
(lexical
|
||||||
|
,@(filter-map
|
||||||
|
(lambda (x)
|
||||||
|
(cond
|
||||||
|
((memq x '(&optional &rest))
|
||||||
|
#f)
|
||||||
|
((symbol? x)
|
||||||
|
x)
|
||||||
|
((list? x)
|
||||||
|
(car x))))
|
||||||
|
args)))
|
||||||
|
,@body)))))
|
||||||
|
form))))
|
||||||
((,sym) (guard (symbol? sym))
|
((,sym) (guard (symbol? sym))
|
||||||
(reference-function loc sym))))
|
(reference-function loc sym))
|
||||||
|
((,x)
|
||||||
|
(make-const loc x))
|
||||||
|
(else (report-error loc "bad function" args))))
|
||||||
|
|
||||||
|
(defspecial function (loc args)
|
||||||
|
(pmatch args
|
||||||
|
((,sym) (guard (symbol? sym))
|
||||||
|
(make-const loc sym))
|
||||||
|
(else ((cdr compile-%function) loc args))))
|
||||||
|
|
||||||
(defspecial defmacro (loc args)
|
(defspecial defmacro (loc args)
|
||||||
(pmatch args
|
(pmatch args
|
||||||
|
@ -715,44 +752,60 @@
|
||||||
(with-native-target
|
(with-native-target
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(compile tree-il #:from 'tree-il #:to 'value)))
|
(compile tree-il #:from 'tree-il #:to 'value)))
|
||||||
tree-il)))))
|
tree-il)))
|
||||||
|
(else (report-error loc "bad defmacro" args))))
|
||||||
(defspecial defun (loc args)
|
|
||||||
(pmatch args
|
|
||||||
((,name ,args . ,body)
|
|
||||||
(if (not (symbol? name))
|
|
||||||
(report-error loc "expected symbol as function name" name)
|
|
||||||
(make-seq loc
|
|
||||||
(set-function! loc
|
|
||||||
name
|
|
||||||
(compile-lambda loc
|
|
||||||
`((name . ,name))
|
|
||||||
args
|
|
||||||
body))
|
|
||||||
(make-const loc name))))))
|
|
||||||
|
|
||||||
(defspecial #{`}# (loc args)
|
(defspecial #{`}# (loc args)
|
||||||
(pmatch args
|
(pmatch args
|
||||||
((,val)
|
((,val)
|
||||||
(process-backquote loc val))))
|
(process-backquote loc val))
|
||||||
|
(else (report-error loc "bad backquote" args))))
|
||||||
|
|
||||||
(defspecial quote (loc args)
|
(defspecial quote (loc args)
|
||||||
(pmatch args
|
(pmatch args
|
||||||
((,val)
|
((,val)
|
||||||
(make-const loc val))))
|
(make-const loc val))
|
||||||
|
(else (report-error loc "bad quote" args))))
|
||||||
|
|
||||||
(defspecial %funcall (loc args)
|
(defspecial %funcall (loc args)
|
||||||
(pmatch args
|
(pmatch args
|
||||||
((,function . ,arguments)
|
((,function . ,arguments)
|
||||||
(make-call loc
|
(make-call loc
|
||||||
(compile-expr function)
|
(compile-expr function)
|
||||||
(map compile-expr arguments)))))
|
(map compile-expr arguments)))
|
||||||
|
(else (report-error loc "bad %funcall" args))))
|
||||||
|
|
||||||
(defspecial %set-lexical-binding-mode (loc args)
|
(defspecial %set-lexical-binding-mode (loc args)
|
||||||
(pmatch args
|
(pmatch args
|
||||||
((,val)
|
((,val)
|
||||||
(fluid-set! lexical-binding val)
|
(set-lexical-binding-mode val)
|
||||||
(make-void loc))))
|
(make-void loc))
|
||||||
|
(else (report-error loc "bad %set-lexical-binding-mode" args))))
|
||||||
|
|
||||||
|
(define special-operators (make-hash-table))
|
||||||
|
|
||||||
|
(for-each
|
||||||
|
(lambda (pair) (hashq-set! special-operators (car pair) (cddr pair)))
|
||||||
|
`((progn . ,compile-progn)
|
||||||
|
(eval-when-compile . ,compile-eval-when-compile)
|
||||||
|
(if . ,compile-if)
|
||||||
|
(defconst . ,compile-defconst)
|
||||||
|
(defvar . ,compile-defvar)
|
||||||
|
(setq . ,compile-setq)
|
||||||
|
(let . ,compile-let)
|
||||||
|
(flet . ,compile-flet)
|
||||||
|
(labels . ,compile-labels)
|
||||||
|
(let* . ,compile-let*)
|
||||||
|
(guile-ref . ,compile-guile-ref)
|
||||||
|
(guile-private-ref . ,compile-guile-private-ref)
|
||||||
|
(guile-primitive . ,compile-guile-primitive)
|
||||||
|
(%function . ,compile-%function)
|
||||||
|
(function . ,compile-function)
|
||||||
|
(defmacro . ,compile-defmacro)
|
||||||
|
(#{`}# . ,#{compile-`}#)
|
||||||
|
(quote . ,compile-quote)
|
||||||
|
(%funcall . ,compile-%funcall)
|
||||||
|
(%set-lexical-binding-mode . ,compile-%set-lexical-binding-mode)))
|
||||||
|
|
||||||
;;; Compile a compound expression to Tree-IL.
|
;;; Compile a compound expression to Tree-IL.
|
||||||
|
|
||||||
|
@ -760,14 +813,14 @@
|
||||||
(let ((operator (car expr))
|
(let ((operator (car expr))
|
||||||
(arguments (cdr expr)))
|
(arguments (cdr expr)))
|
||||||
(cond
|
(cond
|
||||||
((find-operator operator 'special-operator)
|
|
||||||
=> (lambda (special-operator-function)
|
|
||||||
(special-operator-function loc arguments)))
|
|
||||||
((find-operator operator 'macro)
|
((find-operator operator 'macro)
|
||||||
=> (lambda (macro-function)
|
=> (lambda (macro-function)
|
||||||
(compile-expr (apply macro-function arguments))))
|
(compile-expr (apply macro-function arguments))))
|
||||||
|
((hashq-ref special-operators operator)
|
||||||
|
=> (lambda (special-operator-function)
|
||||||
|
(special-operator-function loc arguments)))
|
||||||
(else
|
(else
|
||||||
(compile-expr `(%funcall (function ,operator) ,@arguments))))))
|
(compile-expr `(%funcall (%function ,operator) ,@arguments))))))
|
||||||
|
|
||||||
;;; Compile a symbol expression. This is a variable reference or maybe
|
;;; Compile a symbol expression. This is a variable reference or maybe
|
||||||
;;; some special value like nil.
|
;;; some special value like nil.
|
||||||
|
@ -789,31 +842,9 @@
|
||||||
(compile-pair loc expr))
|
(compile-pair loc expr))
|
||||||
(else (make-const loc expr)))))
|
(else (make-const loc expr)))))
|
||||||
|
|
||||||
;;; Process the compiler options.
|
|
||||||
;;; FIXME: Why is '(()) passed as options by the REPL?
|
|
||||||
|
|
||||||
(define (valid-symbol-list-arg? value)
|
|
||||||
(or (eq? value 'all)
|
|
||||||
(and (list? value) (and-map symbol? value))))
|
|
||||||
|
|
||||||
(define (process-options! opt)
|
|
||||||
(if (and (not (null? opt))
|
|
||||||
(not (equal? opt '(()))))
|
|
||||||
(if (null? (cdr opt))
|
|
||||||
(report-error #f "Invalid compiler options" opt)
|
|
||||||
(let ((key (car opt))
|
|
||||||
(value (cadr opt)))
|
|
||||||
(case key
|
|
||||||
((#:warnings #:to-file?) ; ignore
|
|
||||||
#f)
|
|
||||||
(else (report-error #f
|
|
||||||
"Invalid compiler option"
|
|
||||||
key)))))))
|
|
||||||
|
|
||||||
(define (compile-tree-il expr env opts)
|
(define (compile-tree-il expr env opts)
|
||||||
(values
|
(values
|
||||||
(with-fluids ((bindings-data (make-bindings)))
|
(with-fluids ((bindings-data (make-bindings)))
|
||||||
(process-options! opts)
|
|
||||||
(compile-expr expr))
|
(compile-expr expr))
|
||||||
env
|
env
|
||||||
env))
|
env))
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
(define-module (language elisp lexer)
|
(define-module (language elisp lexer)
|
||||||
#:use-module (ice-9 regex)
|
#:use-module (ice-9 regex)
|
||||||
|
#:use-module (language elisp runtime)
|
||||||
#:export (get-lexer get-lexer/1))
|
#:export (get-lexer get-lexer/1))
|
||||||
|
|
||||||
;;; This is the lexical analyzer for the elisp reader. It is
|
;;; This is the lexical analyzer for the elisp reader. It is
|
||||||
|
@ -316,7 +317,9 @@
|
||||||
(let ((cur (read-char port)))
|
(let ((cur (read-char port)))
|
||||||
(case cur
|
(case cur
|
||||||
((#\")
|
((#\")
|
||||||
(return 'string (list->string (reverse result-chars))))
|
(return 'string
|
||||||
|
(make-lisp-string
|
||||||
|
(list->string (reverse result-chars)))))
|
||||||
((#\\)
|
((#\\)
|
||||||
(let ((escaped (read-char port)))
|
(let ((escaped (read-char port)))
|
||||||
(case escaped
|
(case escaped
|
||||||
|
|
|
@ -19,22 +19,39 @@
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
(define-module (language elisp runtime)
|
(define-module (language elisp runtime)
|
||||||
|
#:use-module (ice-9 format)
|
||||||
|
#:use-module ((system base compile)
|
||||||
|
#:select (compile))
|
||||||
#:export (nil-value
|
#:export (nil-value
|
||||||
t-value
|
t-value
|
||||||
value-slot-module
|
value-slot-module
|
||||||
function-slot-module
|
function-slot-module
|
||||||
elisp-bool
|
elisp-bool
|
||||||
ensure-fluid!
|
ensure-dynamic!
|
||||||
symbol-fluid
|
symbol-name
|
||||||
set-symbol-fluid!
|
|
||||||
symbol-value
|
symbol-value
|
||||||
set-symbol-value!
|
set-symbol-value!
|
||||||
symbol-function
|
symbol-function
|
||||||
set-symbol-function!
|
set-symbol-function!
|
||||||
|
symbol-plist
|
||||||
|
set-symbol-plist!
|
||||||
symbol-bound?
|
symbol-bound?
|
||||||
symbol-fbound?
|
symbol-fbound?
|
||||||
|
bind-symbol
|
||||||
makunbound!
|
makunbound!
|
||||||
fmakunbound!)
|
fmakunbound!
|
||||||
|
symbol-desc
|
||||||
|
proclaim-special!
|
||||||
|
special?
|
||||||
|
emacs!
|
||||||
|
unbound
|
||||||
|
lexical-binding?
|
||||||
|
set-lexical-binding-mode
|
||||||
|
log!
|
||||||
|
eval-elisp
|
||||||
|
local-eval-elisp
|
||||||
|
make-lisp-string
|
||||||
|
lisp-string?)
|
||||||
#:export-syntax (defspecial prim))
|
#:export-syntax (defspecial prim))
|
||||||
|
|
||||||
;;; This module provides runtime support for the Elisp front-end.
|
;;; This module provides runtime support for the Elisp front-end.
|
||||||
|
@ -45,13 +62,21 @@
|
||||||
|
|
||||||
(define t-value #t)
|
(define t-value #t)
|
||||||
|
|
||||||
|
(define make-lisp-string identity)
|
||||||
|
(define lisp-string? string?)
|
||||||
|
|
||||||
;;; 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 (resolve-module '(elisp-symbols)))
|
||||||
|
|
||||||
(define function-slot-module '(language elisp runtime function-slot))
|
(define function-slot-module (resolve-module '(elisp-functions)))
|
||||||
|
|
||||||
|
(define plist-slot-module (resolve-module '(elisp-plists)))
|
||||||
|
|
||||||
|
(define nil_ 'nil)
|
||||||
|
(define t_ 't)
|
||||||
|
|
||||||
;;; Routines for access to elisp dynamically bound symbols. This is
|
;;; Routines for access to elisp dynamically bound symbols. This is
|
||||||
;;; used for runtime access using functions like symbol-value or set,
|
;;; used for runtime access using functions like symbol-value or set,
|
||||||
|
@ -59,75 +84,163 @@
|
||||||
;;; always access the dynamic binding and can not be used for the
|
;;; always access the dynamic binding and can not be used for the
|
||||||
;;; lexical!
|
;;; lexical!
|
||||||
|
|
||||||
(define (ensure-fluid! module sym)
|
(define lexical-binding #t)
|
||||||
(let ((intf (resolve-interface module))
|
|
||||||
(resolved (resolve-module module)))
|
|
||||||
(if (not (module-defined? intf sym))
|
|
||||||
(let ((fluid (make-unbound-fluid)))
|
|
||||||
(module-define! resolved sym fluid)
|
|
||||||
(module-export! resolved `(,sym))))))
|
|
||||||
|
|
||||||
(define (symbol-fluid symbol)
|
(define (lexical-binding?)
|
||||||
(let ((module (resolve-module value-slot-module)))
|
lexical-binding)
|
||||||
(ensure-fluid! value-slot-module symbol) ;++ implicit special proclamation
|
|
||||||
(module-ref module symbol)))
|
|
||||||
|
|
||||||
(define (set-symbol-fluid! symbol fluid)
|
(define (set-lexical-binding-mode x)
|
||||||
(let ((module (resolve-module value-slot-module)))
|
(set! lexical-binding x))
|
||||||
(module-define! module symbol fluid)
|
|
||||||
(module-export! module (list symbol)))
|
(define unbound (make-symbol "unbound"))
|
||||||
fluid)
|
|
||||||
|
(define dynamic? vector?)
|
||||||
|
(define (make-dynamic)
|
||||||
|
(vector #f 4 0 0 unbound))
|
||||||
|
(define (dynamic-ref x)
|
||||||
|
(vector-ref x 4))
|
||||||
|
(define (dynamic-set! x v)
|
||||||
|
(vector-set! x 4 v))
|
||||||
|
(define (dynamic-unset! x)
|
||||||
|
(vector-set! x 4 unbound))
|
||||||
|
(define (dynamic-bound? x)
|
||||||
|
(not (eq? (vector-ref x 4) unbound)))
|
||||||
|
(define (dynamic-bind x v thunk)
|
||||||
|
(let ((old (vector-ref x 4)))
|
||||||
|
(dynamic-wind
|
||||||
|
(lambda () (vector-set! x 4 v))
|
||||||
|
thunk
|
||||||
|
(lambda () (vector-set! x 4 old)))))
|
||||||
|
|
||||||
|
(define-inlinable (ensure-present! module sym thunk)
|
||||||
|
(or (module-local-variable module sym)
|
||||||
|
(let ((variable (make-variable (thunk))))
|
||||||
|
(module-add! module sym variable)
|
||||||
|
variable)))
|
||||||
|
|
||||||
|
(define-inlinable (ensure-desc! module sym)
|
||||||
|
(ensure-present! module
|
||||||
|
sym
|
||||||
|
(lambda ()
|
||||||
|
(let ((x (make-dynamic)))
|
||||||
|
(vector-set! x 0 sym)
|
||||||
|
x))))
|
||||||
|
|
||||||
|
(define-inlinable (schemify symbol)
|
||||||
|
(case symbol
|
||||||
|
((#nil) nil_)
|
||||||
|
((#t) t_)
|
||||||
|
(else symbol)))
|
||||||
|
|
||||||
|
(define (symbol-name symbol)
|
||||||
|
(symbol->string (schemify symbol)))
|
||||||
|
|
||||||
|
(define (symbol-desc symbol)
|
||||||
|
(let ((symbol (schemify symbol)))
|
||||||
|
(let ((module value-slot-module))
|
||||||
|
(variable-ref (ensure-desc! module symbol)))))
|
||||||
|
|
||||||
|
(define (ensure-dynamic! sym)
|
||||||
|
(vector-set! (symbol-desc sym) 3 1))
|
||||||
|
|
||||||
|
(define (symbol-dynamic symbol)
|
||||||
|
(ensure-dynamic! symbol)
|
||||||
|
(symbol-desc symbol))
|
||||||
|
|
||||||
(define (symbol-value symbol)
|
(define (symbol-value symbol)
|
||||||
(fluid-ref (symbol-fluid symbol)))
|
(dynamic-ref (symbol-desc symbol)))
|
||||||
|
|
||||||
(define (set-symbol-value! symbol value)
|
(define (set-symbol-value! symbol value)
|
||||||
(fluid-set! (symbol-fluid symbol) value)
|
(dynamic-set! (symbol-desc symbol) value)
|
||||||
value)
|
value)
|
||||||
|
|
||||||
(define (symbol-function symbol)
|
(define (symbol-function symbol)
|
||||||
(let ((module (resolve-module function-slot-module)))
|
(set! symbol (schemify symbol))
|
||||||
|
(ensure-present! function-slot-module symbol (lambda () #nil))
|
||||||
|
(let ((module function-slot-module))
|
||||||
(module-ref module symbol)))
|
(module-ref module symbol)))
|
||||||
|
|
||||||
(define (set-symbol-function! symbol value)
|
(define (set-symbol-function! symbol value)
|
||||||
(let ((module (resolve-module function-slot-module)))
|
(set! symbol (schemify symbol))
|
||||||
|
(ensure-present! function-slot-module symbol (lambda () #nil))
|
||||||
|
(let ((module function-slot-module))
|
||||||
|
(module-define! module symbol value)
|
||||||
|
(module-export! module (list symbol)))
|
||||||
|
value)
|
||||||
|
|
||||||
|
(define (symbol-plist symbol)
|
||||||
|
(set! symbol (schemify symbol))
|
||||||
|
(ensure-present! plist-slot-module symbol (lambda () #nil))
|
||||||
|
(let ((module plist-slot-module))
|
||||||
|
(module-ref module symbol)))
|
||||||
|
|
||||||
|
(define (set-symbol-plist! symbol value)
|
||||||
|
(set! symbol (schemify symbol))
|
||||||
|
(ensure-present! plist-slot-module symbol (lambda () #nil))
|
||||||
|
(let ((module plist-slot-module))
|
||||||
(module-define! module symbol value)
|
(module-define! module symbol value)
|
||||||
(module-export! module (list symbol)))
|
(module-export! module (list symbol)))
|
||||||
value)
|
value)
|
||||||
|
|
||||||
(define (symbol-bound? symbol)
|
(define (symbol-bound? symbol)
|
||||||
|
(set! symbol (schemify symbol))
|
||||||
(and
|
(and
|
||||||
(module-bound? (resolve-interface value-slot-module) symbol)
|
(module-bound? value-slot-module symbol)
|
||||||
(let ((var (module-variable (resolve-module value-slot-module)
|
(let ((var (module-variable value-slot-module
|
||||||
symbol)))
|
symbol)))
|
||||||
(and (variable-bound? var)
|
(and (variable-bound? var)
|
||||||
(if (fluid? (variable-ref var))
|
(if (dynamic? (variable-ref var))
|
||||||
(fluid-bound? (variable-ref var))
|
(dynamic-bound? (variable-ref var))
|
||||||
#t)))))
|
#t)))))
|
||||||
|
|
||||||
(define (symbol-fbound? symbol)
|
(define (symbol-fbound? symbol)
|
||||||
|
(set! symbol (schemify symbol))
|
||||||
(and
|
(and
|
||||||
(module-bound? (resolve-interface function-slot-module) symbol)
|
(module-bound? function-slot-module symbol)
|
||||||
(variable-bound?
|
(variable-bound?
|
||||||
(module-variable (resolve-module function-slot-module)
|
(module-variable function-slot-module symbol))
|
||||||
symbol))))
|
(variable-ref (module-variable function-slot-module symbol))))
|
||||||
|
|
||||||
|
(define (bind-symbol symbol value thunk)
|
||||||
|
(dynamic-bind (symbol-desc symbol) value thunk))
|
||||||
|
|
||||||
(define (makunbound! symbol)
|
(define (makunbound! symbol)
|
||||||
(if (module-bound? (resolve-interface value-slot-module) symbol)
|
(if (module-bound? value-slot-module symbol)
|
||||||
(let ((var (module-variable (resolve-module value-slot-module)
|
(let ((var (module-variable value-slot-module
|
||||||
symbol)))
|
symbol)))
|
||||||
(if (and (variable-bound? var) (fluid? (variable-ref var)))
|
(if (and (variable-bound? var) (dynamic? (variable-ref var)))
|
||||||
(fluid-unset! (variable-ref var))
|
(dynamic-unset! (variable-ref var))
|
||||||
(variable-unset! var))))
|
(variable-unset! var))))
|
||||||
symbol)
|
symbol)
|
||||||
|
|
||||||
(define (fmakunbound! symbol)
|
(define (fmakunbound! symbol)
|
||||||
(if (module-bound? (resolve-interface function-slot-module) symbol)
|
(if (module-bound? function-slot-module symbol)
|
||||||
(variable-unset! (module-variable
|
(variable-unset! (module-variable function-slot-module symbol)))
|
||||||
(resolve-module function-slot-module)
|
|
||||||
symbol)))
|
|
||||||
symbol)
|
symbol)
|
||||||
|
|
||||||
|
(define (special? sym)
|
||||||
|
(eqv? (vector-ref (symbol-desc sym) 3) 1))
|
||||||
|
|
||||||
|
(define (proclaim-special! sym)
|
||||||
|
(vector-set! (symbol-desc sym) 3 1)
|
||||||
|
#nil)
|
||||||
|
|
||||||
|
(define (emacs! ref set boundp bind)
|
||||||
|
(set! symbol-value ref)
|
||||||
|
(set! set-symbol-value! set)
|
||||||
|
(set! symbol-bound? boundp)
|
||||||
|
(set! bind-symbol bind)
|
||||||
|
(set! lexical-binding? (lambda () (symbol-value 'lexical-binding)))
|
||||||
|
(set! set-lexical-binding-mode (lambda (x) (set-symbol-value! 'lexical-binding x))))
|
||||||
|
|
||||||
|
(define (eval-elisp form)
|
||||||
|
(compile form #:from 'elisp #:to 'value))
|
||||||
|
|
||||||
|
(set-symbol-value! nil_ #nil)
|
||||||
|
(set-symbol-value! t_ #t)
|
||||||
|
|
||||||
|
(define (make-string s) s)
|
||||||
|
|
||||||
;;; Define a predefined macro for use in the function-slot module.
|
;;; Define a predefined macro for use in the function-slot module.
|
||||||
|
|
||||||
(define (make-id template-id . data)
|
(define (make-id template-id . data)
|
||||||
|
|
|
@ -24,14 +24,25 @@
|
||||||
#:use-module (system base language)
|
#:use-module (system base language)
|
||||||
#:use-module (system base compile)
|
#:use-module (system base compile)
|
||||||
#:use-module (system base target)
|
#:use-module (system base target)
|
||||||
|
#:use-module (system vm vm)
|
||||||
#:export (elisp))
|
#:export (elisp))
|
||||||
|
|
||||||
|
(save-module-excursion
|
||||||
|
(lambda ()
|
||||||
|
(define-module (elisp-symbols) #:pure #:filename #f)
|
||||||
|
(define-module (elisp-functions) #:pure #:filename #f)
|
||||||
|
(define-module (elisp-plists) #:pure #:filename #f)))
|
||||||
|
|
||||||
(define-language elisp
|
(define-language elisp
|
||||||
#:title "Emacs Lisp"
|
#:title "Emacs Lisp"
|
||||||
#:reader (lambda (port env) (read-elisp port))
|
#:reader (lambda (port env) (read-elisp port))
|
||||||
|
;;#:joiner (lambda (exps env) (cons 'progn exps))
|
||||||
#:printer write
|
#:printer write
|
||||||
#:compilers `((tree-il . ,compile-tree-il)))
|
#:compilers `((tree-il . ,compile-tree-il)))
|
||||||
|
|
||||||
|
(set-default-vm-engine! 'debug)
|
||||||
|
(set-vm-engine! 'debug)
|
||||||
|
|
||||||
;; Compile and load the Elisp boot code for the native host
|
;; Compile and load the Elisp boot code for the native host
|
||||||
;; architecture. We must specifically ask for native compilation here,
|
;; architecture. We must specifically ask for native compilation here,
|
||||||
;; because this module might be loaded in a dynamic environment where
|
;; because this module might be loaded in a dynamic environment where
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue