I am trying to generate some python code from Hy. How is that done better?
I have tried several approaches. One is with a macro:
(defmacro make-vars [data]
(setv res '())
(for [element data]
(setv varname (HySymbol (+ "var" (str element))))
(setv res (cons `(setv ~varname 0) res)))
`(do ~@res))
Then after capturing macroexpansion, I print python disassembly of a code.
However, it seems that with macros I am unable to pass variables, so that:
(setv vnames [1 2 3])
(make-vars vnames)
defines varv
, varn
, vara
and so on, in stead of var1
, var2
, var3
. It seems that correct invocation could be made with:
(macroexpand `(make-vars ~vnames))
but that seems to be excessively complex.
Other issue I have encountered is the necessity of HySymbol
, which came as a big surprise. But I have really been hurt by that, when I tried second approach, where I made a function that returns quoted forms:
(defn make-faction-detaches [faction metadata unit-types]
(let [meta-base (get metadata "Base")
meta-pattern (get metadata "Sections")
class-cand []
class-def '()
class-grouping (dict)]
(for [(, sec-name sec-flag) (.iteritems meta-pattern)]
;; if section flag is set but no unit types with the section are found, break and return nothing
(print "checking" sec-name)
(if-not (or (not sec-flag) (any (genexpr (in sec-name (. ut roles)) [ut unit-types])))
(break)
;; save unit types for section
(do
(print "match for section" sec-name)
(setv sec-grouping (list-comp ut [ut unit-types]
(in sec-name (. ut roles))))
(print (len sec-grouping) "types found for section" sec-name)
(when sec-grouping
(assoc class-grouping sec-name sec-grouping))))
;; in case we finished the cycle
(else
(do
(def
class-name (.format "{}_{}" (. meta-base __name__) (fix-faction-string faction))
army-id (.format "{}_{}" (. meta-base army_id) (fix-faction-string faction))
army-name (.format "{} ({})" (fix-faction-name faction) (. meta-base army_name)))
(print "Class name is" class-name)
(print "Army id is" army-id)
(print "Army name is" army-name)
(setv class-cand [(HySymbol class-name)])
(setv class-def [`(defclass ~(HySymbol class-name) [~(HySymbol (. meta-base __name__))]
[army_name ~(HyString army-name)
faction ~(HyString faction)
army_id ~(HyString army-id)]
(defn --init-- [self]
(.--init-- (super) ~(HyDict (interleave (genexpr (HyString k) [k class-grouping])
(cycle [(HyInteger 1)]))))
~@(map (fn [key]
`(.add-classes (. self ~(HySymbol key))
~(HyList (genexpr (HySymbol (. ut __name__))
[ut (get class-grouping key)]))))
class-grouping)))]))))
(, class-def class-cand)))
That function takes metadata that looks like this in python:
metadata = [
{'Base': DetachPatrol,
'Sections': {'hq': True, 'elite': False,
'troops': True, 'fast': False,
'heavy': False, 'fliers': False,
'transports': False}}]
And takes a list of classes that have form of:
class SomeSection(object):
roles = ['hq']
It required extensive usage of internal classes of hy, and I failed to properly represent True and False, resorting to HyInteger(1)
and HyInteger(0)
instead.
To get python code from this function, I run its result through disassemble
.
To summarise:
- What would be the best way to generate python code from Hy?
- What is internal representation for True and False?
- Can one call a function that processes its parameters and returns a quoted Hy form from a macro and how?