Pregunta

Supongamos que necesito para crear mi propia pequeña DSL que usar Python para describir una determinada estructura de datos. P.ej. Me gustaría ser capaz de escribir algo como

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

y tienen Python, en lugar de quejarse acerca de los identificadores declarados o intentar invocar la función some_stuff, convertirlo en una expresión literal para mi mayor comodidad.

Es posible obtener una aproximación razonable a este mediante la creación de una clase con métodos __getattr__ y __setattr__ adecuadamente redefinidos y utilizarlo de la siguiente manera:

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

Sería fresco sin embargo, si fuera posible deshacerse del molesto "e". prefijos y tal vez incluso evitar el uso de []. Así que me preguntaba, ¿es posible de alguna manera temporalmente "re-significar" la búsqueda de nombres globales y las asignaciones? En una nota relacionada, tal vez hay buenos paquetes para lograr fácilmente tales "citar" funcionalidad de expresiones Python?

¿Fue útil?

Solución

No estoy seguro de que es una idea buena, pero pensé que había darle una oportunidad . Para resumir:

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

Otros consejos

Es posible que desee echar un vistazo a los módulos ast o parser incluidas con Python para analizar, acceder y transformar el árbol de sintaxis abstracta (o árbol de análisis sintáctico, respectivamente) del código de entrada. Por lo que yo sé, el Sage matemática sistema, escrito en Python, tiene una especie similar de precompilador.

En respuesta al comentario de Wai, aquí está una solución de diversión que he encontrado. En primer lugar, para explicar una vez más lo que hace, suponga que tiene el siguiente código:

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)')

donde añadiendo definiciones implica analizar los lados de la mano izquierda y los laterales a derecha y haciendo otras cosas feas. Ahora uno (no necesariamente bueno, pero ciertamente divertido) El enfoque aquí permitiría a escribir el código anterior de la siguiente manera:

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

y tienen Python hacer la mayor parte del análisis bajo el capó. La idea se basa en la declaración exec <code> in <environment> simple, mencionado por Ian, con una adición hacker. A saber, el código de bytes de la función debe ser ligeramente modificado y todas las operaciones de acceso variable local (LOAD_FAST) cambió a acceso variable desde el medio ambiente (LOAD_NAME).

Es más fácil que se muestra explica: http://fouryears.eu/wp-content / uploads / pydsl /

Hay varios trucos que usted puede querer hacer para que sea práctico. Por ejemplo, en el código presentado en el enlace de arriba no se puede utilizar incorporado funciones y construcciones del lenguaje como para los bucles y si las declaraciones dentro de una función @my_dsl. Usted puede hacer los trabajos, sin embargo, mediante la adición de un comportamiento más a la clase Env.

Actualizar . Aquí es un poco más prolija explicación de lo mismo .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top