;; I need some advice regarding DSLs and code walking. The DSL is VHDL-like, ;; with the twist that process' bodies are just Lisp code. For example, ;; (defcomponent some-component () (:process )). This defines a component ;; (just like defining a class) which can later be instantiated and simulated. ;; When simulated, the code within each process is run. ;; Currently, DEFCOMPONENT just expands into a call to MAKE-INSTANCE which ;; stores the component's definition, along with the body of all of its ;; processes. The idea is to COMPILE the process bodies manually later on, since ;; the bodies by themselves aren't yet valid Lisp code. ;; A special function "<-" is used to assign a value to a signal within the ;; process, e.g. (<- a 1). The signals are known when defining the component. ;; The catch is that I need to, as part of a component's definition, gather all ;; of the signals that a particular process sets. That information is required ;; in order to be able to instantiate a component later on and prepare the ;; simulation. ;; What are my options? Since it's arbitrary Lisp code I can't really detect the ;; usage of "<-" by hand. I could use a code walker though and enumerate all of ;; the calls to "<-" within that body. I tried using SB-WALKER so far but I'm ;; not really sure how to find all the function calls with it. Using a different ;; code walker might give better results. ;; The second option is making "<-" a macro that registers that information ;; within its macroexpansion. This would require changing DEFCOMPONENT into ;; something that will arrange for "<-" to be macroexpanded. Perhaps putting ;; that body in a lambda? Are there other ways to force macroexpansion? Aside ;; from having to be careful regarding macroexpansion and compiler environments, ;; this would also require that the body of a process is valid Lisp code, which ;; it isn't until further analysis is done. I don't know if I want all of this ;; to have to be done at macroexpansion time. (defcomponent receiver ((a 8 :in)) (:process r3 (wait :for 1) (fmt "~a " a))) (defcomponent proxy ((a 8 :in)) (:signals (wa 8)) (:map (receiver r wa)) (:process r2 (<- wa a) (wait :for 0))) (defcomponent system () (:signals (a 8)) (:map (proxy p a)) (:process r1 (<- a 1) (wait :for 1) (<- a 2) (wait :for 1) (<- a 3) (wait :for 2) (exit)))