Generating Python code with Hy macros

Viewed 1387

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:

  1. What would be the best way to generate python code from Hy?
  2. What is internal representation for True and False?
  3. Can one call a function that processes its parameters and returns a quoted Hy form from a macro and how?
1 Answers
Related