aboutsummaryrefslogtreecommitdiff
path: root/src/core.lisp
blob: 6c151ce20bd4d4d7e83b33eff391d3b65cc60c48 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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)))