يعتبر الديكور أحد أكثر الميزات غير المعتادة في Python. إنها أداة لا يمكن أن توجد إلا بشكل كامل بلغة مترجمة بشكل ديناميكي. في الجزء الأول من المقال يا صديقيعوض محمد عطيه 136 أوضحت كيف في C ++ لتنفيذ النسخة الأقرب من النسخة المرجعية (Python) من الديكور.
سأخبرك كيف قررت أن أحاول تنفيذ الديكور في لغة برمجة مُجمَّعة ، والتي كتبتُ مُجمِّعًا صغيرًا خاصًا بي يعتمد على Haskell بناءً على LLVM .
جدول المحتويات
كيف يعمل الديكور في بيثون
قبل الغوص في خوارزمية تجميع الديكور ، دعنا نتحدث عن تنفيذ الديكور في الثعبان ، ولماذا لا يمكن استنساخه بنفس الشكل في اللغة المترجمة. ألاحظ على الفور أنه في هذه المقالة ، يُفهم الثعبان على أنه 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 , , , , . , ( , ), - .
ملاحظة: لقد كانت تجربة مثيرة للاهتمام وغير عادية بالنسبة لي - آمل أن تكون أنت أيضًا قادرًا على تعلم شيء مفيد من هذه القصة. إذا كنت بحاجة إلى مقال منفصل حول كتابة مترجم هاسكل القائم على LLVM - اكتب في التعليقات.
سأحاول الإجابة على أي أسئلة في التعليقات ، أو في برقية - @ nu11_pointer_exception