34 #include <sys/types.h>
46 #include "opcode_enum.h"
103 EXPR_CLASS_PARAMETERS,
230 #define OPTIONS_FLAG_COMPILE_TIME_BUILTINS (1 << 0)
231 #define OPTIONS_FLAG_NO_IMPLICIT_SELF (1 << 1)
284 static void _GlobalState_gcscan(
KrkInstance * _self) {
286 Compiler * compiler =
self->current;
287 while (compiler != NULL) {
294 static void _GlobalState_gcsweep(
KrkInstance * _self) {
298 #define currentChunk() (&state->current->codeobject->chunk)
300 #define EMIT_OPERAND_OP(opc, arg) do { if (arg < 256) { emitBytes(opc, arg); } \
301 else { emitBytes(opc ## _LONG, arg >> 16); emitBytes(arg >> 8, arg); } } while (0)
303 static int isMethod(
int type) {
307 static int isCoroutine(
int type) {
311 static char * calculateQualName(
struct GlobalState * state) {
312 static char space[1024];
314 char * writer = &space[1023];
316 #define WRITE(s) do { \
317 size_t len = strlen(s); \
318 if (writer - len < space) goto _exit; \
320 memcpy(writer, s, len); \
340 #define codeobject_from_chunk_pointer(ptr) ((KrkCodeObject*)((char *)(ptr) - offsetof(KrkCodeObject, chunk)))
342 return (
ChunkRecorder){in->count, in->linesCount, in->constants.
count, codeobject_from_chunk_pointer(in)->expressionsCount};
346 out->count = from.
count;
347 out->linesCount = from.
lines;
349 codeobject_from_chunk_pointer(out)->expressionsCount = from.
expressions;
351 #undef codeobject_from_chunk_pointer
359 compiler->
type = type;
384 char * qualname = calculateQualName(state);
388 if (isMethod(type) && !(compiler->
optionsFlags & OPTIONS_FLAG_NO_IMPLICIT_SELF)) {
392 local->
name.start =
"self";
393 local->
name.length = 4;
394 renameLocal(state, 0, local->
name);
403 local->
name.start =
"";
404 local->
name.length = 0;
405 renameLocal(state, 0, local->
name);
413 static void rememberClassProperty(
struct GlobalState * state,
size_t ind) {
421 static ParseRule * getRule(KrkTokenType type);
424 static void defDeclaration(
struct GlobalState * state);
425 static void asyncDeclaration(
struct GlobalState * state,
int);
427 static void declaration(
struct GlobalState * state);
429 static void declareVariable(
struct GlobalState * state);
433 static void complexAssignmentTargets(
struct GlobalState * state,
KrkScanner oldScanner,
Parser oldParser,
size_t targetCount,
int parenthesized,
size_t argBefore,
size_t argAfter);
434 static int invalidTarget(
struct GlobalState * state,
int exprType,
const char * description);
438 if (!token->linePtr) token->linePtr = token->start;
440 while (token->linePtr[i] && token->linePtr[i] !=
'\n') i++;
459 #ifdef KRK_NO_DOCUMENTATION
460 # define raiseSyntaxError(token, ...) do { if (state->parser.hadError) break; krk_runtimeError(vm.exceptions->syntaxError, "syntax error"); finishError(state,token); } while (0)
462 # define raiseSyntaxError(token, ...) do { if (state->parser.hadError) break; krk_runtimeError(vm.exceptions->syntaxError, __VA_ARGS__); finishError(state,token); } while (0)
465 #define error(...) raiseSyntaxError(&state->parser.previous, __VA_ARGS__)
466 #define errorAtCurrent(...) raiseSyntaxError(&state->parser.current, __VA_ARGS__)
485 #define advance() _advance(state)
487 static void _skipToEnd(
struct GlobalState * state) {
491 #define skipToEnd() _skipToEnd(state)
493 static void _startEatingWhitespace(
struct GlobalState * state) {
498 #define startEatingWhitespace() _startEatingWhitespace(state)
500 static void _stopEatingWhitespace(
struct GlobalState * state) {
502 error(
"Internal scanner error: Invalid nesting of `startEatingWhitespace`/`stopEatingWhitespace` calls.");
507 #define stopEatingWhitespace() _stopEatingWhitespace(state)
509 static void _consume(
struct GlobalState * state, KrkTokenType type,
const char * message) {
518 errorAtCurrent(
"%s", message);
521 #define consume(...) _consume(state,__VA_ARGS__)
523 static int _check(
struct GlobalState * state, KrkTokenType type) {
527 #define check(t) _check(state,t)
529 static int _match(
struct GlobalState * state, KrkTokenType type) {
530 if (!check(type))
return 0;
535 #define match(t) _match(state,t)
538 return (a->length == b->length && memcmp(a->start, b->start, a->length) == 0);
544 token.length = (int)strlen(text);
549 #define syntheticToken(t) _syntheticToken(state,t)
551 static void _emitByte(
struct GlobalState * state, uint8_t
byte) {
555 #define emitByte(b) _emitByte(state,b)
557 static void _emitBytes(
struct GlobalState * state, uint8_t byte1, uint8_t byte2) {
562 #define emitBytes(a,b) _emitBytes(state,a,b)
564 static void emitReturn(
struct GlobalState * state) {
574 for (
size_t i = 0; i <
function->localNameCount; i++) {
575 if (function->localNames[i].deathday == 0) {
579 function->localNames = KRK_GROW_ARRAY(
KrkLocalEntry, function->localNames,
587 function->chunk.lines = KRK_GROW_ARRAY(
KrkLineMap, function->chunk.lines,
588 function->chunk.linesCapacity, function->chunk.linesCount);
589 function->chunk.linesCapacity =
function->chunk.linesCount;
590 function->chunk.code = KRK_GROW_ARRAY(uint8_t, function->chunk.code,
591 function->chunk.capacity, function->chunk.count);
592 function->chunk.capacity =
function->chunk.count;
595 function->expressionsCapacity, function->expressionsCount);
596 function->expressionsCapacity =
function->expressionsCount;
599 for (
int i = 0; i <
function->potentialPositionals; ++i) {
600 if (i < state->current->unnamedArgs) {
610 size_t args =
function->potentialPositionals;
611 if (function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_ARGS) {
620 for (
int i = 0; i <
function->keywordArgs; ++i) {
627 args +=
function->keywordArgs;
629 if (function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_KWS) {
638 function->totalArguments =
function->potentialPositionals +
function->keywordArgs + !!(
function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_ARGS) + !!(function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_KWS);
640 #if !defined(KRK_NO_DISASSEMBLY) && !defined(KRK_DISABLE_DEBUG)
650 static void freeCompiler(
Compiler * compiler) {
667 #define emitConstant(v) _emitConstant(state,v)
669 static int isMangleable(
const char * name,
size_t len) {
670 return (len > 2 && name[0] ==
'_' && name[1] ==
'_' && name[len-1] !=
'_' && (len < 4 || name[len-2] !=
'_'));
674 if (state->
currentClass && isMangleable(name->start, name->length)) {
678 while (classLength && *className ==
'_') {
684 krk_pushStringBuilderFormat(&sb,
"_%.*s%.*s",
685 (
int)classLength, className,
686 (
int)name->length, name->start);
699 for (ssize_t i = compiler->
localCount - 1; i >= 0; i--) {
701 if (identifiersEqual(name, &local->
name)) {
702 if (local->
depth == -1) {
703 error(
"Invalid recursive reference in declaration initializer");
705 if (local->
depth == -2) {
740 renameLocal(state, out, name);
746 static void declareVariable(
struct GlobalState * state) {
753 if (identifiersEqual(name, &local->
name)) {
754 error(
"Duplicate definition for local '%.*s' in this scope.", (
int)name->literalWidth, name->start);
757 addLocal(state, *name);
760 static ssize_t parseVariable(
struct GlobalState * state,
const char * errorMessage) {
761 consume(TOKEN_IDENTIFIER, errorMessage);
763 declareVariable(state);
769 error(
"Conflicting declaration of global '%.*s' is invalid when 'compile_time_builtins' is enabled.",
778 static void markInitialized(
struct GlobalState * state) {
783 static size_t anonymousLocal(
struct GlobalState * state) {
784 size_t val = addLocal(state, syntheticToken(
""));
785 markInitialized(state);
789 static void defineVariable(
struct GlobalState * state,
size_t global) {
791 markInitialized(state);
795 EMIT_OPERAND_OP(OP_DEFINE_GLOBAL, global);
800 invalidTarget(state, exprType,
"literal");
803 if (start[j] ==
'x' || start[j] ==
'X')
break;
804 if (start[j] ==
'.' || start[j] ==
'e' || start[j] ==
'E') {
808 error(
"no float support");
816 if (IS_NONE(result)) {
817 error(
"invalid numeric literal");
820 emitConstant(result);
823 static int _emitJump(
struct GlobalState * state, uint8_t opcode) {
825 emitBytes(0xFF, 0xFF);
826 return currentChunk()->count - 2;
828 #define emitJump(o) _emitJump(state,o)
841 static void _emitOverlongJump(
struct GlobalState * state,
int offset,
int jump) {
855 currentChunk()->code[offset-1] = OP_OVERLONG_JUMP;
861 static void _patchJump(
struct GlobalState * state,
int offset) {
862 int jump = currentChunk()->count - offset - 2;
865 _emitOverlongJump(state, offset, jump);
868 currentChunk()->code[offset] = (jump >> 8) & 0xFF;
869 currentChunk()->code[offset + 1] = (jump) & 0xFF;
872 #define patchJump(o) _patchJump(state,o)
892 #ifndef KRK_DISABLE_DEBUG
894 if (after->linePtr != before->linePtr)
return;
900 if (before->col > 255 || current->col > 255 ||
901 (current->col + current->literalWidth) > 255 ||
902 (after->col + after->literalWidth) > 255)
return;
905 before->col, current->col,
906 current->col + current->literalWidth,
907 after->col + after->literalWidth);
913 if (operatorType == TOKEN_NOT) consume(TOKEN_IN,
"'in' must follow infix 'not'");
914 int invert = (operatorType == TOKEN_IS && match(TOKEN_NOT));
918 ParseRule * rule = getRule(operatorType);
923 emitBytes(OP_DUP, 1);
926 switch (operatorType) {
927 case TOKEN_BANG_EQUAL: emitByte(OP_EQUAL); invert = 1;
break;
928 case TOKEN_EQUAL_EQUAL: emitByte(OP_EQUAL);
break;
929 case TOKEN_GREATER: emitByte(OP_GREATER);
break;
930 case TOKEN_GREATER_EQUAL: emitByte(OP_GREATER_EQUAL);
break;
931 case TOKEN_LESS: emitByte(OP_LESS);
break;
932 case TOKEN_LESS_EQUAL: emitByte(OP_LESS_EQUAL);
break;
934 case TOKEN_IS: emitByte(OP_IS);
break;
936 case TOKEN_IN: emitByte(OP_INVOKE_CONTAINS);
break;
937 case TOKEN_NOT: emitByte(OP_INVOKE_CONTAINS); invert = 1;
break;
939 default: error(
"Invalid binary comparison operator?");
break;
942 writeExpressionLocation(preceding, &state->
parser.
previous, &
this, state);
943 if (invert) emitByte(OP_NOT);
946 size_t exitJump = emitJump(OP_JUMP_IF_FALSE_OR_POP);
948 compareChained(state, 1, &next);
952 emitBytes(OP_SWAP,OP_POP);
963 invalidTarget(state, exprType,
"operator");
968 ParseRule * rule = getRule(operatorType);
971 invalidTarget(state, exprType,
"operator");
973 switch (operatorType) {
974 case TOKEN_PIPE: emitByte(OP_BITOR);
break;
975 case TOKEN_CARET: emitByte(OP_BITXOR);
break;
976 case TOKEN_AMPERSAND: emitByte(OP_BITAND);
break;
977 case TOKEN_LEFT_SHIFT: emitByte(OP_SHIFTLEFT);
break;
978 case TOKEN_RIGHT_SHIFT: emitByte(OP_SHIFTRIGHT);
break;
980 case TOKEN_PLUS: emitByte(OP_ADD);
break;
981 case TOKEN_MINUS: emitByte(OP_SUBTRACT);
break;
982 case TOKEN_ASTERISK: emitByte(OP_MULTIPLY);
break;
983 case TOKEN_POW: emitByte(OP_POW);
break;
984 case TOKEN_SOLIDUS: emitByte(OP_DIVIDE);
break;
985 case TOKEN_DOUBLE_SOLIDUS: emitByte(OP_FLOORDIV);
break;
986 case TOKEN_MODULO: emitByte(OP_MODULO);
break;
987 case TOKEN_IN: emitByte(OP_EQUAL);
break;
988 case TOKEN_AT: emitByte(OP_MATMUL);
break;
994 static int matchAssignment(
struct GlobalState * state) {
998 static int checkEndOfDel(
struct GlobalState * state) {
999 if (check(TOKEN_COMMA) || check(TOKEN_EOL) || check(TOKEN_EOF) || check(TOKEN_SEMICOLON)) {
1006 static int matchComplexEnd(
struct GlobalState * state) {
1007 return match(TOKEN_COMMA) ||
1008 match(TOKEN_EQUAL) ||
1009 match(TOKEN_RIGHT_PAREN);
1012 static int invalidTarget(
struct GlobalState * state,
int exprType,
const char * description) {
1014 error(
"Can not assign to %s", description);
1019 error(
"Can not delete %s", description);
1026 static void assignmentValue(
struct GlobalState * state) {
1029 if (type == TOKEN_PLUS_PLUS || type == TOKEN_MINUS_MINUS) {
1030 emitConstant(INTEGER_VAL(1));
1036 case TOKEN_PIPE_EQUAL: emitByte(OP_INPLACE_BITOR);
break;
1037 case TOKEN_CARET_EQUAL: emitByte(OP_INPLACE_BITXOR);
break;
1038 case TOKEN_AMP_EQUAL: emitByte(OP_INPLACE_BITAND);
break;
1039 case TOKEN_LSHIFT_EQUAL: emitByte(OP_INPLACE_SHIFTLEFT);
break;
1040 case TOKEN_RSHIFT_EQUAL: emitByte(OP_INPLACE_SHIFTRIGHT);
break;
1042 case TOKEN_PLUS_EQUAL: emitByte(OP_INPLACE_ADD);
break;
1043 case TOKEN_PLUS_PLUS: emitByte(OP_INPLACE_ADD);
break;
1044 case TOKEN_MINUS_EQUAL: emitByte(OP_INPLACE_SUBTRACT);
break;
1045 case TOKEN_MINUS_MINUS: emitByte(OP_INPLACE_SUBTRACT);
break;
1046 case TOKEN_ASTERISK_EQUAL: emitByte(OP_INPLACE_MULTIPLY);
break;
1047 case TOKEN_POW_EQUAL: emitByte(OP_INPLACE_POW);
break;
1048 case TOKEN_SOLIDUS_EQUAL: emitByte(OP_INPLACE_DIVIDE);
break;
1049 case TOKEN_DSOLIDUS_EQUAL: emitByte(OP_INPLACE_FLOORDIV);
break;
1050 case TOKEN_MODULO_EQUAL: emitByte(OP_INPLACE_MODULO);
break;
1051 case TOKEN_AT_EQUAL: emitByte(OP_INPLACE_MATMUL);
break;
1054 error(
"Unexpected operand in assignment");
1057 writeExpressionLocation(&left,&state->
parser.
previous,&left,state);
1060 static void expression(
struct GlobalState * state) {
1064 static void sliceExpression(
struct GlobalState * state) {
1066 if (match(TOKEN_COLON)) {
1072 if (isSlice || match(TOKEN_COLON)) {
1074 if (check(TOKEN_RIGHT_SQUARE) || check(TOKEN_COMMA)) {
1077 EMIT_OPERAND_OP(OP_SLICE, 2);
1079 if (check(TOKEN_COLON)) {
1086 if (match(TOKEN_COLON) && !check(TOKEN_RIGHT_SQUARE) && !check(TOKEN_COMMA)) {
1089 EMIT_OPERAND_OP(OP_SLICE, 3);
1092 EMIT_OPERAND_OP(OP_SLICE, 2);
1103 sliceExpression(state);
1105 if (match(TOKEN_COMMA)) {
1106 size_t argCount = 1;
1107 if (!check(TOKEN_RIGHT_SQUARE)) {
1109 sliceExpression(state);
1111 }
while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_SQUARE));
1113 EMIT_OPERAND_OP(OP_TUPLE, argCount);
1116 consume(TOKEN_RIGHT_SQUARE,
"Expected ']' after index.");
1118 if (matchComplexEnd(state)) {
1119 EMIT_OPERAND_OP(OP_DUP, 2);
1120 emitByte(OP_INVOKE_SETTER);
1121 writeExpressionLocation(left,&state->
parser.
current,&
this,state);
1129 emitByte(OP_INVOKE_SETTER);
1130 writeExpressionLocation(left,&state->
parser.
previous,&
this,state);
1132 emitBytes(OP_DUP, 1);
1133 emitBytes(OP_DUP, 1);
1134 emitByte(OP_INVOKE_GETTER);
1135 writeExpressionLocation(left,&state->
parser.
previous,&
this,state);
1136 assignmentValue(state);
1137 emitByte(OP_INVOKE_SETTER);
1138 writeExpressionLocation(left,&state->
parser.
previous,&
this,state);
1140 emitByte(OP_INVOKE_DELETE);
1141 writeExpressionLocation(left,&state->
parser.
previous,&
this,state);
1143 emitByte(OP_INVOKE_GETTER);
1144 writeExpressionLocation(left,&state->
parser.
previous,&
this,state);
1148 static void attributeUnpack(
struct GlobalState * state,
int exprType) {
1149 startEatingWhitespace();
1150 size_t argCount = 0;
1151 size_t argSpace = 1;
1152 ssize_t * args = KRK_GROW_ARRAY(ssize_t,NULL,0,1);
1155 if (argSpace < argCount + 1) {
1156 size_t old = argSpace;
1157 argSpace = KRK_GROW_CAPACITY(old);
1158 args = KRK_GROW_ARRAY(ssize_t,args,old,argSpace);
1160 consume(TOKEN_IDENTIFIER,
"Expected attribute name");
1162 args[argCount++] = ind;
1163 }
while (match(TOKEN_COMMA));
1165 stopEatingWhitespace();
1166 consume(TOKEN_RIGHT_PAREN,
"Expected ')' after attribute list");
1169 error(
"Can not assign to '.(' in multiple target list");
1174 size_t expressionCount = 0;
1178 }
while (match(TOKEN_COMMA));
1180 if (expressionCount == 1 && argCount > 1) {
1181 EMIT_OPERAND_OP(OP_UNPACK, argCount);
1182 }
else if (expressionCount > 1 && argCount == 1) {
1183 EMIT_OPERAND_OP(OP_TUPLE, expressionCount);
1184 }
else if (expressionCount != argCount) {
1185 error(
"Invalid assignment to attribute pack");
1189 for (
size_t i = argCount; i > 0; i--) {
1191 emitBytes(OP_DUP, i);
1194 EMIT_OPERAND_OP(OP_SET_PROPERTY, args[i-1]);
1200 for (
size_t i = 0; i < argCount; i++) {
1201 emitBytes(OP_DUP,0);
1202 EMIT_OPERAND_OP(OP_GET_PROPERTY,args[i]);
1206 emitBytes(OP_TUPLE,argCount);
1210 KRK_FREE_ARRAY(ssize_t,args,argSpace);
1215 if (match(TOKEN_LEFT_PAREN)) {
1216 attributeUnpack(state, exprType);
1221 consume(TOKEN_IDENTIFIER,
"Expected property name");
1224 if (matchComplexEnd(state)) {
1225 EMIT_OPERAND_OP(OP_DUP, 1);
1226 EMIT_OPERAND_OP(OP_SET_PROPERTY, ind);
1235 EMIT_OPERAND_OP(OP_SET_PROPERTY, ind);
1238 emitBytes(OP_DUP, 0);
1239 EMIT_OPERAND_OP(OP_GET_PROPERTY, ind);
1241 assignmentValue(state);
1242 EMIT_OPERAND_OP(OP_SET_PROPERTY, ind);
1245 EMIT_OPERAND_OP(OP_DEL_PROPERTY, ind);
1247 }
else if (match(TOKEN_LEFT_PAREN)) {
1248 EMIT_OPERAND_OP(OP_GET_METHOD, ind);
1252 EMIT_OPERAND_OP(OP_GET_PROPERTY, ind);
1258 invalidTarget(state, exprType,
"literal");
1260 case TOKEN_FALSE: emitByte(OP_FALSE);
break;
1261 case TOKEN_NONE: emitByte(OP_NONE);
break;
1262 case TOKEN_TRUE: emitByte(OP_TRUE);
break;
1268 invalidTarget(state, exprType,
"literal");
1271 error(
"internal compiler error");
1274 emitConstant(value);
1277 static void typeHintLocal(
struct GlobalState * state) {
1287 static void letDeclaration(
struct GlobalState * state) {
1288 size_t argCount = 0;
1289 size_t argSpace = 1;
1290 ssize_t * args = KRK_GROW_ARRAY(ssize_t,NULL,0,1);
1293 if (argSpace < argCount + 1) {
1294 size_t old = argSpace;
1295 argSpace = KRK_GROW_CAPACITY(old);
1296 args = KRK_GROW_ARRAY(ssize_t,args,old,argSpace);
1298 ssize_t ind = parseVariable(state,
"Expected variable name.");
1304 args[argCount++] = ind;
1306 if (check(TOKEN_COLON)) {
1310 typeHintLocal(state);
1312 KrkToken annotations = syntheticToken(
"__annotations__");
1313 size_t ind = identifierConstant(state, &annotations);
1314 EMIT_OPERAND_OP(OP_GET_GLOBAL, ind);
1315 emitConstant(OBJECT_VAL(
krk_copyString(name.start, name.length)));
1317 emitBytes(OP_INVOKE_SETTER, OP_POP);
1320 }
while (match(TOKEN_COMMA));
1322 if (match(TOKEN_EQUAL)) {
1323 size_t expressionCount = 0;
1327 }
while (match(TOKEN_COMMA));
1328 if (expressionCount == 1 && argCount > 1) {
1329 EMIT_OPERAND_OP(OP_UNPACK, argCount);
1330 }
else if (expressionCount == argCount) {
1332 }
else if (expressionCount > 1 && argCount == 1) {
1333 EMIT_OPERAND_OP(OP_TUPLE, expressionCount);
1335 error(
"Invalid sequence unpack in 'let' statement");
1340 for (
size_t i = 0; i < argCount; ++i) {
1346 for (
size_t i = argCount; i > 0; i--) {
1347 defineVariable(state, args[i-1]);
1350 for (
size_t i = 0; i < argCount; i++) {
1356 KRK_FREE_ARRAY(ssize_t,args,argSpace);
1360 static void declaration(
struct GlobalState * state) {
1361 if (check(TOKEN_DEF)) {
1362 defDeclaration(state);
1363 }
else if (check(TOKEN_CLASS)) {
1364 KrkToken className = classDeclaration(state);
1365 size_t classConst = identifierConstant(state, &className);
1367 declareVariable(state);
1368 defineVariable(state, classConst);
1369 }
else if (check(TOKEN_AT)) {
1371 }
else if (check(TOKEN_ASYNC)) {
1372 asyncDeclaration(state, 1);
1373 }
else if (match(TOKEN_EOL) || match(TOKEN_EOF)) {
1375 }
else if (check(TOKEN_INDENTATION)) {
1384 static void expressionStatement(
struct GlobalState * state) {
1389 static void beginScope(
struct GlobalState * state) {
1393 static void endScope(
struct GlobalState * state) {
1403 if (popCount == 1) emitByte(OP_POP);
1404 else { EMIT_OPERAND_OP(OP_POP_MANY, popCount); }
1410 if (closeCount == 1) emitByte(OP_CLOSE_UPVALUE);
1411 else { EMIT_OPERAND_OP(OP_CLOSE_MANY, closeCount); }
1427 if (popCount == 1) emitByte(OP_POP);
1428 else { EMIT_OPERAND_OP(OP_POP_MANY, popCount); }
1431 if (closeCount == 1) emitByte(OP_CLOSE_UPVALUE);
1432 else { EMIT_OPERAND_OP(OP_CLOSE_MANY, closeCount); }
1436 static void block(
struct GlobalState * state,
size_t indentation,
const char * blockName) {
1437 if (match(TOKEN_EOL)) {
1438 if (check(TOKEN_INDENTATION)) {
1440 if (currentIndentation <= indentation)
return;
1442 if (!strcmp(blockName,
"def") && (match(TOKEN_STRING) || match(TOKEN_BIG_STRING))) {
1443 size_t before = currentChunk()->count;
1449 currentChunk()->count = before;
1452 consume(TOKEN_EOL,
"Garbage after docstring defintion");
1453 if (!check(TOKEN_INDENTATION) || state->
parser.
current.length != currentIndentation) {
1454 error(
"Expected at least one statement in function with docstring.");
1459 while (check(TOKEN_INDENTATION)) {
1460 if (state->
parser.
current.length < currentIndentation)
break;
1463 if (check(TOKEN_EOL)) {
1475 assert(!!function->upvalueCount == !!compiler->
upvalues);
1476 for (
size_t i = 0; i <
function->upvalueCount; ++i) {
1480 emitByte((index >> 16) & 0xFF);
1481 emitByte((index >> 8) & 0xFF);
1483 emitByte(index & 0xFF);
1494 emitConstant(OBJECT_VAL(
krk_copyString(name.start, name.length)));
1501 static void hideLocal(
struct GlobalState * state) {
1505 static void argumentDefinition(
struct GlobalState * state,
int hasCollectors) {
1506 if (match(TOKEN_EQUAL)) {
1517 EMIT_OPERAND_OP(OP_GET_LOCAL, myLocal);
1518 int jumpIndex = emitJump(OP_TEST_ARG);
1521 EMIT_OPERAND_OP(OP_SET_LOCAL_POP, myLocal);
1523 patchJump(jumpIndex);
1524 if (hasCollectors) {
1530 if (hasCollectors) {
1532 EMIT_OPERAND_OP(OP_GET_LOCAL, myLocal);
1533 int jumpIndex = emitJump(OP_TEST_ARG);
1535 patchJump(jumpIndex);
1539 error(
"non-default argument follows default argument");
1554 EMIT_OPERAND_OP(OP_CLOSURE, ind);
1555 doUpvalues(state, compiler, func);
1557 emitByte(OP_ANNOTATE);
1559 freeCompiler(compiler);
1563 int hasCollectors = 0;
1564 KrkToken self = syntheticToken(
"self");
1568 isMethod(type) && check(TOKEN_IDENTIFIER) &&
1571 errorAtCurrent(
"Argument name 'self' in a method signature is reserved for the implicit first argument.");
1578 typeHint(state, name);
1580 if (check(TOKEN_EQUAL)) {
1581 errorAtCurrent(
"'self' can not be a default argument.");
1586 if (match(TOKEN_SOLIDUS)) {
1588 error(
"Syntax error.");
1594 if (match(TOKEN_ASTERISK) || check(TOKEN_POW)) {
1595 if (match(TOKEN_POW)) {
1596 if (hasCollectors == 2) {
1597 error(
"Duplicate ** in parameter list.");
1603 if (hasCollectors) {
1604 error(
"Syntax error.");
1608 if (check(TOKEN_COMMA)) {
1614 ssize_t paramConstant = parseVariable(state,
1615 (hasCollectors == 1) ?
"Expected parameter name after '*'." :
"Expected parameter name after '**'.");
1617 defineVariable(state, paramConstant);
1619 if (!(state->
current->
optionsFlags & OPTIONS_FLAG_NO_IMPLICIT_SELF) && isMethod(type) && identifiersEqual(&name,&
self)) {
1620 errorAtCurrent(
"Argument name 'self' in a method signature is reserved for the implicit first argument.");
1625 typeHint(state, name);
1629 EMIT_OPERAND_OP(OP_GET_LOCAL, myLocal);
1631 int jumpIndex = emitJump(OP_TEST_ARG);
1634 if (hasCollectors == 1) EMIT_OPERAND_OP(OP_MAKE_LIST,0);
1635 else EMIT_OPERAND_OP(OP_MAKE_DICT,0);
1636 EMIT_OPERAND_OP(OP_SET_LOCAL_POP, myLocal);
1639 patchJump(jumpIndex);
1642 if (hasCollectors == 2) {
1643 error(
"arguments follow catch-all keyword collector");
1646 ssize_t paramConstant = parseVariable(state,
"Expected parameter name.");
1652 typeHint(state, name);
1654 argumentDefinition(state, hasCollectors);
1655 defineVariable(state, paramConstant);
1656 }
while (match(TOKEN_COMMA));
1663 initCompiler(state, &compiler, type);
1668 consume(TOKEN_LEFT_PAREN,
"Expected start of parameter list after function name.");
1669 startEatingWhitespace();
1670 if (!check(TOKEN_RIGHT_PAREN)) {
1671 if (argumentList(state, type))
goto _bail;
1673 stopEatingWhitespace();
1674 consume(TOKEN_RIGHT_PAREN,
"Expected end of parameter list.");
1676 if (match(TOKEN_ARROW)) {
1677 typeHint(state, syntheticToken(
"return"));
1680 consume(TOKEN_COLON,
"Expected colon after function signature.");
1681 block(state, blockWidth,
"def");
1683 functionPrologue(state, &compiler);
1686 static void classBody(
struct GlobalState * state,
size_t blockWidth) {
1687 if (match(TOKEN_EOL)) {
1691 if (check(TOKEN_AT)) {
1694 }
else if (match(TOKEN_IDENTIFIER)) {
1698 if (check(TOKEN_COLON)) {
1703 KrkToken annotations = syntheticToken(
"__annotations__");
1704 size_t ind = identifierConstant(state, &annotations);
1706 EMIT_OPERAND_OP(OP_MAKE_DICT, 0);
1707 EMIT_OPERAND_OP(OP_SET_NAME, ind);
1710 EMIT_OPERAND_OP(OP_GET_NAME, ind);
1712 emitConstant(OBJECT_VAL(
krk_copyString(name.start, name.length)));
1714 emitBytes(OP_INVOKE_SETTER, OP_POP);
1717 if (match(TOKEN_EOL) || match(TOKEN_EOF))
return;
1720 consume(TOKEN_EQUAL,
"Class field must have value.");
1725 rememberClassProperty(state, ind);
1726 EMIT_OPERAND_OP(OP_SET_NAME, ind);
1729 if (!match(TOKEN_EOL) && !match(TOKEN_EOF)) {
1730 errorAtCurrent(
"Expected end of line after class attribute declaration");
1732 }
else if (match(TOKEN_PASS)) {
1734 consume(TOKEN_EOL,
"Expected end of line after 'pass' in class body.");
1738 if (match(TOKEN_ASYNC)) {
1740 consume(TOKEN_DEF,
"Expected 'def' after 'async'");
1741 }
else if (!match(TOKEN_DEF)) {
1742 error(
"Expected method, decorator, or class variable.");
1744 consume(TOKEN_IDENTIFIER,
"Expected method name after 'def'");
1747 static struct CompilerSpecialMethod {
const char * name;
int type; } compilerSpecialMethods[] = {
1755 for (
struct CompilerSpecialMethod * method = compilerSpecialMethods; method->name; method++) {
1756 if (state->
parser.
previous.length == strlen(method->name) && memcmp(state->
parser.
previous.start, method->name, strlen(method->name)) == 0) {
1758 error(
"'%s' can not be a coroutine",method->name);
1761 type = method->type;
1765 function(state, type, blockWidth);
1766 rememberClassProperty(state, ind);
1767 EMIT_OPERAND_OP(OP_SET_NAME, ind);
1772 #define ATTACH_PROPERTY(propName,how,propValue) do { \
1773 KrkToken val_tok = syntheticToken(propValue); \
1774 size_t val_ind = nonidentifierTokenConstant(state, &val_tok); \
1775 EMIT_OPERAND_OP(how, val_ind); \
1776 KrkToken name_tok = syntheticToken(propName); \
1777 size_t name_ind = identifierConstant(state, &name_tok); \
1778 EMIT_OPERAND_OP(OP_SET_NAME, name_ind); \
1787 consume(TOKEN_IDENTIFIER,
"Expected class name after 'class'.");
1789 emitByte(OP_PUSH_BUILD_CLASS);
1792 initCompiler(state, &subcompiler,
TYPE_CLASS);
1798 assert(addUpvalue(state, state->
current, 0, 4, classNameToken) == 0);
1809 if (match(TOKEN_LEFT_PAREN)) {
1811 while (!check(TOKEN_EOF)) {
1812 if (check(TOKEN_RIGHT_PAREN) && parenDepth == 0) {
1815 }
else if (match(TOKEN_LEFT_BRACE)) {
1817 }
else if (match(TOKEN_RIGHT_BRACE)) {
1827 consume(TOKEN_COLON,
"Expected ':' after class.");
1831 ATTACH_PROPERTY(
"__module__", OP_GET_GLOBAL,
"__name__");
1832 ATTACH_PROPERTY(
"__qualname__", OP_CONSTANT, calculateQualName(state));
1834 if (match(TOKEN_EOL)) {
1835 if (check(TOKEN_INDENTATION)) {
1837 if (currentIndentation <= blockWidth) {
1838 errorAtCurrent(
"Unexpected indentation level for class");
1841 if (match(TOKEN_STRING) || match(TOKEN_BIG_STRING)) {
1843 KrkToken doc = syntheticToken(
"__doc__");
1844 size_t ind = identifierConstant(state, &doc);
1845 EMIT_OPERAND_OP(OP_SET_NAME, ind);
1847 consume(TOKEN_EOL,
"Garbage after docstring defintion");
1848 if (!check(TOKEN_INDENTATION) || state->
parser.
current.length != currentIndentation) {
1853 classBody(state, currentIndentation);
1854 while (check(TOKEN_INDENTATION)) {
1855 if (state->
parser.
current.length < currentIndentation)
break;
1857 classBody(state, currentIndentation);
1865 size_t indFunc =
krk_addConstant(currentChunk(), OBJECT_VAL(makeclass));
1869 size_t nameInd = nonidentifierTokenConstant(state, &classNameToken);
1874 EMIT_OPERAND_OP(OP_CLOSURE, indFunc);
1875 doUpvalues(state, &subcompiler, makeclass);
1876 freeCompiler(&subcompiler);
1877 EMIT_OPERAND_OP(OP_CONSTANT, nameInd);
1879 if (match(TOKEN_LEFT_PAREN)) {
1880 call(state, EXPR_CLASS_PARAMETERS, NULL);
1882 emitBytes(OP_CALL, 2);
1888 return classCompiler.
name;
1894 initCompiler(state, &lambdaCompiler,
TYPE_LAMBDA);
1898 if (!check(TOKEN_COLON)) {
1902 consume(TOKEN_COLON,
"Expected ':' after lambda arguments");
1906 functionPrologue(state, &lambdaCompiler);
1908 invalidTarget(state, exprType,
"lambda");
1911 static void defDeclaration(
struct GlobalState * state) {
1915 ssize_t global = parseVariable(state,
"Expected function name after 'def'.");
1917 markInitialized(state);
1920 defineVariable(state, global);
1923 static void asyncDeclaration(
struct GlobalState * state,
int declarationLevel) {
1927 if (match(TOKEN_DEF)) {
1928 if (!declarationLevel) {
1929 error(
"'async def' not valid here");
1932 ssize_t global = parseVariable(state,
"Expected coroutine name after 'async def'");
1934 markInitialized(state);
1937 defineVariable(state, global);
1938 }
else if (match(TOKEN_FOR)) {
1940 error(
"'async for' outside of async function");
1943 error(
"'async for' unsupported (GH-12)");
1945 }
else if (match(TOKEN_WITH)) {
1947 error(
"'async with' outside of async function");
1950 error(
"'async with' unsupported (GH-12)");
1953 errorAtCurrent(
"Expected 'def' after 'async'.");
1965 KrkToken at_staticmethod = syntheticToken(
"staticmethod");
1966 KrkToken at_classmethod = syntheticToken(
"classmethod");
1979 consume(TOKEN_EOL,
"Expected end of line after decorator.");
1981 consume(TOKEN_INDENTATION,
"Expected next line after decorator to have same indentation.");
1982 if (state->
parser.
previous.length != blockWidth) error(
"Expected next line after decorator to have same indentation.");
1985 if (check(TOKEN_DEF)) {
1988 consume(TOKEN_IDENTIFIER,
"Expected function name after 'def'");
1990 if (type ==
TYPE_METHOD && funcName.length == 8 && !memcmp(funcName.start,
"__init__",8)) {
1994 declareVariable(state);
1995 markInitialized(state);
1997 function(state, type, blockWidth);
1998 }
else if (match(TOKEN_ASYNC)) {
1999 if (!match(TOKEN_DEF)) {
2000 errorAtCurrent(
"Expected 'def' after 'async' with decorator, not '%*.s'",
2003 consume(TOKEN_IDENTIFIER,
"Expected coroutine name after 'def'.");
2006 declareVariable(state);
2007 markInitialized(state);
2010 }
else if (check(TOKEN_AT)) {
2011 funcName = decorator(state, level+1, type);
2012 }
else if (check(TOKEN_CLASS)) {
2014 error(
"Invalid decorator applied to class");
2017 funcName = classDeclaration(state);
2019 error(
"Expected a function declaration or another decorator.");
2023 emitBytes(OP_CALL, 1);
2028 size_t ind = identifierConstant(state, &funcName);
2029 defineVariable(state, ind);
2031 emitByte(OP_SWAP_POP);
2034 size_t ind = identifierConstant(state, &funcName);
2035 rememberClassProperty(state, ind);
2036 EMIT_OPERAND_OP(OP_SET_NAME, ind);
2044 static void emitLoop(
struct GlobalState * state,
int loopStart, uint8_t loopType) {
2054 int offset = currentChunk()->count - loopStart + ((loopType == OP_LOOP_ITER) ? -1 : 2);
2055 if (offset > 0xFFFF) {
2056 _emitOverlongJump(state, currentChunk()->count, offset);
2058 emitBytes(offset >> 8, offset);
2063 static void withStatement(
struct GlobalState * state) {
2074 if (match(TOKEN_AS)) {
2075 consume(TOKEN_IDENTIFIER,
"Expected variable name after 'as'");
2077 declareVariable(state);
2078 defineVariable(state, ind);
2081 anonymousLocal(state);
2085 anonymousLocal(state);
2088 anonymousLocal(state);
2089 int withJump = emitJump(OP_PUSH_WITH);
2091 if (check(TOKEN_COMMA)) {
2093 withStatement(state);
2095 consume(TOKEN_COLON,
"Expected ',' or ':' after 'with' statement");
2098 block(state,blockWidth,
"with");
2102 patchJump(withJump);
2103 emitByte(OP_CLEANUP_WITH);
2109 static void ifStatement(
struct GlobalState * state) {
2121 consume(TOKEN_COLON,
"Expected ':' after 'if' condition.");
2125 int thenJump = emitJump(OP_POP_JUMP_IF_FALSE);
2129 block(state,blockWidth,
"if");
2135 if (blockWidth == 0 || (check(TOKEN_INDENTATION) && (state->
parser.
current.length == blockWidth))) {
2142 if (match(TOKEN_ELSE) || check(TOKEN_ELIF)) {
2143 int elseJump = emitJump(OP_JUMP);
2144 patchJump(thenJump);
2145 if (state->
parser.
current.type == TOKEN_ELIF || check(TOKEN_IF)) {
2149 consume(TOKEN_COLON,
"Expected ':' after 'else'.");
2151 block(state,blockWidth,
"else");
2154 patchJump(elseJump);
2156 }
else if (!check(TOKEN_EOF) && !check(TOKEN_EOL)) {
2167 patchJump(thenJump);
2170 static void patchBreaks(
struct GlobalState * state,
int loopStart) {
2178 static void breakStatement(
struct GlobalState * state) {
2192 static void continueStatement(
struct GlobalState * state) {
2206 static void optionalElse(
struct GlobalState * state,
size_t blockWidth) {
2209 if (blockWidth == 0 || (check(TOKEN_INDENTATION) && (state->
parser.
current.length == blockWidth))) {
2210 if (blockWidth) advance();
2211 if (match(TOKEN_ELSE)) {
2212 consume(TOKEN_COLON,
"Expected ':' after 'else'.");
2214 block(state,blockWidth,
"else");
2218 state->
parser = parserBefore;
2223 static void whileStatement(
struct GlobalState * state) {
2227 int loopStart = currentChunk()->count;
2232 if (!(match(TOKEN_TRUE) && match(TOKEN_COLON)) &&
2240 consume(TOKEN_COLON,
"Expected ':' after 'while' condition.");
2242 exitJump = emitJump(OP_JUMP_IF_FALSE_OR_POP);
2248 block(state,blockWidth,
"while");
2252 emitLoop(state, loopStart, OP_LOOP);
2255 patchJump(exitJump);
2261 optionalElse(state, blockWidth);
2263 patchBreaks(state, loopStart);
2266 static void forStatement(
struct GlobalState * state) {
2276 ssize_t varCount = 0;
2277 int matchedEquals = 0;
2279 if (!check(TOKEN_IDENTIFIER)) {
2280 errorAtCurrent(
"Empty variable list in 'for'");
2285 if (!check(TOKEN_IDENTIFIER))
break;
2286 ssize_t ind = parseVariable(state,
"Expected name for loop iterator.");
2288 if (match(TOKEN_EQUAL)) {
2294 defineVariable(state, ind);
2296 if (check(TOKEN_COMMA)) sawComma = 1;
2297 }
while (match(TOKEN_COMMA));
2303 if (!matchedEquals && match(TOKEN_IN)) {
2309 anonymousLocal(state);
2310 emitByte(OP_INVOKE_ITER);
2311 loopStart = currentChunk()->count;
2312 exitJump = emitJump(OP_CALL_ITER);
2314 if (varCount > 1 || sawComma) {
2315 EMIT_OPERAND_OP(OP_UNPACK, varCount);
2316 for (ssize_t i = loopInd + varCount - 1; i >= loopInd; i--) {
2317 EMIT_OPERAND_OP(OP_SET_LOCAL_POP, i);
2320 EMIT_OPERAND_OP(OP_SET_LOCAL_POP, loopInd);
2326 consume(TOKEN_SEMICOLON,
"Expected ';' after C-style loop initializer.");
2327 loopStart = currentChunk()->count;
2332 exitJump = emitJump(OP_JUMP_IF_FALSE_OR_POP);
2334 if (check(TOKEN_SEMICOLON)) {
2336 int bodyJump = emitJump(OP_JUMP);
2337 int incrementStart = currentChunk()->count;
2340 expressionStatement(state);
2341 }
while (match(TOKEN_COMMA));
2344 emitLoop(state, loopStart, OP_LOOP);
2345 loopStart = incrementStart;
2346 patchJump(bodyJump);
2350 consume(TOKEN_COLON,
"Expected ':' after loop conditions.");
2355 block(state,blockWidth,
"for");
2359 emitLoop(state, loopStart, isIter ? OP_LOOP_ITER : OP_LOOP);
2360 patchJump(exitJump);
2362 optionalElse(state, blockWidth);
2363 patchBreaks(state, loopStart);
2367 static void returnStatement(
struct GlobalState * state) {
2368 if (check(TOKEN_EOL) || check(TOKEN_EOF)) {
2372 error(
"__init__ may not return a value.");
2375 emitByte(OP_RETURN);
2379 static void tryStatement(
struct GlobalState * state) {
2382 consume(TOKEN_COLON,
"Expected ':' after 'try'.");
2386 int tryJump = emitJump(OP_PUSH_TRY);
2388 size_t exceptionObject = anonymousLocal(state);
2389 anonymousLocal(state);
2392 block(state,blockWidth,
"try");
2397 #define EXIT_JUMP_MAX 64
2399 int exitJumpOffsets[EXIT_JUMP_MAX] = {0};
2402 exitJumpOffsets[0] = emitJump(OP_JUMP);
2407 exitJumpOffsets[1] = emitJump(OP_ENTER_EXCEPT);
2414 if (blockWidth == 0 || (check(TOKEN_INDENTATION) && (state->
parser.
current.length == blockWidth))) {
2420 if (exitJumps && !firstJump && match(TOKEN_EXCEPT)) {
2421 if (nextJump != -1) {
2422 patchJump(nextJump);
2425 if (!check(TOKEN_COLON) && !check(TOKEN_AS)) {
2430 nextJump = emitJump(OP_FILTER_EXCEPT);
2434 if (match(TOKEN_AS)) {
2435 consume(TOKEN_IDENTIFIER,
"Expected identifier after 'as'.");
2438 nameInd = renameLocal(state, exceptionObject, state->
parser.
previous);
2443 consume(TOKEN_COLON,
"Expected ':' after 'except'.");
2445 block(state,blockWidth,
"except");
2451 if (exitJumps < EXIT_JUMP_MAX) {
2452 exitJumpOffsets[exitJumps++] = emitJump(OP_JUMP);
2454 error(
"Too many 'except' clauses.");
2458 goto _anotherExcept;
2459 }
else if (firstJump != 1 && match(TOKEN_ELSE)) {
2460 consume(TOKEN_COLON,
"Expected ':' after 'else'.");
2461 patchJump(exitJumpOffsets[0]);
2463 emitByte(OP_TRY_ELSE);
2466 block(state, blockWidth,
"else");
2468 if (nextJump == -1) {
2474 goto _anotherExcept;
2475 }
else if (match(TOKEN_FINALLY)) {
2476 consume(TOKEN_COLON,
"Expected ':' after 'finally'.");
2477 for (
int i = firstJump; i < exitJumps; ++i) {
2478 patchJump(exitJumpOffsets[i]);
2480 if (nextJump != -1) {
2481 patchJump(nextJump);
2483 emitByte(OP_BEGIN_FINALLY);
2487 block(state,blockWidth,
"finally");
2490 emitByte(OP_END_FINALLY);
2491 }
else if (!check(TOKEN_EOL) && !check(TOKEN_EOF)) {
2502 for (
int i = firstJump; i < exitJumps; ++i) {
2503 patchJump(exitJumpOffsets[i]);
2506 if (nextJump >= 0) {
2507 patchJump(nextJump);
2508 emitByte(OP_BEGIN_FINALLY);
2509 emitByte(OP_END_FINALLY);
2515 static void raiseStatement(
struct GlobalState * state) {
2518 if (match(TOKEN_FROM)) {
2520 emitByte(OP_RAISE_FROM);
2526 static size_t importModule(
struct GlobalState * state,
KrkToken * startOfName,
int leadingDots) {
2530 for (
int i = 0; i < leadingDots; ++i) {
2531 pushStringBuilder(&sb,
'.');
2534 if (!(leadingDots && check(TOKEN_IMPORT))) {
2535 consume(TOKEN_IDENTIFIER,
"Expected module name after 'import'.");
2539 while (match(TOKEN_DOT)) {
2541 consume(TOKEN_IDENTIFIER,
"Expected module path element after '.'");
2547 startOfName->start = sb.bytes;
2548 startOfName->length = sb.length;
2550 ind = identifierConstant(state, startOfName);
2551 EMIT_OPERAND_OP(OP_IMPORT, ind);
2554 discardStringBuilder(&sb);
2558 static void importStatement(
struct GlobalState * state) {
2562 size_t ind = importModule(state, &startOfName, 0);
2563 if (match(TOKEN_AS)) {
2564 consume(TOKEN_IDENTIFIER,
"Expected identifier after 'as'.");
2566 }
else if (startOfName.length != firstName.length) {
2576 ind = identifierConstant(state, &firstName);
2577 EMIT_OPERAND_OP(OP_IMPORT, ind);
2579 declareVariable(state);
2580 defineVariable(state, ind);
2581 }
while (match(TOKEN_COMMA));
2584 static void optionsImport(
struct GlobalState * state) {
2585 int expectCloseParen = 0;
2587 KrkToken compile_time_builtins = syntheticToken(
"compile_time_builtins");
2588 KrkToken no_implicit_self = syntheticToken(
"no_implicit_self");
2591 consume(TOKEN_IMPORT,
"__options__ is not a package\n");
2593 if (match(TOKEN_LEFT_PAREN)) {
2594 expectCloseParen = 1;
2595 startEatingWhitespace();
2599 consume(TOKEN_IDENTIFIER,
"Expected member name");
2602 if (identifiersEqual(&state->
parser.
previous, &compile_time_builtins)) {
2604 }
else if (identifiersEqual(&state->
parser.
previous, &no_implicit_self)) {
2607 error(
"'%.*s' is not a recognized __options__ import",
2612 if (check(TOKEN_AS)) {
2613 errorAtCurrent(
"__options__ imports can not be given names");
2617 }
while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_PAREN));
2619 if (expectCloseParen) {
2620 stopEatingWhitespace();
2621 consume(TOKEN_RIGHT_PAREN,
"Expected ')' after import list started with '('");
2625 static void fromImportStatement(
struct GlobalState * state) {
2626 int expectCloseParen = 0;
2628 int leadingDots = 0;
2630 KrkToken options = syntheticToken(
"__options__");
2631 if (check(TOKEN_IDENTIFIER) && identifiersEqual(&state->
parser.
current, &options)) {
2633 optionsImport(state);
2637 while (match(TOKEN_DOT) || match(TOKEN_ELLIPSIS)) {
2641 importModule(state, &startOfName, leadingDots);
2642 consume(TOKEN_IMPORT,
"Expected 'import' after module name");
2643 if (match(TOKEN_LEFT_PAREN)) {
2644 expectCloseParen = 1;
2645 startEatingWhitespace();
2648 consume(TOKEN_IDENTIFIER,
"Expected member name");
2649 size_t member = identifierConstant(state, &state->
parser.
previous);
2650 emitBytes(OP_DUP, 0);
2651 EMIT_OPERAND_OP(OP_IMPORT_FROM, member);
2652 if (match(TOKEN_AS)) {
2653 consume(TOKEN_IDENTIFIER,
"Expected identifier after 'as'");
2660 declareVariable(state);
2661 defineVariable(state, member);
2662 }
while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_PAREN));
2663 if (expectCloseParen) {
2664 stopEatingWhitespace();
2665 consume(TOKEN_RIGHT_PAREN,
"Expected ')' after import list started with '('");
2670 static void delStatement(
struct GlobalState * state) {
2675 errorAtCurrent(
"Invalid del target");
2677 }
while (match(TOKEN_COMMA));
2680 static void assertStatement(
struct GlobalState * state) {
2682 int elseJump = emitJump(OP_JUMP_IF_TRUE_OR_POP);
2684 KrkToken assertionError = syntheticToken(
"AssertionError");
2685 size_t ind = identifierConstant(state, &assertionError);
2686 EMIT_OPERAND_OP(OP_GET_GLOBAL, ind);
2689 if (match(TOKEN_COMMA)) {
2694 EMIT_OPERAND_OP(OP_CALL, args);
2697 patchJump(elseJump);
2701 static void errorAfterStatement(
struct GlobalState * state) {
2703 case TOKEN_RIGHT_BRACE:
2704 case TOKEN_RIGHT_PAREN:
2705 case TOKEN_RIGHT_SQUARE:
2706 errorAtCurrent(
"Unmatched '%.*s'",
2709 case TOKEN_IDENTIFIER:
2710 errorAtCurrent(
"Unexpected %.*s after statement.",10,
"identifier");
2713 case TOKEN_BIG_STRING:
2714 errorAtCurrent(
"Unexpected %.*s after statement.",6,
"string");
2717 errorAtCurrent(
"Unexpected %.*s after statement.",
2722 static void simpleStatement(
struct GlobalState * state) {
2723 _anotherSimpleStatement:
2724 if (match(TOKEN_RAISE)) {
2725 raiseStatement(state);
2726 }
else if (match(TOKEN_RETURN)) {
2727 returnStatement(state);
2728 }
else if (match(TOKEN_IMPORT)) {
2729 importStatement(state);
2730 }
else if (match(TOKEN_FROM)) {
2731 fromImportStatement(state);
2732 }
else if (match(TOKEN_BREAK)) {
2733 breakStatement(state);
2734 }
else if (match(TOKEN_CONTINUE)) {
2735 continueStatement(state);
2736 }
else if (match(TOKEN_DEL)) {
2737 delStatement(state);
2738 }
else if (match(TOKEN_ASSERT)) {
2739 assertStatement(state);
2740 }
else if (match(TOKEN_PASS)) {
2742 }
else if (match(TOKEN_LET)) {
2743 letDeclaration(state);
2745 expressionStatement(state);
2747 if (match(TOKEN_SEMICOLON))
goto _anotherSimpleStatement;
2748 if (!match(TOKEN_EOL) && !match(TOKEN_EOF)) {
2749 errorAfterStatement(state);
2753 static void statement(
struct GlobalState * state) {
2754 if (match(TOKEN_EOL) || match(TOKEN_EOF)) {
2758 if (check(TOKEN_IF)) {
2760 }
else if (check(TOKEN_WHILE)) {
2761 whileStatement(state);
2762 }
else if (check(TOKEN_FOR)) {
2763 forStatement(state);
2764 }
else if (check(TOKEN_ASYNC)) {
2765 asyncDeclaration(state, 0);
2766 }
else if (check(TOKEN_TRY)) {
2767 tryStatement(state);
2768 }
else if (check(TOKEN_WITH)) {
2769 withStatement(state);
2772 simpleStatement(state);
2780 error(
"'yield' outside function");
2784 if (match(TOKEN_FROM)) {
2786 emitByte(OP_INVOKE_ITER);
2788 size_t loopContinue = currentChunk()->count;
2789 size_t exitJump = emitJump(OP_YIELD_FROM);
2791 emitLoop(state, loopContinue, OP_LOOP);
2792 patchJump(exitJump);
2793 }
else if (check(TOKEN_EOL) || check(TOKEN_EOF) || check(TOKEN_RIGHT_PAREN) || check(TOKEN_RIGHT_BRACE)) {
2800 invalidTarget(state, exprType,
"yield");
2805 error(
"'await' outside async function");
2810 emitByte(OP_INVOKE_AWAIT);
2812 size_t loopContinue = currentChunk()->count;
2813 size_t exitJump = emitJump(OP_YIELD_FROM);
2815 emitLoop(state, loopContinue, OP_LOOP);
2816 patchJump(exitJump);
2817 invalidTarget(state, exprType,
"await");
2823 invalidTarget(state, exprType,
"operator");
2829 invalidTarget(state, exprType,
"operator");
2830 switch (operatorType) {
2831 case TOKEN_PLUS: emitByte(OP_POS);
break;
2832 case TOKEN_MINUS: emitByte(OP_NEGATE);
break;
2833 case TOKEN_TILDE: emitByte(OP_BITNEGATE);
break;
2834 case TOKEN_BANG: emitByte(OP_NOT);
break;
2839 static int isHex(
int c) {
2840 return (c >=
'0' && c <=
'9') || (c >=
'a' && c <=
'f') || (c >=
'A' && c <=
'F');
2843 static int _pushHex(
struct GlobalState * state,
int isBytes,
struct StringBuilder * sb,
const char *c,
const char *end,
size_t n,
char type) {
2844 char tmpbuf[10] = {0};
2845 for (
size_t i = 0; i < n; ++i) {
2846 if (c + i + 2 == end || !isHex(c[i+2])) {
2847 error(
"truncated \\%c escape", type);
2852 unsigned long value = strtoul(tmpbuf, NULL, 16);
2853 if (value >= 0x110000) {
2854 error(
"invalid codepoint in \\%c escape", type);
2860 unsigned char bytes[5] = {0};
2869 #define PUSH_CHAR(c) krk_pushStringBuilder(&sb, c)
2870 #define PUSH_HEX(n, type) _pushHex(state, isBytes, &sb, c, end, n, type)
2879 if ((isBytes || isFormat || isRaw) && !(match(TOKEN_STRING) || match(TOKEN_BIG_STRING))) {
2880 error(
"Expected string after prefix? (Internal error - scanner should not have produced this.)");
2884 int formatElements = 0;
2894 int type = state->
parser.
previous.type == TOKEN_BIG_STRING ? 3 : 1;
2900 case '\\': PUSH_CHAR(
'\\');
break;
2901 case '\'': PUSH_CHAR(
'\'');
break;
2902 case '\"': PUSH_CHAR(
'\"');
break;
2903 case 'a': PUSH_CHAR(
'\a');
break;
2904 case 'b': PUSH_CHAR(
'\b');
break;
2905 case 'f': PUSH_CHAR(
'\f');
break;
2906 case 'n': PUSH_CHAR(
'\n');
break;
2907 case 'r': PUSH_CHAR(
'\r');
break;
2908 case 't': PUSH_CHAR(
'\t');
break;
2909 case 'v': PUSH_CHAR(
'\v');
break;
2910 case '[': PUSH_CHAR(
'\033');
break;
2935 if (c[1] >=
'0' && c[1] <=
'7') {
2936 int out = c[1] -
'0';
2937 if (c + 2 != end && (c[2] >=
'0' && c[2] <=
'7')) {
2941 if (c + 1 != end && (c[2] >=
'0' && c[2] <=
'7')) {
2951 unsigned char bytes[5] = {0};
2953 for (
size_t i = 0; i < len; i++) PUSH_CHAR(bytes[i]);
2962 }
else if (isFormat && *c ==
'}') {
2964 error(
"single '}' not allowed in f-string");
2970 }
else if (isFormat && *c ==
'{') {
2980 const char * start = c+1;
2983 KrkScanner inner = (
KrkScanner){.start=c+1, .cur=c+1, .linePtr=lineBefore, .line=lineNo, .startOfLine = 0, .hasUnget = 0};
2990 state->
parser = parserBefore;
2995 while (*c ==
' ') c++;
2998 while (*c ==
' ') c++;
3001 formatType |= FORMAT_OP_EQ;
3008 formatType |= FORMAT_OP_REPR;
3009 }
else if (*c ==
's') {
3010 formatType |= FORMAT_OP_STR;
3012 error(
"Unsupported conversion flag '%c' for f-string expression.", *c);
3020 const char * formatStart = c+1;
3022 while (c < end && *c !=
'}') c++;
3023 emitConstant(OBJECT_VAL(
krk_copyString(formatStart,c-formatStart)));
3024 formatType |= FORMAT_OP_FORMAT;
3028 if (!(formatType & (FORMAT_OP_FORMAT | FORMAT_OP_STR)) && (formatType & FORMAT_OP_EQ)) {
3029 formatType |= FORMAT_OP_REPR;
3032 EMIT_OPERAND_OP(OP_FORMAT_VALUE, formatType);
3035 error(
"Expected closing '}' after expression in f-string");
3042 if (*(
unsigned char*)c > 127 && isBytes) {
3043 error(
"bytes literal can only contain ASCII characters");
3056 if (match(TOKEN_PREFIX_F)) {
3058 }
else if (match(TOKEN_PREFIX_R)) {
3062 }
while ((!isBytes || match(TOKEN_PREFIX_B)) && (match(TOKEN_STRING) || match(TOKEN_BIG_STRING)));
3063 if (isBytes && (match(TOKEN_STRING) || match(TOKEN_BIG_STRING))) {
3064 error(
"Can not mix bytes and string literals");
3071 if (sb.length || !formatElements) {
3075 if (formatElements != 1) {
3076 EMIT_OPERAND_OP(OP_MAKE_STRING, formatElements);
3085 for (
size_t i = 0; i < upvalueCount; ++i) {
3087 if ((ssize_t)upvalue->
index == index && upvalue->
isLocal == isLocal) {
3104 for (
size_t i = 0; i < upvalueCount; ++i) {
3105 if (identifiersEqual(name, &compiler->
upvalues[i].
name)) {
3110 if (compiler->
enclosing == NULL)
return -1;
3112 ssize_t local = resolveLocal(state, compiler->
enclosing, name);
3115 return addUpvalue(state, compiler, local, 1, *name);
3117 ssize_t upvalue = resolveUpvalue(state, compiler->
enclosing, name);
3118 if (upvalue != -1) {
3119 return addUpvalue(state, compiler, upvalue, 0, *name);
3124 #define OP_NONE_LONG -1
3125 #define DO_VARIABLE(opset,opget,opdel) do { \
3126 if (exprType == EXPR_ASSIGN_TARGET) { \
3127 if (matchComplexEnd(state)) { \
3128 EMIT_OPERAND_OP(opset, arg); \
3131 exprType = EXPR_NORMAL; \
3133 if (exprType == EXPR_CAN_ASSIGN && match(TOKEN_EQUAL)) { \
3134 parsePrecedence(state, PREC_ASSIGNMENT); \
3135 EMIT_OPERAND_OP(opset, arg); \
3136 } else if (exprType == EXPR_CAN_ASSIGN && matchAssignment(state)) { \
3137 EMIT_OPERAND_OP(opget, arg); \
3138 assignmentValue(state); \
3139 EMIT_OPERAND_OP(opset, arg); \
3140 } else if (exprType == EXPR_DEL_TARGET && checkEndOfDel(state)) {\
3141 if (opdel == OP_NONE) { emitByte(OP_NONE); EMIT_OPERAND_OP(opset, arg); } \
3142 else { EMIT_OPERAND_OP(opdel, arg); } \
3144 EMIT_OPERAND_OP(opget, arg); \
3151 while (properties) {
3152 KrkString * constant = AS_STRING(currentChunk()->constants.values[properties->
ind]);
3153 if (constant->
length == name.length && !memcmp(constant->
chars, name.start, name.length)) {
3154 ssize_t arg = properties->
ind;
3155 DO_VARIABLE(OP_SET_NAME, OP_GET_NAME, OP_NONE);
3158 properties = properties->
next;
3161 ssize_t arg = resolveLocal(state, state->
current, &name);
3163 DO_VARIABLE(OP_SET_LOCAL, OP_GET_LOCAL, OP_NONE);
3164 }
else if ((arg = resolveUpvalue(state, state->
current, &name)) != -1) {
3165 DO_VARIABLE(OP_SET_UPVALUE, OP_GET_UPVALUE, OP_NONE);
3167 if ((state->
current->
optionsFlags & OPTIONS_FLAG_COMPILE_TIME_BUILTINS) && *name.start !=
'_') {
3173 error(
"Can not assign to '%.*s' when 'compile_time_builtins' is enabled.",
3174 (
int)name.length, name.start);
3176 error(
"Can not delete '%.*s' when 'compile_time_builtins' is enabled.",
3177 (
int)name.length, name.start);
3179 emitConstant(value);
3184 arg = identifierConstant(state, &name);
3185 DO_VARIABLE(OP_SET_GLOBAL, OP_GET_GLOBAL, OP_DEL_GLOBAL);
3199 consume(TOKEN_LEFT_PAREN,
"Expected 'super' to be called.");
3202 if (match(TOKEN_RIGHT_PAREN)) {
3204 error(
"super() outside of a method body requires arguments");
3208 error(
"super() is not valid in a function with no arguments");
3212 EMIT_OPERAND_OP(OP_GET_LOCAL, 0);
3215 if (match(TOKEN_COMMA)) {
3220 consume(TOKEN_RIGHT_PAREN,
"Expected ')' after argument list");
3222 consume(TOKEN_DOT,
"Expected a field of 'super()' to be referenced.");
3223 consume(TOKEN_IDENTIFIER,
"Expected a field name.");
3225 EMIT_OPERAND_OP(OP_GET_SUPER,
ind);
3230 ssize_t varCount = 0;
3232 if (!check(TOKEN_IDENTIFIER)) {
3233 errorAtCurrent(
"Empty variable list in comprehension");
3237 if (!check(TOKEN_IDENTIFIER))
break;
3238 defineVariable(state, parseVariable(state,
"Expected name for iteration variable."));
3241 defineVariable(state, loopInd);
3243 if (check(TOKEN_COMMA)) sawComma = 1;
3244 }
while (match(TOKEN_COMMA));
3246 consume(TOKEN_IN,
"Only iterator loops (for ... in ...) are allowed in generator expressions.");
3249 parsePrecedence(state,
PREC_OR);
3252 anonymousLocal(state);
3253 emitByte(OP_INVOKE_ITER);
3254 int loopStart = currentChunk()->count;
3255 int exitJump = emitJump(OP_CALL_ITER);
3257 if (varCount > 1 || sawComma) {
3258 EMIT_OPERAND_OP(OP_UNPACK, varCount);
3259 for (ssize_t i = loopInd + varCount - 1; i >= loopInd; i--) {
3260 EMIT_OPERAND_OP(OP_SET_LOCAL_POP, i);
3263 EMIT_OPERAND_OP(OP_SET_LOCAL_POP, loopInd);
3266 if (match(TOKEN_IF)) {
3267 parsePrecedence(state,
PREC_OR);
3268 int acceptJump = emitJump(OP_JUMP_IF_TRUE_OR_POP);
3269 emitLoop(state, loopStart, OP_LOOP);
3270 patchJump(acceptJump);
3275 if (match(TOKEN_FOR)) {
3276 comprehensionInner(state, scannerBefore, parserBefore, body, arg);
3281 state->
parser = parserBefore;
3286 state->
parser = parserAfter;
3290 emitLoop(state, loopStart, OP_LOOP_ITER);
3291 patchJump(exitJump);
3295 static void yieldInner(
struct GlobalState * state,
size_t arg) {
3298 emitBytes(OP_YIELD, OP_POP);
3318 comprehensionInner(state, scannerBefore, parserBefore, body, 0);
3322 size_t indFunc =
krk_addConstant(currentChunk(), OBJECT_VAL(subfunction));
3323 EMIT_OPERAND_OP(OP_CLOSURE, indFunc);
3324 doUpvalues(state, &subcompiler, subfunction);
3325 freeCompiler(&subcompiler);
3326 emitBytes(OP_CALL, 0);
3348 size_t ind = anonymousLocal(state);
3351 comprehensionInner(state, scannerBefore, parserBefore, body,
ind);
3355 size_t indFunc =
krk_addConstant(currentChunk(), OBJECT_VAL(subfunction));
3356 EMIT_OPERAND_OP(OP_CLOSURE, indFunc);
3357 doUpvalues(state, &subcompiler, subfunction);
3358 freeCompiler(&subcompiler);
3359 emitBytes(OP_CALL, 0);
3362 static size_t finishStarComma(
struct GlobalState * state,
size_t arg,
size_t * argBefore,
size_t *argAfter) {
3365 EMIT_OPERAND_OP(OP_MAKE_LIST,arg);
3367 emitByte(OP_LIST_EXTEND_TOP);
3369 if (arg == 0 && !check(TOKEN_COMMA)) {
3373 error(
"* expression not valid here");
3379 while (match(TOKEN_COMMA)) {
3381 if (match(TOKEN_ASTERISK)) {
3383 emitByte(OP_LIST_EXTEND_TOP);
3386 emitByte(OP_LIST_APPEND_TOP);
3393 emitByte(OP_TUPLE_FROM_LIST);
3415 int maybeValidAssignment = 0;
3417 size_t argCount = 0;
3418 size_t argAfter = 0;
3419 size_t argBefore = 0;
3422 startEatingWhitespace();
3424 if (check(TOKEN_RIGHT_PAREN)) {
3426 emitBytes(OP_TUPLE,0);
3427 }
else if (match(TOKEN_ASTERISK)) {
3428 argCount = finishStarComma(state, 0, &argBefore, &argAfter);
3429 maybeValidAssignment = 1;
3432 maybeValidAssignment = 1;
3435 if (match(TOKEN_FOR)) {
3437 maybeValidAssignment = 0;
3438 rewindChunk(currentChunk(), before);
3439 generatorExpression(state, scannerBefore, parserBefore, yieldInner);
3440 }
else if (match(TOKEN_COMMA)) {
3442 if (!check(TOKEN_RIGHT_PAREN)) {
3445 if (match(TOKEN_ASTERISK)) {
3446 argCount = finishStarComma(state, argCount, &argBefore, &argAfter);
3451 }
while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_PAREN));
3453 EMIT_OPERAND_OP(OP_TUPLE, argCount);
3458 stopEatingWhitespace();
3460 if (!match(TOKEN_RIGHT_PAREN)) {
3462 case TOKEN_EQUAL: error(
"Assignment value expression must be enclosed in parentheses.");
break;
3463 default: error(
"Expected ')' at end of parenthesized expression.");
break;
3469 error(
"Can not assign to empty target list.");
3470 }
else if (!maybeValidAssignment) {
3471 error(
"Can not assign to generator expression.");
3473 complexAssignment(state, before, scannerBefore, parserBefore, argCount, 1, argBefore, argAfter);
3475 }
else if (exprType ==
EXPR_ASSIGN_TARGET && (check(TOKEN_EQUAL) || check(TOKEN_COMMA) || check(TOKEN_RIGHT_PAREN))) {
3477 error(
"Can not assign to empty target list.");
3478 }
else if (!maybeValidAssignment) {
3479 error(
"Can not assign to generator expression.");
3481 rewindChunk(currentChunk(), before);
3482 complexAssignmentTargets(state, scannerBefore, parserBefore, argCount, 2, argBefore, argAfter);
3483 if (!matchComplexEnd(state)) {
3484 errorAtCurrent(
"Unexpected end of nested target list");
3495 static void listInner(
struct GlobalState * state,
size_t arg) {
3497 EMIT_OPERAND_OP(OP_LIST_APPEND, arg);
3500 static void finishStarList(
struct GlobalState * state,
size_t arg) {
3501 EMIT_OPERAND_OP(OP_MAKE_LIST, arg);
3504 emitByte(OP_LIST_EXTEND_TOP);
3506 while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_SQUARE)) {
3507 if (match(TOKEN_ASTERISK)) {
3509 emitByte(OP_LIST_EXTEND_TOP);
3512 emitByte(OP_LIST_APPEND_TOP);
3516 stopEatingWhitespace();
3518 consume(TOKEN_RIGHT_SQUARE,
"Expected ']' at end of list expression.");
3529 startEatingWhitespace();
3531 if (!check(TOKEN_RIGHT_SQUARE)) {
3534 if (match(TOKEN_ASTERISK)) {
3535 finishStarList(state, 0);
3540 if (match(TOKEN_FOR)) {
3542 rewindChunk(currentChunk(), before);
3545 comprehensionExpression(state, scannerBefore, parserBefore, listInner, OP_MAKE_LIST);
3547 size_t argCount = 1;
3548 while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_SQUARE)) {
3549 if (match(TOKEN_ASTERISK)) {
3550 finishStarList(state, argCount);
3556 EMIT_OPERAND_OP(OP_MAKE_LIST, argCount);
3560 EMIT_OPERAND_OP(OP_MAKE_LIST, 0);
3563 stopEatingWhitespace();
3565 consume(TOKEN_RIGHT_SQUARE,
"Expected ']' at end of list expression.");
3571 static void dictInner(
struct GlobalState * state,
size_t arg) {
3573 consume(TOKEN_COLON,
"Expected ':' after dict key.");
3575 EMIT_OPERAND_OP(OP_DICT_SET, arg);
3581 static void setInner(
struct GlobalState * state,
size_t arg) {
3583 EMIT_OPERAND_OP(OP_SET_ADD, arg);
3586 static void finishStarSet(
struct GlobalState * state,
size_t args) {
3587 EMIT_OPERAND_OP(OP_MAKE_SET, args);
3590 emitByte(OP_SET_UPDATE_TOP);
3592 while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_BRACE)) {
3593 if (match(TOKEN_ASTERISK)) {
3595 emitByte(OP_SET_UPDATE_TOP);
3598 emitByte(OP_SET_ADD_TOP);
3602 stopEatingWhitespace();
3603 consume(TOKEN_RIGHT_BRACE,
"Expected '}' at end of dict expression.");
3606 static void finishStarDict(
struct GlobalState * state,
size_t args) {
3607 EMIT_OPERAND_OP(OP_MAKE_DICT, args);
3610 emitByte(OP_DICT_UPDATE_TOP);
3612 while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_BRACE)) {
3613 if (match(TOKEN_POW)) {
3615 emitByte(OP_DICT_UPDATE_TOP);
3618 consume(TOKEN_COLON,
"Expected ':' after dict key.");
3620 emitByte(OP_DICT_SET_TOP);
3624 stopEatingWhitespace();
3625 consume(TOKEN_RIGHT_BRACE,
"Expected '}' at end of dict expression.");
3642 startEatingWhitespace();
3644 if (!check(TOKEN_RIGHT_BRACE)) {
3648 if (match(TOKEN_ASTERISK)) {
3649 finishStarSet(state, 0);
3651 }
else if (match(TOKEN_POW)) {
3652 finishStarDict(state, 0);
3657 if (check(TOKEN_COMMA) || check(TOKEN_RIGHT_BRACE)) {
3659 size_t argCount = 1;
3660 while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_BRACE)) {
3661 if (match(TOKEN_ASTERISK)) {
3662 finishStarSet(state, argCount);
3668 EMIT_OPERAND_OP(OP_MAKE_SET, argCount);
3669 }
else if (match(TOKEN_FOR)) {
3671 rewindChunk(currentChunk(), before);
3673 comprehensionExpression(state, scannerBefore, parserBefore, setInner, OP_MAKE_SET);
3676 consume(TOKEN_COLON,
"Expected ':' after dict key.");
3679 if (match(TOKEN_FOR)) {
3681 rewindChunk(currentChunk(), before);
3683 comprehensionExpression(state, scannerBefore, parserBefore, dictInner, OP_MAKE_DICT);
3690 size_t argCount = 2;
3691 while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_BRACE)) {
3692 if (match(TOKEN_POW)) {
3693 finishStarDict(state, argCount);
3697 consume(TOKEN_COLON,
"Expected ':' after dict key.");
3701 EMIT_OPERAND_OP(OP_MAKE_DICT, argCount);
3706 EMIT_OPERAND_OP(OP_MAKE_DICT, 0);
3709 stopEatingWhitespace();
3711 consume(TOKEN_RIGHT_BRACE,
"Expected '}' at end of dict expression.");
3716 rewindChunk(currentChunk(), rewind->
before);
3718 parsePrecedence(state,
PREC_OR);
3720 int thenJump = emitJump(OP_JUMP_IF_TRUE_OR_POP);
3721 consume(TOKEN_ELSE,
"Expected 'else' after ternary condition");
3728 int elseJump = emitJump(OP_JUMP);
3729 patchJump(thenJump);
3734 parsePrecedence(state,
PREC_OR);
3735 patchJump(elseJump);
3737 if (!check(TOKEN_IF)) {
3739 error(
"syntax error");
3743 state->
parser = outParser;
3746 static void complexAssignmentTargets(
struct GlobalState * state,
KrkScanner oldScanner,
Parser oldParser,
size_t targetCount,
int parenthesized,
size_t argBefore,
size_t argAfter) {
3747 emitBytes(OP_DUP, 0);
3750 if (argBefore > 255 || argAfter > 256) {
3751 error(
"Too many assignment targets");
3754 EMIT_OPERAND_OP(OP_UNPACK_EX,((argBefore << 8) | (argAfter-1)));
3756 EMIT_OPERAND_OP(OP_UNPACK,targetCount);
3758 EMIT_OPERAND_OP(OP_REVERSE,targetCount);
3762 state->
parser = oldParser;
3765 size_t checkTargetCount = 0;
3769 if (match(TOKEN_ASTERISK)) {
3771 errorAtCurrent(
"multiple *expr in assignment");
3779 if (checkTargetCount == targetCount && state->
parser.
previous.type == TOKEN_COMMA) {
3780 if (!match(parenthesized ? TOKEN_RIGHT_PAREN : TOKEN_EQUAL)) {
3781 goto _errorAtCurrent;
3785 if (checkTargetCount == targetCount && parenthesized) {
3787 goto _errorAtCurrent;
3791 if (checkTargetCount == targetCount && parenthesized) {
3792 if (parenthesized == 1 && !match(TOKEN_EQUAL)) {
3793 goto _errorAtCurrent;
3797 if (checkTargetCount == targetCount)
return;
3799 if (check(TOKEN_COMMA) || check(TOKEN_EQUAL) || check(TOKEN_RIGHT_PAREN)) {
3800 goto _errorAtCurrent;
3806 errorAtCurrent(
"Invalid complex assignment target");
3809 static void complexAssignment(
struct GlobalState * state,
ChunkRecorder before,
KrkScanner oldScanner,
Parser oldParser,
size_t targetCount,
int parenthesized,
size_t argBefore,
size_t argAfter) {
3811 rewindChunk(currentChunk(), before);
3818 complexAssignmentTargets(state, oldScanner,oldParser,targetCount,parenthesized, argBefore, argAfter);
3822 state->
parser = outParser;
3826 size_t expressionCount = 1;
3827 size_t argBefore = 0;
3828 size_t argAfter = 0;
3831 if (match(TOKEN_ASTERISK)) {
3832 expressionCount = finishStarComma(state, expressionCount, &argBefore, &argAfter);
3838 }
while (match(TOKEN_COMMA));
3840 EMIT_OPERAND_OP(OP_TUPLE,expressionCount);
3842 _maybeassign: (void)0;
3844 complexAssignment(state, rewind->
before, rewind->
oldScanner, rewind->
oldParser, expressionCount, 0, argBefore, argAfter);
3849 size_t argBefore = 0;
3850 size_t argAfter = 0;
3851 size_t totalArgs = finishStarComma(state,0, &argBefore, &argAfter);
3860 startEatingWhitespace();
3861 size_t argCount = 0, specialArgs = 0, keywordArgs = 0, seenKeywordUnpacking = 0;
3862 if (!check(TOKEN_RIGHT_PAREN)) {
3863 size_t chunkBefore = currentChunk()->count;
3867 if (check(TOKEN_RIGHT_PAREN))
break;
3868 if (match(TOKEN_ASTERISK) || check(TOKEN_POW)) {
3870 if (match(TOKEN_POW)) {
3871 seenKeywordUnpacking = 1;
3872 emitBytes(OP_EXPAND_ARGS, 2);
3876 if (seenKeywordUnpacking) {
3877 error(
"Iterable expansion follows keyword argument unpacking.");
3880 emitBytes(OP_EXPAND_ARGS, 1);
3885 if (match(TOKEN_IDENTIFIER)) {
3887 if (check(TOKEN_EQUAL)) {
3891 size_t ind = identifierConstant(state, &argName);
3892 EMIT_OPERAND_OP(OP_CONSTANT,
ind);
3905 }
else if (seenKeywordUnpacking) {
3906 error(
"Positional argument follows keyword argument unpacking");
3908 }
else if (keywordArgs) {
3909 error(
"Positional argument follows keyword argument");
3913 emitBytes(OP_EXPAND_ARGS, 0);
3919 if (argCount == 0 && match(TOKEN_FOR)) {
3920 currentChunk()->count = chunkBefore;
3921 generatorExpression(state, scannerBefore, parserBefore, yieldInner);
3923 if (match(TOKEN_COMMA)) {
3924 error(
"Generator expression must be parenthesized");
3930 }
while (match(TOKEN_COMMA));
3932 stopEatingWhitespace();
3933 consume(TOKEN_RIGHT_PAREN,
"Expected ')' after arguments.");
3941 EMIT_OPERAND_OP(OP_KWARGS, specialArgs);
3948 argCount += 1 + 2 * specialArgs;
3952 EMIT_OPERAND_OP(OP_CALL_METHOD, argCount);
3953 }
else if (exprType == EXPR_CLASS_PARAMETERS) {
3954 EMIT_OPERAND_OP(OP_CALL, (argCount + 2));
3956 EMIT_OPERAND_OP(OP_CALL, argCount);
3958 writeExpressionLocation(&left,&state->
parser.
previous,&
this,state);
3960 invalidTarget(state, exprType,
"function call");
3964 int endJump = emitJump(OP_JUMP_IF_FALSE_OR_POP);
3967 invalidTarget(state, exprType,
"operator");
3971 int endJump = emitJump(OP_JUMP_IF_TRUE_OR_POP);
3972 parsePrecedence(state,
PREC_OR);
3974 invalidTarget(state, exprType,
"operator");
3985 if (prefixRule == pstar && precedence >
PREC_COMMA) prefixRule = NULL;
3987 if (prefixRule == NULL) {
3989 case TOKEN_RIGHT_BRACE:
3990 case TOKEN_RIGHT_PAREN:
3991 case TOKEN_RIGHT_SQUARE:
3992 error(
"Unmatched '%.*s'",
3997 error(
"Unexpected end of line");
4000 error(
"Unexpected end of input");
4003 error(
"'%.*s' does not start an expression",
4012 prefixRule(state, exprType, &rewind);
4023 infixRule(state, exprType, &rewind);
4027 error(
"Invalid assignment target");
4032 static int maybeSingleExpression(
struct GlobalState * state) {
4044 if (check(TOKEN_STRING) || check(TOKEN_BIG_STRING)) {
4046 if (match(TOKEN_EOL)) {
4049 int isEof = check(TOKEN_EOF);
4057 if (isEof)
return 1;
4060 KrkToken doc = syntheticToken(
"__doc__");
4061 size_t ind = identifierConstant(state, &doc);
4062 EMIT_OPERAND_OP(OP_DEFINE_GLOBAL,
ind);
4079 if (match(TOKEN_SEMICOLON)) {
4081 simpleStatement(state);
4087 if (match(TOKEN_EOL) && !check(TOKEN_EOF)) {
4095 if (check(TOKEN_EOF))
4099 errorAfterStatement(state);
4107 void _createAndBind_compilerClass(
void) {
4108 KrkClass * CompilerState = ADD_BASE_CLASS(KRK_BASE_CLASS(CompilerState),
"CompilerState", KRK_BASE_CLASS(
object));
4110 CompilerState->
_ongcscan = _GlobalState_gcscan;
4111 CompilerState->
_ongcsweep = _GlobalState_gcsweep;
4112 CompilerState->
obj.
flags |= KRK_OBJ_FLAGS_NO_INHERIT;
4149 if (maybeSingleExpression(state)) {
4153 while (!match(TOKEN_EOF)) {
4157 if (check(TOKEN_EOL) || check(TOKEN_INDENTATION) || check(TOKEN_EOF)) {
4164 freeCompiler(&compiler);
4177 #define RULE(token, a, b, c) [TOKEN_ ## token] = {a, b, c}
4193 RULE(LEFT_BRACE, dict, NULL, PREC_NONE),
4194 RULE(RIGHT_PAREN, NULL, NULL, PREC_NONE),
4195 RULE(RIGHT_SQUARE, NULL, NULL, PREC_NONE),
4196 RULE(RIGHT_BRACE, NULL, NULL, PREC_NONE),
4197 RULE(COLON, NULL, NULL, PREC_NONE),
4198 RULE(SEMICOLON, NULL, NULL, PREC_NONE),
4199 RULE(EQUAL, NULL, NULL, PREC_NONE),
4200 RULE(WALRUS, NULL, NULL, PREC_NONE),
4201 RULE(PLUS_EQUAL, NULL, NULL, PREC_NONE),
4202 RULE(MINUS_EQUAL, NULL, NULL, PREC_NONE),
4203 RULE(PLUS_PLUS, NULL, NULL, PREC_NONE),
4204 RULE(MINUS_MINUS, NULL, NULL, PREC_NONE),
4205 RULE(CARET_EQUAL, NULL, NULL, PREC_NONE),
4206 RULE(PIPE_EQUAL, NULL, NULL, PREC_NONE),
4207 RULE(LSHIFT_EQUAL, NULL, NULL, PREC_NONE),
4208 RULE(RSHIFT_EQUAL, NULL, NULL, PREC_NONE),
4209 RULE(AMP_EQUAL, NULL, NULL, PREC_NONE),
4210 RULE(SOLIDUS_EQUAL, NULL, NULL, PREC_NONE),
4211 RULE(DSOLIDUS_EQUAL,NULL, NULL, PREC_NONE),
4212 RULE(ASTERISK_EQUAL,NULL, NULL, PREC_NONE),
4213 RULE(MODULO_EQUAL, NULL, NULL, PREC_NONE),
4214 RULE(AT_EQUAL, NULL, NULL, PREC_NONE),
4215 RULE(POW_EQUAL, NULL, NULL, PREC_NONE),
4216 RULE(ARROW, NULL, NULL, PREC_NONE),
4217 RULE(MINUS, unary, binary,
PREC_SUM),
4218 RULE(PLUS, unary, binary,
PREC_SUM),
4219 RULE(TILDE, unary, NULL, PREC_NONE),
4220 RULE(BANG, unary, NULL, PREC_NONE),
4222 RULE(DOUBLE_SOLIDUS,NULL, binary,
PREC_TERM),
4223 RULE(ASTERISK, pstar, binary,
PREC_TERM),
4241 RULE(IDENTIFIER, variable, NULL, PREC_NONE),
4242 RULE(STRING,
string, NULL, PREC_NONE),
4243 RULE(BIG_STRING,
string, NULL, PREC_NONE),
4244 RULE(PREFIX_B,
string, NULL, PREC_NONE),
4245 RULE(PREFIX_F,
string, NULL, PREC_NONE),
4246 RULE(PREFIX_R,
string, NULL, PREC_NONE),
4247 RULE(NUMBER, number, NULL, PREC_NONE),
4250 RULE(FALSE, literal, NULL, PREC_NONE),
4251 RULE(NONE, literal, NULL, PREC_NONE),
4252 RULE(TRUE, literal, NULL, PREC_NONE),
4253 RULE(ELLIPSIS, ellipsis, NULL, PREC_NONE),
4254 RULE(YIELD, yield, NULL, PREC_NONE),
4255 RULE(AWAIT, await, NULL, PREC_NONE),
4256 RULE(LAMBDA, lambda, NULL, PREC_NONE),
4257 RULE(SUPER, super_, NULL, PREC_NONE),
4258 RULE(CLASS, NULL, NULL, PREC_NONE),
4259 RULE(ELSE, NULL, NULL, PREC_NONE),
4260 RULE(FOR, NULL, NULL, PREC_NONE),
4261 RULE(DEF, NULL, NULL, PREC_NONE),
4262 RULE(DEL, NULL, NULL, PREC_NONE),
4263 RULE(LET, NULL, NULL, PREC_NONE),
4264 RULE(RETURN, NULL, NULL, PREC_NONE),
4265 RULE(WHILE, NULL, NULL, PREC_NONE),
4266 RULE(BREAK, NULL, NULL, PREC_NONE),
4267 RULE(CONTINUE, NULL, NULL, PREC_NONE),
4268 RULE(IMPORT, NULL, NULL, PREC_NONE),
4269 RULE(RAISE, NULL, NULL, PREC_NONE),
4270 RULE(ASYNC, NULL, NULL, PREC_NONE),
4271 RULE(PASS, NULL, NULL, PREC_NONE),
4272 RULE(ASSERT, NULL, NULL, PREC_NONE),
4273 RULE(FINALLY, NULL, NULL, PREC_NONE),
4274 RULE(ELIF, NULL, NULL, PREC_NONE),
4275 RULE(TRY, NULL, NULL, PREC_NONE),
4276 RULE(EXCEPT, NULL, NULL, PREC_NONE),
4277 RULE(AS, NULL, NULL, PREC_NONE),
4278 RULE(FROM, NULL, NULL, PREC_NONE),
4279 RULE(WITH, NULL, NULL, PREC_NONE),
4284 RULE(INDENTATION, NULL, NULL, PREC_NONE),
4285 RULE(ERROR, NULL, NULL, PREC_NONE),
4286 RULE(EOL, NULL, NULL, PREC_NONE),
4287 RULE(EOF, NULL, NULL, PREC_NONE),
4288 RULE(RETRY, NULL, NULL, PREC_NONE),
4291 static ParseRule * getRule(KrkTokenType type) {
ParseRule krk_parseRules[]
Parse rules table.
FunctionType
Function compilation type.
ExpressionType
Expression type.
struct Compiler Compiler
Subcompiler state.
KrkCodeObject * krk_compile(const char *src, const char *fileName)
Compile a source string to bytecode.
struct RewindState RewindState
Compiler emit and parse state prior to this expression.
Precedence
Parse precedence ladder.
struct ClassCompiler ClassCompiler
Class compilation context.
void(* ParseFn)(struct GlobalState *, int, struct RewindState *)
Subexpression parser function.
struct ChunkRecorder ChunkRecorder
Bytecode emitter backtracking breadcrumb.
Exported methods for the source compiler.
Functions for debugging bytecode execution.
void krk_disassembleCodeObject(FILE *f, KrkCodeObject *func, const char *name)
Print a disassembly of 'func' to the stream 'f'.
Top-level header with configuration macros.
Functions for dealing with garbage collection and memory allocation.
void krk_markObject(KrkObj *object)
During a GC scan cycle, mark an object as used.
KrkValue krk_parse_float(const char *s, size_t l)
Parse a string into a float.
Struct definitions for core object types.
Definitions used by the token scanner.
void krk_ungetToken(KrkScanner *, KrkToken token)
Push a token back to the scanner to be reprocessed.
KrkToken krk_scanToken(KrkScanner *)
Read the next token from the scanner.
KrkScanner krk_initScanner(const char *src)
Initialize the compiler to scan tokens from 'src'.
KrkScanner krk_tellScanner(KrkScanner *)
Retreive a copy of the current scanner state.
void krk_rewindScanner(KrkScanner *, KrkScanner to)
Rewind the scanner to a previous state.
Bytecode emitter backtracking breadcrumb.
size_t count
Offset into the bytecode.
size_t constants
Number of constants in the constants table.
size_t lines
Offset into the line map.
size_t expressions
Number of expression mapping entries.
Class compilation context.
struct ClassCompiler * enclosing
Enclosing class scope.
int hasAnnotations
Flag indicating if an annotation dictionary has been attached to this class.
KrkToken name
Name of the current class.
size_t continueCount
Number of continue statements.
size_t localNameCapacity
How much space is available in the codeobject's local names table.
struct IndexWithNext * properties
Linked list of class property constant indices.
FunctionType type
Type of function being compiled.
size_t continueSpace
Space in continues array.
size_t optionsFlags
Special options imports; similar to future in Python.
size_t localsSpace
Space in the locals array.
int delSatisfied
Flag indicating if a 'del' target has been completed.
struct Compiler * enclosed
Subcompiler we are enclosing, need for type annotation compilation.
size_t loopLocalCount
Tracks how many locals to pop off the stack when exiting a loop.
size_t localCount
Total number of local variables.
size_t scopeDepth
Depth of nested scope blocks.
size_t breakSpace
Space in breaks array.
size_t upvaluesSpace
Space in the upvalues array.
Local * locals
Array of local variable references.
struct LoopExit * continues
Array of loop exit instruction indices for continue statements.
struct LoopExit * breaks
Array of loop exit instruction indices for break statements.
size_t annotationCount
Number of type annotations found while compiling function signature.
KrkCodeObject * codeobject
Bytecode emitter.
size_t breakCount
Number of break statements.
struct Compiler * enclosing
Enclosing function compiler, or NULL for a module.
Upvalue * upvalues
Array of upvalue references. Count is stored in the codeobject.
int unnamedArgs
Number of positional arguments that will not be assignable through keywords.
KrkScanner scanner
Scanner state.
Parser parser
Parser state.
ClassCompiler * currentClass
Current in-progress class definition (or NULL)
Compiler * current
Current compiler (in-progress code object) state.
KrkInstance inst
Base instance.
size_t ind
Index of an identifier constant.
struct IndexWithNext * next
Linked list next pointer.
Opcode chunk of a code object.
size_t krk_writeConstant(KrkChunk *chunk, KrkValue value, size_t line)
Add a new constant and write an instruction for it.
size_t krk_addConstant(KrkChunk *chunk, KrkValue value)
Add a new constant value to an opcode chunk.
void krk_writeChunk(KrkChunk *chunk, uint8_t byte, size_t line)
Append a byte to an opcode chunk.
KrkCleanupCallback _ongcsweep
C function to call when the garbage collector is discarding an instance of this class.
KrkCleanupCallback _ongcscan
C function to call when the garbage collector visits an instance of this class in the scan phase.
size_t allocSize
Size to allocate when creating instances of this class.
void krk_finalizeClass(KrkClass *_class)
Finalize a class by collecting pointers to core methods.
unsigned short potentialPositionals
Precalculated positional arguments for complex argument processing.
size_t overlongJumpsCount
Number of entries in pessimal jump table.
KrkChunk chunk
Bytecode data.
size_t upvalueCount
Number of upvalues this function collects as a closure.
void krk_debug_addExpression(KrkCodeObject *codeobject, uint8_t start, uint8_t midStart, uint8_t midEnd, uint8_t end)
Add an expression mapping to the bytecode chunk.
KrkLocalEntry * localNames
Stores the names of local variables used in the function, for debugging.
unsigned short keywordArgs
Arity of keyword (default) arguments.
KrkOverlongJump * overlongJumps
Pessimal overlong jump container.
unsigned short requiredArgs
Arity of required (non-default) arguments.
KrkString * docstring
Docstring attached to the function.
KrkCodeObject * krk_newCodeObject(void)
Create a new, uninitialized code object.
size_t localNameCount
Number of entries in localNames.
KrkString * name
Name of the function.
size_t overlongJumpsCapacity
Number of possible entries in pessimal jump table.
KrkString * qualname
The dotted name of the function.
Map entry of opcode offsets to expressions spans.
KrkInstance * krk_newInstance(KrkClass *_class)
Create a new instance of the given class.
KrkTable fields
Attributes table.
Map entry of instruction offsets to line numbers.
Metadata on a local variable name in a function.
size_t birthday
Instruction offset that this local name became valid on.
KrkString * name
Name of the local.
size_t id
Local ID as used by opcodes; offset from the frame's stack base.
size_t deathday
Instruction offset that this local name becomes invalid on.
The most basic object type.
uint16_t flags
General object flags, mostly related to garbage collection.
uint16_t intendedTarget
High bytes of the intended target.
uint8_t originalOpcode
Original jump opcode to execute.
uint32_t instructionOffset
Instruction (operand offset) this jump target applies to.
Immutable sequence of Unicode codepoints.
KrkString * krk_copyString(const char *chars, size_t length)
Obtain a string object representation of the given C string.
char * chars
UTF8 canonical data.
size_t length
String length in bytes.
size_t krk_codepointToBytes(krk_integer_type value, unsigned char *out)
Convert an integer codepoint to a UTF-8 byte representation.
int krk_tableGet(KrkTable *table, KrkValue key, KrkValue *value)
Obtain the value associated with a key in a table.
void krk_attachNamedObject(KrkTable *table, const char name[], KrkObj *obj)
Attach an object to an attribute table.
void krk_attachNamedValue(KrkTable *table, const char name[], KrkValue obj)
Attach a value to an attribute table.
int krk_tableGet_fast(KrkTable *table, struct KrkString *str, KrkValue *value)
Obtain the value associated with a string key in a table.
KrkValue currentException
A token from the scanner.
void krk_writeValueArray(KrkValueArray *array, KrkValue value)
Add a value to a value array.
Stack reference or primative value.
Local variable reference.
KrkToken name
Token that provided the name for this variable.
ssize_t depth
Stack depth, or -1 if uninitialized.
char isCaptured
Flag indicating if the variable is captured by a closure.
Tracks 'break' and 'continue' statements.
KrkToken token
Token for this exit statement, so its location can be printed in an error message.
int offset
Offset of the jump expression to patch.
ParseFn infix
Parse function to call when this token appears after an expression.
Precedence precedence
Precedence ordering for Pratt parsing, Precedence.
ParseFn prefix
Parse function to call when this token appears at the start of an expression.
KrkToken previous
Last token matched, consumed, or advanced over.
KrkToken current
Token to be parsed.
unsigned int eatingWhitespace
Depth of whitespace-ignoring parse functions.
char hadError
Flag indicating if the parser encountered an error.
Compiler emit and parse state prior to this expression.
ChunkRecorder before
Bytecode and constant table output offsets.
Parser oldParser
Previous/current tokens.
KrkScanner oldScanner
Scanner cursor state.
Inline flexible string array.
Closure upvalue reference.
char isLocal
Flag indicating if Kuroko Language Reference is a local or upvalue index.
KrkToken name
Name for direct lookup. Mainly for non-automatically-populated upvalue cells.
size_t index
Enclosing local index or upvalue index.
Utilities for creating native bindings.
void krk_pushStringBuilderStr(struct StringBuilder *sb, const char *str, size_t len)
Append a string to the end of a string builder.
KrkValue krk_finishStringBuilderBytes(struct StringBuilder *sb)
Finalize a string builder in a bytes object.
KrkValue krk_discardStringBuilder(struct StringBuilder *sb)
Discard the contents of a string builder.
KrkValue krk_finishStringBuilder(struct StringBuilder *sb)
Finalize a string builder into a string object.
void krk_pushStringBuilder(struct StringBuilder *sb, char c)
Add a character to the end of a string builder.
Core API for the bytecode virtual machine.
krk_threadLocal KrkThreadState krk_currentThread
Thread-local VM state.
#define vm
Convenience macro for namespacing.
KrkValue krk_pop(void)
Pop the top of the stack.
void krk_push(KrkValue value)
Push a stack value.