summaryrefslogtreecommitdiff
path: root/src/enum.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'src/enum.lisp')
-rw-r--r--src/enum.lisp59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/enum.lisp b/src/enum.lisp
new file mode 100644
index 0000000..c678ec7
--- /dev/null
+++ b/src/enum.lisp
@@ -0,0 +1,59 @@
1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/enum
4 (:use :c2cl :iterate)
5 (:import-from :ukkoclot/bot/impl :fixup-value :parse-value)
6 (:import-from :string-case :string-case)
7 (:local-nicknames
8 (:jzon :com.inuoe.jzon))
9 (:export :define-enum))
10(in-package :ukkoclot/enum)
11
12(eval-when (:compile-toplevel :load-toplevel :execute)
13 (defstruct (field (:constructor make-field%)) name string)
14
15 (defun make-field (name string)
16 (make-field% :name name :string string))
17
18 (defun parse-field-specs (field-specs)
19 (iter (for field-spec in field-specs)
20 (collect (apply #'make-field field-spec))))
21
22 (defun emit-defconst (field)
23 `(defconstant ,(field-name field) ',(field-name field)))
24
25 (defun emit-deftype (name fields)
26 `(deftype ,name ()
27 '(member ,@(iter (for field in fields) (collect (field-name field))))))
28
29 (defun emit-fixup-method (field)
30 (let ((arg (gensym "ARG")))
31 `(defmethod fixup-value ((,arg (eql ',(field-name field))))
32 ,(field-string field))))
33
34 (defun emit-jzon-write-method (field)
35 (let ((writer (gensym "WRITER"))
36 (arg (gensym "ARG")))
37 `(defmethod jzon:write-value (,writer (,arg (eql ',(field-name field))))
38 (jzon::write-string ,(field-string field) ,writer))))
39
40 (defun emit-parse-value (name fields)
41 (let ((type (gensym "TYPE"))
42 (source (gensym "SOURCE")))
43 `(defmethod parse-value ((,type (eql ',name)) ,source)
44 ;; nil in, nil out
45 (when ,source
46 (string-case (,source)
47 ,@(iter (for field in fields)
48 (collect `(,(field-string field) ,(field-name field))))))))))
49
50(defmacro define-enum (name &body field-specs)
51 (let ((fields (parse-field-specs field-specs)))
52 `(progn
53 ,(emit-deftype name fields)
54 ,(emit-parse-value name fields)
55 ,@(iter (for field in fields)
56 (collect `(progn
57 ,(emit-defconst field)
58 ,(emit-fixup-method field)
59 ,(emit-jzon-write-method field)))))))