diff --git a/src/codeobject.h b/src/codeobject.h index 805061db..6bd8873e 100644 --- a/src/codeobject.h +++ b/src/codeobject.h @@ -118,7 +118,7 @@ public: _Str errorSnapshot(){ int line = -1; - if(!isEnd()) line = code->co_code[ip].line; + if(!isEnd()) line = code->co_code[ip-1].line; return code->src->snapshot(line); } diff --git a/src/compiler.h b/src/compiler.h index ef81dcfc..3c286204 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -120,9 +120,9 @@ public: _Str eatStringUntil(char quote) { std::vector buff; while (true) { - char c = parser->eatChar(); + char c = parser->eatCharIncludeNewLine(); if (c == quote) break; - if (c == '\0') syntaxError("EOL while scanning string literal"); + if (c == '\0' || c == '\n') syntaxError("EOL while scanning string literal"); if (c == '\\') { switch (parser->eatCharIncludeNewLine()) { case '"': buff.push_back('"'); break; @@ -177,7 +177,8 @@ public: void lexToken() { parser->previous = parser->current; parser->current = parser->nextToken(); - //printf("<%s> ", TK_STR(peek())); + + //_Str _info = parser->current.info(); printf("%s\n", (const char*)_info); while (parser->peekChar() != '\0') { parser->token_start = parser->current_char; @@ -871,7 +872,8 @@ __LITERAL_EXIT: /***** Error Reporter *****/ _Str getLineSnapshot(){ - int lineno = parser->previous.line; + int lineno = parser->current_line; + if(parser->peekChar() == '\n') lineno--; return parser->src->snapshot(lineno); } diff --git a/src/main.cpp b/src/main.cpp index e898762d..4172c9bc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -33,13 +33,16 @@ VM* newVM(){ std::cout << str; std::cout.flush(); }); - registerModule(vm, "math", "pi = 3.141593"); return vm; } void REPL(){ std::cout << "pocketpy 0.1.0" << std::endl; std::cout << "https://github.com/blueloveTH/pocketpy" << std::endl; +#ifdef PK_DEBUG + std::cout << "[ DEBUG MODE ENABLED ]" << std::endl; +#endif + int need_more_lines = 0; diff --git a/src/parser.h b/src/parser.h index dee0f82a..5ddd4ece 100644 --- a/src/parser.h +++ b/src/parser.h @@ -61,6 +61,14 @@ struct Token{ const _Str str() const { return _Str(start, length); } + + const _Str info() const { + _StrStream ss; + _Str raw = str(); + if (raw == _Str("\n")) raw = "\\n"; + ss << line << ": " << TK_STR(type) << " '" << raw << "'"; + return ss.str(); + } }; enum Precedence { @@ -146,7 +154,7 @@ struct Parser { char eatChar() { char c = peekChar(); - if(c == '\n') throw std::runtime_error("eatChar() cannot consume a newline"); + if(c == '\n') throw UnexpectedError("eatChar() cannot consume a newline"); current_char++; return c; } diff --git a/src/pocketpy.h b/src/pocketpy.h index b4a834c4..3504422d 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -404,18 +404,6 @@ void __runCodeBuiltins(VM* vm, const char* src){ vm->exec(code, {}, vm->builtins); } -#include -void __addModuleRandom(VM* vm){ - srand(time(NULL)); - PyVar random = vm->newModule("random"); - vm->bindFunc(random, "randint", [](VM* vm, PyVarList args) { - int _min = vm->PyInt_AS_C(args[0]); - int _max = vm->PyInt_AS_C(args[1]); - return vm->PyInt(rand() % (_max - _min + 1) + _min); - }); - vm->_modules["random"] = random; -} - #include "builtins.h" #ifdef _WIN32 @@ -432,7 +420,6 @@ extern "C" { VM* vm = new VM(); __initializeBuiltinFunctions(vm); __runCodeBuiltins(vm, __BUILTINS_CODE); - __addModuleRandom(vm); vm->_stdout = _stdout; return vm; } diff --git a/tests/basic.py b/tests/basic.py new file mode 100644 index 00000000..af73e80d --- /dev/null +++ b/tests/basic.py @@ -0,0 +1,94 @@ +# generate assert test for int + +# test == != >= <= < > +# generate 2 cases for each operator +assert -1 == -1 +assert -1 != 1 +assert -1 >= -1 +assert -1 <= -1 +assert -1 < 1 +assert -1 > -2 + +# test + - * % ** // +assert -1 + 1 == 0 +assert -1 - 1 == -2 +assert 4 * -1 == -4 +assert 5 % 2 == 1 +assert 2 ** 3 == 8 +assert 4 // 2 == 2 +assert 5 // 2 == 2 + +# test += -= *= //= +x = 3 +x += 1 +assert x == 4 +x -= 1 +assert x == 3 +x *= 2 +assert x == 6 +x //= 2 +assert x == 3 + +# generate assert test for float + +def eq(a, b): + dt = a - b + return dt > -0.001 and dt < 0.001 + +# test + - * / ** +assert eq(1.5 + 3, 4.5) +assert eq(1.5 + 3.9, 5.4) +assert eq(5.3 - 2.5, 2.8) +assert eq(0.2**2, 0.04) +assert eq(4**(-1.0), 0.25) +assert eq(2/1, 2) +assert eq(3/2.0, 1.5) +assert eq(1/9, 0.11111) + +# test += -= *= /= +x = 3.0 +x += 1 +assert eq(x, 4.0) +x -= 1 +assert eq(x, 3.0) +x *= 2 +assert eq(x, 6.0) +x /= 1.8 +assert eq(x, 3.3333) + +# generate assert test for bool + +assert True == True +assert True != False +assert False == False +assert False != True + +# test and/or/not +assert True and True +assert not (True and False) +assert True or True +assert True or False +assert not False +assert not (not True) + +# generate assert test for str + +assert 'testing' == 'test' + 'ing' +assert 'testing' != 'test' + 'ing2' +assert 'testing' < 'test' + 'ing2' +assert 'testing5' > 'test' + 'ing1' + +# test + *= +assert 'abc' + 'def' == 'abcdef' +assert 'abc' * 3 == 'abcabcabc' + +# generate assert test for list + +assert [1, 2, 3] == [1, 2, 3] +assert [1, 2, 3] != [1, 2, 4] + +# test + *= +assert [1, 2, 3] + [4, 5, 6] == [1, 2, 3, 4, 5, 6] +assert [1, 2, 3] * 3 == [1, 2, 3, 1, 2, 3, 1, 2, 3] + +print("ALL TESTS PASSED") \ No newline at end of file diff --git a/tests/class.pk b/tests/class.pk deleted file mode 100644 index e9bbf6f5..00000000 --- a/tests/class.pk +++ /dev/null @@ -1,6 +0,0 @@ -class Complex: - def __init__(self, realpart, imagpart): - self.r = realpart - self.i = imagpart -x = Complex(3.0, -4.5) -assert x.r == 3.0 \ No newline at end of file