Kompilieren eines Dekorators - C ++, Python und benutzerdefinierte Implementierung. Teil 2

Dekorateure sind eine der ungewöhnlichsten Funktionen von Python. Dies ist ein Tool, das nur in einer dynamisch typisierten, interpretierten Sprache vollständig vorhanden sein kann. Im ersten Teil des Artikels mein FreundHexer136 zeigte, wie in C ++ die Referenzversion (Python) von Dekoratoren am ehesten implementiert werden kann.



Ich erzähle Ihnen, wie ich mich entschlossen habe, Dekorateure in einer kompilierten Programmiersprache zu implementieren , für die ich meinen eigenen kleinen Compiler basierend auf Haskell basierend auf LLVM geschrieben habe .





Inhaltsverzeichnis



  1. Wie Dekorateure in Python arbeiten
  2. Haskell und LLVM - Native Compiler
  3. Wie kompiliert man einen Dekorateur?




Wie Dekorateure in Python arbeiten



Bevor wir uns mit dem Kompilierungsalgorithmus für Dekoratoren befassen, wollen wir uns mit der Implementierung von Dekoratoren in Python befassen und erklären, warum sie in der kompilierten Sprache nicht in derselben Form reproduziert werden können. Ich stelle sofort fest, dass Python in diesem Artikel als CPython verstanden wird. Alle Motorraumteile beziehen sich nur darauf.



, , , , — , .



Python, - , :



decorator, func, old. newold


def decorator(func):
    def new(*args, **kwargs):
        print('Hey!')
        return func(*args, **kwargs)
    return new

@decorator
def old():
    pass

# old()  "Hey!" -   old    new


— , -, — , .



CPython

Python-. , - — , , , . , , , — - "" .



, , , — - "" . : BINARY_SUBSTRACT () TypeError, 1 'a'. , STORE_FAST ( ), , , TypeError, .. STORE_FAST — .



, new — . -, , , decorator old.



1. —



. decorator , :



name = input('  ')

def first(func):
    ...  #  

def second (func):
    ...  #  

if name == 'first':
    decorator = first
elif name == 'second':
    decorator = second
else:
    decorator = lambda f: f   #    

@decorator 
def old():
    pass


, old . (, C++) , (- ), . Python — , , , " ", .



, , old void-, , — , , , .



, Python, : .



2. Python



def decorator(func):
    def two_args(x, y):
        ...
    return two_args

@decorator
def one_arg(x):
    ...


, . one_arg , ( ) — , , , (, "" ). , ? " " . , , decorator -, .



, , , — . , .



— — func? , , — , . func A, A. void* func, , .



func , — Witcher136 . , (. C++ ).






. :



  • — ?
  • — ?
  • , , ( )


, Python — . , — Python — .

— " ", , , . , .



.





Haskell LLVM —



Haskell, , LLVM . Haskell llvm-hs, LLVM. Parsec, , - ( , , Parsec — parser combinators).



, Grit, ( , , ) — . .



Grit — expression-oriented ()



Grit, , if-else, , — , .



int main() = {
    int i = 0;
    i = i + if(someFunction() > 0) {
        1;
    }
    else {
        0;
    };
};


, i 1, someFunction , , 0 .



return



, ( ) .



, — , Grit, — , . returns, — , ; .



, , "" — "", — , .



int simple(int x) = {
    /* 
          
        x   y
    */
    int y = someOtherFunction();
    x + y;
};

/*
   ,    ,    .
      ,   
*/
int incr(int x) = x + 1;

int main() returns statusCode {
    /*
             returns
         ,  
           .
         "" 
         ,     
    */
    int statusCode = 0;
    int result = someFunction();
    if (someFunction < 0) {
        statusCode = 1;
    };
};


Auto — Grit



Grit auto, , ( ) .



— , . — — , — ..

, , returns.



auto half (int x) = x / 2;   //   incr    float





(expression-oriented), return () — Grit. , .

, , .



— ?





?



, , — runtime compile-time, .



, , , — , .



-, Grit — , ( AST, abstract syntax tree), . -, , .



, :



@auto flatten = {
    auto result = @target;
    if (result < 0) {
        0;
    }
    else {
         result;
    };
};


, , 0, 0, .



@auto flattenflatten @auto — , (@ — , , ).



. , — , , , .



@target. , . ( ), , , , ( ).

, AST @target, . , , — . , .



, Grit, — , Python.



, :



@auto lockFunction = {
    mutex.lock();
    @target
};


, - :



@auto optional = if (checkCondition()) {
    @target;
}
else {
    someDefaultValue;
};




Grit :



@auto flatten = {
    auto result = @target;
    if (result < 0) {
        0;
    }
    else {
         result;
    };
};

@flatten
int incr(int x) = x+1;


flatten , .



"" , - :



Decorator "flatten" auto {
  BinaryOp = (Def auto "result") (DecoratorTarget)
  If (BinaryOp < (Var "result") (Int 0)) {
    Int 0
  }
  else {
    Var "result"
  }
}
Function "incr" int ; args [Def int "x"] ; modifiers [Decorator "flatten"] ; returns Nothing {
  BinaryOp + (Var "x") (Int 1)
}


, — Decorator, incr , Decorator "flatten". DecoratorTargetincr.



, — . , , , "" — , .



, :



Function (int -> int) incr ["x"] {
  BinaryOp i= (Def int "result") (
    Block int {
      BinaryOp i+ (Var int "x") (int 1)
    }
  )
  If int (BinaryOp b< (Var int "result") (int 0)) {
    int 0
  }
  else {
    Var int "result"
  }
}


:



  • — AST, .
  • incr — , flatten, DecoratorTarget Block {...} — " ", . , , — int "result". BinaryOp i= int-, result auto — , , .


, , , . Python, , , Grit.



, — , , :



@auto lockF(mutex M) {
    M.lock();
    @target;
};

@lockF()
int someFunction(...)


mutex M, "", (, , Python — ).



, @args, , " " . , @args.length — , @args.1 — . - , - — .



, Haskell , , , , . , ( , ), - .



, stack



PS Es war eine sehr interessante und ungewöhnliche Erfahrung für mich - ich hoffe, dass auch Sie etwas Nützliches aus dieser Geschichte herausholen konnten. Wenn Sie einen separaten Artikel zum Schreiben eines auf LLVM basierenden Haskell-Compilers benötigen, schreiben Sie in die Kommentare.

Ich werde versuchen, alle Fragen in den Kommentaren oder in einem Telegramm zu beantworten - @ nu11_pointer_exception




All Articles