Created
February 11, 2018 15:42
-
-
Save Z-Shang/042c4bb4ba54f8552c8d8543ccfef2a7 to your computer and use it in GitHub Desktop.
Naive-FSM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(in-package :cl-user) | |
(defpackage :naive-fsm | |
(:use :cl) | |
(:export | |
#:new-mm | |
#:state | |
#:on | |
#:mwhen | |
#:trigger | |
#:states)) | |
(in-package :naive-fsm) | |
(defclass micro-machine () | |
((state :reader state | |
:initarg :state | |
:initform nil | |
:type symbol) | |
(transitions :reader transitions | |
:initarg :transitions | |
:initform (make-hash-table :test #'equalp) | |
:type hash-table) | |
(callbacks :reader callbacks | |
:initarg :callbacks | |
:initform (make-hash-table :test #'equalp) | |
:type hash-table))) | |
(defun new-mm (state) | |
(make-instance 'micro-machine :state state)) | |
(define-condition invalid-event (error) | |
((msg :initarg :msg :reader msg))) | |
(define-condition invalid-state (error) | |
((msg :initarg :msg :reader msg))) | |
(defmethod on ((mm micro-machine) key cb) | |
(push cb (gethash key (callbacks mm)))) | |
(defmethod mwhen ((mm micro-machine) event transition) | |
(setf (gethash event (transitions mm)) transition)) | |
(defmethod trigger? ((mm micro-machine) event) | |
(with-slots (transitions state) mm | |
(if (gethash event transitions) | |
(cdr (assoc state (gethash event transitions))) | |
(error 'invalid-event :msg (format nil "Event: ~A is invalid" event))))) | |
(defmethod change ((mm micro-machine) new-state event payload) | |
(with-slots (transitions state callbacks) mm | |
(setf state new-state) | |
(let ((cbs (remove-if #'null (cons (gethash event callbacks) (gethash '_all callbacks))))) | |
(mapcar #'(lambda (f) (funcall f mm event payload)) cbs) | |
t))) | |
(defmethod trigger ((mm micro-machine) event &optional (payload nil)) | |
(let ((s (trigger? mm event))) | |
(if s | |
(change mm s event payload) | |
nil))) | |
(defmethod states ((mm micro-machine)) | |
(remove-duplicates (mapcar #'car (transitions mm)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment