119 lines
3.7 KiB
Common Lisp
119 lines
3.7 KiB
Common Lisp
;;;; cl-scopes/csys - concurrent cybernetic communication systems
|
|
|
|
(defpackage :scopes/csys
|
|
(:use :common-lisp)
|
|
(:local-nicknames (:actor :scopes/core/actor)
|
|
(:config :scopes/config)
|
|
(:message :scopes/core/message)
|
|
(:shape :scopes/shape)
|
|
(:util :scopes/util)
|
|
(:alx :alexandria))
|
|
(:export #:scope #:environ
|
|
#:make-program
|
|
#:neuron #:std-proc #:create
|
|
#:handle-action
|
|
#:notify))
|
|
|
|
(in-package :scopes/csys)
|
|
|
|
;;;; scope: information a neuron has access to
|
|
|
|
(defclass scope ()
|
|
((value :accessor value :initarg :value :initform 0)
|
|
;(params :accessor params :initarg :params :initform nil) ; <- program
|
|
(categ :accessor categ :initarg :categ :initform '(:csys :c00))
|
|
(stage :accessor stage :initarg :stage :initform :initial)
|
|
(proc :accessor proc)
|
|
(program :reader program :initarg :program)
|
|
;(actions :accessor actions :initarg :actions :initform nil) ; <- program
|
|
(syns :accessor syns :initform nil)
|
|
(environ :reader environ :initarg :environ)))
|
|
|
|
(defun scope (prg env &rest args &key (cls 'scope) &allow-other-keys)
|
|
(remf args :cls)
|
|
(apply #'make-instance cls :program prg :environ env args))
|
|
|
|
(defmethod initialize-instance :after ((sc scope) &key &allow-other-keys)
|
|
(set-proc sc))
|
|
|
|
(defun reset-scope (scope &rest args)
|
|
(apply #'scope
|
|
(getf args :program) (program scope)
|
|
(getf args :environ (environ scope))
|
|
:categ (getf args :categ (categ scope))
|
|
args))
|
|
|
|
(defun set-proc (scope)
|
|
(setf (proc scope) (funcall (program scope) scope))
|
|
scope)
|
|
|
|
(defgeneric make-program (spec)
|
|
(:method ((fn function)) (lambda (scope) fn)))
|
|
|
|
;;;; neurons (= async tasks) and synapses (= connections)
|
|
|
|
(defun neuron (scope)
|
|
(actor:create (process scope)))
|
|
|
|
(defun synapse (rcvr &optional (op #'identity))
|
|
(lambda (msg)
|
|
(actor:send rcvr (funcall op msg))))
|
|
|
|
(defun update (scope)
|
|
(actor:become (process scope)))
|
|
|
|
(defun create (prg env &key (categ '(:csys :c00)) name value)
|
|
(let* ((domain (car categ))
|
|
(addr (when name (list domain (cadr categ) name)))
|
|
(scope (apply #'scope prg env :categ categ (when value (list :value value))))
|
|
(msg (message:create (list domain :create)
|
|
:data (when addr (list :addr addr)))))
|
|
(do-create msg scope)))
|
|
|
|
;;;; message handlers, proc steps
|
|
|
|
(defun process (scope)
|
|
(lambda (msg) (funcall (proc scope) msg scope)))
|
|
|
|
(defun std-proc (msg scope)
|
|
(destructuring-bind (nmsg nscope)
|
|
(handle-action msg scope :default #'remember) ; + params, actions
|
|
(forward nmsg (syns nscope))
|
|
(update nscope)))
|
|
|
|
(defun do-create (msg scope)
|
|
(let ((new (neuron (apply #'reset-scope scope (shape:data msg)))))
|
|
(notify-created msg new scope)))
|
|
|
|
(defun do-log (msg scope)
|
|
(util:lgi msg))
|
|
|
|
(defun notify (msg scope)
|
|
(actor:send (environ scope) msg))
|
|
|
|
(defun forward (msg syns)
|
|
(dolist (s syns)
|
|
(funcall s msg)))
|
|
|
|
(defun handle-action (msg scope &key (default #'no-op) actions params)
|
|
(let* ((key (message:action msg))
|
|
;(act (gethash key (actions scope) default))
|
|
(act (getf actions key (getf actions :default default))))
|
|
(apply act msg scope params)))
|
|
|
|
(defun notify-created (msg new scope)
|
|
(let* ((head (list (message:domain msg) :created))
|
|
(data (util:plist-merge (shape:data msg) '(:new new :parent actor:*self*)))
|
|
(msg1 (message:create head :data data)))
|
|
(notify msg1 scope))
|
|
)
|
|
|
|
;;;; predefined neuron actions
|
|
|
|
(defun no-op (msg scope)
|
|
(list msg scope))
|
|
|
|
(defun remember (msg scope)
|
|
(setf (value scope) (shape:data-value msg :value))
|
|
;(list msg (make-neuron-state (shape:data msg) syns))
|
|
(list msg scope))
|