Cara mengkompilasi dekorator - C ++, Python dan implementasinya sendiri. Bagian 2

Dekorator adalah salah satu fitur paling umum dari Python. Ini adalah alat yang hanya bisa ada sepenuhnya dalam bahasa yang diketik dan ditafsirkan secara dinamis. Di bagian pertama artikel, teman sayaPenyihir136 menunjukkan bagaimana menerapkan di C ++ versi yang paling mendekati ke dekorator versi standar (Python).



Saya akan memberi tahu Anda tentang bagaimana saya memutuskan untuk mencoba menerapkan dekorator dalam bahasa pemrograman yang dikompilasi , yang akhirnya saya tulis sendiri kompiler Haskell kecil berdasarkan LLVM .





Daftar Isi



  1. Bagaimana dekorator bekerja dengan Python
  2. Haskell dan LLVM - Compiler Asli
  3. Jadi bagaimana Anda menyusun dekorator?




Bagaimana dekorator bekerja dengan Python



Sebelum menyelam ke dalam algoritma kompilasi dekorator, mari kita bicara tentang implementasi dekorator dalam python, dan mengapa itu tidak dapat direproduksi dalam bentuk yang sama dalam bahasa yang dikompilasi. Saya langsung mencatat bahwa dalam artikel ini, python dipahami sebagai CPython. Semua bagian kompartemen engine hanya merujuk padanya.



, , , , β€” , .



Python, - , :



decorator, func, old. new β€” old


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 flatten β€” flatten @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". DecoratorTarget β€” incr.



, β€” . , , , "" β€” , .



, :



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 Itu pengalaman yang sangat menarik dan tidak biasa bagi saya - saya harap Anda juga bisa belajar sesuatu yang berguna dari cerita ini. Jika Anda memerlukan artikel terpisah tentang menulis kompiler Haskell berbasis LLVM - tulis di komentar.

Saya akan mencoba menjawab pertanyaan apa pun di komentar, atau dalam telegram - @ nu11_pointer_exception




All Articles