Compare commits
4 Commits
9e48519322
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
f1d3a71c32
|
|||
|
6f927bf768
|
|||
|
b8c685fa17
|
|||
|
6e58ad5e3e
|
@ -15,8 +15,8 @@ FetchContent_Declare(
|
|||||||
|
|
||||||
FetchContent_MakeAvailable(refcount)
|
FetchContent_MakeAvailable(refcount)
|
||||||
|
|
||||||
add_compile_options(-fsanitize=address,leak,undefined)
|
# add_compile_options(-fsanitize=address,leak,undefined)
|
||||||
add_link_options(-fsanitize=address,leak,undefined)
|
# add_link_options(-fsanitize=address,leak,undefined)
|
||||||
|
|
||||||
add_executable(simple-lisp src/main.c src/lisp.c src/read.c)
|
add_executable(simple-lisp src/main.c src/lisp.c src/read.c)
|
||||||
target_link_libraries(simple-lisp PUBLIC refcount)
|
target_link_libraries(simple-lisp PUBLIC refcount)
|
||||||
|
|||||||
324
src/kernel.sl
324
src/kernel.sl
@ -3,24 +3,38 @@
|
|||||||
(fset 'null 'not)
|
(fset 'null 'not)
|
||||||
(fset 'list (lambda (&rest r) (declare (name list)) r))
|
(fset 'list (lambda (&rest r) (declare (name list)) r))
|
||||||
|
|
||||||
|
;; these versions do not support (declare) forms
|
||||||
(fset 'defmacro
|
(fset 'defmacro
|
||||||
(lambda (name args &rest body)
|
(lambda (name args &rest body)
|
||||||
(declare (name defmacro) macro)
|
(declare (name defmacro) macro)
|
||||||
(list 'progn
|
|
||||||
(list 'fset (list '\' name)
|
(list 'fset (list '\' name)
|
||||||
(apply 'list 'lambda args
|
(apply 'list 'lambda args
|
||||||
|
(if (and (stringp (head body)) (not (null (tail body))))
|
||||||
|
(progn
|
||||||
|
(apply 'list
|
||||||
|
(head body)
|
||||||
|
(list 'declare (list 'name name)
|
||||||
|
'macro)
|
||||||
|
body))
|
||||||
|
(apply 'list
|
||||||
(list 'declare (list 'name name) 'macro)
|
(list 'declare (list 'name name) 'macro)
|
||||||
body)))))
|
body))))))
|
||||||
|
|
||||||
(defmacro defun (name args &rest body)
|
(defmacro defun (name args &rest body)
|
||||||
(list 'progn
|
|
||||||
(list 'fset (list '\' name)
|
(list 'fset (list '\' name)
|
||||||
(apply 'list 'lambda args
|
(apply 'list 'lambda args
|
||||||
|
(if (and (stringp (head body)) (not (null (tail body))))
|
||||||
|
(progn
|
||||||
|
(apply 'list
|
||||||
|
(head body)
|
||||||
(list 'declare (list 'name name))
|
(list 'declare (list 'name name))
|
||||||
body))))
|
(tail body)))
|
||||||
|
(progn
|
||||||
|
(list 'declare (list 'name name))
|
||||||
|
body)))))
|
||||||
|
|
||||||
(defun ensure-list (arg)
|
(defun ensure-list (arg)
|
||||||
(if (pairp arg)
|
(if (or (null arg) (pairp arg))
|
||||||
arg
|
arg
|
||||||
(list arg)))
|
(list arg)))
|
||||||
|
|
||||||
@ -62,7 +76,7 @@
|
|||||||
(list 'head tail-var))
|
(list 'head tail-var))
|
||||||
(list 'setq tail-var (list 'tail tail-var))))
|
(list 'setq tail-var (list 'tail tail-var))))
|
||||||
(second vars)))
|
(second vars)))
|
||||||
(make-symbol "tail")))
|
'::tail))
|
||||||
|
|
||||||
(defun maphead (func list)
|
(defun maphead (func list)
|
||||||
(funcall
|
(funcall
|
||||||
@ -106,14 +120,13 @@
|
|||||||
(throw 'argument-error))))
|
(throw 'argument-error))))
|
||||||
(apply 'list 'funcall (apply 'list 'lambda
|
(apply 'list 'funcall (apply 'list 'lambda
|
||||||
(reverse vars)
|
(reverse vars)
|
||||||
(list 'declare (list 'name
|
(list 'declare (list 'name '::let))
|
||||||
(make-symbol "let")))
|
|
||||||
body)
|
body)
|
||||||
(reverse vals)))))
|
(reverse vals)))))
|
||||||
|
|
||||||
(defmacro let* (bindings &rest body)
|
(defmacro let* (bindings &rest body)
|
||||||
(list 'funcall (apply 'list 'lambda (apply 'list '&opt bindings)
|
(list 'funcall (apply 'list 'lambda (apply 'list '&opt bindings)
|
||||||
(list 'declare (list 'name (make-symbol "let*")))
|
(list 'declare (list 'name '::let*))
|
||||||
body)))
|
body)))
|
||||||
|
|
||||||
(defun lasttail (list)
|
(defun lasttail (list)
|
||||||
@ -124,12 +137,72 @@
|
|||||||
list (tail list)))
|
list (tail list)))
|
||||||
out))
|
out))
|
||||||
|
|
||||||
|
(defun mapconcat (func list)
|
||||||
|
(let (start end)
|
||||||
|
(dolist (elt list)
|
||||||
|
(if (not start)
|
||||||
|
(setq start (copy-list (funcall func elt))
|
||||||
|
end (lasttail start))
|
||||||
|
(settail end (copy-list (funcall func elt)))
|
||||||
|
(setq end (lasttail end))))
|
||||||
|
start))
|
||||||
|
|
||||||
|
(defun identity (e) e)
|
||||||
|
|
||||||
|
(defun complement (fn)
|
||||||
|
(lambda (&rest args) (not (apply fn args))))
|
||||||
|
|
||||||
|
(defun append (&rest lists)
|
||||||
|
;; another implementation
|
||||||
|
;; (mapconcat 'identity lists)
|
||||||
|
(let* ((start (copy-list (head lists)))
|
||||||
|
(end (lasttail start)))
|
||||||
|
(dolist (list (tail lists))
|
||||||
|
(settail end (copy-list list))
|
||||||
|
(setq end (lasttail end)))
|
||||||
|
start))
|
||||||
|
|
||||||
|
(defmacro prog1 (first-form &rest body)
|
||||||
|
(let ((rval '::rval))
|
||||||
|
(list 'let (list (list rval first-form))
|
||||||
|
(apply 'list 'progn body)
|
||||||
|
rval)))
|
||||||
|
|
||||||
|
;; these versions support (declare) forms
|
||||||
|
(defmacro defmacro (name args &rest body)
|
||||||
|
(list 'fset (list '\' name)
|
||||||
|
(append (list 'lambda args)
|
||||||
|
(when (and (stringp (head body)) (not (null (tail body))))
|
||||||
|
(prog1 (list (head body))
|
||||||
|
(setq body (tail body))))
|
||||||
|
(list
|
||||||
|
(apply 'list 'declare (list 'name name) 'macro
|
||||||
|
(when (and (pairp (head body))
|
||||||
|
(eq (head (head body)) 'declare))
|
||||||
|
(prog1 (tail (head body))
|
||||||
|
(setq body (tail body))))))
|
||||||
|
body)))
|
||||||
|
|
||||||
|
(defmacro defun (name args &rest body)
|
||||||
|
(list 'fset (list '\' name)
|
||||||
|
(append (list 'lambda args)
|
||||||
|
(when (and (stringp (head body)) (not (null (tail body))))
|
||||||
|
(prog1 (list (head body))
|
||||||
|
(setq body (tail body))))
|
||||||
|
(list
|
||||||
|
(apply 'list 'declare (list 'name name)
|
||||||
|
(when (and (pairp (head body))
|
||||||
|
(eq (head (head body)) 'declare))
|
||||||
|
(prog1 (tail (head body))
|
||||||
|
(setq body (tail body))))))
|
||||||
|
body)))
|
||||||
|
|
||||||
(defun internal-expand-single-cond (cond)
|
(defun internal-expand-single-cond (cond)
|
||||||
(if (tail cond)
|
(if (tail cond)
|
||||||
(let ((res (list 'if (head cond)
|
(let ((res (list 'if (head cond)
|
||||||
(apply 'list 'progn (tail cond)))))
|
(apply 'list 'progn (tail cond)))))
|
||||||
(pair res res))
|
(pair res res))
|
||||||
(let* ((res-var (make-symbol "res"))
|
(let* ((res-var '::res)
|
||||||
(if-stmt (list 'if res-var res-var)))
|
(if-stmt (list 'if res-var res-var)))
|
||||||
(pair (list 'let (list (list res-var (head cond)))
|
(pair (list 'let (list (list res-var (head cond)))
|
||||||
if-stmt)
|
if-stmt)
|
||||||
@ -158,7 +231,7 @@
|
|||||||
(defmacro define-type-predicate (name args &rest body)
|
(defmacro define-type-predicate (name args &rest body)
|
||||||
(cond
|
(cond
|
||||||
((eq args 'alias)
|
((eq args 'alias)
|
||||||
(let ((var (make-symbol "var")))
|
(let ((var '::var))
|
||||||
(list 'put (list '\' name) ''type-predicate
|
(list 'put (list '\' name) ''type-predicate
|
||||||
(list 'lambda (list var) (list 'typep var (pair '\' body))))))
|
(list 'lambda (list var) (list 'typep var (pair '\' body))))))
|
||||||
((and (symbolp args) (null body))
|
((and (symbolp args) (null body))
|
||||||
@ -179,10 +252,6 @@
|
|||||||
(throw 'type-error))
|
(throw 'type-error))
|
||||||
(apply pred obj args)))
|
(apply pred obj args)))
|
||||||
|
|
||||||
(defun callablep (obj)
|
|
||||||
(or (functionp obj)
|
|
||||||
(and (pairp obj) (eq (head obj) 'lambda))))
|
|
||||||
|
|
||||||
(define-type-predicate any (obj) t)
|
(define-type-predicate any (obj) t)
|
||||||
(define-type-predicate t alias any)
|
(define-type-predicate t alias any)
|
||||||
(define-type-predicate or (obj &rest preds)
|
(define-type-predicate or (obj &rest preds)
|
||||||
@ -220,10 +289,19 @@
|
|||||||
(define-type-predicate callable callablep)
|
(define-type-predicate callable callablep)
|
||||||
(define-type-predicate hash-table hash-table-p)
|
(define-type-predicate hash-table hash-table-p)
|
||||||
(define-type-predicate user-pointer user-pointer-p)
|
(define-type-predicate user-pointer user-pointer-p)
|
||||||
|
(define-type-predicate record recordp)
|
||||||
|
(define-type-predicate native-record (obj &opt backing-type)
|
||||||
|
(and (recordp obj)
|
||||||
|
(record-native-p obj)
|
||||||
|
(or (not backing-type)
|
||||||
|
(typep (record-native-backing obj) backing-type))))
|
||||||
(define-type-predicate number (obj &opt min max)
|
(define-type-predicate number (obj &opt min max)
|
||||||
(typep obj (list 'or (list 'float min max)
|
(typep obj (list 'or (list 'float min max)
|
||||||
(list 'integer min max))))
|
(list 'integer min max))))
|
||||||
(define-type-predicate readable alias (or number vector pair symbol string))
|
(define-type-predicate callable-record alias (and record callable))
|
||||||
|
|
||||||
|
(defun callable-record-p (obj)
|
||||||
|
(typep obj 'callable-record))
|
||||||
|
|
||||||
(defun readablep (obj)
|
(defun readablep (obj)
|
||||||
(typep obj 'readable))
|
(typep obj 'readable))
|
||||||
@ -233,7 +311,7 @@
|
|||||||
(get symbol 'type-predicate))
|
(get symbol 'type-predicate))
|
||||||
|
|
||||||
(defmacro tcase (obj &rest conds)
|
(defmacro tcase (obj &rest conds)
|
||||||
(let ((obj-var (make-symbol "obj")))
|
(let ((obj-var '::obj))
|
||||||
(list 'let (list (list obj-var obj))
|
(list 'let (list (list obj-var obj))
|
||||||
(pair
|
(pair
|
||||||
'cond
|
'cond
|
||||||
@ -253,7 +331,7 @@
|
|||||||
(list 'return-from nil value))
|
(list 'return-from nil value))
|
||||||
|
|
||||||
(defmacro dotails (vars &rest body)
|
(defmacro dotails (vars &rest body)
|
||||||
(let ((cur (make-symbol "cur")))
|
(let ((cur '::cur))
|
||||||
(list 'let (list (list cur (second vars)))
|
(list 'let (list (list cur (second vars)))
|
||||||
(list 'while (list 'pairp cur)
|
(list 'while (list 'pairp cur)
|
||||||
(apply 'list 'let (list (list (first vars) cur))
|
(apply 'list 'let (list (list (first vars) cur))
|
||||||
@ -284,28 +362,6 @@
|
|||||||
(return-from find-if cur)))
|
(return-from find-if cur)))
|
||||||
default)
|
default)
|
||||||
|
|
||||||
(defun mapconcat (func list)
|
|
||||||
(let (start end)
|
|
||||||
(dolist (elt list)
|
|
||||||
(if (not start)
|
|
||||||
(setq start (copy-list (funcall func elt))
|
|
||||||
end (lasttail start))
|
|
||||||
(settail end (copy-list (funcall func elt)))
|
|
||||||
(setq end (lasttail end))))
|
|
||||||
start))
|
|
||||||
|
|
||||||
(defun identity (e) e)
|
|
||||||
|
|
||||||
(defun append (&rest lists)
|
|
||||||
;; another implementation
|
|
||||||
;; (mapconcat 'identity lists)
|
|
||||||
(let* ((start (copy-list (head lists)))
|
|
||||||
(end (lasttail start)))
|
|
||||||
(dolist (list (tail lists))
|
|
||||||
(settail end (copy-list list))
|
|
||||||
(setq end (lasttail end)))
|
|
||||||
start))
|
|
||||||
|
|
||||||
(defmacro macrolet (macros &rest body)
|
(defmacro macrolet (macros &rest body)
|
||||||
(let* ((found-macros (make-hash-table))
|
(let* ((found-macros (make-hash-table))
|
||||||
(macro-fns (mapconcat (lambda (entry)
|
(macro-fns (mapconcat (lambda (entry)
|
||||||
@ -371,6 +427,7 @@
|
|||||||
(list (list-length seq))
|
(list (list-length seq))
|
||||||
((or vector string) (vector-length seq))
|
((or vector string) (vector-length seq))
|
||||||
(hash-table (hash-table-count seq))
|
(hash-table (hash-table-count seq))
|
||||||
|
(record (record-length seq))
|
||||||
(t (throw 'type-error))))
|
(t (throw 'type-error))))
|
||||||
|
|
||||||
(fset 'copy-vector 'subvector)
|
(fset 'copy-vector 'subvector)
|
||||||
@ -378,6 +435,12 @@
|
|||||||
(defun zerop (n)
|
(defun zerop (n)
|
||||||
(= n 0))
|
(= n 0))
|
||||||
|
|
||||||
|
(defun plusp (n)
|
||||||
|
(> n 0))
|
||||||
|
|
||||||
|
(defun minusp (n)
|
||||||
|
(< n 0))
|
||||||
|
|
||||||
(defun nth (n list)
|
(defun nth (n list)
|
||||||
(unless (integerp n)
|
(unless (integerp n)
|
||||||
(throw 'type-error '(integerp) n))
|
(throw 'type-error '(integerp) n))
|
||||||
@ -435,12 +498,175 @@
|
|||||||
(defun char-code (str)
|
(defun char-code (str)
|
||||||
(aref str 0))
|
(aref str 0))
|
||||||
|
|
||||||
(defun print-readably (obj &opt (newline t) stream)
|
(defmacro defvar (name value &opt doc)
|
||||||
(unless (readablep obj)
|
(unless (symbolp name)
|
||||||
(throw 'type-error '(readablep) obj))
|
(throw 'type-error '(symbolp) name))
|
||||||
(tcase obj
|
(unless (or (not doc) (stringp doc))
|
||||||
(symbol (print (quote-symbol-for-read obj :as-needed)))
|
(throw 'type-error '(null stringp) doc))
|
||||||
(string (print (quote-string obj)))
|
(apply 'list 'progn
|
||||||
(t (print obj)))
|
(list 'make-symbol-special (list '\' name))
|
||||||
(when newline
|
(list 'setq name value)
|
||||||
(println)))
|
(when doc
|
||||||
|
(list (list 'set-symbol-value-docstr
|
||||||
|
(list '\' name) doc)))))
|
||||||
|
|
||||||
|
;; Object stuff
|
||||||
|
(defun symbol-class (symbol)
|
||||||
|
(unless (symbolp symbol)
|
||||||
|
(throw 'type-error '(symbolp) symbol))
|
||||||
|
(get symbol 'class))
|
||||||
|
|
||||||
|
(defun set-symbol-class (symbol class)
|
||||||
|
(unless (symbolp symbol)
|
||||||
|
(throw 'type-error '(symbolp) symbol))
|
||||||
|
(put symbol 'class class))
|
||||||
|
|
||||||
|
(defun classp (obj)
|
||||||
|
(or (eq (type-of obj) 'class)))
|
||||||
|
(define-type-predicate class classp)
|
||||||
|
|
||||||
|
(defun %default-slot-value (class obj slot)
|
||||||
|
(let* ((slots (record-slot class 3))
|
||||||
|
(unbound ::unbound)
|
||||||
|
(res (gethash slots slot unbound)))
|
||||||
|
(when (eq res unbound)
|
||||||
|
(throw 'slot-error slot))
|
||||||
|
(record-slot obj res)))
|
||||||
|
|
||||||
|
(defun %default-set-slot-value (class obj slot value)
|
||||||
|
(let* ((slots (record-slot class 3))
|
||||||
|
(unbound ::unbound)
|
||||||
|
(res (gethash slots slot unbound)))
|
||||||
|
(when (eq res unbound)
|
||||||
|
(throw 'slot-error slot))
|
||||||
|
(set-record-slot obj res value)))
|
||||||
|
|
||||||
|
(defun %default-lookup-method (class method)
|
||||||
|
(let* ((methods (record-slot class 4))
|
||||||
|
(unbound ::unbound)
|
||||||
|
(res (gethash methods method unbound)))
|
||||||
|
(unless (eq res unbound)
|
||||||
|
res)))
|
||||||
|
|
||||||
|
(defun %default-define-method (class method function)
|
||||||
|
(let* ((methods (record-slot class 4)))
|
||||||
|
(puthash methods method function)))
|
||||||
|
|
||||||
|
(defun %construct-class (class name superclass &rest slots)
|
||||||
|
nil)
|
||||||
|
|
||||||
|
;; Objects are records that have a class object as their first slot
|
||||||
|
;; Classes are records with their type set to 'class. The slots are
|
||||||
|
;; - class (class)
|
||||||
|
;; - name (symbol)
|
||||||
|
;; - superclass (class)
|
||||||
|
;; - slots (hash-table[symbol->integer])
|
||||||
|
;; - methods (hash-table[symbol->function])
|
||||||
|
;;
|
||||||
|
;; Special methods:
|
||||||
|
;; - (@construct obj &rest args)
|
||||||
|
;; Called when a new instance of this class is created. The newly allocated
|
||||||
|
;; object is passed to OBJ and the arguments to 'make-instance are passed to
|
||||||
|
;; ARGS.
|
||||||
|
;; - (@print obj stream)
|
||||||
|
;; Called to write OBJ out to STREAM.
|
||||||
|
(set-symbol-class 'class (make-record 'class 3))
|
||||||
|
(let ((class (symbol-class 'standard-class))
|
||||||
|
(slots (make-hash-table))
|
||||||
|
(methods (make-hash-table)))
|
||||||
|
(set-record-slot class 0 class)
|
||||||
|
(set-record-slot class 1 'class)
|
||||||
|
(set-record-slot class 2 class)
|
||||||
|
(set-record-slot class 3 slots)
|
||||||
|
(set-record-slot class 4 methods)
|
||||||
|
|
||||||
|
(puthash slots 'name 1)
|
||||||
|
(puthash slots 'superclass 2)
|
||||||
|
(puthash slots 'slots 3)
|
||||||
|
(puthash slots 'methods 4)
|
||||||
|
|
||||||
|
(puthash methods '@construct '%construct-class)
|
||||||
|
(puthash methods '@slot-value '%default-slot-value)
|
||||||
|
(puthash methods '@set-slot-value '%default-set-slot-value)
|
||||||
|
(puthash methods '@lookup-method '%default-lookup-method)
|
||||||
|
(puthash methods '@define-method '%default-define-method))
|
||||||
|
|
||||||
|
(defun objectp (obj)
|
||||||
|
"Return non-nil if OBJ is an object."
|
||||||
|
(and (recordp obj)
|
||||||
|
(plusp (length obj))
|
||||||
|
(classp (record-slot obj 0))))
|
||||||
|
(define-type-predicate object objectp)
|
||||||
|
|
||||||
|
(defun object-class (obj)
|
||||||
|
"Return the class of OBJ."
|
||||||
|
(unless (objectp obj)
|
||||||
|
(throw 'type-error '(objectp) obj))
|
||||||
|
(record-slot obj 0))
|
||||||
|
|
||||||
|
(defun methodp (obj)
|
||||||
|
"Return non-nil if OBJ is a method object."
|
||||||
|
(if (symbolp obj)
|
||||||
|
(methodp (symbol-function obj t))
|
||||||
|
(and (eq (type-of obj) 'method)
|
||||||
|
(= (length obj) 1)
|
||||||
|
(callable-record-p obj))))
|
||||||
|
(define-type-predicate method methodp)
|
||||||
|
|
||||||
|
;; Methods are callable records of length 1. The first slot is a hash table
|
||||||
|
;; mapping extra types to functions.
|
||||||
|
(defun make-method ()
|
||||||
|
"Return a new empty method object."
|
||||||
|
(let ((record (make-record 'method 1))
|
||||||
|
(extra-types (make-hash-table)))
|
||||||
|
(flet ((call-default (obj &rest args)
|
||||||
|
(let* ((unbound ::unbound)
|
||||||
|
(res (gethash extra-types t unbound)))
|
||||||
|
(when (eq res unbound)
|
||||||
|
(throw 'no-applicable-method-error obj))
|
||||||
|
(apply res obj args))))
|
||||||
|
(set-record-function
|
||||||
|
record
|
||||||
|
(lambda (obj &rest args)
|
||||||
|
(if (objectp obj)
|
||||||
|
(let ((method ()))))
|
||||||
|
(cond
|
||||||
|
((and (objectp obj)))))))
|
||||||
|
(set-record-slot record 0 extra-types)
|
||||||
|
record))
|
||||||
|
|
||||||
|
(defun %class-max-slot-index (class)
|
||||||
|
"Return the highest slot index of CLASS."
|
||||||
|
(let ((max 0))
|
||||||
|
(foreach (lambda (key val)
|
||||||
|
(when (> val max)
|
||||||
|
(setq max val)))
|
||||||
|
(record-slot class 2))
|
||||||
|
max))
|
||||||
|
|
||||||
|
(defun make-instance (class &rest args)
|
||||||
|
(tcase class
|
||||||
|
(symbol (setq class (symbol-class class)))
|
||||||
|
((not class) (throw 'type-error '(classp) class)))
|
||||||
|
(let ((constructor (gethash (record-slot class 3) '@construct))
|
||||||
|
(object (make-record (record-slot class
|
||||||
|
(%class-max-slot-index class)))))
|
||||||
|
(when (functionp constructor)
|
||||||
|
(apply constructor object args))
|
||||||
|
object))
|
||||||
|
|
||||||
|
(defmacro defclass (name &rest rest)
|
||||||
|
(unless (symbolp name)
|
||||||
|
(throw 'type-error '(symbolp) name))
|
||||||
|
(let (doc)
|
||||||
|
(when (stringp (head rest))
|
||||||
|
(setq doc (head rest)
|
||||||
|
rest (head rest)))
|
||||||
|
()))
|
||||||
|
|
||||||
|
(println (make-instance ()))
|
||||||
|
|
||||||
|
(println (symbol-class 'standard-class))
|
||||||
|
(doindex (i (symbol-class 'standard-class))
|
||||||
|
(print "- ")
|
||||||
|
(println (record-slot (symbol-class 'standard-class) i)))
|
||||||
|
|||||||
1305
src/lisp.c
1305
src/lisp.c
File diff suppressed because it is too large
Load Diff
146
src/lisp.h
146
src/lisp.h
@ -2,6 +2,7 @@
|
|||||||
#define INCLUDED_LISP_H
|
#define INCLUDED_LISP_H
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <refcount/refcount.h>
|
#include <refcount/refcount.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -33,15 +34,10 @@ typedef enum {
|
|||||||
TYPE_HASHTABLE,
|
TYPE_HASHTABLE,
|
||||||
TYPE_USER_POINTER,
|
TYPE_USER_POINTER,
|
||||||
TYPE_PACKAGE,
|
TYPE_PACKAGE,
|
||||||
|
TYPE_RECORD,
|
||||||
N_LISP_TYPES,
|
N_LISP_TYPES,
|
||||||
} LispType;
|
} LispType;
|
||||||
|
|
||||||
struct _TypeNameEntry {
|
|
||||||
const char *name;
|
|
||||||
size_t len;
|
|
||||||
};
|
|
||||||
extern struct _TypeNameEntry LISP_TYPE_NAMES[N_LISP_TYPES];
|
|
||||||
|
|
||||||
#define LISP_OBJECT_HEADER \
|
#define LISP_OBJECT_HEADER \
|
||||||
LispType type; \
|
LispType type; \
|
||||||
RefcountEntry refcount
|
RefcountEntry refcount
|
||||||
@ -51,6 +47,8 @@ typedef struct {
|
|||||||
} LispVal;
|
} LispVal;
|
||||||
#define LISPVAL(obj) ((LispVal *) (obj))
|
#define LISPVAL(obj) ((LispVal *) (obj))
|
||||||
|
|
||||||
|
extern LispVal *LISP_TYPE_SYMS[N_LISP_TYPES];
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
LISP_OBJECT_HEADER;
|
LISP_OBJECT_HEADER;
|
||||||
|
|
||||||
@ -67,7 +65,10 @@ typedef struct {
|
|||||||
LispVal *plist;
|
LispVal *plist;
|
||||||
LispVal *function;
|
LispVal *function;
|
||||||
LispVal *value;
|
LispVal *value;
|
||||||
bool is_constant;
|
LispVal *value_doc;
|
||||||
|
unsigned int is_const_value : 1;
|
||||||
|
unsigned int is_const_func : 1;
|
||||||
|
unsigned int is_special_var : 1;
|
||||||
} LispSymbol;
|
} LispSymbol;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -161,6 +162,15 @@ typedef struct {
|
|||||||
LispVal *imported; // list of (package . (str -> bool))
|
LispVal *imported; // list of (package . (str -> bool))
|
||||||
} LispPackage;
|
} LispPackage;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
LISP_OBJECT_HEADER;
|
||||||
|
|
||||||
|
LispVal *record_type;
|
||||||
|
LispVal *function;
|
||||||
|
size_t length;
|
||||||
|
LispVal **data;
|
||||||
|
} LispRecord;
|
||||||
|
|
||||||
// #######################
|
// #######################
|
||||||
// # nil, unbound, and t #
|
// # nil, unbound, and t #
|
||||||
// #######################
|
// #######################
|
||||||
@ -188,6 +198,16 @@ extern LispVal *Qrest;
|
|||||||
extern LispVal *Qdeclare;
|
extern LispVal *Qdeclare;
|
||||||
extern LispVal *Qname;
|
extern LispVal *Qname;
|
||||||
|
|
||||||
|
// Type symbols not defined elsewhere
|
||||||
|
extern LispVal *Qsymbol;
|
||||||
|
extern LispVal *Qinteger;
|
||||||
|
extern LispVal *Qfloat;
|
||||||
|
extern LispVal *Qfunction;
|
||||||
|
extern LispVal *Qhash_table;
|
||||||
|
extern LispVal *Quser_pointer;
|
||||||
|
extern LispVal *Qpackage;
|
||||||
|
extern LispVal *Qrecord;
|
||||||
|
|
||||||
// ############################
|
// ############################
|
||||||
// # Global Package Variables #
|
// # Global Package Variables #
|
||||||
// ############################
|
// ############################
|
||||||
@ -203,7 +223,9 @@ extern LispVal *current_package;
|
|||||||
#define TYPEOF(v) (LISPVAL(v)->type)
|
#define TYPEOF(v) (LISPVAL(v)->type)
|
||||||
|
|
||||||
// only use on symbols!
|
// only use on symbols!
|
||||||
#define VALUE_CONSTANTP(v) (((LispSymbol *) (v))->is_constant)
|
#define VALUE_CONSTANTP(v) (((LispSymbol *) (v))->is_const_value || KEYWORDP(v))
|
||||||
|
#define FUNC_CONSTANTP(v) (((LispSymbol *) (v))->is_const_func)
|
||||||
|
#define SPECIALP(v) (((LispSymbol *) (v))->is_special_var)
|
||||||
|
|
||||||
#define NILP(v) (((void *) (v)) == (void *) Qnil)
|
#define NILP(v) (((void *) (v)) == (void *) Qnil)
|
||||||
#define STRINGP(v) (TYPEOF(v) == TYPE_STRING)
|
#define STRINGP(v) (TYPEOF(v) == TYPE_STRING)
|
||||||
@ -216,6 +238,7 @@ extern LispVal *current_package;
|
|||||||
#define HASHTABLEP(v) (TYPEOF(v) == TYPE_HASHTABLE)
|
#define HASHTABLEP(v) (TYPEOF(v) == TYPE_HASHTABLE)
|
||||||
#define USER_POINTER_P(v) (TYPEOF(v) == TYPE_USER_POINTER)
|
#define USER_POINTER_P(v) (TYPEOF(v) == TYPE_USER_POINTER)
|
||||||
#define PACKAGEP(v) (TYPEOF(v) == TYPE_PACKAGE)
|
#define PACKAGEP(v) (TYPEOF(v) == TYPE_PACKAGE)
|
||||||
|
#define RECORDP(v) (TYPEOF(v) == TYPE_RECORD)
|
||||||
|
|
||||||
#define ATOM(v) (TYPEOF(v) != TYPE_PAIR)
|
#define ATOM(v) (TYPEOF(v) != TYPE_PAIR)
|
||||||
|
|
||||||
@ -250,7 +273,10 @@ inline static bool NUMBERP(LispVal *v) {
|
|||||||
.plist = Qnil, \
|
.plist = Qnil, \
|
||||||
.function = Qnil, \
|
.function = Qnil, \
|
||||||
.value = Qunbound, \
|
.value = Qunbound, \
|
||||||
.is_constant = false, \
|
.value_doc = Qnil, \
|
||||||
|
.is_const_value = false, \
|
||||||
|
.is_const_func = false, \
|
||||||
|
.is_special_var = false, \
|
||||||
}; \
|
}; \
|
||||||
LispVal *Q##c_name = LISPVAL(&_Q##c_name)
|
LispVal *Q##c_name = LISPVAL(&_Q##c_name)
|
||||||
#define DECLARE_FUNCTION(c_name, args) \
|
#define DECLARE_FUNCTION(c_name, args) \
|
||||||
@ -258,7 +284,9 @@ inline static bool NUMBERP(LispVal *v) {
|
|||||||
extern LispVal *Q##c_name
|
extern LispVal *Q##c_name
|
||||||
// The args and doc fields are filled when the function is registered
|
// The args and doc fields are filled when the function is registered
|
||||||
#define _INTERNAL_DEFUN_EXTENDED(macrop, du, c_name, lisp_name, c_args, \
|
#define _INTERNAL_DEFUN_EXTENDED(macrop, du, c_name, lisp_name, c_args, \
|
||||||
static_kw) \
|
static_kw, lisp_args, doc_cstr) \
|
||||||
|
static const char _F##c_name##lisp_args_cstr[] = lisp_args; \
|
||||||
|
static const char _F##c_name##doccstr[] = doc_cstr; \
|
||||||
static_kw LispVal *F##c_name c_args; \
|
static_kw LispVal *F##c_name c_args; \
|
||||||
DEF_STATIC_STRING(_Q##c_name##_fnnamestr, lisp_name); \
|
DEF_STATIC_STRING(_Q##c_name##_fnnamestr, lisp_name); \
|
||||||
static LispSymbol _Q##c_name; \
|
static LispSymbol _Q##c_name; \
|
||||||
@ -283,21 +311,29 @@ inline static bool NUMBERP(LispVal *v) {
|
|||||||
.package = Qnil, \
|
.package = Qnil, \
|
||||||
.plist = Qnil, \
|
.plist = Qnil, \
|
||||||
.value = Qunbound, \
|
.value = Qunbound, \
|
||||||
|
.value_doc = Qnil, \
|
||||||
.function = LISPVAL(&_Q##c_name##_function), \
|
.function = LISPVAL(&_Q##c_name##_function), \
|
||||||
.is_constant = false, \
|
.is_const_value = false, \
|
||||||
|
.is_const_func = true, \
|
||||||
|
.is_special_var = false, \
|
||||||
}; \
|
}; \
|
||||||
LispVal *Q##c_name = (LispVal *) &_Q##c_name; \
|
LispVal *Q##c_name = (LispVal *) &_Q##c_name; \
|
||||||
static_kw LispVal *F##c_name c_args
|
static_kw LispVal *F##c_name c_args
|
||||||
#define DEFUN(c_name, lisp_name, c_args) \
|
#define DEFUN(c_name, lisp_name, c_args, lisp_args, doc_cstr) \
|
||||||
_INTERNAL_DEFUN_EXTENDED(false, false, c_name, lisp_name, c_args, )
|
_INTERNAL_DEFUN_EXTENDED(false, false, c_name, lisp_name, c_args, , \
|
||||||
#define DEFUN_DISTINGUISHED(c_name, lisp_name, c_args) \
|
lisp_args, doc_cstr)
|
||||||
_INTERNAL_DEFUN_EXTENDED(false, true, c_name, lisp_name, c_args, )
|
#define DEFUN_DISTINGUISHED(c_name, lisp_name, c_args, lisp_args, doc_cstr) \
|
||||||
#define DEFMACRO(c_name, lisp_name, c_args) \
|
_INTERNAL_DEFUN_EXTENDED(false, true, c_name, lisp_name, c_args, , \
|
||||||
_INTERNAL_DEFUN_EXTENDED(true, false, c_name, lisp_name, c_args, )
|
lisp_args, doc_cstr)
|
||||||
#define STATIC_DEFUN(c_name, lisp_name, c_args) \
|
#define DEFMACRO(c_name, lisp_name, c_args, lisp_args, doc_cstr) \
|
||||||
_INTERNAL_DEFUN_EXTENDED(false, false, c_name, lisp_name, c_args, static)
|
_INTERNAL_DEFUN_EXTENDED(true, false, c_name, lisp_name, c_args, , \
|
||||||
#define STATIC_DEFMACRO(c_name, lisp_name, c_args) \
|
lisp_args, doc_cstr)
|
||||||
_INTERNAL_DEFUN_EXTENDED(true, false, c_name, lisp_name, c_args, static)
|
#define STATIC_DEFUN(c_name, lisp_name, c_args, lisp_args, doc_cstr) \
|
||||||
|
_INTERNAL_DEFUN_EXTENDED(false, false, c_name, lisp_name, c_args, static, \
|
||||||
|
lisp_args, doc_cstr)
|
||||||
|
#define STATIC_DEFMACRO(c_name, lisp_name, c_args, lisp_args, doc_cstr) \
|
||||||
|
_INTERNAL_DEFUN_EXTENDED(true, false, c_name, lisp_name, c_args, static, \
|
||||||
|
lisp_args, doc_cstr)
|
||||||
|
|
||||||
// registration
|
// registration
|
||||||
#define REGISTER_SYMBOL_NOINTERN(sym) \
|
#define REGISTER_SYMBOL_NOINTERN(sym) \
|
||||||
@ -312,21 +348,26 @@ inline static bool NUMBERP(LispVal *v) {
|
|||||||
#define REGISTER_SYMBOL_INTO(sym, pkg) \
|
#define REGISTER_SYMBOL_INTO(sym, pkg) \
|
||||||
REGISTER_SYMBOL_NOINTERN(sym) \
|
REGISTER_SYMBOL_NOINTERN(sym) \
|
||||||
REGISTER_DO_INTERN(sym, pkg)
|
REGISTER_DO_INTERN(sym, pkg)
|
||||||
|
#define REGISTER_KEYWORD(sym) \
|
||||||
|
REGISTER_SYMBOL_NOINTERN(sym) \
|
||||||
|
REGISTER_DO_INTERN(sym, keyword_package) \
|
||||||
|
((LispSymbol *) Q##sym)->is_const_value = true; \
|
||||||
|
((LispSymbol *) Q##sym)->is_special_var = true;
|
||||||
#define REGISTER_SYMBOL(sym) REGISTER_SYMBOL_INTO(sym, system_package)
|
#define REGISTER_SYMBOL(sym) REGISTER_SYMBOL_INTO(sym, system_package)
|
||||||
#define REGISTER_STATIC_FUNCTION(name, args, docstr) \
|
#define REGISTER_STATIC_FUNCTION(name) \
|
||||||
REGISTER_SYMBOL_NOINTERN(name); \
|
REGISTER_SYMBOL_NOINTERN(name); \
|
||||||
{ \
|
{ \
|
||||||
LispVal *obj = ((LispSymbol *) Q##name)->function; \
|
LispVal *obj = ((LispSymbol *) Q##name)->function; \
|
||||||
refcount_init_static(obj); \
|
refcount_init_static(obj); \
|
||||||
((LispFunction *) (obj))->doc = STATIC_STRING(docstr); \
|
((LispFunction *) (obj))->doc = STATIC_STRING(_F##name##doccstr); \
|
||||||
LispVal *src = STATIC_STRING(args); \
|
LispVal *src = STATIC_STRING(_F##name##lisp_args_cstr); \
|
||||||
LispVal *a = Fread(src, system_package); \
|
LispVal *a = Fread(src, system_package); \
|
||||||
set_function_args((LispFunction *) (obj), a); \
|
set_function_args((LispFunction *) (obj), a); \
|
||||||
refcount_unref(src); \
|
refcount_unref(src); \
|
||||||
refcount_unref(a); \
|
refcount_unref(a); \
|
||||||
}
|
}
|
||||||
#define REGISTER_FUNCTION(fn, args, docstr) \
|
#define REGISTER_FUNCTION(fn) \
|
||||||
REGISTER_STATIC_FUNCTION(fn, args, docstr); \
|
REGISTER_STATIC_FUNCTION(fn); \
|
||||||
((LispSymbol *) Q##fn)->package = refcount_ref(system_package); \
|
((LispSymbol *) Q##fn)->package = refcount_ref(system_package); \
|
||||||
puthash(((LispPackage *) system_package)->obarray, \
|
puthash(((LispPackage *) system_package)->obarray, \
|
||||||
LISPVAL(((LispSymbol *) Q##fn)->name), Q##fn);
|
LISPVAL(((LispSymbol *) Q##fn)->name), Q##fn);
|
||||||
@ -376,6 +417,7 @@ LispVal *make_user_pointer(void *data, void (*free_func)(void *));
|
|||||||
#define ALLOC_USERPTR(type, free_func) \
|
#define ALLOC_USERPTR(type, free_func) \
|
||||||
(make_user_pointer(lisp_malloc(sizeof(type)), &free_func))
|
(make_user_pointer(lisp_malloc(sizeof(type)), &free_func))
|
||||||
LispVal *make_lisp_package(LispVal *name);
|
LispVal *make_lisp_package(LispVal *name);
|
||||||
|
LispVal *make_lisp_record(LispVal *type, size_t length);
|
||||||
|
|
||||||
LispVal *predicate_for_type(LispType type);
|
LispVal *predicate_for_type(LispType type);
|
||||||
|
|
||||||
@ -396,12 +438,22 @@ DECLARE_FUNCTION(breakpoint, (LispVal * id));
|
|||||||
DECLARE_FUNCTION(not, (LispVal * obj));
|
DECLARE_FUNCTION(not, (LispVal * obj));
|
||||||
DECLARE_FUNCTION(type_of, (LispVal * val));
|
DECLARE_FUNCTION(type_of, (LispVal * val));
|
||||||
DECLARE_FUNCTION(user_pointer_p, (LispVal * val));
|
DECLARE_FUNCTION(user_pointer_p, (LispVal * val));
|
||||||
|
DECLARE_FUNCTION(callablep, (LispVal * val));
|
||||||
|
inline static bool CALLABLEP(LispVal *v) {
|
||||||
|
LispVal *res = Fcallablep(v);
|
||||||
|
bool rv = !NILP(res);
|
||||||
|
refcount_unref(res);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
inline static bool CALLABLE_RECORD_P(LispVal *v) {
|
||||||
|
return RECORDP(v) && CALLABLEP(v);
|
||||||
|
}
|
||||||
|
DECLARE_FUNCTION(native_type_p, (LispVal * sym));
|
||||||
|
|
||||||
// ##################################
|
// ##################################
|
||||||
// # Evaluation and Macro Expansion #
|
// # Evaluation and Macro Expansion #
|
||||||
// ##################################
|
// ##################################
|
||||||
DECLARE_FUNCTION(eval_in_env, (LispVal * form, LispVal *lexenv));
|
DECLARE_FUNCTION(eval, (LispVal * form, LispVal *lexenv));
|
||||||
DECLARE_FUNCTION(eval, (LispVal * form));
|
|
||||||
DECLARE_FUNCTION(funcall, (LispVal * function, LispVal *rest));
|
DECLARE_FUNCTION(funcall, (LispVal * function, LispVal *rest));
|
||||||
DECLARE_FUNCTION(apply, (LispVal * function, LispVal *rest));
|
DECLARE_FUNCTION(apply, (LispVal * function, LispVal *rest));
|
||||||
DECLARE_FUNCTION(macroexpand_1, (LispVal * form, LispVal *lexical_macros));
|
DECLARE_FUNCTION(macroexpand_1, (LispVal * form, LispVal *lexical_macros));
|
||||||
@ -490,14 +542,22 @@ LispVal *find_package(const char *name, size_t length);
|
|||||||
// ####################
|
// ####################
|
||||||
DECLARE_FUNCTION(symbolp, (LispVal * val));
|
DECLARE_FUNCTION(symbolp, (LispVal * val));
|
||||||
DECLARE_FUNCTION(keywordp, (LispVal * val));
|
DECLARE_FUNCTION(keywordp, (LispVal * val));
|
||||||
|
DECLARE_FUNCTION(const_value_p, (LispVal * val));
|
||||||
|
DECLARE_FUNCTION(const_func_p, (LispVal * val));
|
||||||
|
DECLARE_FUNCTION(specialp, (LispVal * val));
|
||||||
DECLARE_FUNCTION(make_symbol, (LispVal * name));
|
DECLARE_FUNCTION(make_symbol, (LispVal * name));
|
||||||
|
DECLARE_FUNCTION(make_symbol_special, (LispVal * sym));
|
||||||
DECLARE_FUNCTION(symbol_package, (LispVal * symbol));
|
DECLARE_FUNCTION(symbol_package, (LispVal * symbol));
|
||||||
DECLARE_FUNCTION(symbol_name, (LispVal * symbol));
|
DECLARE_FUNCTION(symbol_name, (LispVal * symbol));
|
||||||
DECLARE_FUNCTION(symbol_function, (LispVal * symbol, LispVal *resolve));
|
DECLARE_FUNCTION(symbol_function, (LispVal * symbol, LispVal *resolve));
|
||||||
DECLARE_FUNCTION(symbol_value, (LispVal * symbol));
|
DECLARE_FUNCTION(fset, (LispVal * sym, LispVal *new_func));
|
||||||
|
DECLARE_FUNCTION(symbol_value, (LispVal * symbol, LispVal *default_only));
|
||||||
|
DECLARE_FUNCTION(set,
|
||||||
|
(LispVal * symbol, LispVal *value, LispVal *default_only));
|
||||||
|
DECLARE_FUNCTION(symbol_value_docstr, (LispVal * symbol));
|
||||||
|
DECLARE_FUNCTION(set_symbol_value_docstr, (LispVal * symbol, LispVal *docstr));
|
||||||
DECLARE_FUNCTION(symbol_plist, (LispVal * symbol));
|
DECLARE_FUNCTION(symbol_plist, (LispVal * symbol));
|
||||||
DECLARE_FUNCTION(setplist, (LispVal * symbol, LispVal *plist));
|
DECLARE_FUNCTION(setplist, (LispVal * symbol, LispVal *plist));
|
||||||
DECLARE_FUNCTION(fset, (LispVal * sym, LispVal *new_func));
|
|
||||||
DECLARE_FUNCTION(exported_symbol_p, (LispVal * symbol));
|
DECLARE_FUNCTION(exported_symbol_p, (LispVal * symbol));
|
||||||
DECLARE_FUNCTION(intern_soft, (LispVal * name, LispVal *def, LispVal *package,
|
DECLARE_FUNCTION(intern_soft, (LispVal * name, LispVal *def, LispVal *package,
|
||||||
LispVal *included_too));
|
LispVal *included_too));
|
||||||
@ -507,7 +567,7 @@ DECLARE_FUNCTION(quote_symbol_name, (LispVal * name));
|
|||||||
DECLARE_FUNCTION(symbol_accessible_p, (LispVal * symbol, LispVal *package));
|
DECLARE_FUNCTION(symbol_accessible_p, (LispVal * symbol, LispVal *package));
|
||||||
extern LispVal *Qkw_as_needed;
|
extern LispVal *Qkw_as_needed;
|
||||||
DECLARE_FUNCTION(quote_symbol_for_read,
|
DECLARE_FUNCTION(quote_symbol_for_read,
|
||||||
(LispVal * target, LispVal *include_package));
|
(LispVal * target, LispVal *include_package, LispVal *from));
|
||||||
LispVal *intern(const char *name, size_t length, bool take, LispVal *package,
|
LispVal *intern(const char *name, size_t length, bool take, LispVal *package,
|
||||||
bool included_too);
|
bool included_too);
|
||||||
|
|
||||||
@ -521,7 +581,7 @@ DECLARE_FUNCTION(hash_table_count, (LispVal * table));
|
|||||||
DECLARE_FUNCTION(maphash, (LispVal * func, LispVal *table));
|
DECLARE_FUNCTION(maphash, (LispVal * func, LispVal *table));
|
||||||
DECLARE_FUNCTION(puthash, (LispVal * table, LispVal *key, LispVal *value));
|
DECLARE_FUNCTION(puthash, (LispVal * table, LispVal *key, LispVal *value));
|
||||||
DECLARE_FUNCTION(gethash, (LispVal * table, LispVal *key, LispVal *def));
|
DECLARE_FUNCTION(gethash, (LispVal * table, LispVal *key, LispVal *def));
|
||||||
DECLARE_FUNCTION(remhash, (LispVal * table, LispVal *key));
|
DECLARE_FUNCTION(remhash, (LispVal * table, LispVal *key, LispVal *def));
|
||||||
struct HashtableDataArray {
|
struct HashtableDataArray {
|
||||||
size_t size;
|
size_t size;
|
||||||
struct HashtableEntry *entries;
|
struct HashtableEntry *entries;
|
||||||
@ -531,7 +591,7 @@ void free_hash_table_data_array(void *data);
|
|||||||
// Don't ref their return value
|
// Don't ref their return value
|
||||||
LispVal *puthash(LispVal *table, LispVal *key, LispVal *value);
|
LispVal *puthash(LispVal *table, LispVal *key, LispVal *value);
|
||||||
LispVal *gethash(LispVal *table, LispVal *key, LispVal *def);
|
LispVal *gethash(LispVal *table, LispVal *key, LispVal *def);
|
||||||
LispVal *remhash(LispVal *table, LispVal *key);
|
void remhash(LispVal *table, LispVal *key);
|
||||||
|
|
||||||
// #####################
|
// #####################
|
||||||
// # Numeric Functions #
|
// # Numeric Functions #
|
||||||
@ -570,11 +630,23 @@ DECLARE_FUNCTION(concat, (LispVal * strings));
|
|||||||
LispVal *sprintf_lisp(const char *format, ...) PRINTF_FORMAT(1, 2);
|
LispVal *sprintf_lisp(const char *format, ...) PRINTF_FORMAT(1, 2);
|
||||||
bool strings_equal_nocase(const char *s1, const char *s2, size_t n);
|
bool strings_equal_nocase(const char *s1, const char *s2, size_t n);
|
||||||
|
|
||||||
|
// ####################
|
||||||
|
// # Record Functions #
|
||||||
|
// ####################
|
||||||
|
DECLARE_FUNCTION(recordp, (LispVal * val));
|
||||||
|
DECLARE_FUNCTION(make_record, (LispVal * type, LispVal *length));
|
||||||
|
DECLARE_FUNCTION(record_function, (LispVal * record));
|
||||||
|
DECLARE_FUNCTION(set_record_function, (LispVal * record, LispVal *value));
|
||||||
|
DECLARE_FUNCTION(record_length, (LispVal * record));
|
||||||
|
DECLARE_FUNCTION(record_slot, (LispVal * record, LispVal *index));
|
||||||
|
DECLARE_FUNCTION(set_record_slot,
|
||||||
|
(LispVal * record, LispVal *index, LispVal *value));
|
||||||
|
|
||||||
// ################
|
// ################
|
||||||
// # IO Functions #
|
// # IO Functions #
|
||||||
// ################
|
// ################
|
||||||
DECLARE_FUNCTION(print, (LispVal * obj, LispVal *stream));
|
DECLARE_FUNCTION(print, (LispVal * obj, LispVal *readably, LispVal *stream));
|
||||||
DECLARE_FUNCTION(println, (LispVal * obj, LispVal *stream));
|
DECLARE_FUNCTION(println, (LispVal * obj, LispVal *readably, LispVal *stream));
|
||||||
|
|
||||||
// ########################
|
// ########################
|
||||||
// # Lexenv and the Stack #
|
// # Lexenv and the Stack #
|
||||||
@ -599,6 +671,7 @@ typedef struct StackFrame {
|
|||||||
LispVal *return_tag;
|
LispVal *return_tag;
|
||||||
LispVal *detail; // function arguments
|
LispVal *detail; // function arguments
|
||||||
LispVal *lexenv; // symbol -> value
|
LispVal *lexenv; // symbol -> value
|
||||||
|
LispVal *dynenv; // symbol -> value (for dynamic variables)
|
||||||
bool enable_handlers;
|
bool enable_handlers;
|
||||||
LispVal *handlers; // symbol -> (error-var form)
|
LispVal *handlers; // symbol -> (error-var form)
|
||||||
LispVal *unwind_form;
|
LispVal *unwind_form;
|
||||||
@ -677,10 +750,13 @@ void cancel_cleanup(void *handle);
|
|||||||
// # Errors and Conditions #
|
// # Errors and Conditions #
|
||||||
// #########################
|
// #########################
|
||||||
extern LispVal *Qshutdown_signal;
|
extern LispVal *Qshutdown_signal;
|
||||||
|
extern LispVal *Qerror;
|
||||||
extern LispVal *Qtype_error;
|
extern LispVal *Qtype_error;
|
||||||
extern LispVal *Qread_error;
|
extern LispVal *Qread_error;
|
||||||
extern LispVal *Qeof_error;
|
extern LispVal *Qeof_error;
|
||||||
extern LispVal *Qunclosed_error;
|
extern LispVal *Qunclosed_error;
|
||||||
|
extern LispVal *Qconstant_function_error;
|
||||||
|
extern LispVal *Qconstant_value_error;
|
||||||
extern LispVal *Qvoid_variable_error;
|
extern LispVal *Qvoid_variable_error;
|
||||||
extern LispVal *Qvoid_function_error;
|
extern LispVal *Qvoid_function_error;
|
||||||
extern LispVal *Qcircular_error;
|
extern LispVal *Qcircular_error;
|
||||||
|
|||||||
21
src/main.c
21
src/main.c
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
static int exit_status = 0;
|
static int exit_status = 0;
|
||||||
|
|
||||||
STATIC_DEFUN(toplevel_exit_handler, "toplevel-exit-handler",
|
STATIC_DEFUN(toplevel_exit_handler, "toplevel-exit-handler", (LispVal * except),
|
||||||
(LispVal * except)) {
|
"(except)", "Internal function.") {
|
||||||
LispVal *detail = TAIL(HEAD(except));
|
LispVal *detail = TAIL(HEAD(except));
|
||||||
if (NILP(detail) || NILP(HEAD(detail))) {
|
if (NILP(detail) || NILP(HEAD(detail))) {
|
||||||
exit_status = 0;
|
exit_status = 0;
|
||||||
@ -17,20 +17,25 @@ STATIC_DEFUN(toplevel_exit_handler, "toplevel-exit-handler",
|
|||||||
}
|
}
|
||||||
|
|
||||||
STATIC_DEFUN(toplevel_error_handler, "toplevel-error-handler",
|
STATIC_DEFUN(toplevel_error_handler, "toplevel-error-handler",
|
||||||
(LispVal * except)) {
|
(LispVal * except), "(except)", "Internal function.") {
|
||||||
LispVal *type = HEAD(HEAD(except));
|
LispVal *type = HEAD(HEAD(except));
|
||||||
LispVal *detail = TAIL(HEAD(except));
|
LispVal *detail = TAIL(HEAD(except));
|
||||||
LispVal *backtrace = HEAD(TAIL(except));
|
LispVal *backtrace = HEAD(TAIL(except));
|
||||||
fprintf(stderr, "Caught signal of type ");
|
fprintf(stderr, "Caught signal of type ");
|
||||||
debug_dump(stderr, type, true);
|
debug_dump(stderr, type, true);
|
||||||
|
LispVal *stream = make_lisp_integer(fileno(stderr));
|
||||||
if (!NILP(detail)) {
|
if (!NILP(detail)) {
|
||||||
fprintf(stderr, "Details: ");
|
fprintf(stderr, "Details: ");
|
||||||
debug_dump(stderr, detail, true);
|
Fprintln(detail, Qt, stream);
|
||||||
}
|
}
|
||||||
fprintf(stderr, "\nBacktrace (toplevel comes last):\n");
|
fprintf(stderr, "\nBacktrace (toplevel comes last):\n");
|
||||||
FOREACH(frame, backtrace) {
|
FOREACH(frame, backtrace) {
|
||||||
fprintf(stderr, " ");
|
fprintf(stderr, " ");
|
||||||
debug_dump(stderr, frame, true);
|
Fprint(frame, Qt, stream);
|
||||||
|
if (SYMBOLP(HEAD(frame)) && !NILP(Fmacrop(HEAD(frame), Qnil))) {
|
||||||
|
fprintf(stderr, " ;; macro");
|
||||||
|
}
|
||||||
|
fputc('\n', stderr);
|
||||||
}
|
}
|
||||||
exit_status = 1;
|
exit_status = 1;
|
||||||
return Qnil;
|
return Qnil;
|
||||||
@ -56,8 +61,8 @@ int main(int argc, const char **argv) {
|
|||||||
fclose(in);
|
fclose(in);
|
||||||
lisp_init();
|
lisp_init();
|
||||||
REGISTER_SYMBOL(toplevel_read);
|
REGISTER_SYMBOL(toplevel_read);
|
||||||
REGISTER_STATIC_FUNCTION(toplevel_error_handler, "(e)", "");
|
REGISTER_STATIC_FUNCTION(toplevel_error_handler);
|
||||||
REGISTER_STATIC_FUNCTION(toplevel_exit_handler, "(e)", "");
|
REGISTER_STATIC_FUNCTION(toplevel_exit_handler);
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
WITH_PUSH_FRAME(Qtoplevel, Qnil, false, {
|
WITH_PUSH_FRAME(Qtoplevel, Qnil, false, {
|
||||||
the_stack->hidden = false;
|
the_stack->hidden = false;
|
||||||
@ -92,7 +97,7 @@ int main(int argc, const char **argv) {
|
|||||||
&& list_length(tv) == 2) {
|
&& list_length(tv) == 2) {
|
||||||
refcount_unref(Fset_current_package(HEAD(TAIL(tv))));
|
refcount_unref(Fset_current_package(HEAD(TAIL(tv))));
|
||||||
} else {
|
} else {
|
||||||
refcount_unref(Feval(tv)); //
|
refcount_unref(Feval(tv, the_stack->lexenv)); //
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -575,7 +575,8 @@ size_t read_from_buffer(const char *text, size_t length, LispVal *package,
|
|||||||
return state.off;
|
return state.off;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN(read, "read", (LispVal * source, LispVal *package)) {
|
DEFUN(read, "read", (LispVal * source, LispVal *package), "(source package)",
|
||||||
|
"Read a single form from SOURCE.") {
|
||||||
LispString *str = (LispString *) source;
|
LispString *str = (LispString *) source;
|
||||||
CHECK_TYPE(TYPE_STRING, source);
|
CHECK_TYPE(TYPE_STRING, source);
|
||||||
struct ReadState state = {
|
struct ReadState state = {
|
||||||
@ -600,3 +601,7 @@ DEFUN(read, "read", (LispVal * source, LispVal *package)) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void register_reader_functions(void) {
|
||||||
|
REGISTER_FUNCTION(read);
|
||||||
|
}
|
||||||
|
|||||||
@ -13,4 +13,6 @@ size_t read_from_buffer(const char *text, size_t length, LispVal *package,
|
|||||||
|
|
||||||
DECLARE_FUNCTION(read, (LispVal * source, LispVal *package));
|
DECLARE_FUNCTION(read, (LispVal * source, LispVal *package));
|
||||||
|
|
||||||
|
void register_reader_functions(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user