summaryrefslogtreecommitdiff
path: root/src/instr.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'src/instr.lisp')
-rw-r--r--src/instr.lisp49
1 files changed, 49 insertions, 0 deletions
diff --git a/src/instr.lisp b/src/instr.lisp
new file mode 100644
index 0000000..a5c94c6
--- /dev/null
+++ b/src/instr.lisp
@@ -0,0 +1,49 @@
+(defpackage #:sarcasm.instr
+ (:use #:cl)
+ (:shadow cl:return cl:if cl:block cl:loop cl:t)
+ (:local-nicknames
+ (#:a #:alexandria-2)))
+
+(in-package #:sarcasm.instr)
+
+(defclass instr () ())
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (defun expand-instr-plist (plist)
+ (destructuring-bind (&key instr code type) plist
+ (let* ((class-name
+ (intern (string-upcase (first instr))))
+ (immediates
+ (cl:loop
+ :for arg :in (rest instr)
+ :for slot-name := (intern (string-upcase arg))
+ :for reader := (intern (format nil "~a-~a" class-name slot-name))
+ :for initarg := (a:make-keyword slot-name)
+ :collect `(,slot-name
+ :reader ,reader
+ :initarg ,initarg
+ :initform (error "~a required" ',slot-name)))))
+ `(defclass ,class-name (instr)
+ ((instr-name
+ :allocation :class
+ :type string
+ :initform ,(first instr)
+ :reader instr-name)
+ (instr-code
+ :allocation :class
+ :type (vector (unsigned-byte 8) ,(length code))
+ :initform (make-array ,(length code)
+ :element-type '(unsigned-byte 8)
+ :initial-contents ',code))
+ (instr-type
+ :allocation :class
+ :type t
+ :initform ',type)
+ ,@immediates))))))
+
+(macrolet ((create-instr-classes (raw)
+ `(progn
+ ,@(mapcar #'expand-instr-plist raw))))
+ (create-instr-classes #.sarcasm.raw-instrs:raw-instrs))
+
+