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)
283 static void _GlobalState_gcscan(
KrkInstance * _self) {
285 Compiler * compiler =
self->current;
286 while (compiler != NULL) {
293 static void _GlobalState_gcsweep(
KrkInstance * _self) {
297 #define currentChunk() (&state->current->codeobject->chunk)
299 #define EMIT_OPERAND_OP(opc, arg) do { if (arg < 256) { emitBytes(opc, arg); } \
300 else { emitBytes(opc ## _LONG, arg >> 16); emitBytes(arg >> 8, arg); } } while (0)
302 static int isMethod(
int type) {
306 static int isCoroutine(
int type) {
310 static char * calculateQualName(
struct GlobalState * state) {
311 static char space[1024];
313 char * writer = &space[1023];
315 #define WRITE(s) do { \
316 size_t len = strlen(s); \
317 if (writer - len < space) goto _exit; \
319 memcpy(writer, s, len); \
344 out->count = from.
count;
345 out->linesCount = from.
lines;
355 compiler->
type = type;
380 char * qualname = calculateQualName(state);
384 if (isMethod(type) && !(compiler->
optionsFlags & OPTIONS_FLAG_NO_IMPLICIT_SELF)) {
388 local->
name.start =
"self";
389 local->
name.length = 4;
390 renameLocal(state, 0, local->
name);
399 local->
name.start =
"";
400 local->
name.length = 0;
401 renameLocal(state, 0, local->
name);
409 static void rememberClassProperty(
struct GlobalState * state,
size_t ind) {
417 static ParseRule * getRule(KrkTokenType type);
420 static void defDeclaration(
struct GlobalState * state);
421 static void asyncDeclaration(
struct GlobalState * state,
int);
423 static void declaration(
struct GlobalState * state);
425 static void declareVariable(
struct GlobalState * state);
429 static void complexAssignmentTargets(
struct GlobalState * state,
KrkScanner oldScanner,
Parser oldParser,
size_t targetCount,
int parenthesized,
size_t argBefore,
size_t argAfter);
430 static int invalidTarget(
struct GlobalState * state,
int exprType,
const char * description);
434 if (!token->linePtr) token->linePtr = token->start;
436 while (token->linePtr[i] && token->linePtr[i] !=
'\n') i++;
455 #ifdef KRK_NO_DOCUMENTATION
456 # define raiseSyntaxError(token, ...) do { if (state->parser.hadError) break; krk_runtimeError(vm.exceptions->syntaxError, "syntax error"); finishError(state,token); } while (0)
458 # define raiseSyntaxError(token, ...) do { if (state->parser.hadError) break; krk_runtimeError(vm.exceptions->syntaxError, __VA_ARGS__); finishError(state,token); } while (0)
461 #define error(...) raiseSyntaxError(&state->parser.previous, __VA_ARGS__)
462 #define errorAtCurrent(...) raiseSyntaxError(&state->parser.current, __VA_ARGS__)
481 #define advance() _advance(state)
483 static void _skipToEnd(
struct GlobalState * state) {
487 #define skipToEnd() _skipToEnd(state)
489 static void _startEatingWhitespace(
struct GlobalState * state) {
494 #define startEatingWhitespace() _startEatingWhitespace(state)
496 static void _stopEatingWhitespace(
struct GlobalState * state) {
498 error(
"Internal scanner error: Invalid nesting of `startEatingWhitespace`/`stopEatingWhitespace` calls.");
503 #define stopEatingWhitespace() _stopEatingWhitespace(state)
505 static void _consume(
struct GlobalState * state, KrkTokenType type,
const char * message) {
514 errorAtCurrent(
"%s", message);
517 #define consume(...) _consume(state,__VA_ARGS__)
519 static int _check(
struct GlobalState * state, KrkTokenType type) {
523 #define check(t) _check(state,t)
525 static int _match(
struct GlobalState * state, KrkTokenType type) {
526 if (!check(type))
return 0;
531 #define match(t) _match(state,t)
534 return (a->length == b->length && memcmp(a->start, b->start, a->length) == 0);
540 token.length = (int)strlen(text);
545 #define syntheticToken(t) _syntheticToken(state,t)
547 static void _emitByte(
struct GlobalState * state, uint8_t
byte) {
551 #define emitByte(b) _emitByte(state,b)
553 static void _emitBytes(
struct GlobalState * state, uint8_t byte1, uint8_t byte2) {
558 #define emitBytes(a,b) _emitBytes(state,a,b)
560 static void emitReturn(
struct GlobalState * state) {
570 for (
size_t i = 0; i <
function->localNameCount; i++) {
571 if (function->localNames[i].deathday == 0) {
575 function->localNames = GROW_ARRAY(
KrkLocalEntry, function->localNames, \
583 for (
int i = 0; i <
function->potentialPositionals; ++i) {
584 if (i < state->current->unnamedArgs) {
594 size_t args =
function->potentialPositionals;
595 if (function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_ARGS) {
604 for (
int i = 0; i <
function->keywordArgs; ++i) {
611 args +=
function->keywordArgs;
613 if (function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_KWS) {
622 function->totalArguments =
function->potentialPositionals +
function->keywordArgs + !!(
function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_ARGS) + !!(function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_KWS);
624 #ifndef KRK_NO_DISASSEMBLY
634 static void freeCompiler(
Compiler * compiler) {
651 #define emitConstant(v) _emitConstant(state,v)
653 static int isMangleable(
const char * name,
size_t len) {
654 return (len > 2 && name[0] ==
'_' && name[1] ==
'_' && name[len-1] !=
'_' && (len < 4 || name[len-2] !=
'_'));
658 if (state->
currentClass && isMangleable(name->start, name->length)) {
662 while (classLength && *className ==
'_') {
668 krk_pushStringBuilderFormat(&sb,
"_%.*s%.*s",
669 (
int)classLength, className,
670 (
int)name->length, name->start);
683 for (ssize_t i = compiler->
localCount - 1; i >= 0; i--) {
685 if (identifiersEqual(name, &local->
name)) {
686 if (local->
depth == -1) {
687 error(
"Invalid recursive reference in declaration initializer");
689 if (local->
depth == -2) {
724 renameLocal(state, out, name);
730 static void declareVariable(
struct GlobalState * state) {
737 if (identifiersEqual(name, &local->
name)) {
738 error(
"Duplicate definition for local '%.*s' in this scope.", (
int)name->literalWidth, name->start);
741 addLocal(state, *name);
744 static ssize_t parseVariable(
struct GlobalState * state,
const char * errorMessage) {
745 consume(TOKEN_IDENTIFIER, errorMessage);
747 declareVariable(state);
753 error(
"Conflicting declaration of global '%.*s' is invalid when 'compile_time_builtins' is enabled.",
762 static void markInitialized(
struct GlobalState * state) {
767 static size_t anonymousLocal(
struct GlobalState * state) {
768 size_t val = addLocal(state, syntheticToken(
""));
769 markInitialized(state);
773 static void defineVariable(
struct GlobalState * state,
size_t global) {
775 markInitialized(state);
779 EMIT_OPERAND_OP(OP_DEFINE_GLOBAL, global);
784 invalidTarget(state, exprType,
"literal");
789 double value = strtod(start, NULL);
790 emitConstant(FLOATING_VAL(value));
792 error(
"no float support");
800 if (IS_NONE(result)) {
801 error(
"invalid numeric literal");
804 emitConstant(result);
807 static int _emitJump(
struct GlobalState * state, uint8_t opcode) {
809 emitBytes(0xFF, 0xFF);
810 return currentChunk()->count - 2;
812 #define emitJump(o) _emitJump(state,o)
814 static void _patchJump(
struct GlobalState * state,
int offset) {
815 int jump = currentChunk()->count - offset - 2;
816 if (jump > 0xFFFF) error(
"Jump offset is too large for opcode.");
818 currentChunk()->code[offset] = (jump >> 8) & 0xFF;
819 currentChunk()->code[offset + 1] = (jump) & 0xFF;
822 #define patchJump(o) _patchJump(state,o)
824 static void compareChained(
struct GlobalState * state,
int inner) {
826 if (operatorType == TOKEN_NOT) consume(TOKEN_IN,
"'in' must follow infix 'not'");
827 int invert = (operatorType == TOKEN_IS && match(TOKEN_NOT));
829 ParseRule * rule = getRule(operatorType);
834 emitBytes(OP_DUP, 1);
837 switch (operatorType) {
838 case TOKEN_BANG_EQUAL: emitBytes(OP_EQUAL, OP_NOT);
break;
839 case TOKEN_EQUAL_EQUAL: emitByte(OP_EQUAL);
break;
840 case TOKEN_GREATER: emitByte(OP_GREATER);
break;
841 case TOKEN_GREATER_EQUAL: emitByte(OP_GREATER_EQUAL);
break;
842 case TOKEN_LESS: emitByte(OP_LESS);
break;
843 case TOKEN_LESS_EQUAL: emitByte(OP_LESS_EQUAL);
break;
845 case TOKEN_IS: emitByte(OP_IS);
if (invert) emitByte(OP_NOT);
break;
847 case TOKEN_IN: emitByte(OP_INVOKE_CONTAINS);
break;
848 case TOKEN_NOT: emitBytes(OP_INVOKE_CONTAINS, OP_NOT);
break;
850 default: error(
"Invalid binary comparison operator?");
break;
854 size_t exitJump = emitJump(OP_JUMP_IF_FALSE_OR_POP);
856 compareChained(state, 1);
860 emitBytes(OP_SWAP,OP_POP);
870 compareChained(state, 0);
871 invalidTarget(state, exprType,
"operator");
876 ParseRule * rule = getRule(operatorType);
878 invalidTarget(state, exprType,
"operator");
880 switch (operatorType) {
881 case TOKEN_PIPE: emitByte(OP_BITOR);
break;
882 case TOKEN_CARET: emitByte(OP_BITXOR);
break;
883 case TOKEN_AMPERSAND: emitByte(OP_BITAND);
break;
884 case TOKEN_LEFT_SHIFT: emitByte(OP_SHIFTLEFT);
break;
885 case TOKEN_RIGHT_SHIFT: emitByte(OP_SHIFTRIGHT);
break;
887 case TOKEN_PLUS: emitByte(OP_ADD);
break;
888 case TOKEN_MINUS: emitByte(OP_SUBTRACT);
break;
889 case TOKEN_ASTERISK: emitByte(OP_MULTIPLY);
break;
890 case TOKEN_POW: emitByte(OP_POW);
break;
891 case TOKEN_SOLIDUS: emitByte(OP_DIVIDE);
break;
892 case TOKEN_DOUBLE_SOLIDUS: emitByte(OP_FLOORDIV);
break;
893 case TOKEN_MODULO: emitByte(OP_MODULO);
break;
894 case TOKEN_IN: emitByte(OP_EQUAL);
break;
895 case TOKEN_AT: emitByte(OP_MATMUL);
break;
900 static int matchAssignment(
struct GlobalState * state) {
904 static int checkEndOfDel(
struct GlobalState * state) {
905 if (check(TOKEN_COMMA) || check(TOKEN_EOL) || check(TOKEN_EOF) || check(TOKEN_SEMICOLON)) {
912 static int matchComplexEnd(
struct GlobalState * state) {
913 return match(TOKEN_COMMA) ||
914 match(TOKEN_EQUAL) ||
915 match(TOKEN_RIGHT_PAREN);
918 static int invalidTarget(
struct GlobalState * state,
int exprType,
const char * description) {
920 error(
"Can not assign to %s", description);
925 error(
"Can not delete %s", description);
932 static void assignmentValue(
struct GlobalState * state) {
934 if (type == TOKEN_PLUS_PLUS || type == TOKEN_MINUS_MINUS) {
935 emitConstant(INTEGER_VAL(1));
941 case TOKEN_PIPE_EQUAL: emitByte(OP_INPLACE_BITOR);
break;
942 case TOKEN_CARET_EQUAL: emitByte(OP_INPLACE_BITXOR);
break;
943 case TOKEN_AMP_EQUAL: emitByte(OP_INPLACE_BITAND);
break;
944 case TOKEN_LSHIFT_EQUAL: emitByte(OP_INPLACE_SHIFTLEFT);
break;
945 case TOKEN_RSHIFT_EQUAL: emitByte(OP_INPLACE_SHIFTRIGHT);
break;
947 case TOKEN_PLUS_EQUAL: emitByte(OP_INPLACE_ADD);
break;
948 case TOKEN_PLUS_PLUS: emitByte(OP_INPLACE_ADD);
break;
949 case TOKEN_MINUS_EQUAL: emitByte(OP_INPLACE_SUBTRACT);
break;
950 case TOKEN_MINUS_MINUS: emitByte(OP_INPLACE_SUBTRACT);
break;
951 case TOKEN_ASTERISK_EQUAL: emitByte(OP_INPLACE_MULTIPLY);
break;
952 case TOKEN_POW_EQUAL: emitByte(OP_INPLACE_POW);
break;
953 case TOKEN_SOLIDUS_EQUAL: emitByte(OP_INPLACE_DIVIDE);
break;
954 case TOKEN_DSOLIDUS_EQUAL: emitByte(OP_INPLACE_FLOORDIV);
break;
955 case TOKEN_MODULO_EQUAL: emitByte(OP_INPLACE_MODULO);
break;
956 case TOKEN_AT_EQUAL: emitByte(OP_INPLACE_MATMUL);
break;
959 error(
"Unexpected operand in assignment");
964 static void expression(
struct GlobalState * state) {
968 static void sliceExpression(
struct GlobalState * state) {
970 if (match(TOKEN_COLON)) {
976 if (isSlice || match(TOKEN_COLON)) {
978 if (check(TOKEN_RIGHT_SQUARE) || check(TOKEN_COMMA)) {
981 EMIT_OPERAND_OP(OP_SLICE, 2);
983 if (check(TOKEN_COLON)) {
990 if (match(TOKEN_COLON) && !check(TOKEN_RIGHT_SQUARE) && !check(TOKEN_COMMA)) {
993 EMIT_OPERAND_OP(OP_SLICE, 3);
996 EMIT_OPERAND_OP(OP_SLICE, 2);
1004 sliceExpression(state);
1006 if (match(TOKEN_COMMA)) {
1007 size_t argCount = 1;
1008 if (!check(TOKEN_RIGHT_SQUARE)) {
1010 sliceExpression(state);
1012 }
while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_SQUARE));
1014 EMIT_OPERAND_OP(OP_TUPLE, argCount);
1017 consume(TOKEN_RIGHT_SQUARE,
"Expected ']' after index.");
1019 if (matchComplexEnd(state)) {
1020 EMIT_OPERAND_OP(OP_DUP, 2);
1021 emitByte(OP_INVOKE_SETTER);
1029 emitByte(OP_INVOKE_SETTER);
1031 emitBytes(OP_DUP, 1);
1032 emitBytes(OP_DUP, 1);
1033 emitByte(OP_INVOKE_GETTER);
1034 assignmentValue(state);
1035 emitByte(OP_INVOKE_SETTER);
1037 emitByte(OP_INVOKE_DELETE);
1039 emitByte(OP_INVOKE_GETTER);
1043 static void attributeUnpack(
struct GlobalState * state,
int exprType) {
1044 startEatingWhitespace();
1045 size_t argCount = 0;
1046 size_t argSpace = 1;
1047 ssize_t * args = GROW_ARRAY(ssize_t,NULL,0,1);
1050 if (argSpace < argCount + 1) {
1051 size_t old = argSpace;
1052 argSpace = GROW_CAPACITY(old);
1053 args = GROW_ARRAY(ssize_t,args,old,argSpace);
1055 consume(TOKEN_IDENTIFIER,
"Expected attribute name");
1057 args[argCount++] = ind;
1058 }
while (match(TOKEN_COMMA));
1060 stopEatingWhitespace();
1061 consume(TOKEN_RIGHT_PAREN,
"Expected ')' after attribute list");
1064 error(
"Can not assign to '.(' in multiple target list");
1069 size_t expressionCount = 0;
1073 }
while (match(TOKEN_COMMA));
1075 if (expressionCount == 1 && argCount > 1) {
1076 EMIT_OPERAND_OP(OP_UNPACK, argCount);
1077 }
else if (expressionCount > 1 && argCount == 1) {
1078 EMIT_OPERAND_OP(OP_TUPLE, expressionCount);
1079 }
else if (expressionCount != argCount) {
1080 error(
"Invalid assignment to attribute pack");
1084 for (
size_t i = argCount; i > 0; i--) {
1086 emitBytes(OP_DUP, i);
1089 EMIT_OPERAND_OP(OP_SET_PROPERTY, args[i-1]);
1095 for (
size_t i = 0; i < argCount; i++) {
1096 emitBytes(OP_DUP,0);
1097 EMIT_OPERAND_OP(OP_GET_PROPERTY,args[i]);
1101 emitBytes(OP_TUPLE,argCount);
1105 FREE_ARRAY(ssize_t,args,argSpace);
1110 if (match(TOKEN_LEFT_PAREN)) {
1111 attributeUnpack(state, exprType);
1114 consume(TOKEN_IDENTIFIER,
"Expected property name");
1117 if (matchComplexEnd(state)) {
1118 EMIT_OPERAND_OP(OP_DUP, 1);
1119 EMIT_OPERAND_OP(OP_SET_PROPERTY, ind);
1127 EMIT_OPERAND_OP(OP_SET_PROPERTY, ind);
1129 emitBytes(OP_DUP, 0);
1130 EMIT_OPERAND_OP(OP_GET_PROPERTY, ind);
1131 assignmentValue(state);
1132 EMIT_OPERAND_OP(OP_SET_PROPERTY, ind);
1134 EMIT_OPERAND_OP(OP_DEL_PROPERTY, ind);
1135 }
else if (match(TOKEN_LEFT_PAREN)) {
1136 EMIT_OPERAND_OP(OP_GET_METHOD, ind);
1139 EMIT_OPERAND_OP(OP_GET_PROPERTY, ind);
1144 invalidTarget(state, exprType,
"literal");
1146 case TOKEN_FALSE: emitByte(OP_FALSE);
break;
1147 case TOKEN_NONE: emitByte(OP_NONE);
break;
1148 case TOKEN_TRUE: emitByte(OP_TRUE);
break;
1153 static void typeHintLocal(
struct GlobalState * state) {
1163 static void letDeclaration(
struct GlobalState * state) {
1164 size_t argCount = 0;
1165 size_t argSpace = 1;
1166 ssize_t * args = GROW_ARRAY(ssize_t,NULL,0,1);
1169 if (argSpace < argCount + 1) {
1170 size_t old = argSpace;
1171 argSpace = GROW_CAPACITY(old);
1172 args = GROW_ARRAY(ssize_t,args,old,argSpace);
1174 ssize_t ind = parseVariable(state,
"Expected variable name.");
1180 args[argCount++] = ind;
1182 if (check(TOKEN_COLON)) {
1186 typeHintLocal(state);
1188 KrkToken annotations = syntheticToken(
"__annotations__");
1189 size_t ind = identifierConstant(state, &annotations);
1190 EMIT_OPERAND_OP(OP_GET_GLOBAL, ind);
1191 emitConstant(OBJECT_VAL(
krk_copyString(name.start, name.length)));
1193 emitBytes(OP_INVOKE_SETTER, OP_POP);
1196 }
while (match(TOKEN_COMMA));
1198 if (match(TOKEN_EQUAL)) {
1199 size_t expressionCount = 0;
1203 }
while (match(TOKEN_COMMA));
1204 if (expressionCount == 1 && argCount > 1) {
1205 EMIT_OPERAND_OP(OP_UNPACK, argCount);
1206 }
else if (expressionCount == argCount) {
1208 }
else if (expressionCount > 1 && argCount == 1) {
1209 EMIT_OPERAND_OP(OP_TUPLE, expressionCount);
1211 error(
"Invalid sequence unpack in 'let' statement");
1216 for (
size_t i = 0; i < argCount; ++i) {
1222 for (
size_t i = argCount; i > 0; i--) {
1223 defineVariable(state, args[i-1]);
1226 for (
size_t i = 0; i < argCount; i++) {
1232 FREE_ARRAY(ssize_t,args,argSpace);
1236 static void declaration(
struct GlobalState * state) {
1237 if (check(TOKEN_DEF)) {
1238 defDeclaration(state);
1239 }
else if (check(TOKEN_CLASS)) {
1240 KrkToken className = classDeclaration(state);
1241 size_t classConst = identifierConstant(state, &className);
1243 declareVariable(state);
1244 defineVariable(state, classConst);
1245 }
else if (check(TOKEN_AT)) {
1247 }
else if (check(TOKEN_ASYNC)) {
1248 asyncDeclaration(state, 1);
1249 }
else if (match(TOKEN_EOL) || match(TOKEN_EOF)) {
1251 }
else if (check(TOKEN_INDENTATION)) {
1260 static void expressionStatement(
struct GlobalState * state) {
1265 static void beginScope(
struct GlobalState * state) {
1269 static void endScope(
struct GlobalState * state) {
1279 if (popCount == 1) emitByte(OP_POP);
1280 else { EMIT_OPERAND_OP(OP_POP_MANY, popCount); }
1286 if (closeCount == 1) emitByte(OP_CLOSE_UPVALUE);
1287 else { EMIT_OPERAND_OP(OP_CLOSE_MANY, closeCount); }
1303 if (popCount == 1) emitByte(OP_POP);
1304 else { EMIT_OPERAND_OP(OP_POP_MANY, popCount); }
1307 if (closeCount == 1) emitByte(OP_CLOSE_UPVALUE);
1308 else { EMIT_OPERAND_OP(OP_CLOSE_MANY, closeCount); }
1312 static void block(
struct GlobalState * state,
size_t indentation,
const char * blockName) {
1313 if (match(TOKEN_EOL)) {
1314 if (check(TOKEN_INDENTATION)) {
1316 if (currentIndentation <= indentation)
return;
1318 if (!strcmp(blockName,
"def") && (match(TOKEN_STRING) || match(TOKEN_BIG_STRING))) {
1319 size_t before = currentChunk()->count;
1325 currentChunk()->count = before;
1328 consume(TOKEN_EOL,
"Garbage after docstring defintion");
1329 if (!check(TOKEN_INDENTATION) || state->
parser.
current.length != currentIndentation) {
1330 error(
"Expected at least one statement in function with docstring.");
1335 while (check(TOKEN_INDENTATION)) {
1336 if (state->
parser.
current.length < currentIndentation)
break;
1339 if (check(TOKEN_EOL)) {
1351 assert(!!function->upvalueCount == !!compiler->
upvalues);
1352 for (
size_t i = 0; i <
function->upvalueCount; ++i) {
1356 emitByte((index >> 16) & 0xFF);
1357 emitByte((index >> 8) & 0xFF);
1359 emitByte(index & 0xFF);
1370 emitConstant(OBJECT_VAL(
krk_copyString(name.start, name.length)));
1377 static void hideLocal(
struct GlobalState * state) {
1381 static void argumentDefinition(
struct GlobalState * state,
int hasCollectors) {
1382 if (match(TOKEN_EQUAL)) {
1393 EMIT_OPERAND_OP(OP_GET_LOCAL, myLocal);
1394 int jumpIndex = emitJump(OP_TEST_ARG);
1397 EMIT_OPERAND_OP(OP_SET_LOCAL_POP, myLocal);
1399 patchJump(jumpIndex);
1400 if (hasCollectors) {
1406 if (hasCollectors) {
1408 EMIT_OPERAND_OP(OP_GET_LOCAL, myLocal);
1409 int jumpIndex = emitJump(OP_TEST_ARG);
1411 patchJump(jumpIndex);
1415 error(
"non-default argument follows default argument");
1430 EMIT_OPERAND_OP(OP_CLOSURE, ind);
1431 doUpvalues(state, compiler, func);
1433 emitByte(OP_ANNOTATE);
1435 freeCompiler(compiler);
1439 int hasCollectors = 0;
1440 KrkToken self = syntheticToken(
"self");
1444 isMethod(type) && check(TOKEN_IDENTIFIER) &&
1447 errorAtCurrent(
"Argument name 'self' in a method signature is reserved for the implicit first argument.");
1454 typeHint(state, name);
1456 if (check(TOKEN_EQUAL)) {
1457 errorAtCurrent(
"'self' can not be a default argument.");
1462 if (match(TOKEN_SOLIDUS)) {
1464 error(
"Syntax error.");
1470 if (match(TOKEN_ASTERISK) || check(TOKEN_POW)) {
1471 if (match(TOKEN_POW)) {
1472 if (hasCollectors == 2) {
1473 error(
"Duplicate ** in parameter list.");
1479 if (hasCollectors) {
1480 error(
"Syntax error.");
1484 if (check(TOKEN_COMMA)) {
1490 ssize_t paramConstant = parseVariable(state,
1491 (hasCollectors == 1) ?
"Expected parameter name after '*'." :
"Expected parameter name after '**'.");
1493 defineVariable(state, paramConstant);
1495 if (!(state->
current->
optionsFlags & OPTIONS_FLAG_NO_IMPLICIT_SELF) && isMethod(type) && identifiersEqual(&name,&
self)) {
1496 errorAtCurrent(
"Argument name 'self' in a method signature is reserved for the implicit first argument.");
1501 typeHint(state, name);
1505 EMIT_OPERAND_OP(OP_GET_LOCAL, myLocal);
1507 int jumpIndex = emitJump(OP_TEST_ARG);
1510 if (hasCollectors == 1) EMIT_OPERAND_OP(OP_MAKE_LIST,0);
1511 else EMIT_OPERAND_OP(OP_MAKE_DICT,0);
1512 EMIT_OPERAND_OP(OP_SET_LOCAL_POP, myLocal);
1515 patchJump(jumpIndex);
1518 if (hasCollectors == 2) {
1519 error(
"arguments follow catch-all keyword collector");
1522 ssize_t paramConstant = parseVariable(state,
"Expected parameter name.");
1528 typeHint(state, name);
1530 argumentDefinition(state, hasCollectors);
1531 defineVariable(state, paramConstant);
1532 }
while (match(TOKEN_COMMA));
1539 initCompiler(state, &compiler, type);
1544 consume(TOKEN_LEFT_PAREN,
"Expected start of parameter list after function name.");
1545 startEatingWhitespace();
1546 if (!check(TOKEN_RIGHT_PAREN)) {
1547 if (argumentList(state, type))
goto _bail;
1549 stopEatingWhitespace();
1550 consume(TOKEN_RIGHT_PAREN,
"Expected end of parameter list.");
1552 if (match(TOKEN_ARROW)) {
1553 typeHint(state, syntheticToken(
"return"));
1556 consume(TOKEN_COLON,
"Expected colon after function signature.");
1557 block(state, blockWidth,
"def");
1559 functionPrologue(state, &compiler);
1562 static void classBody(
struct GlobalState * state,
size_t blockWidth) {
1563 if (match(TOKEN_EOL)) {
1567 if (check(TOKEN_AT)) {
1570 }
else if (match(TOKEN_IDENTIFIER)) {
1574 if (check(TOKEN_COLON)) {
1579 KrkToken annotations = syntheticToken(
"__annotations__");
1580 size_t ind = identifierConstant(state, &annotations);
1582 EMIT_OPERAND_OP(OP_MAKE_DICT, 0);
1583 EMIT_OPERAND_OP(OP_SET_NAME, ind);
1586 EMIT_OPERAND_OP(OP_GET_NAME, ind);
1588 emitConstant(OBJECT_VAL(
krk_copyString(name.start, name.length)));
1590 emitBytes(OP_INVOKE_SETTER, OP_POP);
1593 if (match(TOKEN_EOL) || match(TOKEN_EOF))
return;
1596 consume(TOKEN_EQUAL,
"Class field must have value.");
1601 rememberClassProperty(state, ind);
1602 EMIT_OPERAND_OP(OP_SET_NAME, ind);
1605 if (!match(TOKEN_EOL) && !match(TOKEN_EOF)) {
1606 errorAtCurrent(
"Expected end of line after class attribute declaration");
1608 }
else if (match(TOKEN_PASS)) {
1610 consume(TOKEN_EOL,
"Expected end of line after 'pass' in class body.");
1614 if (match(TOKEN_ASYNC)) {
1616 consume(TOKEN_DEF,
"Expected 'def' after 'async'");
1617 }
else if (!match(TOKEN_DEF)) {
1618 error(
"Expected method, decorator, or class variable.");
1620 consume(TOKEN_IDENTIFIER,
"Expected method name after 'def'");
1623 static struct CompilerSpecialMethod {
const char * name;
int type; } compilerSpecialMethods[] = {
1631 for (
struct CompilerSpecialMethod * method = compilerSpecialMethods; method->name; method++) {
1632 if (state->
parser.
previous.length == strlen(method->name) && memcmp(state->
parser.
previous.start, method->name, strlen(method->name)) == 0) {
1634 error(
"'%s' can not be a coroutine",method->name);
1637 type = method->type;
1641 function(state, type, blockWidth);
1642 rememberClassProperty(state, ind);
1643 EMIT_OPERAND_OP(OP_SET_NAME, ind);
1648 #define ATTACH_PROPERTY(propName,how,propValue) do { \
1649 KrkToken val_tok = syntheticToken(propValue); \
1650 size_t val_ind = nonidentifierTokenConstant(state, &val_tok); \
1651 EMIT_OPERAND_OP(how, val_ind); \
1652 KrkToken name_tok = syntheticToken(propName); \
1653 size_t name_ind = identifierConstant(state, &name_tok); \
1654 EMIT_OPERAND_OP(OP_SET_NAME, name_ind); \
1663 consume(TOKEN_IDENTIFIER,
"Expected class name after 'class'.");
1665 KrkToken buildClass = syntheticToken(
"__build_class__");
1666 size_t ind = identifierConstant(state, &buildClass);
1667 EMIT_OPERAND_OP(OP_GET_GLOBAL, ind);
1670 initCompiler(state, &subcompiler,
TYPE_CLASS);
1676 assert(addUpvalue(state, state->
current, 0, 4, classNameToken) == 0);
1687 if (match(TOKEN_LEFT_PAREN)) {
1689 while (!check(TOKEN_EOF)) {
1690 if (check(TOKEN_RIGHT_PAREN) && parenDepth == 0) {
1693 }
else if (match(TOKEN_LEFT_BRACE)) {
1695 }
else if (match(TOKEN_RIGHT_BRACE)) {
1705 consume(TOKEN_COLON,
"Expected ':' after class.");
1709 ATTACH_PROPERTY(
"__module__", OP_GET_GLOBAL,
"__name__");
1710 ATTACH_PROPERTY(
"__qualname__", OP_CONSTANT, calculateQualName(state));
1712 if (match(TOKEN_EOL)) {
1713 if (check(TOKEN_INDENTATION)) {
1715 if (currentIndentation <= blockWidth) {
1716 errorAtCurrent(
"Unexpected indentation level for class");
1719 if (match(TOKEN_STRING) || match(TOKEN_BIG_STRING)) {
1721 KrkToken doc = syntheticToken(
"__doc__");
1722 size_t ind = identifierConstant(state, &doc);
1723 EMIT_OPERAND_OP(OP_SET_NAME, ind);
1725 consume(TOKEN_EOL,
"Garbage after docstring defintion");
1726 if (!check(TOKEN_INDENTATION) || state->
parser.
current.length != currentIndentation) {
1731 classBody(state, currentIndentation);
1732 while (check(TOKEN_INDENTATION)) {
1733 if (state->
parser.
current.length < currentIndentation)
break;
1735 classBody(state, currentIndentation);
1743 size_t indFunc =
krk_addConstant(currentChunk(), OBJECT_VAL(makeclass));
1744 EMIT_OPERAND_OP(OP_CLOSURE, indFunc);
1745 doUpvalues(state, &subcompiler, makeclass);
1746 freeCompiler(&subcompiler);
1750 size_t nameInd = nonidentifierTokenConstant(state, &classNameToken);
1751 EMIT_OPERAND_OP(OP_CONSTANT, nameInd);
1756 if (match(TOKEN_LEFT_PAREN)) {
1757 call(state, EXPR_CLASS_PARAMETERS, NULL);
1759 emitBytes(OP_CALL, 2);
1765 return classCompiler.
name;
1771 initCompiler(state, &lambdaCompiler,
TYPE_LAMBDA);
1775 if (!check(TOKEN_COLON)) {
1779 consume(TOKEN_COLON,
"Expected ':' after lambda arguments");
1783 functionPrologue(state, &lambdaCompiler);
1785 invalidTarget(state, exprType,
"lambda");
1788 static void defDeclaration(
struct GlobalState * state) {
1792 ssize_t global = parseVariable(state,
"Expected function name after 'def'.");
1794 markInitialized(state);
1797 defineVariable(state, global);
1800 static void asyncDeclaration(
struct GlobalState * state,
int declarationLevel) {
1804 if (match(TOKEN_DEF)) {
1805 if (!declarationLevel) {
1806 error(
"'async def' not valid here");
1809 ssize_t global = parseVariable(state,
"Expected coroutine name after 'async def'");
1811 markInitialized(state);
1814 defineVariable(state, global);
1815 }
else if (match(TOKEN_FOR)) {
1817 error(
"'async for' outside of async function");
1820 error(
"'async for' unsupported (GH-12)");
1822 }
else if (match(TOKEN_WITH)) {
1824 error(
"'async with' outside of async function");
1827 error(
"'async with' unsupported (GH-12)");
1830 errorAtCurrent(
"Expected 'def' after 'async'.");
1842 KrkToken at_staticmethod = syntheticToken(
"staticmethod");
1843 KrkToken at_classmethod = syntheticToken(
"classmethod");
1852 consume(TOKEN_EOL,
"Expected end of line after decorator.");
1854 consume(TOKEN_INDENTATION,
"Expected next line after decorator to have same indentation.");
1855 if (state->
parser.
previous.length != blockWidth) error(
"Expected next line after decorator to have same indentation.");
1858 if (check(TOKEN_DEF)) {
1861 consume(TOKEN_IDENTIFIER,
"Expected function name after 'def'");
1863 if (type ==
TYPE_METHOD && funcName.length == 8 && !memcmp(funcName.start,
"__init__",8)) {
1866 function(state, type, blockWidth);
1867 }
else if (match(TOKEN_ASYNC)) {
1868 if (!match(TOKEN_DEF)) {
1869 errorAtCurrent(
"Expected 'def' after 'async' with decorator, not '%*.s'",
1872 consume(TOKEN_IDENTIFIER,
"Expected coroutine name after 'def'.");
1875 }
else if (check(TOKEN_AT)) {
1876 funcName = decorator(state, level+1, type);
1877 }
else if (check(TOKEN_CLASS)) {
1879 error(
"Invalid decorator applied to class");
1882 funcName = classDeclaration(state);
1884 error(
"Expected a function declaration or another decorator.");
1888 emitBytes(OP_CALL, 1);
1893 declareVariable(state);
1894 size_t ind = (state->
current->
scopeDepth > 0) ? 0 : identifierConstant(state, &funcName);
1895 defineVariable(state, ind);
1897 size_t ind = identifierConstant(state, &funcName);
1898 rememberClassProperty(state, ind);
1899 EMIT_OPERAND_OP(OP_SET_NAME, ind);
1907 static void emitLoop(
struct GlobalState * state,
int loopStart, uint8_t loopType) {
1917 int offset = currentChunk()->count - loopStart + ((loopType == OP_LOOP_ITER) ? -1 : 2);
1918 if (offset > 0xFFFF) error(
"Loop jump offset is too large for opcode.");
1919 emitBytes(offset >> 8, offset);
1924 static void withStatement(
struct GlobalState * state) {
1935 if (match(TOKEN_AS)) {
1936 consume(TOKEN_IDENTIFIER,
"Expected variable name after 'as'");
1938 declareVariable(state);
1939 defineVariable(state, ind);
1942 anonymousLocal(state);
1946 anonymousLocal(state);
1949 anonymousLocal(state);
1950 int withJump = emitJump(OP_PUSH_WITH);
1952 if (check(TOKEN_COMMA)) {
1954 withStatement(state);
1956 consume(TOKEN_COLON,
"Expected ',' or ':' after 'with' statement");
1959 block(state,blockWidth,
"with");
1963 patchJump(withJump);
1964 emitByte(OP_CLEANUP_WITH);
1970 static void ifStatement(
struct GlobalState * state) {
1982 consume(TOKEN_COLON,
"Expected ':' after 'if' condition.");
1986 int thenJump = emitJump(OP_POP_JUMP_IF_FALSE);
1990 block(state,blockWidth,
"if");
1995 int elseJump = emitJump(OP_JUMP);
1996 patchJump(thenJump);
1999 if (blockWidth == 0 || (check(TOKEN_INDENTATION) && (state->
parser.
current.length == blockWidth))) {
2006 if (match(TOKEN_ELSE) || check(TOKEN_ELIF)) {
2007 if (state->
parser.
current.type == TOKEN_ELIF || check(TOKEN_IF)) {
2011 consume(TOKEN_COLON,
"Expected ':' after 'else'.");
2013 block(state,blockWidth,
"else");
2016 }
else if (!check(TOKEN_EOF) && !check(TOKEN_EOL)) {
2027 patchJump(elseJump);
2030 static void patchBreaks(
struct GlobalState * state,
int loopStart) {
2038 static void breakStatement(
struct GlobalState * state) {
2052 static void continueStatement(
struct GlobalState * state) {
2066 static void optionalElse(
struct GlobalState * state,
size_t blockWidth) {
2069 if (blockWidth == 0 || (check(TOKEN_INDENTATION) && (state->
parser.
current.length == blockWidth))) {
2070 if (blockWidth) advance();
2071 if (match(TOKEN_ELSE)) {
2072 consume(TOKEN_COLON,
"Expected ':' after 'else'.");
2074 block(state,blockWidth,
"else");
2078 state->
parser = parserBefore;
2083 static void whileStatement(
struct GlobalState * state) {
2087 int loopStart = currentChunk()->count;
2092 if (!(match(TOKEN_TRUE) && match(TOKEN_COLON)) &&
2100 consume(TOKEN_COLON,
"Expected ':' after 'while' condition.");
2102 exitJump = emitJump(OP_JUMP_IF_FALSE_OR_POP);
2108 block(state,blockWidth,
"while");
2112 emitLoop(state, loopStart, OP_LOOP);
2115 patchJump(exitJump);
2121 optionalElse(state, blockWidth);
2123 patchBreaks(state, loopStart);
2126 static void forStatement(
struct GlobalState * state) {
2136 ssize_t varCount = 0;
2137 int matchedEquals = 0;
2139 if (!check(TOKEN_IDENTIFIER)) {
2140 errorAtCurrent(
"Empty variable list in 'for'");
2145 if (!check(TOKEN_IDENTIFIER))
break;
2146 ssize_t ind = parseVariable(state,
"Expected name for loop iterator.");
2148 if (match(TOKEN_EQUAL)) {
2154 defineVariable(state, ind);
2156 if (check(TOKEN_COMMA)) sawComma = 1;
2157 }
while (match(TOKEN_COMMA));
2163 if (!matchedEquals && match(TOKEN_IN)) {
2169 anonymousLocal(state);
2170 emitByte(OP_INVOKE_ITER);
2171 loopStart = currentChunk()->count;
2172 exitJump = emitJump(OP_CALL_ITER);
2174 if (varCount > 1 || sawComma) {
2175 EMIT_OPERAND_OP(OP_UNPACK, varCount);
2176 for (ssize_t i = loopInd + varCount - 1; i >= loopInd; i--) {
2177 EMIT_OPERAND_OP(OP_SET_LOCAL_POP, i);
2180 EMIT_OPERAND_OP(OP_SET_LOCAL_POP, loopInd);
2186 consume(TOKEN_SEMICOLON,
"Expected ';' after C-style loop initializer.");
2187 loopStart = currentChunk()->count;
2192 exitJump = emitJump(OP_JUMP_IF_FALSE_OR_POP);
2194 if (check(TOKEN_SEMICOLON)) {
2196 int bodyJump = emitJump(OP_JUMP);
2197 int incrementStart = currentChunk()->count;
2200 expressionStatement(state);
2201 }
while (match(TOKEN_COMMA));
2204 emitLoop(state, loopStart, OP_LOOP);
2205 loopStart = incrementStart;
2206 patchJump(bodyJump);
2210 consume(TOKEN_COLON,
"Expected ':' after loop conditions.");
2215 block(state,blockWidth,
"for");
2219 emitLoop(state, loopStart, isIter ? OP_LOOP_ITER : OP_LOOP);
2220 patchJump(exitJump);
2222 optionalElse(state, blockWidth);
2223 patchBreaks(state, loopStart);
2227 static void returnStatement(
struct GlobalState * state) {
2228 if (check(TOKEN_EOL) || check(TOKEN_EOF)) {
2232 error(
"__init__ may not return a value.");
2235 emitByte(OP_RETURN);
2239 static void tryStatement(
struct GlobalState * state) {
2242 consume(TOKEN_COLON,
"Expected ':' after 'try'.");
2246 int tryJump = emitJump(OP_PUSH_TRY);
2248 size_t exceptionObject = anonymousLocal(state);
2249 anonymousLocal(state);
2252 block(state,blockWidth,
"try");
2257 #define EXIT_JUMP_MAX 64
2259 int exitJumpOffsets[EXIT_JUMP_MAX] = {0};
2262 exitJumpOffsets[0] = emitJump(OP_JUMP);
2267 exitJumpOffsets[1] = emitJump(OP_ENTER_EXCEPT);
2274 if (blockWidth == 0 || (check(TOKEN_INDENTATION) && (state->
parser.
current.length == blockWidth))) {
2280 if (exitJumps && !firstJump && match(TOKEN_EXCEPT)) {
2281 if (nextJump != -1) {
2282 patchJump(nextJump);
2285 if (!check(TOKEN_COLON) && !check(TOKEN_AS)) {
2290 nextJump = emitJump(OP_FILTER_EXCEPT);
2294 if (match(TOKEN_AS)) {
2295 consume(TOKEN_IDENTIFIER,
"Expected identifier after 'as'.");
2298 nameInd = renameLocal(state, exceptionObject, state->
parser.
previous);
2303 consume(TOKEN_COLON,
"Expected ':' after 'except'.");
2305 block(state,blockWidth,
"except");
2311 if (exitJumps < EXIT_JUMP_MAX) {
2312 exitJumpOffsets[exitJumps++] = emitJump(OP_JUMP);
2314 error(
"Too many 'except' clauses.");
2318 goto _anotherExcept;
2319 }
else if (firstJump != 1 && match(TOKEN_ELSE)) {
2320 consume(TOKEN_COLON,
"Expected ':' after 'else'.");
2321 patchJump(exitJumpOffsets[0]);
2323 emitByte(OP_TRY_ELSE);
2326 block(state, blockWidth,
"else");
2328 if (nextJump == -1) {
2334 goto _anotherExcept;
2335 }
else if (match(TOKEN_FINALLY)) {
2336 consume(TOKEN_COLON,
"Expected ':' after 'finally'.");
2337 for (
int i = firstJump; i < exitJumps; ++i) {
2338 patchJump(exitJumpOffsets[i]);
2340 if (nextJump != -1) {
2341 patchJump(nextJump);
2343 emitByte(OP_BEGIN_FINALLY);
2347 block(state,blockWidth,
"finally");
2350 emitByte(OP_END_FINALLY);
2351 }
else if (!check(TOKEN_EOL) && !check(TOKEN_EOF)) {
2362 for (
int i = firstJump; i < exitJumps; ++i) {
2363 patchJump(exitJumpOffsets[i]);
2366 if (nextJump >= 0) {
2367 patchJump(nextJump);
2368 emitByte(OP_BEGIN_FINALLY);
2369 emitByte(OP_END_FINALLY);
2375 static void raiseStatement(
struct GlobalState * state) {
2378 if (match(TOKEN_FROM)) {
2380 emitByte(OP_RAISE_FROM);
2386 static size_t importModule(
struct GlobalState * state,
KrkToken * startOfName,
int leadingDots) {
2390 for (
int i = 0; i < leadingDots; ++i) {
2391 pushStringBuilder(&sb,
'.');
2394 if (!(leadingDots && check(TOKEN_IMPORT))) {
2395 consume(TOKEN_IDENTIFIER,
"Expected module name after 'import'.");
2399 while (match(TOKEN_DOT)) {
2401 consume(TOKEN_IDENTIFIER,
"Expected module path element after '.'");
2407 startOfName->start = sb.bytes;
2408 startOfName->length = sb.length;
2410 ind = identifierConstant(state, startOfName);
2411 EMIT_OPERAND_OP(OP_IMPORT, ind);
2414 discardStringBuilder(&sb);
2418 static void importStatement(
struct GlobalState * state) {
2422 size_t ind = importModule(state, &startOfName, 0);
2423 if (match(TOKEN_AS)) {
2424 consume(TOKEN_IDENTIFIER,
"Expected identifier after 'as'.");
2426 }
else if (startOfName.length != firstName.length) {
2436 ind = identifierConstant(state, &firstName);
2437 EMIT_OPERAND_OP(OP_IMPORT, ind);
2439 declareVariable(state);
2440 defineVariable(state, ind);
2441 }
while (match(TOKEN_COMMA));
2444 static void optionsImport(
struct GlobalState * state) {
2445 int expectCloseParen = 0;
2447 KrkToken compile_time_builtins = syntheticToken(
"compile_time_builtins");
2448 KrkToken no_implicit_self = syntheticToken(
"no_implicit_self");
2451 consume(TOKEN_IMPORT,
"__options__ is not a package\n");
2453 if (match(TOKEN_LEFT_PAREN)) {
2454 expectCloseParen = 1;
2455 startEatingWhitespace();
2459 consume(TOKEN_IDENTIFIER,
"Expected member name");
2462 if (identifiersEqual(&state->
parser.
previous, &compile_time_builtins)) {
2464 }
else if (identifiersEqual(&state->
parser.
previous, &no_implicit_self)) {
2467 error(
"'%.*s' is not a recognized __options__ import",
2472 if (check(TOKEN_AS)) {
2473 errorAtCurrent(
"__options__ imports can not be given names");
2477 }
while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_PAREN));
2479 if (expectCloseParen) {
2480 stopEatingWhitespace();
2481 consume(TOKEN_RIGHT_PAREN,
"Expected ')' after import list started with '('");
2485 static void fromImportStatement(
struct GlobalState * state) {
2486 int expectCloseParen = 0;
2488 int leadingDots = 0;
2490 KrkToken options = syntheticToken(
"__options__");
2491 if (check(TOKEN_IDENTIFIER) && identifiersEqual(&state->
parser.
current, &options)) {
2493 optionsImport(state);
2497 while (match(TOKEN_DOT)) {
2501 importModule(state, &startOfName, leadingDots);
2502 consume(TOKEN_IMPORT,
"Expected 'import' after module name");
2503 if (match(TOKEN_LEFT_PAREN)) {
2504 expectCloseParen = 1;
2505 startEatingWhitespace();
2508 consume(TOKEN_IDENTIFIER,
"Expected member name");
2509 size_t member = identifierConstant(state, &state->
parser.
previous);
2510 emitBytes(OP_DUP, 0);
2511 EMIT_OPERAND_OP(OP_IMPORT_FROM, member);
2512 if (match(TOKEN_AS)) {
2513 consume(TOKEN_IDENTIFIER,
"Expected identifier after 'as'");
2520 declareVariable(state);
2521 defineVariable(state, member);
2522 }
while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_PAREN));
2523 if (expectCloseParen) {
2524 stopEatingWhitespace();
2525 consume(TOKEN_RIGHT_PAREN,
"Expected ')' after import list started with '('");
2530 static void delStatement(
struct GlobalState * state) {
2535 errorAtCurrent(
"Invalid del target");
2537 }
while (match(TOKEN_COMMA));
2540 static void assertStatement(
struct GlobalState * state) {
2542 int elseJump = emitJump(OP_JUMP_IF_TRUE_OR_POP);
2544 KrkToken assertionError = syntheticToken(
"AssertionError");
2545 size_t ind = identifierConstant(state, &assertionError);
2546 EMIT_OPERAND_OP(OP_GET_GLOBAL, ind);
2549 if (match(TOKEN_COMMA)) {
2554 EMIT_OPERAND_OP(OP_CALL, args);
2557 patchJump(elseJump);
2561 static void errorAfterStatement(
struct GlobalState * state) {
2563 case TOKEN_RIGHT_BRACE:
2564 case TOKEN_RIGHT_PAREN:
2565 case TOKEN_RIGHT_SQUARE:
2566 errorAtCurrent(
"Unmatched '%.*s'",
2569 case TOKEN_IDENTIFIER:
2570 errorAtCurrent(
"Unexpected %.*s after statement.",10,
"identifier");
2573 case TOKEN_BIG_STRING:
2574 errorAtCurrent(
"Unexpected %.*s after statement.",6,
"string");
2577 errorAtCurrent(
"Unexpected %.*s after statement.",
2582 static void simpleStatement(
struct GlobalState * state) {
2583 _anotherSimpleStatement:
2584 if (match(TOKEN_RAISE)) {
2585 raiseStatement(state);
2586 }
else if (match(TOKEN_RETURN)) {
2587 returnStatement(state);
2588 }
else if (match(TOKEN_IMPORT)) {
2589 importStatement(state);
2590 }
else if (match(TOKEN_FROM)) {
2591 fromImportStatement(state);
2592 }
else if (match(TOKEN_BREAK)) {
2593 breakStatement(state);
2594 }
else if (match(TOKEN_CONTINUE)) {
2595 continueStatement(state);
2596 }
else if (match(TOKEN_DEL)) {
2597 delStatement(state);
2598 }
else if (match(TOKEN_ASSERT)) {
2599 assertStatement(state);
2600 }
else if (match(TOKEN_PASS)) {
2602 }
else if (match(TOKEN_LET)) {
2603 letDeclaration(state);
2605 expressionStatement(state);
2607 if (match(TOKEN_SEMICOLON))
goto _anotherSimpleStatement;
2608 if (!match(TOKEN_EOL) && !match(TOKEN_EOF)) {
2609 errorAfterStatement(state);
2613 static void statement(
struct GlobalState * state) {
2614 if (match(TOKEN_EOL) || match(TOKEN_EOF)) {
2618 if (check(TOKEN_IF)) {
2620 }
else if (check(TOKEN_WHILE)) {
2621 whileStatement(state);
2622 }
else if (check(TOKEN_FOR)) {
2623 forStatement(state);
2624 }
else if (check(TOKEN_ASYNC)) {
2625 asyncDeclaration(state, 0);
2626 }
else if (check(TOKEN_TRY)) {
2627 tryStatement(state);
2628 }
else if (check(TOKEN_WITH)) {
2629 withStatement(state);
2632 simpleStatement(state);
2640 error(
"'yield' outside function");
2644 if (match(TOKEN_FROM)) {
2646 emitByte(OP_INVOKE_ITER);
2648 size_t loopContinue = currentChunk()->count;
2649 size_t exitJump = emitJump(OP_YIELD_FROM);
2651 emitLoop(state, loopContinue, OP_LOOP);
2652 patchJump(exitJump);
2653 }
else if (check(TOKEN_EOL) || check(TOKEN_EOF) || check(TOKEN_RIGHT_PAREN) || check(TOKEN_RIGHT_BRACE)) {
2660 invalidTarget(state, exprType,
"yield");
2665 error(
"'await' outside async function");
2670 emitByte(OP_INVOKE_AWAIT);
2672 size_t loopContinue = currentChunk()->count;
2673 size_t exitJump = emitJump(OP_YIELD_FROM);
2675 emitLoop(state, loopContinue, OP_LOOP);
2676 patchJump(exitJump);
2677 invalidTarget(state, exprType,
"await");
2683 invalidTarget(state, exprType,
"operator");
2689 invalidTarget(state, exprType,
"operator");
2690 switch (operatorType) {
2691 case TOKEN_PLUS: emitByte(OP_POS);
break;
2692 case TOKEN_MINUS: emitByte(OP_NEGATE);
break;
2693 case TOKEN_TILDE: emitByte(OP_BITNEGATE);
break;
2694 case TOKEN_BANG: emitByte(OP_NOT);
break;
2699 static int isHex(
int c) {
2700 return (c >=
'0' && c <=
'9') || (c >=
'a' && c <=
'f') || (c >=
'A' && c <=
'F');
2703 static int _pushHex(
struct GlobalState * state,
int isBytes,
struct StringBuilder * sb,
const char *c,
const char *end,
size_t n,
char type) {
2704 char tmpbuf[10] = {0};
2705 for (
size_t i = 0; i < n; ++i) {
2706 if (c + i + 2 == end || !isHex(c[i+2])) {
2707 error(
"truncated \\%c escape", type);
2712 unsigned long value = strtoul(tmpbuf, NULL, 16);
2713 if (value >= 0x110000) {
2714 error(
"invalid codepoint in \\%c escape", type);
2720 unsigned char bytes[5] = {0};
2729 #define PUSH_CHAR(c) krk_pushStringBuilder(&sb, c)
2730 #define PUSH_HEX(n, type) _pushHex(state, isBytes, &sb, c, end, n, type)
2739 if ((isBytes || isFormat || isRaw) && !(match(TOKEN_STRING) || match(TOKEN_BIG_STRING))) {
2740 error(
"Expected string after prefix? (Internal error - scanner should not have produced this.)");
2744 int formatElements = 0;
2754 int type = state->
parser.
previous.type == TOKEN_BIG_STRING ? 3 : 1;
2760 case '\\': PUSH_CHAR(
'\\');
break;
2761 case '\'': PUSH_CHAR(
'\'');
break;
2762 case '\"': PUSH_CHAR(
'\"');
break;
2763 case 'a': PUSH_CHAR(
'\a');
break;
2764 case 'b': PUSH_CHAR(
'\b');
break;
2765 case 'f': PUSH_CHAR(
'\f');
break;
2766 case 'n': PUSH_CHAR(
'\n');
break;
2767 case 'r': PUSH_CHAR(
'\r');
break;
2768 case 't': PUSH_CHAR(
'\t');
break;
2769 case 'v': PUSH_CHAR(
'\v');
break;
2770 case '[': PUSH_CHAR(
'\033');
break;
2795 if (c[1] >=
'0' && c[1] <=
'7') {
2796 int out = c[1] -
'0';
2797 if (c + 2 != end && (c[2] >=
'0' && c[2] <=
'7')) {
2801 if (c + 1 != end && (c[2] >=
'0' && c[2] <=
'7')) {
2811 unsigned char bytes[5] = {0};
2813 for (
size_t i = 0; i < len; i++) PUSH_CHAR(bytes[i]);
2822 }
else if (isFormat && *c ==
'}') {
2824 error(
"single '}' not allowed in f-string");
2830 }
else if (isFormat && *c ==
'{') {
2840 const char * start = c+1;
2843 KrkScanner inner = (
KrkScanner){.start=c+1, .cur=c+1, .linePtr=lineBefore, .line=lineNo, .startOfLine = 0, .hasUnget = 0};
2850 state->
parser = parserBefore;
2855 while (*c ==
' ') c++;
2858 while (*c ==
' ') c++;
2861 formatType |= FORMAT_OP_EQ;
2868 formatType |= FORMAT_OP_REPR;
2869 }
else if (*c ==
's') {
2870 formatType |= FORMAT_OP_STR;
2872 error(
"Unsupported conversion flag '%c' for f-string expression.", *c);
2880 const char * formatStart = c+1;
2882 while (c < end && *c !=
'}') c++;
2883 emitConstant(OBJECT_VAL(
krk_copyString(formatStart,c-formatStart)));
2884 formatType |= FORMAT_OP_FORMAT;
2888 if (!(formatType & (FORMAT_OP_FORMAT | FORMAT_OP_STR)) && (formatType & FORMAT_OP_EQ)) {
2889 formatType |= FORMAT_OP_REPR;
2892 EMIT_OPERAND_OP(OP_FORMAT_VALUE, formatType);
2895 error(
"Expected closing '}' after expression in f-string");
2902 if (*(
unsigned char*)c > 127 && isBytes) {
2903 error(
"bytes literal can only contain ASCII characters");
2916 if (match(TOKEN_PREFIX_F)) {
2918 }
else if (match(TOKEN_PREFIX_R)) {
2922 }
while ((!isBytes || match(TOKEN_PREFIX_B)) && (match(TOKEN_STRING) || match(TOKEN_BIG_STRING)));
2923 if (isBytes && (match(TOKEN_STRING) || match(TOKEN_BIG_STRING))) {
2924 error(
"Can not mix bytes and string literals");
2931 if (sb.length || !formatElements) {
2935 if (formatElements != 1) {
2936 EMIT_OPERAND_OP(OP_MAKE_STRING, formatElements);
2945 for (
size_t i = 0; i < upvalueCount; ++i) {
2947 if ((ssize_t)upvalue->
index == index && upvalue->
isLocal == isLocal) {
2964 for (
size_t i = 0; i < upvalueCount; ++i) {
2965 if (identifiersEqual(name, &compiler->
upvalues[i].
name)) {
2970 if (compiler->
enclosing == NULL)
return -1;
2972 ssize_t local = resolveLocal(state, compiler->
enclosing, name);
2975 return addUpvalue(state, compiler, local, 1, *name);
2977 ssize_t upvalue = resolveUpvalue(state, compiler->
enclosing, name);
2978 if (upvalue != -1) {
2979 return addUpvalue(state, compiler, upvalue, 0, *name);
2984 #define OP_NONE_LONG -1
2985 #define DO_VARIABLE(opset,opget,opdel) do { \
2986 if (exprType == EXPR_ASSIGN_TARGET) { \
2987 if (matchComplexEnd(state)) { \
2988 EMIT_OPERAND_OP(opset, arg); \
2991 exprType = EXPR_NORMAL; \
2993 if (exprType == EXPR_CAN_ASSIGN && match(TOKEN_EQUAL)) { \
2994 parsePrecedence(state, PREC_ASSIGNMENT); \
2995 EMIT_OPERAND_OP(opset, arg); \
2996 } else if (exprType == EXPR_CAN_ASSIGN && matchAssignment(state)) { \
2997 EMIT_OPERAND_OP(opget, arg); \
2998 assignmentValue(state); \
2999 EMIT_OPERAND_OP(opset, arg); \
3000 } else if (exprType == EXPR_DEL_TARGET && checkEndOfDel(state)) {\
3001 if (opdel == OP_NONE) { emitByte(OP_NONE); EMIT_OPERAND_OP(opset, arg); } \
3002 else { EMIT_OPERAND_OP(opdel, arg); } \
3004 EMIT_OPERAND_OP(opget, arg); \
3011 while (properties) {
3012 KrkString * constant = AS_STRING(currentChunk()->constants.values[properties->
ind]);
3013 if (constant->
length == name.length && !memcmp(constant->
chars, name.start, name.length)) {
3014 ssize_t arg = properties->
ind;
3015 DO_VARIABLE(OP_SET_NAME, OP_GET_NAME, OP_NONE);
3018 properties = properties->
next;
3021 ssize_t arg = resolveLocal(state, state->
current, &name);
3023 DO_VARIABLE(OP_SET_LOCAL, OP_GET_LOCAL, OP_NONE);
3024 }
else if ((arg = resolveUpvalue(state, state->
current, &name)) != -1) {
3025 DO_VARIABLE(OP_SET_UPVALUE, OP_GET_UPVALUE, OP_NONE);
3027 if ((state->
current->
optionsFlags & OPTIONS_FLAG_COMPILE_TIME_BUILTINS) && *name.start !=
'_') {
3033 error(
"Can not assign to '%.*s' when 'compile_time_builtins' is enabled.",
3034 (
int)name.length, name.start);
3036 error(
"Can not delete '%.*s' when 'compile_time_builtins' is enabled.",
3037 (
int)name.length, name.start);
3039 emitConstant(value);
3044 arg = identifierConstant(state, &name);
3045 DO_VARIABLE(OP_SET_GLOBAL, OP_GET_GLOBAL, OP_DEL_GLOBAL);
3059 consume(TOKEN_LEFT_PAREN,
"Expected 'super' to be called.");
3062 if (match(TOKEN_RIGHT_PAREN)) {
3064 error(
"super() outside of a method body requires arguments");
3068 error(
"super() is not valid in a function with no arguments");
3072 EMIT_OPERAND_OP(OP_GET_LOCAL, 0);
3075 if (match(TOKEN_COMMA)) {
3080 consume(TOKEN_RIGHT_PAREN,
"Expected ')' after argument list");
3082 consume(TOKEN_DOT,
"Expected a field of 'super()' to be referenced.");
3083 consume(TOKEN_IDENTIFIER,
"Expected a field name.");
3085 EMIT_OPERAND_OP(OP_GET_SUPER,
ind);
3090 ssize_t varCount = 0;
3092 if (!check(TOKEN_IDENTIFIER)) {
3093 errorAtCurrent(
"Empty variable list in comprehension");
3097 if (!check(TOKEN_IDENTIFIER))
break;
3098 defineVariable(state, parseVariable(state,
"Expected name for iteration variable."));
3101 defineVariable(state, loopInd);
3103 if (check(TOKEN_COMMA)) sawComma = 1;
3104 }
while (match(TOKEN_COMMA));
3106 consume(TOKEN_IN,
"Only iterator loops (for ... in ...) are allowed in generator expressions.");
3109 parsePrecedence(state,
PREC_OR);
3112 anonymousLocal(state);
3113 emitByte(OP_INVOKE_ITER);
3114 int loopStart = currentChunk()->count;
3115 int exitJump = emitJump(OP_CALL_ITER);
3117 if (varCount > 1 || sawComma) {
3118 EMIT_OPERAND_OP(OP_UNPACK, varCount);
3119 for (ssize_t i = loopInd + varCount - 1; i >= loopInd; i--) {
3120 EMIT_OPERAND_OP(OP_SET_LOCAL_POP, i);
3123 EMIT_OPERAND_OP(OP_SET_LOCAL_POP, loopInd);
3126 if (match(TOKEN_IF)) {
3127 parsePrecedence(state,
PREC_OR);
3128 int acceptJump = emitJump(OP_JUMP_IF_TRUE_OR_POP);
3129 emitLoop(state, loopStart, OP_LOOP);
3130 patchJump(acceptJump);
3135 if (match(TOKEN_FOR)) {
3136 comprehensionInner(state, scannerBefore, parserBefore, body, arg);
3141 state->
parser = parserBefore;
3146 state->
parser = parserAfter;
3150 emitLoop(state, loopStart, OP_LOOP_ITER);
3151 patchJump(exitJump);
3155 static void yieldInner(
struct GlobalState * state,
size_t arg) {
3158 emitBytes(OP_YIELD, OP_POP);
3178 comprehensionInner(state, scannerBefore, parserBefore, body, 0);
3182 size_t indFunc =
krk_addConstant(currentChunk(), OBJECT_VAL(subfunction));
3183 EMIT_OPERAND_OP(OP_CLOSURE, indFunc);
3184 doUpvalues(state, &subcompiler, subfunction);
3185 freeCompiler(&subcompiler);
3186 emitBytes(OP_CALL, 0);
3208 size_t ind = anonymousLocal(state);
3211 comprehensionInner(state, scannerBefore, parserBefore, body,
ind);
3215 size_t indFunc =
krk_addConstant(currentChunk(), OBJECT_VAL(subfunction));
3216 EMIT_OPERAND_OP(OP_CLOSURE, indFunc);
3217 doUpvalues(state, &subcompiler, subfunction);
3218 freeCompiler(&subcompiler);
3219 emitBytes(OP_CALL, 0);
3222 static size_t finishStarComma(
struct GlobalState * state,
size_t arg,
size_t * argBefore,
size_t *argAfter) {
3225 EMIT_OPERAND_OP(OP_MAKE_LIST,arg);
3227 emitByte(OP_LIST_EXTEND_TOP);
3229 if (arg == 0 && !check(TOKEN_COMMA)) {
3233 error(
"* expression not valid here");
3239 while (match(TOKEN_COMMA)) {
3241 if (match(TOKEN_ASTERISK)) {
3243 emitByte(OP_LIST_EXTEND_TOP);
3246 emitByte(OP_LIST_APPEND_TOP);
3253 emitByte(OP_TUPLE_FROM_LIST);
3275 int maybeValidAssignment = 0;
3277 size_t argCount = 0;
3278 size_t argAfter = 0;
3279 size_t argBefore = 0;
3282 startEatingWhitespace();
3284 if (check(TOKEN_RIGHT_PAREN)) {
3286 emitBytes(OP_TUPLE,0);
3287 }
else if (match(TOKEN_ASTERISK)) {
3288 argCount = finishStarComma(state, 0, &argBefore, &argAfter);
3289 maybeValidAssignment = 1;
3292 maybeValidAssignment = 1;
3295 if (match(TOKEN_FOR)) {
3297 maybeValidAssignment = 0;
3298 rewindChunk(currentChunk(), before);
3299 generatorExpression(state, scannerBefore, parserBefore, yieldInner);
3300 }
else if (match(TOKEN_COMMA)) {
3302 if (!check(TOKEN_RIGHT_PAREN)) {
3305 if (match(TOKEN_ASTERISK)) {
3306 argCount = finishStarComma(state, argCount, &argBefore, &argAfter);
3311 }
while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_PAREN));
3313 EMIT_OPERAND_OP(OP_TUPLE, argCount);
3318 stopEatingWhitespace();
3320 if (!match(TOKEN_RIGHT_PAREN)) {
3322 case TOKEN_EQUAL: error(
"Assignment value expression must be enclosed in parentheses.");
break;
3323 default: error(
"Expected ')' at end of parenthesized expression.");
break;
3329 error(
"Can not assign to empty target list.");
3330 }
else if (!maybeValidAssignment) {
3331 error(
"Can not assign to generator expression.");
3333 complexAssignment(state, before, scannerBefore, parserBefore, argCount, 1, argBefore, argAfter);
3335 }
else if (exprType ==
EXPR_ASSIGN_TARGET && (check(TOKEN_EQUAL) || check(TOKEN_COMMA) || check(TOKEN_RIGHT_PAREN))) {
3337 error(
"Can not assign to empty target list.");
3338 }
else if (!maybeValidAssignment) {
3339 error(
"Can not assign to generator expression.");
3341 rewindChunk(currentChunk(), before);
3342 complexAssignmentTargets(state, scannerBefore, parserBefore, argCount, 2, argBefore, argAfter);
3343 if (!matchComplexEnd(state)) {
3344 errorAtCurrent(
"Unexpected end of nested target list");
3355 static void listInner(
struct GlobalState * state,
size_t arg) {
3357 EMIT_OPERAND_OP(OP_LIST_APPEND, arg);
3360 static void finishStarList(
struct GlobalState * state,
size_t arg) {
3361 EMIT_OPERAND_OP(OP_MAKE_LIST, arg);
3364 emitByte(OP_LIST_EXTEND_TOP);
3366 while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_SQUARE)) {
3367 if (match(TOKEN_ASTERISK)) {
3369 emitByte(OP_LIST_EXTEND_TOP);
3372 emitByte(OP_LIST_APPEND_TOP);
3376 stopEatingWhitespace();
3378 consume(TOKEN_RIGHT_SQUARE,
"Expected ']' at end of list expression.");
3389 startEatingWhitespace();
3391 if (!check(TOKEN_RIGHT_SQUARE)) {
3394 if (match(TOKEN_ASTERISK)) {
3395 finishStarList(state, 0);
3400 if (match(TOKEN_FOR)) {
3402 rewindChunk(currentChunk(), before);
3405 comprehensionExpression(state, scannerBefore, parserBefore, listInner, OP_MAKE_LIST);
3407 size_t argCount = 1;
3408 while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_SQUARE)) {
3409 if (match(TOKEN_ASTERISK)) {
3410 finishStarList(state, argCount);
3416 EMIT_OPERAND_OP(OP_MAKE_LIST, argCount);
3420 EMIT_OPERAND_OP(OP_MAKE_LIST, 0);
3423 stopEatingWhitespace();
3425 consume(TOKEN_RIGHT_SQUARE,
"Expected ']' at end of list expression.");
3431 static void dictInner(
struct GlobalState * state,
size_t arg) {
3433 consume(TOKEN_COLON,
"Expected ':' after dict key.");
3435 EMIT_OPERAND_OP(OP_DICT_SET, arg);
3441 static void setInner(
struct GlobalState * state,
size_t arg) {
3443 EMIT_OPERAND_OP(OP_SET_ADD, arg);
3446 static void finishStarSet(
struct GlobalState * state,
size_t args) {
3447 EMIT_OPERAND_OP(OP_MAKE_SET, args);
3450 emitByte(OP_SET_UPDATE_TOP);
3452 while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_BRACE)) {
3453 if (match(TOKEN_ASTERISK)) {
3455 emitByte(OP_SET_UPDATE_TOP);
3458 emitByte(OP_SET_ADD_TOP);
3462 stopEatingWhitespace();
3463 consume(TOKEN_RIGHT_BRACE,
"Expected '}' at end of dict expression.");
3466 static void finishStarDict(
struct GlobalState * state,
size_t args) {
3467 EMIT_OPERAND_OP(OP_MAKE_DICT, args);
3470 emitByte(OP_DICT_UPDATE_TOP);
3472 while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_BRACE)) {
3473 if (match(TOKEN_POW)) {
3475 emitByte(OP_DICT_UPDATE_TOP);
3478 consume(TOKEN_COLON,
"Expected ':' after dict key.");
3480 emitByte(OP_DICT_SET_TOP);
3484 stopEatingWhitespace();
3485 consume(TOKEN_RIGHT_BRACE,
"Expected '}' at end of dict expression.");
3502 startEatingWhitespace();
3504 if (!check(TOKEN_RIGHT_BRACE)) {
3508 if (match(TOKEN_ASTERISK)) {
3509 finishStarSet(state, 0);
3511 }
else if (match(TOKEN_POW)) {
3512 finishStarDict(state, 0);
3517 if (check(TOKEN_COMMA) || check(TOKEN_RIGHT_BRACE)) {
3519 size_t argCount = 1;
3520 while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_BRACE)) {
3521 if (match(TOKEN_ASTERISK)) {
3522 finishStarSet(state, argCount);
3528 EMIT_OPERAND_OP(OP_MAKE_SET, argCount);
3529 }
else if (match(TOKEN_FOR)) {
3531 rewindChunk(currentChunk(), before);
3533 comprehensionExpression(state, scannerBefore, parserBefore, setInner, OP_MAKE_SET);
3536 consume(TOKEN_COLON,
"Expected ':' after dict key.");
3539 if (match(TOKEN_FOR)) {
3541 rewindChunk(currentChunk(), before);
3543 comprehensionExpression(state, scannerBefore, parserBefore, dictInner, OP_MAKE_DICT);
3550 size_t argCount = 2;
3551 while (match(TOKEN_COMMA) && !check(TOKEN_RIGHT_BRACE)) {
3552 if (match(TOKEN_POW)) {
3553 finishStarDict(state, argCount);
3557 consume(TOKEN_COLON,
"Expected ':' after dict key.");
3561 EMIT_OPERAND_OP(OP_MAKE_DICT, argCount);
3566 EMIT_OPERAND_OP(OP_MAKE_DICT, 0);
3569 stopEatingWhitespace();
3571 consume(TOKEN_RIGHT_BRACE,
"Expected '}' at end of dict expression.");
3576 rewindChunk(currentChunk(), rewind->
before);
3578 parsePrecedence(state,
PREC_OR);
3580 int thenJump = emitJump(OP_JUMP_IF_TRUE_OR_POP);
3581 consume(TOKEN_ELSE,
"Expected 'else' after ternary condition");
3588 int elseJump = emitJump(OP_JUMP);
3589 patchJump(thenJump);
3594 parsePrecedence(state,
PREC_OR);
3595 patchJump(elseJump);
3597 if (!check(TOKEN_IF)) {
3599 error(
"syntax error");
3603 state->
parser = outParser;
3606 static void complexAssignmentTargets(
struct GlobalState * state,
KrkScanner oldScanner,
Parser oldParser,
size_t targetCount,
int parenthesized,
size_t argBefore,
size_t argAfter) {
3607 emitBytes(OP_DUP, 0);
3610 if (argBefore > 255 || argAfter > 256) {
3611 error(
"Too many assignment targets");
3614 EMIT_OPERAND_OP(OP_UNPACK_EX,((argBefore << 8) | (argAfter-1)));
3616 EMIT_OPERAND_OP(OP_UNPACK,targetCount);
3618 EMIT_OPERAND_OP(OP_REVERSE,targetCount);
3622 state->
parser = oldParser;
3625 size_t checkTargetCount = 0;
3629 if (match(TOKEN_ASTERISK)) {
3631 errorAtCurrent(
"multiple *expr in assignment");
3639 if (checkTargetCount == targetCount && state->
parser.
previous.type == TOKEN_COMMA) {
3640 if (!match(parenthesized ? TOKEN_RIGHT_PAREN : TOKEN_EQUAL)) {
3641 goto _errorAtCurrent;
3645 if (checkTargetCount == targetCount && parenthesized) {
3647 goto _errorAtCurrent;
3651 if (checkTargetCount == targetCount && parenthesized) {
3652 if (parenthesized == 1 && !match(TOKEN_EQUAL)) {
3653 goto _errorAtCurrent;
3657 if (checkTargetCount == targetCount)
return;
3659 if (check(TOKEN_COMMA) || check(TOKEN_EQUAL) || check(TOKEN_RIGHT_PAREN)) {
3660 goto _errorAtCurrent;
3666 errorAtCurrent(
"Invalid complex assignment target");
3669 static void complexAssignment(
struct GlobalState * state,
ChunkRecorder before,
KrkScanner oldScanner,
Parser oldParser,
size_t targetCount,
int parenthesized,
size_t argBefore,
size_t argAfter) {
3671 rewindChunk(currentChunk(), before);
3678 complexAssignmentTargets(state, oldScanner,oldParser,targetCount,parenthesized, argBefore, argAfter);
3682 state->
parser = outParser;
3686 size_t expressionCount = 1;
3687 size_t argBefore = 0;
3688 size_t argAfter = 0;
3691 if (match(TOKEN_ASTERISK)) {
3692 expressionCount = finishStarComma(state, expressionCount, &argBefore, &argAfter);
3698 }
while (match(TOKEN_COMMA));
3700 EMIT_OPERAND_OP(OP_TUPLE,expressionCount);
3702 _maybeassign: (void)0;
3704 complexAssignment(state, rewind->
before, rewind->
oldScanner, rewind->
oldParser, expressionCount, 0, argBefore, argAfter);
3709 size_t argBefore = 0;
3710 size_t argAfter = 0;
3711 size_t totalArgs = finishStarComma(state,0, &argBefore, &argAfter);
3718 startEatingWhitespace();
3719 size_t argCount = 0, specialArgs = 0, keywordArgs = 0, seenKeywordUnpacking = 0;
3720 if (!check(TOKEN_RIGHT_PAREN)) {
3721 size_t chunkBefore = currentChunk()->count;
3725 if (check(TOKEN_RIGHT_PAREN))
break;
3726 if (match(TOKEN_ASTERISK) || check(TOKEN_POW)) {
3728 if (match(TOKEN_POW)) {
3729 seenKeywordUnpacking = 1;
3730 emitBytes(OP_EXPAND_ARGS, 2);
3734 if (seenKeywordUnpacking) {
3735 error(
"Iterable expansion follows keyword argument unpacking.");
3738 emitBytes(OP_EXPAND_ARGS, 1);
3743 if (match(TOKEN_IDENTIFIER)) {
3745 if (check(TOKEN_EQUAL)) {
3749 size_t ind = identifierConstant(state, &argName);
3750 EMIT_OPERAND_OP(OP_CONSTANT,
ind);
3763 }
else if (seenKeywordUnpacking) {
3764 error(
"Positional argument follows keyword argument unpacking");
3766 }
else if (keywordArgs) {
3767 error(
"Positional argument follows keyword argument");
3771 emitBytes(OP_EXPAND_ARGS, 0);
3777 if (argCount == 0 && match(TOKEN_FOR)) {
3778 currentChunk()->count = chunkBefore;
3779 generatorExpression(state, scannerBefore, parserBefore, yieldInner);
3781 if (match(TOKEN_COMMA)) {
3782 error(
"Generator expression must be parenthesized");
3788 }
while (match(TOKEN_COMMA));
3790 stopEatingWhitespace();
3791 consume(TOKEN_RIGHT_PAREN,
"Expected ')' after arguments.");
3799 EMIT_OPERAND_OP(OP_KWARGS, specialArgs);
3806 argCount += 1 + 2 * specialArgs;
3810 EMIT_OPERAND_OP(OP_CALL_METHOD, argCount);
3811 }
else if (exprType == EXPR_CLASS_PARAMETERS) {
3812 EMIT_OPERAND_OP(OP_CALL, (argCount + 2));
3814 EMIT_OPERAND_OP(OP_CALL, argCount);
3817 invalidTarget(state, exprType,
"function call");
3821 int endJump = emitJump(OP_JUMP_IF_FALSE_OR_POP);
3824 invalidTarget(state, exprType,
"operator");
3828 int endJump = emitJump(OP_JUMP_IF_TRUE_OR_POP);
3829 parsePrecedence(state,
PREC_OR);
3831 invalidTarget(state, exprType,
"operator");
3842 if (prefixRule == pstar && precedence >
PREC_COMMA) prefixRule = NULL;
3844 if (prefixRule == NULL) {
3846 case TOKEN_RIGHT_BRACE:
3847 case TOKEN_RIGHT_PAREN:
3848 case TOKEN_RIGHT_SQUARE:
3849 error(
"Unmatched '%.*s'",
3854 error(
"Unexpected end of line");
3857 error(
"Unexpected end of input");
3860 error(
"'%.*s' does not start an expression",
3869 prefixRule(state, exprType, &rewind);
3880 infixRule(state, exprType, &rewind);
3884 error(
"Invalid assignment target");
3889 static int maybeSingleExpression(
struct GlobalState * state) {
3901 if (check(TOKEN_STRING) || check(TOKEN_BIG_STRING)) {
3903 if (match(TOKEN_EOL)) {
3906 int isEof = check(TOKEN_EOF);
3914 if (isEof)
return 1;
3917 KrkToken doc = syntheticToken(
"__doc__");
3918 size_t ind = identifierConstant(state, &doc);
3919 EMIT_OPERAND_OP(OP_DEFINE_GLOBAL,
ind);
3936 if (match(TOKEN_SEMICOLON)) {
3938 simpleStatement(state);
3944 if (match(TOKEN_EOL) && !check(TOKEN_EOF)) {
3952 if (check(TOKEN_EOF))
3956 errorAfterStatement(state);
3964 void _createAndBind_compilerClass(
void) {
3965 KrkClass * CompilerState = ADD_BASE_CLASS(KRK_BASE_CLASS(CompilerState),
"CompilerState", KRK_BASE_CLASS(
object));
3967 CompilerState->
_ongcscan = _GlobalState_gcscan;
3968 CompilerState->
_ongcsweep = _GlobalState_gcsweep;
3969 CompilerState->
obj.
flags |= KRK_OBJ_FLAGS_NO_INHERIT;
4006 if (maybeSingleExpression(state)) {
4010 while (!match(TOKEN_EOF)) {
4014 if (check(TOKEN_EOL) || check(TOKEN_INDENTATION) || check(TOKEN_EOF)) {
4021 freeCompiler(&compiler);
4034 #define RULE(token, a, b, c) [TOKEN_ ## token] = {a, b, c}
4050 RULE(LEFT_BRACE, dict, NULL, PREC_NONE),
4051 RULE(RIGHT_PAREN, NULL, NULL, PREC_NONE),
4052 RULE(RIGHT_SQUARE, NULL, NULL, PREC_NONE),
4053 RULE(RIGHT_BRACE, NULL, NULL, PREC_NONE),
4054 RULE(COLON, NULL, NULL, PREC_NONE),
4055 RULE(SEMICOLON, NULL, NULL, PREC_NONE),
4056 RULE(EQUAL, NULL, NULL, PREC_NONE),
4057 RULE(WALRUS, NULL, NULL, PREC_NONE),
4058 RULE(PLUS_EQUAL, NULL, NULL, PREC_NONE),
4059 RULE(MINUS_EQUAL, NULL, NULL, PREC_NONE),
4060 RULE(PLUS_PLUS, NULL, NULL, PREC_NONE),
4061 RULE(MINUS_MINUS, NULL, NULL, PREC_NONE),
4062 RULE(CARET_EQUAL, NULL, NULL, PREC_NONE),
4063 RULE(PIPE_EQUAL, NULL, NULL, PREC_NONE),
4064 RULE(LSHIFT_EQUAL, NULL, NULL, PREC_NONE),
4065 RULE(RSHIFT_EQUAL, NULL, NULL, PREC_NONE),
4066 RULE(AMP_EQUAL, NULL, NULL, PREC_NONE),
4067 RULE(SOLIDUS_EQUAL, NULL, NULL, PREC_NONE),
4068 RULE(DSOLIDUS_EQUAL,NULL, NULL, PREC_NONE),
4069 RULE(ASTERISK_EQUAL,NULL, NULL, PREC_NONE),
4070 RULE(MODULO_EQUAL, NULL, NULL, PREC_NONE),
4071 RULE(AT_EQUAL, NULL, NULL, PREC_NONE),
4072 RULE(POW_EQUAL, NULL, NULL, PREC_NONE),
4073 RULE(ARROW, NULL, NULL, PREC_NONE),
4074 RULE(MINUS, unary, binary,
PREC_SUM),
4075 RULE(PLUS, unary, binary,
PREC_SUM),
4076 RULE(TILDE, unary, NULL, PREC_NONE),
4077 RULE(BANG, unary, NULL, PREC_NONE),
4079 RULE(DOUBLE_SOLIDUS,NULL, binary,
PREC_TERM),
4080 RULE(ASTERISK, pstar, binary,
PREC_TERM),
4098 RULE(IDENTIFIER, variable, NULL, PREC_NONE),
4099 RULE(STRING,
string, NULL, PREC_NONE),
4100 RULE(BIG_STRING,
string, NULL, PREC_NONE),
4101 RULE(PREFIX_B,
string, NULL, PREC_NONE),
4102 RULE(PREFIX_F,
string, NULL, PREC_NONE),
4103 RULE(PREFIX_R,
string, NULL, PREC_NONE),
4104 RULE(NUMBER, number, NULL, PREC_NONE),
4107 RULE(FALSE, literal, NULL, PREC_NONE),
4108 RULE(NONE, literal, NULL, PREC_NONE),
4109 RULE(TRUE, literal, NULL, PREC_NONE),
4110 RULE(YIELD, yield, NULL, PREC_NONE),
4111 RULE(AWAIT, await, NULL, PREC_NONE),
4112 RULE(LAMBDA, lambda, NULL, PREC_NONE),
4113 RULE(SUPER, super_, NULL, PREC_NONE),
4114 RULE(CLASS, NULL, NULL, PREC_NONE),
4115 RULE(ELSE, NULL, NULL, PREC_NONE),
4116 RULE(FOR, NULL, NULL, PREC_NONE),
4117 RULE(DEF, NULL, NULL, PREC_NONE),
4118 RULE(DEL, NULL, NULL, PREC_NONE),
4119 RULE(LET, NULL, NULL, PREC_NONE),
4120 RULE(RETURN, NULL, NULL, PREC_NONE),
4121 RULE(WHILE, NULL, NULL, PREC_NONE),
4122 RULE(BREAK, NULL, NULL, PREC_NONE),
4123 RULE(CONTINUE, NULL, NULL, PREC_NONE),
4124 RULE(IMPORT, NULL, NULL, PREC_NONE),
4125 RULE(RAISE, NULL, NULL, PREC_NONE),
4126 RULE(ASYNC, NULL, NULL, PREC_NONE),
4127 RULE(PASS, NULL, NULL, PREC_NONE),
4128 RULE(ASSERT, NULL, NULL, PREC_NONE),
4129 RULE(FINALLY, NULL, NULL, PREC_NONE),
4130 RULE(ELIF, NULL, NULL, PREC_NONE),
4131 RULE(TRY, NULL, NULL, PREC_NONE),
4132 RULE(EXCEPT, NULL, NULL, PREC_NONE),
4133 RULE(AS, NULL, NULL, PREC_NONE),
4134 RULE(FROM, NULL, NULL, PREC_NONE),
4135 RULE(WITH, NULL, NULL, PREC_NONE),
4140 RULE(INDENTATION, NULL, NULL, PREC_NONE),
4141 RULE(ERROR, NULL, NULL, PREC_NONE),
4142 RULE(EOL, NULL, NULL, PREC_NONE),
4143 RULE(EOF, NULL, NULL, PREC_NONE),
4144 RULE(RETRY, NULL, NULL, PREC_NONE),
4147 static ParseRule * getRule(KrkTokenType type) {
ParseRule krk_parseRules[]
Parse rules table.
FunctionType
Function compilation type.
ExpressionType
Expression type.
struct Compiler Compiler
Subcompiler state.
struct RewindState RewindState
Compiler emit and parse state prior to this expression.
Precedence
Parse precedence ladder.
struct ClassCompiler ClassCompiler
Class compilation context.
KrkCodeObject * krk_compile(const char *src, char *fileName)
Compile a source string to bytecode.
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.
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.
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.
KrkChunk chunk
Bytecode data.
size_t upvalueCount
Number of upvalues this function collects as a closure.
KrkLocalEntry * localNames
Stores the names of local variables used in the function, for debugging.
unsigned short keywordArgs
Arity of keyword (default) arguments.
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.
KrkString * qualname
The dotted name of the function.
KrkInstance * krk_newInstance(KrkClass *_class)
Create a new instance of the given class.
KrkTable fields
Attributes table.
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.
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.
#define vm
Convenience macro for namespacing.
KrkValue krk_pop(void)
Pop the top of the stack.
threadLocal KrkThreadState krk_currentThread
Thread-local VM state.
void krk_push(KrkValue value)
Push a stack value.