-
Notifications
You must be signed in to change notification settings - Fork 3
/
actors-user-macros.lisp
74 lines (63 loc) · 2.51 KB
/
actors-user-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
(in-package :actors-base)
;; ------------------------------------------------------
;; Macro for creating actors with the behavior specified by body
(defmacro become (behavior &environment env)
;; change the behavior of the Actor for future messages (ugh!)
(let ((a!self (anaphor 'self)))
(ensure-self-binding
`(setf (actor-behavior ,a!self) ,behavior)
env)
))
(defmacro behav (args state &body body &environment env)
;; can only be used inside actor's body code to produce a new actor
;; state
(let* ((a!self (anaphor 'self))
(a!me (anaphor 'me))
(subst `(let ,state
(labels ((,a!me ,(cons a!self args)
(declare (ignorable ,a!self))
,@body))
#',a!me))
))
(ensure-thread-eval subst env)))
(defun generate-actor (behav-fn)
(let ((actor (make-instance 'Actor
:behav behav-fn)))
(add-actor actor)
actor))
(defmacro def-factory (name args state &body body)
;; state is like a LET binding
;; args is a list of args expected by the outer behavior.
;;
;; This macro builds a function that can be called to make multiple
;; instances of the same behavior (same kind of Actor), each with
;; their own private copy of internal state.
;;
;; within body you can refer to symbols ME = body code function,
;; SELF = current actor, and any of the symbols named in the binding
;; forms of the initial state
`(defun ,name (&key ,@state)
(generate-actor (behav ,args () ,@body))) )
(defmacro make-actor (args state &body body)
;; MAKE-ACTOR is to the Actor system what LAMBDA is to Lisp. It
;; constructs an anonymous embodiment of behaior with a partially
;; known argument list. (i.e., the SELF argument is always sent as
;; the first arg)
`(generate-actor (behav ,args ,state ,@body)))
(defun spawn (behavior &rest args)
;; SPAWN - like MAKE-ACTOR combined with SEND
(let ((actor (make-actor (&rest run-args)
()
(apply behavior run-args))))
(apply #'send actor args)
actor))
;; ----------------------------------------------------------------------------
(defmacro lambdac (args &body body &environment env)
(ensure-thread-eval `(lambda ,args ,@body) env))
(defmacro defunc (name args &body body &environment env)
(let ((subst `(defun ,name ,args ,@body)))
(if (in-eval-mode-p env)
`(progn
,subst
(compile ',name))
subst)))