Add 'assert' statement

This commit is contained in:
K. Lange 2021-03-01 11:55:51 +09:00
parent 5ce03ebcf5
commit a65f2dcf81
8 changed files with 48 additions and 2 deletions

View File

@ -1734,6 +1734,27 @@ static void delStatement() {
inDel = 0;
}
static void assertStatement() {
expression();
int elseJump = emitJump(OP_JUMP_IF_TRUE);
KrkToken assertionError = syntheticToken("AssertionError");
size_t ind = identifierConstant(&assertionError);
EMIT_CONSTANT_OP(OP_GET_GLOBAL, ind);
int args = 0;
if (match(TOKEN_COMMA)) {
expression();
args = 1;
}
EMIT_CONSTANT_OP(OP_CALL, args);
emitByte(OP_RAISE);
patchJump(elseJump);
emitByte(OP_POP);
}
static void statement() {
if (match(TOKEN_EOL) || match(TOKEN_EOF)) {
return; /* Meaningless blank line */
@ -1766,6 +1787,8 @@ _anotherSimpleStatement:
continueStatement();
} else if (match(TOKEN_DEL)) {
delStatement();
} else if (match(TOKEN_ASSERT)) {
assertStatement();
} else if (match(TOKEN_PASS)) {
/* Do nothing. */
} else {

View File

@ -158,6 +158,7 @@ void _createAndBind_exceptions(void) {
ADD_EXCEPTION_CLASS(vm.exceptions->keyboardInterrupt, "KeyboardInterrupt", vm.exceptions->baseException);
ADD_EXCEPTION_CLASS(vm.exceptions->zeroDivisionError, "ZeroDivisionError", vm.exceptions->baseException);
ADD_EXCEPTION_CLASS(vm.exceptions->notImplementedError, "NotImplementedError", vm.exceptions->baseException);
ADD_EXCEPTION_CLASS(vm.exceptions->assertionError, "AssertionError", vm.exceptions->baseException);
ADD_EXCEPTION_CLASS(vm.exceptions->syntaxError, "SyntaxError", vm.exceptions->baseException);
krk_defineNative(&vm.exceptions->syntaxError->methods, ".__str__", _syntaxerror_str);
krk_finalizeClass(vm.exceptions->syntaxError);

View File

@ -544,7 +544,7 @@ char * syn_krk_keywords[] = {
"and","class","def","else","for","if","in","import","del",
"let","not","or","return","while","try","except","raise",
"continue","break","as","from","elif","lambda","with","is",
"pass",
"pass","assert",
NULL
};

View File

@ -197,7 +197,11 @@ static KrkTokenType identifierType() {
switch (*scanner.start) {
case 'a': if (MORE(1)) switch(scanner.start[1]) {
case 'n': return checkKeyword(2, "d", TOKEN_AND);
case 's': return checkKeyword(2, "", TOKEN_AS);
case 's': if (MORE(2)) {
return checkKeyword(2, "sert", TOKEN_ASSERT);
} else {
return checkKeyword(2, "", TOKEN_AS);
}
} break;
case 'b': if (MORE(1)) return checkKeyword(1, "reak", TOKEN_BREAK);
else if (scanner.start[1] == '\'' || scanner.start[1] == '"') return TOKEN_PREFIX_B;

View File

@ -90,6 +90,7 @@ typedef enum {
TOKEN_AS,
TOKEN_FROM,
TOKEN_LAMBDA,
TOKEN_ASSERT,
TOKEN_WITH,
TOKEN_PREFIX_B,

View File

@ -120,6 +120,7 @@ struct Exceptions {
KrkClass * zeroDivisionError; /**< @exception ZeroDivisionError A mathematical function attempted to divide by zero. */
KrkClass * notImplementedError; /**< @exception NotImplementedError The method is not implemented, either for the given arguments or in general. */
KrkClass * syntaxError; /**< @exception SyntaxError The compiler encountered an unrecognized or invalid source code input. */
KrkClass * assertionError; /**< @exception AssertionError An @c assert statement failed. */
};
/**

14
test/testAssert.krk Normal file
View File

@ -0,0 +1,14 @@
assert 1 + 1
assert True, "Test"
try:
assert False
except AssertionError:
print("Pass")
try:
assert False, "with a message"
except AssertionError as e:
print("msg =", str(e))

View File

@ -0,0 +1,2 @@
Pass
msg = with a message