Decoradores são um dos recursos mais incomuns do Python. Essa é uma ferramenta que só pode existir completamente em uma linguagem interpretada e de tipo dinâmico. Na primeira parte do artigo, meu amigoWitcher136 mostrou como em C ++ implementar a versão mais próxima da referência (Python) dos decoradores.
Vou contar como decidi tentar implementar decoradores em uma linguagem de programação compilada , para a qual acabei escrevendo meu próprio compilador Haskell pequeno baseado no LLVM .
Índice
- Como os decoradores funcionam em Python
- Haskell e LLVM - compilador nativo
- Então, como você compila um decorador?
Como os decoradores funcionam em Python
Antes de mergulhar no algoritmo de compilação do decorador, vamos falar sobre a implementação de decoradores em python e por que ele não pode ser reproduzido da mesma forma em uma linguagem compilada. Percebo imediatamente que, neste artigo, python é entendido como CPython. Todas as partes do compartimento do motor se referem apenas a ele.
, , , , — , .
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
— , -, — , .
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 — 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 , , , , . , ( , ), - .
PS Foi uma experiência muito interessante e incomum para mim - espero que você também tenha aprendido algo útil com essa história. Se você precisar de um artigo separado sobre como escrever um compilador Haskell baseado em LLVM - escreva nos comentários.
Vou tentar responder a quaisquer perguntas nos comentários ou em um telegrama - @ nu11_pointer_exception