New '__options__' psuedo-module with compile-time changes
This commit is contained in:
parent
b2846c13ce
commit
cdcfb63f41
@ -221,8 +221,12 @@ typedef struct Compiler {
|
|||||||
size_t annotationCount; /**< Number of type annotations found while compiling function signature. */
|
size_t annotationCount; /**< Number of type annotations found while compiling function signature. */
|
||||||
|
|
||||||
int delSatisfied; /**< Flag indicating if a 'del' target has been completed. */
|
int delSatisfied; /**< Flag indicating if a 'del' target has been completed. */
|
||||||
|
|
||||||
|
size_t optionsFlags; /**< Special __options__ imports; similar to __future__ in Python */
|
||||||
} Compiler;
|
} Compiler;
|
||||||
|
|
||||||
|
#define OPTIONS_FLAG_COMPILE_TIME_BUILTINS (1 << 0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Class compilation context.
|
* @brief Class compilation context.
|
||||||
*
|
*
|
||||||
@ -346,6 +350,7 @@ static void initCompiler(Compiler * compiler, FunctionType type) {
|
|||||||
compiler->properties = NULL;
|
compiler->properties = NULL;
|
||||||
compiler->annotationCount = 0;
|
compiler->annotationCount = 0;
|
||||||
compiler->delSatisfied = 0;
|
compiler->delSatisfied = 0;
|
||||||
|
compiler->optionsFlags = compiler->enclosing ? compiler->enclosing->optionsFlags : 0;
|
||||||
|
|
||||||
if (type != TYPE_MODULE) {
|
if (type != TYPE_MODULE) {
|
||||||
current->codeobject->name = krk_copyString(parser.previous.start, parser.previous.length);
|
current->codeobject->name = krk_copyString(parser.previous.start, parser.previous.length);
|
||||||
@ -662,6 +667,15 @@ static ssize_t parseVariable(const char * errorMessage) {
|
|||||||
declareVariable();
|
declareVariable();
|
||||||
if (current->scopeDepth > 0) return 0;
|
if (current->scopeDepth > 0) return 0;
|
||||||
|
|
||||||
|
if ((current->optionsFlags & OPTIONS_FLAG_COMPILE_TIME_BUILTINS) && *parser.previous.start != '_') {
|
||||||
|
KrkValue value;
|
||||||
|
if (krk_tableGet_fast(&vm.builtins->fields, krk_copyString(parser.previous.start, parser.previous.length), &value)) {
|
||||||
|
error("Conflicting declaration of global '%.*s' is invalid when 'compile_time_builtins' is enabled.",
|
||||||
|
(int)parser.previous.length, parser.previous.start);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return identifierConstant(&parser.previous);
|
return identifierConstant(&parser.previous);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2260,11 +2274,56 @@ static void importStatement(void) {
|
|||||||
} while (match(TOKEN_COMMA));
|
} while (match(TOKEN_COMMA));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void optionsImport(void) {
|
||||||
|
int expectCloseParen = 0;
|
||||||
|
|
||||||
|
KrkToken compile_time_builtins = syntheticToken("compile_time_builtins");
|
||||||
|
|
||||||
|
advance();
|
||||||
|
consume(TOKEN_IMPORT, "__options__ is not a package\n");
|
||||||
|
|
||||||
|
if (match(TOKEN_LEFT_PAREN)) {
|
||||||
|
expectCloseParen = 1;
|
||||||
|
startEatingWhitespace();
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
consume(TOKEN_IDENTIFIER, "Expected member name");
|
||||||
|
|
||||||
|
/* Okay, what is it? */
|
||||||
|
if (identifiersEqual(&parser.previous, &compile_time_builtins)) {
|
||||||
|
current->optionsFlags |= OPTIONS_FLAG_COMPILE_TIME_BUILTINS;
|
||||||
|
} else {
|
||||||
|
error("'%.*s' is not a recognized __options__ import",
|
||||||
|
(int)parser.previous.length, parser.previous.start);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check(TOKEN_AS)) {
|
||||||
|
errorAtCurrent("__options__ imports can not be given names");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_PAREN));
|
||||||
|
|
||||||
|
if (expectCloseParen) {
|
||||||
|
stopEatingWhitespace();
|
||||||
|
consume(TOKEN_RIGHT_PAREN, "Expected ')' after import list started with '('");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void fromImportStatement(void) {
|
static void fromImportStatement(void) {
|
||||||
int expectCloseParen = 0;
|
int expectCloseParen = 0;
|
||||||
KrkToken startOfName = {0};
|
KrkToken startOfName = {0};
|
||||||
int leadingDots = 0;
|
int leadingDots = 0;
|
||||||
|
|
||||||
|
KrkToken options = syntheticToken("__options__");
|
||||||
|
if (check(TOKEN_IDENTIFIER) && identifiersEqual(&parser.current, &options)) {
|
||||||
|
/* from __options__ import ... */
|
||||||
|
optionsImport();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (match(TOKEN_DOT)) {
|
while (match(TOKEN_DOT)) {
|
||||||
leadingDots++;
|
leadingDots++;
|
||||||
}
|
}
|
||||||
@ -2769,6 +2828,23 @@ static void namedVariable(KrkToken name, int exprType) {
|
|||||||
} else if ((arg = resolveUpvalue(current, &name)) != -1) {
|
} else if ((arg = resolveUpvalue(current, &name)) != -1) {
|
||||||
DO_VARIABLE(OP_SET_UPVALUE, OP_GET_UPVALUE, OP_NONE);
|
DO_VARIABLE(OP_SET_UPVALUE, OP_GET_UPVALUE, OP_NONE);
|
||||||
} else {
|
} else {
|
||||||
|
if ((current->optionsFlags & OPTIONS_FLAG_COMPILE_TIME_BUILTINS) && *name.start != '_') {
|
||||||
|
KrkValue value;
|
||||||
|
if (krk_tableGet_fast(&vm.builtins->fields, krk_copyString(name.start, name.length), &value)) {
|
||||||
|
if ((exprType == EXPR_ASSIGN_TARGET && matchComplexEnd()) ||
|
||||||
|
(exprType == EXPR_CAN_ASSIGN && match(TOKEN_EQUAL)) ||
|
||||||
|
(exprType == EXPR_CAN_ASSIGN && matchAssignment())) {
|
||||||
|
error("Can not assign to '%.*s' when 'compile_time_builtins' is enabled.",
|
||||||
|
(int)name.length, name.start);
|
||||||
|
} else if (exprType == EXPR_DEL_TARGET && checkEndOfDel()) {
|
||||||
|
error("Can not delete '%.*s' when 'compile_time_builtins' is enabled.",
|
||||||
|
(int)name.length, name.start);
|
||||||
|
} else {
|
||||||
|
emitConstant(value);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
arg = identifierConstant(&name);
|
arg = identifierConstant(&name);
|
||||||
DO_VARIABLE(OP_SET_GLOBAL, OP_GET_GLOBAL, OP_DEL_GLOBAL);
|
DO_VARIABLE(OP_SET_GLOBAL, OP_GET_GLOBAL, OP_DEL_GLOBAL);
|
||||||
}
|
}
|
||||||
|
5
test/testOptionsCompileTimeBuiltins.krk
Normal file
5
test/testOptionsCompileTimeBuiltins.krk
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from __options__ import compile_time_builtins
|
||||||
|
|
||||||
|
print('hello world')
|
||||||
|
|
||||||
|
print(sum(abs(x) for x in range(-4,4)))
|
2
test/testOptionsCompileTimeBuiltins.krk.expect
Normal file
2
test/testOptionsCompileTimeBuiltins.krk.expect
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
hello world
|
||||||
|
16
|
Loading…
Reference in New Issue
Block a user