82 lines
3.2 KiB
C
82 lines
3.2 KiB
C
|
|
/**
|
||
|
|
* @file known_reference_defects.c
|
||
|
|
* @brief Asserts the *correct* contract for defects carried over from the reference.
|
||
|
|
*
|
||
|
|
* Registered in AKBASIC_KNOWN_FAILING_TESTS, so CTest expects it to fail. Every
|
||
|
|
* assertion here states what the interpreter *should* do, not what it currently
|
||
|
|
* does -- pinning current-but-wrong behaviour would turn the eventual fix into a
|
||
|
|
* test failure.
|
||
|
|
*
|
||
|
|
* When one of these is fixed, this test starts passing and CTest reports
|
||
|
|
* "unexpectedly passed". That is the cue to split the fixed assertion out into
|
||
|
|
* the corresponding suite in AKBASIC_TESTS and strike the item from TODO.md
|
||
|
|
* section 12.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "harness.h"
|
||
|
|
|
||
|
|
int main(void)
|
||
|
|
{
|
||
|
|
akbasic_ASTLeaf *leaf = NULL;
|
||
|
|
akbasic_Value *out = NULL;
|
||
|
|
char rendered[AKBASIC_MAX_STRING_LENGTH];
|
||
|
|
|
||
|
|
TEST_REQUIRE_OK(harness_start(NULL));
|
||
|
|
|
||
|
|
/*
|
||
|
|
* 12.12 -- subtraction stops after one operator, so `1 - 2 - 3` parses as
|
||
|
|
* `1 - 2` and abandons the rest of the line. It should fold left, the way
|
||
|
|
* addition does.
|
||
|
|
*/
|
||
|
|
TEST_REQUIRE_OK(harness_parse("A# = 1 - 2 - 3", &leaf));
|
||
|
|
TEST_REQUIRE_OK(akbasic_leaf_to_string(leaf, rendered, sizeof(rendered)));
|
||
|
|
TEST_REQUIRE_STR(rendered, "( A# (- (- 1 2) 3))");
|
||
|
|
|
||
|
|
/*
|
||
|
|
* 12.13 -- a unary-minus argument inflates the arity count, because the
|
||
|
|
* counter walks .right and a unary leaf keeps its operand there. ABS(-9)
|
||
|
|
* should be one argument.
|
||
|
|
*/
|
||
|
|
TEST_REQUIRE_OK(akbasic_environment_zero(HARNESS_RUNTIME.environment));
|
||
|
|
TEST_REQUIRE_OK(harness_parse("A# = ABS(-9)", &leaf));
|
||
|
|
TEST_REQUIRE_OK(akbasic_runtime_evaluate(&HARNESS_RUNTIME, leaf, &out));
|
||
|
|
TEST_REQUIRE_INT(out->intval, 9);
|
||
|
|
|
||
|
|
/*
|
||
|
|
* 12.14 -- a comparison operator in the final column of a line is dropped,
|
||
|
|
* because matchNextChar returns without setting a token type when it cannot
|
||
|
|
* peek past the end.
|
||
|
|
*/
|
||
|
|
TEST_REQUIRE_OK(akbasic_scanner_scan(&HARNESS_RUNTIME, "A# =", NULL, 0));
|
||
|
|
TEST_REQUIRE_INT(HARNESS_RUNTIME.environment->nexttoken, 2);
|
||
|
|
|
||
|
|
/*
|
||
|
|
* 12.15 -- hex literals do not survive the scanner. matchNumber lets 'x'
|
||
|
|
* through but not the digits after it, so the parser's base-16 branch is
|
||
|
|
* unreachable.
|
||
|
|
*/
|
||
|
|
TEST_REQUIRE_OK(akbasic_scanner_scan(&HARNESS_RUNTIME, "PRINT 0xff", NULL, 0));
|
||
|
|
TEST_REQUIRE_STR(HARNESS_RUNTIME.environment->tokens[1].lexeme, "0xff");
|
||
|
|
|
||
|
|
/*
|
||
|
|
* 12.16 -- "Reserved word in variable name" never fires, because the lexeme
|
||
|
|
* still carries its type suffix when the verb table is searched. PRINT$
|
||
|
|
* should be refused as a variable name.
|
||
|
|
*/
|
||
|
|
HARNESS_RUNTIME.hasError = false;
|
||
|
|
TEST_REQUIRE_OK(akbasic_scanner_scan(&HARNESS_RUNTIME, "PRINT$ = 1", NULL, 0));
|
||
|
|
TEST_REQUIRE(HARNESS_RUNTIME.hasError, "PRINT$ should be refused as a variable name");
|
||
|
|
|
||
|
|
/*
|
||
|
|
* 12.10 -- a leading zero selects base 8, so `PRINT 010` prints 8 and
|
||
|
|
* `PRINT 08` will not parse. Commodore BASIC has no octal literals.
|
||
|
|
*/
|
||
|
|
TEST_REQUIRE_OK(akbasic_environment_zero(HARNESS_RUNTIME.environment));
|
||
|
|
TEST_REQUIRE_OK(harness_parse("A# = 010", &leaf));
|
||
|
|
TEST_REQUIRE_OK(akbasic_runtime_evaluate(&HARNESS_RUNTIME, leaf, &out));
|
||
|
|
TEST_REQUIRE_INT(out->intval, 10);
|
||
|
|
|
||
|
|
harness_stop();
|
||
|
|
return akbasic_test_failures;
|
||
|
|
}
|