diff --git a/include/ast/decl.hh b/include/ast/decl.hh index 1a7b24a..a09c5cf 100644 --- a/include/ast/decl.hh +++ b/include/ast/decl.hh @@ -15,6 +15,7 @@ #pragma once #include +#include #include #include @@ -34,9 +35,11 @@ namespace rift class DeclVisitor { public: - virtual T visit_decl_stmt(const DeclStmt& decl) const; - virtual T visit_decl_var(const DeclVar& decl) const; - virtual T visit_decl_func(const DeclFunc& decl) const; + DeclVisitor() = default; + virtual ~DeclVisitor() = default; + virtual T visit_decl_stmt(const DeclStmt& decl) const = 0; + virtual T visit_decl_var(const DeclVar& decl) const = 0; + virtual T visit_decl_func(const DeclFunc& decl) const = 0; }; /// @class Decl diff --git a/include/ast/eval.hh b/include/ast/eval.hh index a95a038..5d92f53 100644 --- a/include/ast/eval.hh +++ b/include/ast/eval.hh @@ -30,7 +30,7 @@ namespace rift { namespace ast { - class Eval : public ExprVisitor, StmtVisitor, + class Eval : public ExprVisitor, StmtVisitor, DeclVisitor, ProgramVisitor { public: @@ -48,12 +48,12 @@ namespace rift Token visit_call(const Call& expr) const override; // statements - Token visit_expr_stmt(const StmtExpr& stmt) const override; - Token visit_print_stmt(const StmtPrint& stmt) const override; - Token visit_if_stmt(const StmtIf& stmt) const override; - Token visit_return_stmt(const StmtReturn& stmt) const override; - Token visit_block_stmt(const Block& block) const override; - Token visit_for_stmt(const For& decl) const override; + void visit_expr_stmt(const StmtExpr& stmt) const override; + void visit_print_stmt(const StmtPrint& stmt) const override; + void visit_if_stmt(const StmtIf& stmt) const override; + void visit_return_stmt(const StmtReturn& stmt) const override; + void visit_block_stmt(const Block& block) const override; + void visit_for_stmt(const For& decl) const override; // declarations Token visit_decl_stmt(const DeclStmt& decl) const override; diff --git a/include/ast/expr.hh b/include/ast/expr.hh index 24714c2..29448db 100644 --- a/include/ast/expr.hh +++ b/include/ast/expr.hh @@ -50,22 +50,24 @@ namespace rift class ExprVisitor { public: + ExprVisitor() = default; + virtual ~ExprVisitor() = default; /// @example x = 1 + 2; - virtual T visit_assign(const Assign& expr) const; + virtual T visit_assign(const Assign& expr) const = 0; /// @example 1 + 2 - virtual T visit_binary(const Binary& expr) const; + virtual T visit_binary(const Binary& expr) const = 0; /// @example (1 + 2) - virtual T visit_grouping(const Grouping& expr) const; + virtual T visit_grouping(const Grouping& expr) const = 0; /// @example 1 - virtual T visit_literal(const Literal& expr) const; + virtual T visit_literal(const Literal& expr) const = 0; /// @example x - virtual T visit_var_expr(const VarExpr& expr) const; + virtual T visit_var_expr(const VarExpr& expr) const = 0; /// @example -1 - virtual T visit_unary(const Unary& expr) const; + virtual T visit_unary(const Unary& expr) const = 0; /// @example (true) ? 1 : 2 - virtual T visit_ternary(const Ternary& expr) const; + virtual T visit_ternary(const Ternary& expr) const = 0; /// @example x = foo(1, 2) - virtual T visit_call(const Call& expr) const; + virtual T visit_call(const Call& expr) const = 0; }; /// @class Expr diff --git a/include/ast/grmr.hh b/include/ast/grmr.hh index 495dedb..695c524 100644 --- a/include/ast/grmr.hh +++ b/include/ast/grmr.hh @@ -53,41 +53,41 @@ namespace rift /// call → primary ( "(" arguments? ")" )* ";" /// primary → NUMBER | STRING | "true" | "false" | "nil" | "(" expression ")" ";" - __DEFAULT_FORWARD_VA( - Assign, - Binary, - Grouping, - Literal, - VarExpr, - Unary - ) + // __DEFAULT_FORWARD_VA( + // Assign, + // Binary, + // Grouping, + // Literal, + // VarExpr, + // Unary + // ) - __DEFAULT_FORWARD_VA( - Printer, - Ternary, - For, - Call - ) + // __DEFAULT_FORWARD_VA( + // Printer, + // Ternary, + // For, + // Call + // ) - __DEFAULT_FORWARD_VA( - Stmt, - StmtPrint, - StmtExpr, - StmtIf, - StmtReturn - ) + // __DEFAULT_FORWARD_VA( + // Stmt, + // StmtPrint, + // StmtExpr, + // StmtIf, + // StmtReturn + // ) - __DEFAULT_FORWARD_VA( - Decl, - DeclStmt, - DeclVar, - DeclFunc - ) + // __DEFAULT_FORWARD_VA( + // Decl, + // DeclStmt, + // DeclVar, + // DeclFunc + // ) - __DEFAULT_FORWARD_VA( - Program, - Block - ) + // __DEFAULT_FORWARD_VA( + // Program, + // Block + // ) /// @class Visitor /// @brief implementation of the statements and expressions diff --git a/include/ast/prgm.hh b/include/ast/prgm.hh index ccbd65a..6bd0a7a 100644 --- a/include/ast/prgm.hh +++ b/include/ast/prgm.hh @@ -30,7 +30,10 @@ namespace rift template class ProgramVisitor { - virtual T visit_program(const Program& prgm) const; + public: + ProgramVisitor() = default; + virtual ~ProgramVisitor() = default; + virtual T visit_program(const Program& prgm) const = 0; }; template @@ -38,7 +41,8 @@ namespace rift { public: using vec_t = std::vector>>; - Program(vec_t decls) : decls(std::move(decls)) {} + // Program(vec_t decls) : decls(std::move(decls)) {} + Program(vec_t&& decls): decls(std::move(decls)) {} virtual ~Program() = default; friend class Eval; diff --git a/include/ast/printer.hh b/include/ast/printer.hh index 7a83ed2..cac30cb 100644 --- a/include/ast/printer.hh +++ b/include/ast/printer.hh @@ -41,7 +41,7 @@ namespace rift { public: using vec = std::vector*>; - Printer(); + Printer() = default; ~Printer() = default; /// Prints the given expression string. diff --git a/include/ast/stmt.hh b/include/ast/stmt.hh index 86761f3..4bbff6e 100644 --- a/include/ast/stmt.hh +++ b/include/ast/stmt.hh @@ -16,7 +16,6 @@ #include #include -#include #include namespace rift @@ -37,24 +36,28 @@ namespace rift For ); + __DEFAULT_FORWARD_VA(Decl); + /// @class Visitor /// @brief Visitor pattern for expressions template class StmtVisitor { public: + StmtVisitor() = default; + virtual ~StmtVisitor() = default; /// @example [start, end] = [end, start]; - virtual T visit_expr_stmt(const StmtExpr& stmt) const; + virtual T visit_expr_stmt(const StmtExpr& stmt) const = 0; /// @example print(x); - virtual T visit_print_stmt(const StmtPrint& stmt) const; + virtual T visit_print_stmt(const StmtPrint& stmt) const = 0; /// @example if (cond) {stmt} - virtual T visit_if_stmt(const StmtIf& stmt) const; + virtual T visit_if_stmt(const StmtIf& stmt) const = 0; /// @example return x; - virtual T visit_return_stmt(const StmtReturn& stmt) const; + virtual T visit_return_stmt(const StmtReturn& stmt) const = 0; /// @example { x = 3; } - virtual T visit_block_stmt(const Block& block) const; + virtual T visit_block_stmt(const Block& block) const = 0; /// @example for i in arr {} - virtual T visit_for_stmt(const For& decl) const; + virtual T visit_for_stmt(const For& decl) const = 0; }; /// @class Stmt diff --git a/include/scanner/tokens.hh b/include/scanner/tokens.hh index f79d8cb..b30dc0b 100644 --- a/include/scanner/tokens.hh +++ b/include/scanner/tokens.hh @@ -120,7 +120,7 @@ namespace rift this->l_type = other.l_type; } - ~Token() { } + virtual ~Token() = default; /// @brief Converts a TokenType to a string static std::string convertTypeString(TokenType type); @@ -135,6 +135,7 @@ namespace rift return os; } bool operator==(const Token &token) const; + bool operator!=(const Token &token) const; virtual Token& operator=(const Token& other) = default; diff --git a/include/utils/macros.hh b/include/utils/macros.hh index ca501a4..a6ecf20 100644 --- a/include/utils/macros.hh +++ b/include/utils/macros.hh @@ -52,7 +52,7 @@ class class_name; \ #define __DEFAULT_FORWARD_MULTI(class_name) \ - template \ + template \ class class_name; \ #define __DEFAULT_FORWARD_EACH(...) \ diff --git a/lib/ast/eval.cc b/lib/ast/eval.cc index 7700c70..68fdc96 100644 --- a/lib/ast/eval.cc +++ b/lib/ast/eval.cc @@ -39,7 +39,7 @@ namespace rift return curr_env->at(depth)->getEnv(key); } else { // return curr_env->getEnv(key); - Environment::getInstance(false).getEnv(key); + return Environment::getInstance(false).getEnv(key); } } @@ -329,22 +329,22 @@ namespace rift #pragma mark - Stmt Visitors - Token Eval::visit_expr_stmt(const StmtExpr& stmt) const + void Eval::visit_expr_stmt(const StmtExpr& stmt) const { - return stmt.expr->accept(*this); + stmt.expr->accept(*this); } - Token Eval::visit_print_stmt(const StmtPrint& stmt) const + void Eval::visit_print_stmt(const StmtPrint& stmt) const { Token val = stmt.expr->accept(*this); std::string res = castAnyString(val); if (res.at(0) == '"' && res.at(res.size()-1) == '"') res = res.substr(1, res.size()-2); std::cout << res << std::endl; - return val; + // return val; } - Token Eval::visit_if_stmt(const StmtIf& stmt) const + void Eval::visit_if_stmt(const StmtIf& stmt) const { auto if_stmt = stmt.if_stmt; // if stmt @@ -356,7 +356,6 @@ namespace rift if (if_stmt->blk != nullptr) if_stmt->blk->accept(*this); else if (if_stmt->stmt != nullptr) if_stmt->stmt->accept(*this); else rift::error::runTimeError("If statement should have a statement or block"); - return Token(); } // elif stmt @@ -367,7 +366,6 @@ namespace rift if (elif_stmt->blk != nullptr) elif_stmt->blk->accept(*this); else if (elif_stmt->stmt != nullptr) elif_stmt->stmt->accept(*this); else rift::error::runTimeError("Elif statement should have a statement or block"); - return Token(); } } @@ -378,18 +376,17 @@ namespace rift else if (else_stmt->stmt != nullptr) else_stmt->stmt->accept(*this); else rift::error::runTimeError("Else statement should have a statement or block"); } - return Token(); } - Token Eval::visit_return_stmt(const StmtReturn& stmt) const + void Eval::visit_return_stmt(const StmtReturn& stmt) const { return_token = stmt.expr->accept(*this); - return return_token; + // return return_token; } #pragma mark - Program / Block Visitor - Token Eval::visit_block_stmt(const Block& block) const + void Eval::visit_block_stmt(const Block& block) const { Tokens toks = {}; @@ -400,10 +397,10 @@ namespace rift } curr_env->removeChild(); // remove scope - return return_token; + // return return_token; } - Token Eval::visit_for_stmt(const For& decl) const + void Eval::visit_for_stmt(const For& decl) const { Tokens toks = {}; if (decl.decl != nullptr) decl.decl->accept(*this); @@ -416,7 +413,7 @@ namespace rift if (decl.stmt_r != nullptr) decl.stmt_r->accept(*this); } - return return_token; + // return return_token; } #pragma mark - Decl Visitors diff --git a/lib/ast/parser.cc b/lib/ast/parser.cc index 205a616..803f741 100644 --- a/lib/ast/parser.cc +++ b/lib/ast/parser.cc @@ -31,7 +31,7 @@ namespace rift #pragma mark - Public API - std::unique_ptr Parser::parse() + std::unique_ptr> Parser::parse() { try { return program(); @@ -331,7 +331,8 @@ namespace rift ret->else_stmt = else_stmt; } - return std::make_unique>(std::move(ret)); + // return std::make_unique>(std::move(ret)); + return ret; } std::unique_ptr> Parser::statement_block() @@ -348,8 +349,9 @@ namespace rift if (!match({Token(TokenType::RIGHT_BRACE, "}", "", line)})) rift::error::report(line, "statement_block", "Expected '}' after block", peek(), ParserException("Expected '}' after block")); - auto blk = std::make_unique>(decls); - return std::make_unique>(blk.get()); + auto blk = std::make_unique>(std::move(decls)); + // return std::make_unique>(blk.get()); + return blk; } std::unique_ptr> Parser::statement_return() @@ -357,7 +359,8 @@ namespace rift auto expr = expression(); consume(Token(TokenType::SEMICOLON, ";", "", line), std::unique_ptr(new ParserException("Expected ';' after return statement"))); auto ret_stmt = std::make_unique>(std::move(expr)); - return std::make_unique>(std::move(ret_stmt)); + // return std::make_unique>(std::move(ret_stmt)); + return ret_stmt; } std::unique_ptr> Parser::statement_for() @@ -366,11 +369,8 @@ namespace rift consume(Token(TokenType::LEFT_PAREN, "(", "", line), std::unique_ptr(new ParserException("Expected '(' after for"))); // first ; - if (match({Token(TokenType::VAR, "", "", line)})) { - _for->decl = std::make_unique>(); - // _for->decl = declaration_variable(true); - } else if (match({Token(TokenType::CONST, "", "", line)})) { - _for->decl = declaration_variable(false); + if (consume_va({Token(TokenType::VAR), Token(TokenType::CONST)}, nullptr) != Token()) { + _for->decl = declaration_variable(peekPrev().type == TokenType::VAR); } else if(peek(Token(TokenType::IDENTIFIER, "", "", line))) { _for->stmt_l = std::move(ret_stmt()); } @@ -394,7 +394,8 @@ namespace rift _for->stmt_o = std::move(ret_stmt()); } - return std::make_unique>(_for.get()); + // return std::make_unique>(_for.get()); + return _for; } //////////////////////////////////////////////////////////////////////// @@ -405,7 +406,8 @@ namespace rift { auto stmt = ret_stmt(); auto decl_stmt = std::make_unique>(std::move(stmt)); - return std::make_unique>(stmt.get()); + // return std::make_unique>(stmt.get()); + return decl_stmt; } std::unique_ptr> Parser::declaration_variable(bool mut) @@ -444,7 +446,8 @@ namespace rift // tmp->value = std::unique_ptr(val); // expr = std::unique_ptr(tmp); auto decl_var = std::make_unique>(idt, std::move(expr)); - return std::make_unique>(decl_var.get()); + // return std::make_unique>(decl_var.get()); + return decl_var; } else if (!mut) { rift::error::report(line, "declaration_variable", "🛑 Constants must be defined", idt, ParserException("Constants must be defined")); } @@ -455,8 +458,9 @@ namespace rift consume(Token(TokenType::SEMICOLON, ";", "", line), std::unique_ptr(new ParserException("Expected ';' after variable declaration"))); - std::unique_ptr> decl_var = std::make_unique>(new DeclVar(Token(tok_t, idt.lexeme, idt.literal, idt.line))); - return std::make_unique>(decl_var.get()); + std::unique_ptr> decl_var = std::make_unique>(Token(tok_t, idt.lexeme, idt.literal, idt.line)); + // return std::make_unique>(decl_var.get()); + return decl_var; } std::unique_ptr> Parser::declaration_func() @@ -466,12 +470,13 @@ namespace rift if (_func->func->blk == nullptr) { consume(Token(TokenType::SEMICOLON, ";", "", line), std::unique_ptr(new ParserException("Expected ';' after function declaration"))); } - return std::make_unique>(_func.get()); + // return std::make_unique>(_func.get()); + return _func; } - Program::vec_t Parser::ret_decl() + Program::vec_t Parser::ret_decl() { - Program::vec_t decls = {}; + Program::vec_t decls = {}; if (consume_va({Token(TokenType::VAR), Token(TokenType::CONST)}, nullptr) != Token()) { auto test = declaration_variable(peekPrev().type == TokenType::VAR); decls.emplace_back(std::move(test)); @@ -491,16 +496,16 @@ namespace rift #pragma mark - Application //////////////////////////////////////////////////////////////////////// - std::unique_ptr Parser::program() + std::unique_ptr> Parser::program() { - Program::vec_t decls = {}; + Program::vec_t decls = {}; while (!atEnd()) { auto inner = ret_decl(); decls.insert(decls.end(), std::make_move_iterator(inner.begin()), std::make_move_iterator(inner.end())); } - return std::unique_ptr(new Program(decls)); + return std::make_unique>(std::move(decls)); } //////////////////////////////////////////////////////////////////////// @@ -521,10 +526,12 @@ namespace rift curr_env->setEnv(idt.lexeme, Token(TokenType::FUN, idt.lexeme, ret->params, idt.line), false); if(match({Token(TokenType::LEFT_BRACE, "{", "", line)})) { - auto blk = dynamic_cast*>(statement_block().get()); + auto stmt = statement_block(); + auto blk = dynamic_cast*>(stmt.get()); if (!blk) rift::error::report(line, "function", "Expected block", peek(), ParserException("Expected block")); - ret->blk = std::make_unique>(blk); + // ret->blk = std::make_unique>(blk); + ret->blk = std::unique_ptr>(blk); } else if(match({Token(TokenType::FAT_ARROW, "=>", "", line)})) { // TODO: allow stmt to emulate lambdas rift::error::report(line, "function", "Lambdas not implemented yet", peek(), ParserException("Lambdas not implemented yet")); diff --git a/lib/ast/printer.cc b/lib/ast/printer.cc index a4db36e..76e94bc 100644 --- a/lib/ast/printer.cc +++ b/lib/ast/printer.cc @@ -27,10 +27,6 @@ namespace rift #pragma mark - Printer - Printer::Printer() - { - } - string Printer::print(Expr *expr) const { return expr->accept(*this); @@ -123,26 +119,38 @@ namespace rift return ""; } + string Printer::visit_assign(const Assign& expr) const + { + // Implement the logic for printing an assignment expression + // For example: + // Printer::vec v; + // v.push_back(expr.value.get()); + // return parenthesize(expr.name.lexeme + " =", v); + return ""; + } + //////////////////////////////////////////////////////////////////////// #pragma mark - Statements //////////////////////////////////////////////////////////////////////// string Printer::visit_expr_stmt(const StmtExpr& stmt) const { - auto res = stmt.expr.get(); - Token tok = res->accept(*this); - vec v = {}; // i hate this language... - v.push_back(std::make_unique>(tok).get()); - return parenthesize("expr_stmt", v); + // auto res = stmt.expr.get(); + // Token tok = res->accept(*this); + // vec v = {}; // i hate this language... + // v.push_back(std::make_unique>(tok).get()); + // return parenthesize("expr_stmt", v); + return ""; } string Printer::visit_print_stmt(const StmtPrint& stmt) const { - auto res = stmt.expr.get(); - Token tok = res->accept(*this); - vec v = {}; // i hate this language... - v.push_back(std::make_unique>(tok).get()); - return parenthesize("print", v); + // auto res = stmt.expr.get(); + // Token tok = res->accept(*this); + // vec v = {}; // i hate this language... + // v.push_back(std::make_unique>(tok).get()); + // return parenthesize("print", v); + return ""; } string Printer::visit_if_stmt(const StmtIf& stmt) const diff --git a/lib/driver/driver.cc b/lib/driver/driver.cc index 6ec9102..8b2f7af 100644 --- a/lib/driver/driver.cc +++ b/lib/driver/driver.cc @@ -50,7 +50,7 @@ namespace rift std::unique_ptr> statements = riftParser.parse(); Eval riftEvaluator; - riftEvaluator.evaluate(*statements, interactive); + riftEvaluator.evaluate(statements, interactive); rift::ast::Environment::getInstance(true).printState(); rift::ast::Environment::getInstance(false).printState(); } diff --git a/lib/scanner/tokens.cc b/lib/scanner/tokens.cc index 4048766..5bafe3c 100644 --- a/lib/scanner/tokens.cc +++ b/lib/scanner/tokens.cc @@ -217,4 +217,9 @@ std::any Token::getLiteral() const bool Token::operator==(const Token &token) const { return this->type == token.type; +} + +bool Token::operator!=(const Token &token) const +{ + return this->type != token.type; } \ No newline at end of file diff --git a/proposals/return-blocks.md b/proposals/return-blocks.md new file mode 100644 index 0000000..f1a1cbb --- /dev/null +++ b/proposals/return-blocks.md @@ -0,0 +1,13 @@ +# Return Blocks + +Allow to have inner blocks that return values + +```rust + +let x: i32 = { + if 1>2 { 1 } + 2 +} + +print!(x) // 2 +``` \ No newline at end of file diff --git a/proposals/semi-comments.md b/proposals/semi-comments.md new file mode 100644 index 0000000..4eee8ed --- /dev/null +++ b/proposals/semi-comments.md @@ -0,0 +1,11 @@ +# Semi-Comments + + +allow for semi comments to maybe enable later + +```rs + +let text = ## "Hello World" ## "Hello Mom" + +println!(text) # Prints "Hello Mom" +```