-
Notifications
You must be signed in to change notification settings - Fork 71
/
Copy pathglobal-lexical.lisp
53 lines (40 loc) · 1.78 KB
/
global-lexical.lisp
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
(defpackage #:coalton-impl/global-lexical
(:use #:cl)
(:export
#:get-top-level-binding
#:define-global-lexical))
(in-package #:coalton-impl/global-lexical)
;;;; Global environments:
;;; The global environment contains top level bindings.
(defstruct global-environment
;; A map from variable names to their top level bindings.
(bindings (make-hash-table :test #'eq) :type hash-table))
(defvar *top-level-environment* (make-global-environment)
"The current global top level environment.")
(declaim (type global-environment *top-level-environment*))
;;;; Top level bindings:
;;;;
;;;; We represent top level bindings as conses as they are usually
;;;; only two words on most Lisp implementations. The NAME is supplied
;;;; purely for debugging purposes, which is convenient because we get
;;;; an extra word for it in a CONS cell anyway.
(declaim (ftype (function (symbol global-environment) cons) get-top-level-binding))
;;; Get the top level binding for NAME in ENVIRONMENT.
(defun get-top-level-binding (name environment)
(let ((bindings (global-environment-bindings environment)))
(or (gethash name bindings)
(setf (gethash name bindings)
(cons ':|@@unbound@@| name)))))
(declaim (inline top-level-binding-value
top-level-binding-name
(setf top-level-binding-value)))
(defun top-level-binding-value (binding) (car binding))
(defun top-level-binding-name (binding) (cdr binding))
(defun (setf top-level-binding-value) (new-value binding)
(setf (car binding) new-value))
(defmacro define-global-lexical (var type)
`(progn
(define-symbol-macro ,var
(the ,type
(top-level-binding-value (load-time-value
(get-top-level-binding ',var *top-level-environment*)))))))