1.1--- a/tk.lisp Mon May 08 21:11:03 2023 -0400
1.2+++ b/tk.lisp Fri May 12 22:58:05 2023 -0400
1.3@@ -1,31 +1,15 @@
1.4-(in-package #:demo)
1.5+(in-package :demo)
1.6
1.7-(defvar *cargo-target* #P"/Users/ellis/dev/otom8/demo/target/")
1.8+(defvar *cargo-target* #p"/Users/ellis/dev/otom8/demo/target/")
1.9
1.10 (defvar *rs-macros* nil)
1.11
1.12-(defmacro rs-find-dll (name &optional debug)
1.13- "Find the rust dll specified by NAME."
1.14- (cond
1.15- ((uiop:directory-exists-p (merge-pathnames *cargo-target* "release"))
1.16- `,(mkstr "./target/release/" name))
1.17- ((uiop:directory-exists-p (merge-pathnames *cargo-target* "debug"))
1.18- `,(mkstr "./target/debug/" name))
1.19- (t (progn
1.20- (uiop:run-program `("cargo" "build" ,(unless debug "--release")) :output t)
1.21- `,(find-rust-dll name debug)))))
1.22+(defun mkstr (&rest args)
1.23+ (with-output-to-string (s)
1.24+ (dolist (a args) (princ a s))))
1.25
1.26-(defmacro rs-defmacro (args &body body)
1.27- "Define a macro which expands to a string of Rust code.")
1.28-
1.29-(defun rs-macroexpand-1 (form &optional env))
1.30-
1.31-(defun rs-macroexpand (env &rest body)
1.32- "Cbindgen is quite the menace and really doesn't like our macros used
1.33-to generate C FFI bindings. To compensate for this, we use a tool
1.34-called cargo-expand by the most excellent dtolnay which expands Rust
1.35-macros. The expansions are assembled into an equivalent Rust source
1.36-file which cbindgen won't get stuck in an infinite compile loop on.")
1.37+(defun symb (&rest args)
1.38+ (values (intern (apply #'mkstr args))))
1.39
1.40 (defun random-id ()
1.41 (format NIL "~8,'0x-~8,'0x" (random #xFFFFFFFF) (get-universal-time)))
1.42@@ -34,13 +18,6 @@
1.43 (dolist (path (directory (merge-pathnames (merge-pathnames filename "**/") dir)))
1.44 (funcall callback path)))
1.45
1.46-(defun mkstr (&rest args)
1.47- (with-output-to-string (s)
1.48- (dolist (a args) (princ a s))))
1.49-
1.50-(defun symb (&rest args)
1.51- (values (intern (apply #'mkstr args))))
1.52-
1.53 (defun sbq-reader (stream sub-char numarg)
1.54 "The anaphoric sharp-backquote reader: #`((,a1))"
1.55 (declare (ignore sub-char))
1.56@@ -53,3 +30,80 @@
1.57 (eval-when (:execute)
1.58 (set-dispatch-macro-character
1.59 #\# #\` #'demo:sbq-reader))
1.60+
1.61+;;; RUST MACROS
1.62+(defmacro rs-find-dll (name &optional debug)
1.63+ "Find the rust dll specified by NAME."
1.64+ (cond
1.65+ ((uiop:directory-exists-p (merge-pathnames *cargo-target* "release"))
1.66+ `,(mkstr "./target/release/" name))
1.67+ ((uiop:directory-exists-p (merge-pathnames *cargo-target* "debug"))
1.68+ `,(mkstr "./target/debug/" name))
1.69+ (t `(progn
1.70+ ,(uiop:run-program '("cargo" "build" (unless debug "--release")) :output t)
1.71+ (rs-find-dll ,name ,debug)))))
1.72+
1.73+(defun rs-mod-form (crate &optional mods pub)
1.74+ "Generate a basic mod form (CRATE . [MODS] [PUB])"
1.75+ `(,crate ,mods ,pub))
1.76+
1.77+(defmacro with-rs-env (imports &body body)
1.78+ "Generate an environment for use within a Rust generator macro."
1.79+ `(let ((imports ,(mapcar #'rs-mod-form imports)))
1.80+ (format nil "~A~&~A" imports ',body)))
1.81+
1.82+(defun rs-use (crate &optional mods pub)
1.83+ "Generate a single Rust use statement."
1.84+ (concatenate
1.85+ 'string
1.86+ (if pub "pub " "")
1.87+ "use " crate "::{"
1.88+ (cond
1.89+ ((consp mods)
1.90+ (reduce
1.91+ (lambda (x y) (format nil "~A,~A" x y))
1.92+ mods))
1.93+ (t mods))
1.94+ "};"))
1.95+
1.96+(defun rs-mod (mod &optional pub)
1.97+ "Generate a single Rust mod statement."
1.98+ (concatenate
1.99+ 'string
1.100+ (if pub "pub " "")
1.101+ "mod " mod ";"))
1.102+
1.103+(defun rs-imports (&rest imports)
1.104+ "Generate a string of Rust 'use' statements."
1.105+ (cond
1.106+ ((consp imports)
1.107+ (mapcar (lambda (x) (apply #'rs-use (apply #'rs-mod-form x))) imports))
1.108+ (t imports)))
1.109+
1.110+(defmacro rs-extern-c-fn (name args &optional pub unsafe no-mangle &body body)
1.111+ "Generate a Rust extern 'C' fn."
1.112+ `(concatenate
1.113+ 'string
1.114+ ,(when no-mangle (format nil "#[no_mangle]~&"))
1.115+ ,(when pub "pub ")
1.116+ ,(when unsafe "unsafe ")
1.117+ "extern \"C\" fn " ,name "("
1.118+ ,(cond
1.119+ ((consp args) (reduce (lambda (x y) (format nil "~A,~A" x y)) args))
1.120+ (t args))
1.121+ ")" "{" ,@body "}"))
1.122+
1.123+(defun rs-obj-impl (obj)
1.124+ "Implement Objective for give OBJ."
1.125+ (format nil "impl Objective for ~A {};" obj))
1.126+
1.127+;; (defun rs-macroexpand-1 (form &optional env))
1.128+
1.129+;; (defun rs-macroexpand (env &rest body)
1.130+;; "Cbindgen is quite the menace and really doesn't like our macros used
1.131+;; to generate C FFI bindings. To compensate for this, we use a tool
1.132+;; called cargo-expand by the most excellent dtolnay which expands Rust
1.133+;; macros. The expansions are assembled into an equivalent Rust source
1.134+;; file which cbindgen won't get stuck in an infinite compile loop on.")
1.135+
1.136+;;;