Quietly pretend we didn't just do that different from Python for no reason
This commit is contained in:
parent
7d8dfa2ffe
commit
93af369b8c
23
README.md
23
README.md
@ -642,17 +642,20 @@ f.theMethod("the newly required argument")
|
||||
# I also required this extra argument: the newly required argument
|
||||
```
|
||||
|
||||
Decorators may also take arguments in addition to the function to be wrapped:
|
||||
Decorators are _expressions_, just like in Python, so to make a decorator with arguments create a function that takes those arguments and returns a decorator:
|
||||
|
||||
```py
|
||||
def requirePassword(func, password):
|
||||
print "I am wrapping", func, "and attaching",password
|
||||
def wrapper(secretPassword):
|
||||
if secretPassword != password:
|
||||
print "You didn't say the magic word."
|
||||
return
|
||||
func()
|
||||
return wrapper
|
||||
def requirePassword(password):
|
||||
print "I am creating a decorator."
|
||||
def decorator(func):
|
||||
print "I am wrapping", func, "and attaching",password
|
||||
def wrapper(secretPassword):
|
||||
if secretPassword != password:
|
||||
print "You didn't say the magic word."
|
||||
return
|
||||
func()
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
@requirePassword("hunter2")
|
||||
def superSecretFunction():
|
||||
@ -667,8 +670,6 @@ superSecretFunction("hunter2")
|
||||
# Welcome!
|
||||
```
|
||||
|
||||
_**NOTE:** Arguments in decorators work differently from Python: In Python, decorators with arguments are functions which return a new decorator and _that_ decorator is applied to the wrapped function; in Kuroko, decorators with arguments are no different from those with out - the additional arguments are appended after the passed function._
|
||||
|
||||
## About the REPL
|
||||
|
||||
Kuroko's repl provides an interactive environment for executing code and seeing results.
|
||||
|
24
compiler.c
24
compiler.c
@ -802,20 +802,8 @@ static KrkToken decorator(size_t level, FunctionType type) {
|
||||
size_t blockWidth = (parser.previous.type == TOKEN_INDENTATION) ? parser.previous.length : 0;
|
||||
advance(); /* Collect the `@` */
|
||||
|
||||
beginScope();
|
||||
|
||||
/* Collect an identifier */
|
||||
consume(TOKEN_IDENTIFIER,"Expected a decorator name.");
|
||||
variable(0);
|
||||
size_t outputLocal = current->localCount;
|
||||
|
||||
emitByte(OP_NONE); /* Space for the function */
|
||||
|
||||
/* See if we have an argument list */
|
||||
size_t argCount = 0;
|
||||
if (match(TOKEN_LEFT_PAREN)) {
|
||||
argCount = argumentList();
|
||||
}
|
||||
expression();
|
||||
|
||||
consume(TOKEN_EOL, "Expected line feed after decorator.");
|
||||
if (blockWidth) {
|
||||
@ -839,15 +827,7 @@ static KrkToken decorator(size_t level, FunctionType type) {
|
||||
error("Expected a function declaration or another decorator.");
|
||||
}
|
||||
|
||||
/* As a 'declaration' syntax element, we can always guarantee by the time we
|
||||
* get to this point, we are at the current local level. */
|
||||
size_t argumentDestination = (type == TYPE_FUNCTION) ? (outputLocal + 1) : (outputLocal + 2);
|
||||
EMIT_CONSTANT_OP(OP_SET_LOCAL, argumentDestination);
|
||||
endScope();
|
||||
|
||||
emitByte(OP_POP);
|
||||
|
||||
emitBytes(OP_CALL, 1 + argCount);
|
||||
emitBytes(OP_CALL, 1);
|
||||
|
||||
if (level == 0) {
|
||||
if (type == TYPE_FUNCTION) {
|
||||
|
@ -72,12 +72,14 @@ print "Returned from f.undecorated()"
|
||||
f.decorated("butts")
|
||||
print "Returned from f.decorated()"
|
||||
|
||||
def decoratorWithArgument(func, decoratorArg):
|
||||
print "I am decorating",func,"with this argument:",decoratorArg
|
||||
def wrapped():
|
||||
print "This wrapper captured this decorator arg:", decoratorArg
|
||||
func()
|
||||
return wrapped
|
||||
def decoratorWithArgument(decoratorArg):
|
||||
def theActualDecorator(func):
|
||||
print "I am decorating",func,"with this argument:",decoratorArg
|
||||
def wrapped():
|
||||
print "This wrapper captured this decorator arg:", decoratorArg
|
||||
func()
|
||||
return wrapped
|
||||
return theActualDecorator
|
||||
|
||||
@decoratorWithArgument("foo")
|
||||
def decoratedWithArgument():
|
||||
@ -85,13 +87,15 @@ def decoratedWithArgument():
|
||||
|
||||
decoratedWithArgument()
|
||||
|
||||
def methodDecoratorWithArguments(method, decoratorArgA, decoratorArgB):
|
||||
print "I am decorating", method, "with these args:", decoratorArgA, decoratorArgB
|
||||
def wrapped(instance, wrapperArg):
|
||||
print "I captured these from the decorator:", decoratorArgA, decoratorArgB
|
||||
print "I also take my own argument:", wrapperArg
|
||||
method(instance,"and modify this one")
|
||||
return wrapped
|
||||
def methodDecoratorWithArguments(decoratorArgA, decoratorArgB):
|
||||
def theActualDecorator(method):
|
||||
print "I am decorating", method, "with these args:", decoratorArgA, decoratorArgB
|
||||
def wrapped(instance, wrapperArg):
|
||||
print "I captured these from the decorator:", decoratorArgA, decoratorArgB
|
||||
print "I also take my own argument:", wrapperArg
|
||||
method(instance,"and modify this one")
|
||||
return wrapped
|
||||
return theActualDecorator
|
||||
|
||||
class Bar():
|
||||
@methodDecoratorWithArguments("foo","bar")
|
||||
|
Loading…
Reference in New Issue
Block a user