-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathactors-macros.lisp
108 lines (79 loc) · 3.47 KB
/
actors-macros.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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
;; actors-macros.lisp -- actually, defuns that need to be in place for the macros to be defined later
(in-package #:actors-macros)
;; --------------------------------------------------------
(defun anaphor (sym)
;; ensure that a like symbol is interned into the user's current
;; package, e.g., (let ((a!self (anaphor 'self)) ...)
(intern (string sym)))
(defun gensym-like (sym)
(gensym (string sym)))
;; --------------------------------------------------------------------
;; LW Locks are more than twice as fast as spin-locks in this application
(defmacro make-lock (&rest args)
`(mp:make-lock ,@args))
(defmacro with-lock ((lock) &body body)
`(mp:with-lock (,lock)
,@body))
;; --------------------------------------------------------------------
(defun split-bindings (bindings)
(values (mapcar #'car bindings)
(mapcar #'cadr bindings)))
;; --------------------------------------------------------------------
#|
Assuming your ANAPHOR function is defined something like:
(defun anaphor (name)
(intern (symbol-name name)))
then I think all the problems are caused by having different values of
*PACKAGE* at different times and in different threads.
Note that the definition of ANAPHOR above has a dependency on the value of
*PACKAGE*, so using it at macroexpansion time will create a macroexpansion
time dependency on the value of *PACKAGE*. This is probably OK when compiling
everything because all macros are fully expanded at compile time. However,
when using the interpreter, macros are expanded at run time (as they are
encountered), so you will have a run time dependency on the value of
*PACKAGE*.
Here are two problems with this for interpreted code **within BEHAV**:
1. Any code that statically references SELF will refer to the symbol in
*PACKAGE* at read time, which may be different from the symbol bound by
MAKE-ACTOR at macroexpansion time.
2. If some other macro calls (anaphor 'self) hoping to pick up the binding
made by MAKE-ACTOR, then it will get a symbol named SELF in *PACKAGE* at the
run time (i.e. macroexpansion time) of that code. If that code runs at the
same time as MAKE-ACTOR, then it will work. However, code within a LAMBDA or
LABELS form might run later, in particular on the Executive thread.
Now for the fun part: the value of *PACKAGE* on the Executive thread will
depend on when the thread is created!
This is because the initial value of *PACKAGE* is defined by:
(assoc '*package* mp:*process-initial-bindings*) => (*package* . *package*)
so will capture the value in the thread that calls MP:PROCESS-RUN-FUNCTION.
I think that might explain all of the quirks you are seeing.
--
Martin Simmons
LispWorks Ltd
http://www.lispworks.com/
|#
(defun in-eval-mode-p (env)
(or (null env)
(notany (um:curry #'slot-value env)
'(compiler::compilation-env
compiler::remote-env
compiler::benv
compiler::fenv
compiler::tenv
compiler::venv))))
(defun ensure-thread-eval (form env)
(if (in-eval-mode-p env)
`(funcall (compile nil (lambda () ,form)))
form))
(defun self-visible-p (anaphoric-self env)
(and env
(find anaphoric-self (slot-value env 'compiler::venv)
:key (lambda (venv)
(slot-value venv 'compiler::name)))))
(defun ensure-self-binding (form env)
(let ((a!self (anaphor 'self)))
(if (self-visible-p a!self env)
form
`(let ((,a!self (current-actor)))
,form)
)))