Support unpacking tuples in for ... in ... loops.
This commit is contained in:
parent
8f9c1a4c1d
commit
fc05327c42
2
chunk.h
2
chunk.h
@ -71,6 +71,7 @@ typedef enum {
|
||||
OP_EXPAND_ARGS,
|
||||
OP_FINALIZE,
|
||||
OP_TUPLE,
|
||||
OP_UNPACK_TUPLE,
|
||||
|
||||
OP_CONSTANT_LONG = 128,
|
||||
OP_DEFINE_GLOBAL_LONG,
|
||||
@ -91,6 +92,7 @@ typedef enum {
|
||||
OP_INC_LONG,
|
||||
OP_KWARGS_LONG,
|
||||
OP_TUPLE_LONG,
|
||||
OP_UNPACK_TUPLE_LONG,
|
||||
} KrkOpCode;
|
||||
|
||||
typedef struct {
|
||||
|
28
compiler.c
28
compiler.c
@ -1174,7 +1174,11 @@ static void forStatement() {
|
||||
beginScope();
|
||||
|
||||
ssize_t loopInd = current->localCount;
|
||||
varDeclaration();
|
||||
ssize_t varCount = 0;
|
||||
do {
|
||||
varDeclaration();
|
||||
varCount++;
|
||||
} while (match(TOKEN_COMMA));
|
||||
|
||||
int loopStart;
|
||||
int exitJump;
|
||||
@ -1212,17 +1216,27 @@ static void forStatement() {
|
||||
|
||||
/* Get the loop iterator again */
|
||||
EMIT_CONSTANT_OP(OP_GET_LOCAL, indLoopIter);
|
||||
emitBytes(OP_EQUAL, OP_NOT);
|
||||
exitJump = emitJump(OP_JUMP_IF_FALSE);
|
||||
emitByte(OP_EQUAL);
|
||||
exitJump = emitJump(OP_JUMP_IF_TRUE);
|
||||
emitByte(OP_POP);
|
||||
|
||||
if (varCount > 1) {
|
||||
EMIT_CONSTANT_OP(OP_GET_LOCAL, loopInd);
|
||||
EMIT_CONSTANT_OP(OP_UNPACK_TUPLE, varCount);
|
||||
for (ssize_t i = loopInd + varCount - 1; i >= loopInd; i--) {
|
||||
EMIT_CONSTANT_OP(OP_SET_LOCAL, i);
|
||||
emitByte(OP_POP);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
consume(TOKEN_SEMICOLON,"expect ; after var declaration in for loop");
|
||||
loopStart = currentChunk()->count;
|
||||
|
||||
|
||||
beginScope();
|
||||
expression(); /* condition */
|
||||
do {
|
||||
expression(); /* condition */
|
||||
} while (match(TOKEN_COMMA));
|
||||
endScope();
|
||||
exitJump = emitJump(OP_JUMP_IF_FALSE);
|
||||
emitByte(OP_POP);
|
||||
@ -1232,7 +1246,9 @@ static void forStatement() {
|
||||
int bodyJump = emitJump(OP_JUMP);
|
||||
int incrementStart = currentChunk()->count;
|
||||
beginScope();
|
||||
expression();
|
||||
do {
|
||||
expression();
|
||||
} while (match(TOKEN_COMMA));
|
||||
endScope();
|
||||
emitByte(OP_POP);
|
||||
|
||||
|
1
debug.c
1
debug.c
@ -140,6 +140,7 @@ size_t krk_disassembleInstruction(FILE * f, KrkFunction * func, size_t offset) {
|
||||
OPERAND(OP_CALL, (void)0)
|
||||
OPERAND(OP_INC, (void)0)
|
||||
OPERAND(OP_TUPLE, (void)0)
|
||||
OPERAND(OP_UNPACK_TUPLE, (void)0)
|
||||
JUMP(OP_JUMP,+)
|
||||
JUMP(OP_JUMP_IF_FALSE,+)
|
||||
JUMP(OP_JUMP_IF_TRUE,+)
|
||||
|
31
test/testUnpackIter.krk
Normal file
31
test/testUnpackIter.krk
Normal file
@ -0,0 +1,31 @@
|
||||
for k,v in [(1,2),(3,4),(5,6)]:
|
||||
print(k,v)
|
||||
# 1 2
|
||||
# 3 4
|
||||
# 5 6
|
||||
|
||||
try:
|
||||
for k,v,z in [(1,2,7),(3,4,8),(5,6)]:
|
||||
print(k,v,z)
|
||||
except:
|
||||
print(exception.__class__.__name__)
|
||||
# 1 2 7
|
||||
# 3 4 8
|
||||
# ValueError
|
||||
|
||||
try:
|
||||
for k,v in [1,2,3]:
|
||||
print("type error")
|
||||
except:
|
||||
print(exception.__class__.__name__)
|
||||
# TypeError
|
||||
|
||||
for k, v in {'a': 1, 2: 'b'}.items():
|
||||
print(k,v)
|
||||
# a 1
|
||||
# 2 b
|
||||
|
||||
for i in {'a': 1, 2: 'b'}.items():
|
||||
print(i)
|
||||
# ('a', 1)
|
||||
# (2, 'b')
|
11
test/testUnpackIter.krk.expect
Normal file
11
test/testUnpackIter.krk.expect
Normal file
@ -0,0 +1,11 @@
|
||||
1 2
|
||||
3 4
|
||||
5 6
|
||||
1 2 7
|
||||
3 4 8
|
||||
ValueError
|
||||
TypeError
|
||||
a 1
|
||||
2 b
|
||||
('a', 1)
|
||||
(2, 'b')
|
18
vm.c
18
vm.c
@ -3559,6 +3559,24 @@ static KrkValue run() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_UNPACK_TUPLE_LONG:
|
||||
case OP_UNPACK_TUPLE: {
|
||||
size_t count = readBytes(frame, operandWidth);
|
||||
KrkValue tuple = krk_peek(0);
|
||||
if (!IS_TUPLE(tuple)) {
|
||||
krk_runtimeError(vm.exceptions.typeError, "Can not unpack non-tuple '%s'", krk_typeName(tuple));
|
||||
goto _finishException;
|
||||
} else if (AS_TUPLE(tuple)->values.count != count) {
|
||||
krk_runtimeError(vm.exceptions.valueError, "Wrong number of values to unpack (wanted %d, got %d)", (int)count, (int)AS_TUPLE(tuple)->values.count);
|
||||
goto _finishException;
|
||||
}
|
||||
/* Unpack from 1 to end, then unpack 0 into bottom slot */
|
||||
for (size_t i = 1; i < AS_TUPLE(tuple)->values.count; ++i) {
|
||||
krk_push(AS_TUPLE(tuple)->values.values[i]);
|
||||
}
|
||||
vm.stackTop[-count] = AS_TUPLE(tuple)->values.values[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!(vm.flags & KRK_HAS_EXCEPTION)) continue;
|
||||
_finishException:
|
||||
|
Loading…
Reference in New Issue
Block a user