Question

Je veux pirater autour de l'interpréteur Python et essayer de créer une petite DSL. Y at-il un module où je peux faire quelque chose comme ce code théorique (semblable aux arbres d'expression LINQ)?

expression_tree = Function(
    Print(
        String('Hello world!')
    )
 )
compile_to_bytecode(expression_tree)

Ou serait-il juste plus facile de générer du code source Python? Cela pourrait-il être plus facile en utilisant C ou SWIG ou Cython?

Était-ce utile?

La solution

Travailler via ast et compiler l'arbre en bytecode, comme une autre réponse suggère, est probablement la plus simple; sources de production et la compilation de ceux-ci, presque aussi bien.

Cependant, pour explorer des approches de niveau inférieur, consultez les liens de cette page ; Je l'ai trouvé byteplay particulièrement utile (actuellement ne fonctionne pas sur 2.6 ni 3. *, seulement 2,4 ou 2,5, mais je pense que la fixation pour 2.6 devrait être facile, comme actuellement discuté dans son suivi). Je ne l'ai pas utilisé BytecodeAssembler , mais étant donné la réputation de l'auteur, je suis sûr qu'il est la peine de vérifier it out!

Autres conseils

En Python 2.X, vous approche généralement cela avec le compiler le module et son sous-module ast (mais notez ce module est obsolète depuis la version 2.6). En Python 3.X, utilisez simplement ast .

Les deux offrent une fonction compile() qui passera de la source / AST pour « un objet de code qui peut être exécuté par l'instruction exec ou eval(). »

Il est plus facile de générer du code Python et l'exécuter. Si vous le faites, vous pouvez également déboguer plus facilement car il est source réelle pour le débogueur pour afficher. Voir aussi l'article dans le Borchs Malte numéro de Juillet du magazine Python, où il parle de cette entre autres.

Fernando Meyer a récemment écrit un billet de blog expliquant comment utiliser la directive # coding pour préciser votre propres extensions Python. Exemple (la définition du format actuel est pyspec.py et tokenizer.py ):

# coding: pyspec

class Bow:
    def shot(self):
        print "got shot"

    def score(self):
        return 5

describe Bowling:
    it "should score 0 for gutter game":
        bowling = Bow()
        bowling.shot()
        assert that bowling.score.should_be(5)

Mise à jour pour python3 -. Il y a aussi assembleur très intéressant zachariahreed/byteasm

En fait, le seul à travailler pour moi dans PY3. Il a API très agréable et propre:

>>> import byteasm, dis
>>> b = byteasm.FunctionBuilder()
>>> b.add_positional_arg('x')
>>> b.emit_load_const('Hello!')
>>> b.emit_load_fast('x')
>>> b.emit_build_tuple(2)
>>> b.emit_return_value()
>>> f = b.make('f')
>>> f
<function f at 0xb7012a4c>
>>> dis.dis(f)
  1           0 LOAD_CONST               0 ('Hello!')
              3 LOAD_FAST                0 (x)
              6 BUILD_TUPLE              2
              9 RETURN_VALUE
>>> f(108)
('Hello!', 108)

Consultez le module désassembleur trouvé ici:

http://docs.python.org/library/dis.html

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top