装饰器是Python最不寻常的功能之一。它是只能以动态类型的解释语言完全存在的工具。在文章的第一部分,我的朋友巫师136 展示了如何在C ++中实现最接近参考(Python)版本的装饰器。
我将告诉您有关如何决定尝试以编译的编程语言实现装饰器的信息,为此,我最终基于LLVM编写了自己的小型Haskell编译器。
目录
装饰器在Python中的工作方式
在进入装饰器编译算法之前,让我们先讨论一下python中装饰器的实现,以及为什么不能以相同的形式用编译语言来复制装饰器。我马上注意到在本文中,python被理解为CPython。发动机舱的所有零件都仅参考该零件。
, , , , — , .
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:对我来说,这是一次非常有趣且不寻常的经历-我希望您也能够从这个故事中学到一些有用的东西。如果您需要有关编写基于LLVM的Haskell编译器的单独文章,请在注释中编写。
我将尝试在评论或电报中回答任何问题-@ nu11_pointer_exception