shove list comprehensions into their own fake call frames because everything is terrible

This commit is contained in:
K. Lange 2020-12-30 22:30:09 +09:00
parent bb7e49add7
commit 0b2c9df58f
5 changed files with 47 additions and 0 deletions

View File

@ -73,6 +73,7 @@ typedef enum {
OP_IMPORT_LONG,
OP_GET_SUPER_LONG,
OP_INC_LONG,
OP_INLINE_FUNCTION,
} KrkOpCode;
/**

View File

@ -119,6 +119,20 @@ static void initCompiler(Compiler * compiler, FunctionType type) {
}
}
static void initSubcompiler(Compiler * compiler) {
compiler->enclosing = current;
current = compiler;
compiler->function = compiler->enclosing->function;
compiler->type = compiler->enclosing->type;
compiler->localCount = 0;
compiler->scopeDepth = 1;
compiler->localsSpace = 8;
compiler->localsSpace = 8;
compiler->locals = GROW_ARRAY(Local,NULL,0,8);
compiler->upvaluesSpace = 0;
compiler->upvalues = NULL;
}
static void parsePrecedence(Precedence precedence);
static ssize_t parseVariable(const char * errorMessage);
static void variable(int canAssign);
@ -262,6 +276,10 @@ static KrkFunction * endCompiler() {
return function;
}
static void endSubcompiler() {
current = current->enclosing;
}
static void freeCompiler(Compiler * compiler) {
FREE_ARRAY(Local,compiler->locals, compiler->localsSpace);
FREE_ARRAY(Upvalue,compiler->upvalues, compiler->upvaluesSpace);
@ -1125,6 +1143,10 @@ static void super_(int canAssign) {
}
static void list(int canAssign) {
Compiler subcompiler;
emitByte(OP_INLINE_FUNCTION);
initSubcompiler(&subcompiler);
KrkToken listOf = syntheticToken("listOf");
size_t ind = identifierConstant(&listOf);
EMIT_CONSTANT_OP(OP_GET_GLOBAL, ind);
@ -1273,6 +1295,9 @@ static void list(int canAssign) {
advance();
emitBytes(OP_CALL, 0);
}
emitByte(OP_RETURN);
endSubcompiler();
freeCompiler(&subcompiler);
}
static void dict(int canAssign) {

View File

@ -2,3 +2,10 @@
for i in [x * 5 for x in [1,7,3,5,9,2,8]]:
print i
def sum(iterable):
let total = 0
for v in iterable:
total = total + v
return total
print sum([x * 3 for x in [y * 7 for y in [1,2,3,4,5]]])

13
vm.c
View File

@ -420,6 +420,7 @@ static int call(KrkClosure * closure, int argCount) {
return 0;
}
CallFrame * frame = &vm.frames[vm.frameCount++];
frame->isInlined = 0;
frame->closure = closure;
frame->ip = closure->function->chunk.code;
frame->slots = (vm.stackTop - argCount - 1) - vm.stack;
@ -933,6 +934,9 @@ static KrkValue run() {
KrkValue result = krk_pop();
closeUpvalues(frame->slots);
vm.frameCount--;
if (frame->isInlined) {
vm.frames[vm.frameCount - 1].ip = frame->ip;
}
if (vm.frameCount == 0) {
krk_pop();
return result;
@ -1143,6 +1147,15 @@ static KrkValue run() {
krk_tableAddAll(&vm.object_class->methods, &_class->methods);
break;
}
case OP_INLINE_FUNCTION: {
CallFrame * newFrame = &vm.frames[vm.frameCount++];
newFrame->isInlined = 1;
newFrame->closure = frame->closure;
newFrame->ip = frame->ip;
newFrame->slots = vm.stackTop - vm.stack;
frame = newFrame;
break;
}
case OP_GET_PROPERTY_LONG:
case OP_GET_PROPERTY: {
KrkString * name = READ_STRING(operandWidth);

1
vm.h
View File

@ -13,6 +13,7 @@ typedef struct {
KrkClosure * closure;
uint8_t * ip;
size_t slots;
int isInlined;
} CallFrame;
typedef enum {