diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0f67884..7ae51b1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,7 +2,7 @@ name: CI on: push: - branches: [main] + branches: [main, dev] pull_request: branches: [main] @@ -14,14 +14,16 @@ jobs: steps: - uses: actions/checkout@v3 + # Cache the CMake build outputs - name: Cache build directory uses: actions/cache@v4 with: - path: | - build - key: linux-build-${{ hashFiles('CMakeLists.txt', 'src/**') }} + path: build + key: ${{ runner.os }}-build-${{ hashFiles('CMakeLists.txt', 'src/**') }} + restore-keys: | + ${{ runner.os }}-build- - - name: Install Dependencies + - name: Install System Dependencies run: | sudo apt-get update -y sudo apt-get install -y build-essential llvm clang cmake python3-pip @@ -42,12 +44,23 @@ jobs: steps: - uses: actions/checkout@v3 + # Cache the CMake build outputs - name: Cache build directory uses: actions/cache@v4 with: - path: | - build - key: windows-build-${{ hashFiles('CMakeLists.txt', 'src/**') }} + path: build + key: ${{ runner.os }}-build-${{ hashFiles('CMakeLists.txt', 'src/**') }} + restore-keys: | + ${{ runner.os }}-build- + + # Cache pip download cache on Windows + - name: Cache pip + uses: actions/cache@v4 + with: + path: C:\Users\runneradmin\AppData\Local\pip\Cache + key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- - name: Setup MSVC Developer Command Prompt uses: ilammy/msvc-dev-cmd@v1 diff --git a/examples/functions.zz b/examples/functions.zz index b8536e3..29ccad5 100644 --- a/examples/functions.zz +++ b/examples/functions.zz @@ -7,7 +7,7 @@ fn factorial(x: uint64_t) -> uint64_t{ if(x <= 1){ return 1; }else{ - return multiply(x, factorial(x - 1)); + return multiply(x, factorial(x-1)); } } diff --git a/src/lexer/Lexer.cpp b/src/lexer/Lexer.cpp index a1cb3e6..579cc5e 100644 --- a/src/lexer/Lexer.cpp +++ b/src/lexer/Lexer.cpp @@ -63,7 +63,7 @@ namespace zust { if (std::isalpha(static_cast(c)) || c == '_') return scanIdentifierOrKeywordOrConditional(); - if (std::isdigit(static_cast(c)) || (c == '-' && std::isdigit((unsigned char)peekChar(1)))) + if (std::isdigit(static_cast(c))) return scanNumber(); if (c == '"') @@ -119,9 +119,6 @@ namespace zust { size_t startCol = column_; std::string text; bool seenDot = false; - if (peekChar() == '-' and isdigit(peekChar(1))) { - text.push_back(advance()); - } while (std::isdigit(static_cast(peekChar())) || (!seenDot && peekChar() == '.')) { if (peekChar() == '.') seenDot = true; diff --git a/src/parser/Parser.cpp b/src/parser/Parser.cpp index 0f891b4..495bae4 100644 --- a/src/parser/Parser.cpp +++ b/src/parser/Parser.cpp @@ -180,7 +180,7 @@ namespace zust { void Parser::advance() { currentToken = lexer.nextToken(); } - bool Parser::match(Token::Token::Kind kind) { + bool Parser::match(Token::Kind kind) { if (currentToken.kind == kind) { advance(); return true; @@ -188,7 +188,7 @@ namespace zust { return false; } - void Parser::expect(Token::Token::Kind kind, const std::string& errMsg) { + void Parser::expect(Token::Kind kind, const std::string& errMsg) { if (!match(kind)) { logError({ErrorType::Syntax, errMsg + " at line " + std::to_string(currentToken.line) + @@ -201,7 +201,7 @@ namespace zust { std::unique_ptr Parser::parse() { auto program = ASTNode::makeProgramNode(currentScope); - while (currentToken.kind != Token::Token::Kind::EndOfFile) { + while (currentToken.kind != Token::Kind::EndOfFile) { auto stmt = parseStatement(); if (stmt) program->addChild(std::move(stmt)); @@ -238,9 +238,9 @@ namespace zust { currentToken.text == "extern") || currentToken.kind == Token::Kind::Function) return parseFunctionDeclaration(); - if (match(Token::Token::Kind::Let)) + if (match(Token::Kind::Let)) return parseVariableDeclaration(); - if (currentToken.kind == Token::Token::Kind::Identifier and lexer.peek().kind == Token::Kind::Equal) + if (currentToken.kind == Token::Kind::Identifier and lexer.peek().kind == Token::Kind::Equal) return parseVariableReassignment(); if (currentToken.kind == Token::Kind::If || currentToken.kind == Token::Kind::ElseIf || @@ -458,8 +458,8 @@ namespace zust { } std::unique_ptr Parser::parseVariableDeclaration() { - if (currentToken.kind != Token::Token::Kind::Identifier) - expect(Token::Token::Kind::Identifier, + if (currentToken.kind != Token::Kind::Identifier) + expect(Token::Kind::Identifier, "Expected variable name after 'let'"); std::string name = currentToken.text; @@ -521,9 +521,9 @@ namespace zust { std::string name = currentToken.text; advance(); - expect(Token::Token::Kind::Equal, "Expected '=' for variable reassignment"); + expect(Token::Kind::Equal, "Expected '=' for variable reassignment"); auto expr = parseExpression(); - expect(Token::Token::Kind::SemiColon, "Expected ';' after reassignment"); + expect(Token::Kind::SemiColon, "Expected ';' after reassignment"); return ASTNode::makeVariableReassignmentNode(name, std::move(expr), currentScope); } @@ -538,27 +538,40 @@ namespace zust { } std::unique_ptr Parser::parsePrimary() { + if (currentToken.kind == Token::Kind::Symbol && currentToken.text == "-") { + advance(); + if (currentToken.kind == Token::Kind::FloatLiteral) { + std::string f = currentToken.text; + advance(); + return ASTNode::makeFloatLiteralNode("-" + f, currentScope); + } + if (currentToken.kind == Token::Kind::IntegerLiteral) { + std::string val = currentToken.text; + advance(); + return ASTNode::makeIntegerLiteralNode("-" + val, currentScope); + } + } if (currentToken.kind == Token::Kind::BoolLiteral) { bool val = (currentToken.text == "true"); advance(); return ASTNode::makeBooleanLiteralNode(val, currentScope); } - if (currentToken.kind == Token::Token::Kind::StringLiteral) { + if (currentToken.kind == Token::Kind::StringLiteral) { std::string s = currentToken.text; advance(); return ASTNode::makeStringLiteralNode(s, currentScope); } - if (currentToken.kind == Token::Token::Kind::FloatLiteral) { + if (currentToken.kind == Token::Kind::FloatLiteral) { std::string f = currentToken.text; advance(); return ASTNode::makeFloatLiteralNode(f, currentScope); } - if (currentToken.kind == Token::Token::Kind::IntegerLiteral) { + if (currentToken.kind == Token::Kind::IntegerLiteral) { std::string val = currentToken.text; advance(); return ASTNode::makeIntegerLiteralNode(val, currentScope); } - if (currentToken.kind == Token::Token::Kind::Identifier) { + if (currentToken.kind == Token::Kind::Identifier) { std::string name = currentToken.text; advance();