Search code examples
pythondslpreprocessor

Python preprocessor with rules to simplify class creation (domain specific language)


I'm building something between a Python library and a DSL (domain specific language), for very specific applications, such that we can avoid:

class Car(RoomObject):
    def __init__(self):
        super().__init__()
        self.rect = rect(-20, -20, 40, 40)
        self.zindex = -10
        self.pos = self.rect.midbottom  
        _tempvar = 123
    def do(self, x)
        self.foo = x

and have this instead:

class Car(RoomObject):  # 1) avoid the def and self, all nested paragraphs in class are def 
    init():             # 2) __init__ -> init        3) automatically do the super init
        rect = rect(-20, -20, 40, 40)  # 4) assignations are self. by default...
        zindex = -10
        pos = rect.midbottom  
        _tempvar = 123                 # 5) ...except if variable name begins with _
    do(x):                             # ==> def do(self, x):
        foo = x                        # ==> self.foo = x

Can this be done with a built-in Python library, such as inspect (code introspection) or a preprocessor (if any), or not?


Context: it's for a niche market, where I can't ask non-tech people to write things like def __init__(self): super().__init__() self.rect = ... all the time. I need those specific people to be able to write in a simpler dialect, and my tool translate it into regular Python.


Solution

  • You are trying to write a dialect.

    You can do this to some extent, see the implementation of https://pypi.org/project/pypreprocessor/.

    You can write something like:

    import mypreprocessor
    mypreprocessor.parse()
    
    class Car(RoomObject):  # 1) avoid the def and self, all nested paragraphs in class are def 
        init():             # 2) __init__ -> init        3) automatically do the super init
            rect = rect(-20, -20, 40, 40)  # 4) assignations are self. by default...
            zindex = -10
            pos = rect.midbottom  
            _tempvar = 123                 # 5) ...except if variable name begins with _
        do(x):                             # ==> def do(self, x):
            foo = x                        # ==> self.foo = x
    

    Then in mypreprocessor.parse():

    def parse():
        ... load current file
        ... preprocess
        ... call exec()
        ... sys.exit(0)