Add class and module member annotations
This commit is contained in:
parent
b243aabc82
commit
9ea28e77f1
@ -137,6 +137,7 @@ typedef struct Compiler {
|
||||
typedef struct ClassCompiler {
|
||||
struct ClassCompiler * enclosing;
|
||||
KrkToken name;
|
||||
int hasAnnotations;
|
||||
} ClassCompiler;
|
||||
|
||||
static Parser parser;
|
||||
@ -739,8 +740,23 @@ static void letDeclaration(void) {
|
||||
if (current->scopeDepth > 0) {
|
||||
/* Need locals space */
|
||||
args[argCount++] = current->localCount - 1;
|
||||
if (match(TOKEN_COLON)) {
|
||||
error("Annotation on scoped variable declaration is meaningless.");
|
||||
goto _letDone;
|
||||
}
|
||||
} else {
|
||||
args[argCount++] = ind;
|
||||
if (check(TOKEN_COLON)) {
|
||||
KrkToken name = parser.previous;
|
||||
match(TOKEN_COLON);
|
||||
/* Get __annotations__ from globals */
|
||||
KrkToken annotations = syntheticToken("__annotations__");
|
||||
size_t ind = identifierConstant(&annotations);
|
||||
EMIT_CONSTANT_OP(OP_GET_GLOBAL, ind);
|
||||
emitConstant(OBJECT_VAL(krk_copyString(name.start, name.length)));
|
||||
parsePrecedence(PREC_TERNARY);
|
||||
emitBytes(OP_INVOKE_SETTER, OP_POP);
|
||||
}
|
||||
}
|
||||
} while (match(TOKEN_COMMA));
|
||||
|
||||
@ -1094,6 +1110,24 @@ static void method(size_t blockWidth) {
|
||||
decorator(0, TYPE_METHOD);
|
||||
} else if (match(TOKEN_IDENTIFIER)) {
|
||||
size_t ind = identifierConstant(&parser.previous);
|
||||
if (check(TOKEN_COLON)) {
|
||||
KrkToken name = parser.previous;
|
||||
match(TOKEN_COLON);
|
||||
/* Get __annotations__ from class */
|
||||
emitBytes(OP_DUP, 0);
|
||||
KrkToken annotations = syntheticToken("__annotations__");
|
||||
size_t ind = identifierConstant(&annotations);
|
||||
if (!currentClass->hasAnnotations) {
|
||||
EMIT_CONSTANT_OP(OP_MAKE_DICT, 0);
|
||||
EMIT_CONSTANT_OP(OP_SET_PROPERTY, ind);
|
||||
currentClass->hasAnnotations = 1;
|
||||
} else {
|
||||
EMIT_CONSTANT_OP(OP_GET_PROPERTY, ind);
|
||||
}
|
||||
emitConstant(OBJECT_VAL(krk_copyString(name.start, name.length)));
|
||||
parsePrecedence(PREC_TERNARY);
|
||||
emitBytes(OP_INVOKE_SETTER, OP_POP);
|
||||
}
|
||||
consume(TOKEN_EQUAL, "Class field must have value.");
|
||||
expression();
|
||||
rememberClassProperty(ind);
|
||||
@ -1156,6 +1190,7 @@ static KrkToken classDeclaration() {
|
||||
classCompiler.enclosing = currentClass;
|
||||
currentClass = &classCompiler;
|
||||
int hasSuperclass = 0;
|
||||
classCompiler.hasAnnotations = 0;
|
||||
|
||||
if (match(TOKEN_LEFT_PAREN)) {
|
||||
startEatingWhitespace();
|
||||
@ -1177,13 +1212,10 @@ static KrkToken classDeclaration() {
|
||||
addLocal(syntheticToken("super"));
|
||||
defineVariable(0);
|
||||
|
||||
if (hasSuperclass) {
|
||||
namedVariable(className, 0);
|
||||
emitByte(OP_INHERIT);
|
||||
}
|
||||
|
||||
namedVariable(className, 0);
|
||||
|
||||
emitByte(OP_INHERIT);
|
||||
|
||||
consume(TOKEN_COLON, "Expected colon after class");
|
||||
|
||||
/* Set Class.__module__ to the value of __name__, which is the string
|
||||
|
13
src/vm.c
13
src/vm.c
@ -2157,7 +2157,6 @@ _resumeHook: (void)0;
|
||||
subclass->allocSize = AS_CLASS(superclass)->allocSize;
|
||||
subclass->_ongcsweep = AS_CLASS(superclass)->_ongcsweep;
|
||||
subclass->_ongcscan = AS_CLASS(superclass)->_ongcscan;
|
||||
krk_pop();
|
||||
break;
|
||||
}
|
||||
case OP_DOCSTRING: {
|
||||
@ -2204,12 +2203,17 @@ _resumeHook: (void)0;
|
||||
return result;
|
||||
}
|
||||
case OP_ANNOTATE: {
|
||||
if (!IS_CLOSURE(krk_peek(0))) {
|
||||
if (IS_CLOSURE(krk_peek(0))) {
|
||||
krk_swap(1);
|
||||
AS_CLOSURE(krk_peek(1))->annotations = krk_pop();
|
||||
} else if (IS_NONE(krk_peek(0))) {
|
||||
krk_swap(1);
|
||||
fprintf(stderr, "TODO: Global annotation.\n");
|
||||
krk_pop();
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions->typeError, "Can not annotate '%s'.", krk_typeName(krk_peek(0)));
|
||||
goto _finishException;
|
||||
}
|
||||
krk_swap(1);
|
||||
AS_CLOSURE(krk_peek(1))->annotations = krk_pop();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2626,6 +2630,7 @@ KrkInstance * krk_startModule(const char * name) {
|
||||
krk_attachNamedObject(&vm.modules, name, (KrkObj*)module);
|
||||
krk_attachNamedObject(&module->fields, "__builtins__", (KrkObj*)vm.builtins);
|
||||
krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)krk_copyString(name,strlen(name)));
|
||||
krk_attachNamedValue(&module->fields, "__annotations__", krk_dict_of(0,NULL,0));
|
||||
return module;
|
||||
}
|
||||
|
||||
|
10
test/testClassAnnotation.krk
Normal file
10
test/testClassAnnotation.krk
Normal file
@ -0,0 +1,10 @@
|
||||
class Foo(object):
|
||||
a:int = 42
|
||||
b:float = 96.8
|
||||
s:str = "test"
|
||||
def method(self, foo: type(a)) -> type(a):
|
||||
return self.a + foo
|
||||
d:bool = False
|
||||
|
||||
print(Foo.__annotations__)
|
||||
print(Foo().method(42))
|
2
test/testClassAnnotation.krk.expect
Normal file
2
test/testClassAnnotation.krk.expect
Normal file
@ -0,0 +1,2 @@
|
||||
{'a': <class 'int'>, 'b': <class 'float'>, 's': <class 'str'>, 'd': <class 'bool'>}
|
||||
84
|
Loading…
Reference in New Issue
Block a user