aboutsummaryrefslogtreecommitdiff
path: root/src/core.lisp
diff options
context:
space:
mode:
authorThomas Albers Raviola <thomas@thomaslabs.org>2024-05-13 21:29:31 +0200
committerThomas Albers Raviola <thomas@thomaslabs.org>2024-05-13 21:29:31 +0200
commitf5cb35b87255ebbe2d322bcedde6bc7d5f6aebae (patch)
tree161ec305fb4bef388dee6f50ed1c3ed842d55a2b /src/core.lisp
* Initial commit
Diffstat (limited to 'src/core.lisp')
-rw-r--r--src/core.lisp76
1 files changed, 76 insertions, 0 deletions
diff --git a/src/core.lisp b/src/core.lisp
new file mode 100644
index 0000000..6c151ce
--- /dev/null
+++ b/src/core.lisp
@@ -0,0 +1,76 @@
+(in-package #:chains)
+
+(defun get-var (env key)
+ (if-let ((slot (assoc key env)))
+ (cdr slot)
+ (error "var ~A not found~% ~A~%" key env)))
+
+;; Built-in functions and variables used inside the interpreter use their own
+;; package. This allows the language to have keywords like lambda which
+;; otherwise would be reserved words from the cl package
+
+(defmacro define-function (name (&rest args) &body body)
+ (let ((siblings (gensym)))
+ `(make-closure #'(lambda (environment ,siblings ,@args)
+ (declare (ignore ,siblings))
+ ,@body)
+ ',args
+ nil
+ (complement #'identity))))
+
+(defmacro define-function* (name (&rest args) (siblings group-predicate)
+ &body body)
+ `(make-closure #'(lambda (environment ,siblings ,@args)
+ ,@body)
+ ',args
+ nil
+ ,group-predicate))
+
+(defmacro define-syntax (name (&rest args) &body body)
+ `(make-closure #'(lambda (environment siblings ,@args)
+ ,@body)
+ ',args
+ t
+ (complement #'identity)))
+
+(defmacro define-syntax* (name (&rest args) (siblings group-predicate)
+ &body body)
+ `(make-closure #'(lambda (environment ,siblings ,@args)
+ ,@body)
+ ',args
+ t
+ ,group-predicate))
+
+(defparameter *lambda*
+ (define-syntax lambda (arglist body)
+ (setf arglist (remove-if #'whitespace-text-p arglist))
+ (assert (every #'object-symbolp arglist))
+ (setf arglist (mapcar #'cdr arglist))
+ (let ((env environment))
+ (make-closure #'(lambda (environment siblings &rest args)
+ (tree-eval (append (pairlis arglist args)
+ env
+ environment)
+ body))
+ arglist nil (complement #'identity) env))))
+
+(defparameter *syntax*
+ (define-syntax syntax (arglist body)
+ (setf arglist (remove-if #'whitespace-text-p arglist))
+ (assert (every #'object-symbolp arglist))
+ (setf arglist (mapcar #'cdr arglist))
+ (let ((env environment))
+ (make-closure #'(lambda (environment siblings &rest args)
+ (tree-eval (append (pairlis arglist args)
+ env
+ environment)
+ body))
+ arglist t (complement #'identity) env))))
+
+(defparameter *define*
+ (define-syntax* define (name value) (siblings #'identity)
+ (assert (object-symbolp (first name)))
+ (setf name (cdr (first name)))
+ (setf value (first (tree-eval environment value)))
+ (tree-eval (acons name value environment)
+ siblings)))