Question

Si je dois créer ma propre petite DSL qui utiliserait Python pour décrire une certaine structure de données. Par exemple. Je voudrais pouvoir écrire quelque chose comme

f(x) = some_stuff(a,b,c)

et ont Python, au lieu de se plaindre au sujet des identificateurs non déclarés ou tenter d'appeler la fonction some_stuff, le convertir en une expression littérale pour mon plus pratique.

Il est possible d'obtenir une approximation raisonnable en créant une classe avec des méthodes de __getattr__ et __setattr__ correctement redéfinies et l'utiliser comme suit:

e = Expression()
e.f[e.x] = e.some_stuff(e.a, e.b, e.c)

Ce serait cool si, s'il était possible de se débarrasser de l'ennuyeux « e. » préfixes et peut-être éviter même l'utilisation de []. Alors je me demandais, est-il possible d'une certaine façon temporaire « redéfinir le terme » nom global de recherches et missions? Sur le même sujet, peut-être il y a de bons paquets pour réaliser facilement ces « citant » la fonctionnalité des expressions Python?

Était-ce utile?

La solution

Je ne suis pas sûr que c'est une bonne idée, mais je pensais que je avais essayer . Pour résumer:

class PermissiveDict(dict):
    default = None

    def __getitem__(self, item):
        try:
            return dict.__getitem__(self, item)
        except KeyError:
            return self.default

def exec_with_default(code, default=None):
    ns = PermissiveDict()
    ns.default = default
    exec code in ns
    return ns

Autres conseils

Vous pouvez jeter un oeil sur les modules de ast ou parser inclus avec Python pour analyser, l'accès et transformer l'arbre de syntaxe abstraite (ou arbre syntaxique, respectivement) du code d'entrée. Pour autant que je sache, le système mathématique Sage , écrit en Python, a une sorte semblable de precompiler.

En réponse au commentaire de Wai, voici une solution amusante que j'ai trouvé. Tout d'abord, pour expliquer une fois de plus ce qu'il fait, supposons que vous avez le code suivant:

definitions = Structure()
definitions.add_definition('f[x]', 'x*2')
definitions.add_definition('f[z]', 'some_function(z)')
definitions.add_definition('g.i', 'some_object[i].method(param=value)')

où l'ajout de définitions implique l'analyse syntaxique des côtés de la main gauche et les côtés de la main droite et de faire d'autres choses laides. Maintenant, un (pas nécessairement bonne, mais certainement amusant) approcher ici permettrait d'écrire le code ci-dessus comme suit:

@my_dsl
def definitions():
    f[x] = x*2
    f[z] = some_function(z)
    g.i  = some_object[i].method(param=value)

et ont Python faire la plupart des parsing sous le capot. L'idée est basée sur la simple déclaration de exec <code> in <environment>, mentionnée par Ian, avec un ajout hackish. A savoir, le bytecode de la fonction doit être légèrement modifié et toutes les opérations d'accès aux variables locales (LOAD_FAST) commuté sur l'accès aux variables de l'environnement (LOAD_NAME).

Il est plus facile que montre expliqué: http://fouryears.eu/wp-content / uploads / pydsl /

Il y a plusieurs trucs que vous voudrez peut-être faire pour le rendre pratique. Par exemple, dans le code présenté au lien ci-dessus vous ne pouvez pas utiliser les fonctions et les constructions builtin linguistiques comme pour les boucles et si des déclarations dans une fonction @my_dsl. Vous pouvez faire ces travaux, cependant, en ajoutant plus de comportement à la classe Env.

Mise à jour . est un peu plus bavard explication de la même chose .

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