Skip to content

Commit

Permalink
very annoying UB issues...
Browse files Browse the repository at this point in the history
  • Loading branch information
amanuel2 committed Jun 28, 2024
1 parent 070dbfd commit 2322f32
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 31 deletions.
20 changes: 2 additions & 18 deletions examples/internal/test.rf
Original file line number Diff line number Diff line change
@@ -1,19 +1,3 @@
let a = "global a";
let b = "global b";
let c = "global c";
{
a = "outer a";
b = "outer b";
{
a = "inner a";
print(a);
print(b);
print(c);
}
for(mut a = 0; a < 10; a = a + 1) {
print(a);
print(b);
print(c);
}
print(a);
print(b);
print(c);
}
23 changes: 23 additions & 0 deletions include/ast/decl.hh
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ namespace rift
class DeclVar: public Decl
{
public:
DeclVar(const Token&identifier): identifier(identifier), expr(nullptr) {};
DeclVar(const Token &identifier, std::unique_ptr<Expr> expr): identifier(identifier), expr(std::move(expr)) {};
Tokens accept(const Visitor &visitor) const override { return visitor.visit_decl_var(*this); }

Expand Down Expand Up @@ -77,5 +78,27 @@ namespace rift
string accept_printer(const Visitor& visitor) const override { return "unimplemented"; }
#pragma clang diagnostic pop
};

class For : public Decl
{
public:
For(): expr(nullptr), stmt_l(nullptr), stmt_r(nullptr), decl(nullptr), blk(nullptr), stmt_o(nullptr) {};
~For() = default;

std::unique_ptr<Expr> expr;
std::unique_ptr<Stmt> stmt_l;
std::unique_ptr<Stmt> stmt_r;
std::unique_ptr<Decl> decl;

std::unique_ptr<Block> blk;
std::unique_ptr<Stmt> stmt_o;

Tokens accept(const Visitor &visitor) const override { return visitor.visit_for(*this); };
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
// must uncomment visit_printer in printer.hh
string accept_printer(const Visitor& visitor) const override { return "unimplemented"; }
#pragma clang diagnostic pop
};
}
}
12 changes: 8 additions & 4 deletions include/ast/grmr.hh
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ namespace rift
/// program → decl * EOF
/// decl → varDecl | statement
/// block → "{" decl* "}"
/// for → "for" "(" (decl|stmt)? ";" expr ";" (stmt)? ")" stmt|blk
/// statement → exprStmt | printStmt | block ";"
/// varDecl → "var" IDENTIFIER ( "=" expression ) ";"
/// varDecl → "mut" IDENTIFIER ( "=" stmt ) ";"
/// constDecl → "mut!" IDENTIFIER ( "=" expr ) ";"
/// printStmt → "print" "(" expression ");"
/// exprStmt → expression ";"
/// ifStmt → "if" "(" expression ")" statement|block ( "elif" statment|block )* ( "else" statement|block )?
/// ifStmt → "if" "(" expression ")" statement|block ( "elif" statment|block )* ( "else" statement|block )?
/// ternary → expression "?" expression ":" expression ";"
/// expression → equality ";"
/// assignment → IDENTIFIER "=" assignment | equality
Expand All @@ -56,7 +58,8 @@ namespace rift

__DEFAULT_FORWARD_NONE_VA(
Printer,
Ternary
Ternary,
For
)

__DEFAULT_FORWARD_NONE_VA(
Expand Down Expand Up @@ -101,7 +104,8 @@ namespace rift
/* decl */
virtual Tokens visit_decl_stmt(const DeclStmt& decl) const;
virtual Tokens visit_decl_var(const DeclVar& decl) const;

/* c-flow */
virtual Tokens visit_for(const For& decl) const;
/* block */
virtual Tokens visit_block_stmt(const Block& block) const;
/* prgm */
Expand Down
4 changes: 4 additions & 0 deletions include/ast/parser.hh
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,17 @@ namespace rift
std::unique_ptr<StmtPrint> statement_print();
/// @example if (1+2) print(3);
std::unique_ptr<StmtIf> statement_if();


/// @note rules in order of precedence <Decl>
/// @example var x = 1;
std::unique_ptr<DeclStmt> declaration_statement();
/// @example var x = 1;
std::unique_ptr<DeclVar> declaration_variable();

/// @example while(true) print("hi");
std::unique_ptr<For> for_();

/// @example { var x = 1; }
std::unique_ptr<Block> block();
/// @note program
Expand Down
37 changes: 32 additions & 5 deletions lib/ast/eval.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,10 @@ namespace rift
{
Token val = expr.value;
any literal;

if (val.type == TokenType::IDENTIFIER) {

if (val.type == TokenType::NIL)
return Token(TokenType::NIL, "nil", nullptr, expr.value.line);
else if (val.type == TokenType::IDENTIFIER) {
Token res = env::getInstance().getEnv(castString(val));
if (res.type == TokenType::NIL) rift::error::runTimeError("Undefined variable '" + castString(val) + "'");
literal = res.getLiteral();
Expand Down Expand Up @@ -97,11 +99,11 @@ namespace rift

/* Other Literals */
else if (literal.type() == typeid(std::nullptr_t))
return Token(TokenType::NIL, "null", nullptr, expr.value.line);
return Token(TokenType::NIL, "nil", nullptr, expr.value.line);
else if (literal.type() == typeid(bool))
return Token(std::any_cast<bool>(literal)?TokenType::TRUE:TokenType::FALSE, std::to_string(std::any_cast<bool>(literal)), std::any_cast<bool>(literal), expr.value.line);
else if (literal.type() == typeid(std::nullptr_t))
return Token(TokenType::NIL, "null", nullptr, expr.value.line);
return Token(TokenType::NIL, "nil", nullptr, expr.value.line);
else
rift::error::runTimeError("Unknown literal type");
return Token();
Expand Down Expand Up @@ -357,7 +359,32 @@ namespace rift
{
// check performed in parser, undefined variables are CT errors
std::vector<Token> toks;
toks.push_back(decl.expr->accept(*this));
if (decl.expr != nullptr) {
toks.push_back(decl.expr->accept(*this));
} else {
auto niltok = Token(TokenType::NIL, "null", nullptr, decl.identifier.line);
env::getInstance().setEnv(decl.identifier.lexeme, niltok);
toks.push_back(niltok);
}
return toks;
}

Tokens Visitor::visit_for(const For& decl) const
{
Tokens toks = {};
if (decl.decl != nullptr) decl.decl->accept(*this);
else if (decl.stmt_l != nullptr) decl.stmt_l->accept(*this);

while(truthy(decl.expr->accept(*this))) {
if(decl.stmt_o != nullptr) toks.push_back(decl.stmt_o->accept(*this));
else if (decl.blk != nullptr) {
auto bk = decl.blk->accept(*this);
toks.insert(toks.begin(), bk.begin(), bk.end());
}
else rift::error::runTimeError("For statement should have a statement or block");

if (decl.stmt_r != nullptr) decl.stmt_r->accept(*this);
}
return toks;
}
}
Expand Down
52 changes: 48 additions & 4 deletions lib/ast/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -307,9 +307,50 @@ namespace rift
rift::error::report(line, "declaration_variable", "🛑 Variable '" + castString(idt) + "' already declared at line: " + castNumberString(idt.line), idt, ParserException("Variable '" + castString(idt) + "' already declared"));
env::getInstance().setEnv(castString(idt), idt);

auto expr = assignment();
consume(Token(TokenType::SEMICOLON, ";", "", line), std::unique_ptr<ParserException>(new ParserException("Expected ';' after variable assignment")));
return std::make_unique<DeclVar>(idt, std::move(expr));
if(peekNext() == Token(TokenType::EQUAL, "=", "", line)) {
auto expr = assignment();
consume(Token(TokenType::SEMICOLON, ";", "", line), std::unique_ptr<ParserException>(new ParserException("Expected ';' after variable assignment")));
return std::make_unique<DeclVar>(idt, std::move(expr));
}

idt = consume(Token(TokenType::IDENTIFIER, "", "", line), std::unique_ptr<ParserException>(new ParserException("Expected variable name")));
consume(Token(TokenType::SEMICOLON, ";", "", line), std::unique_ptr<ParserException>(new ParserException("Expected ';' after variable declaration")));
// return std::make_unique<DeclVar>(idt, std::unique_ptr<Literal>(new Literal(Token(TokenType::NIL, "nil", "", line))));
return std::make_unique<DeclVar>(idt);
}

std::unique_ptr<For> Parser::for_()
{
std::unique_ptr<For> _for = std::make_unique<For>();
consume(Token(TokenType::LEFT_PAREN, "(", "", line), std::unique_ptr<ParserException>(new ParserException("Expected '(' after for")));

// first ;
if (match({Token(TokenType::VAR, "", "", line)})) {
_for->decl = std::move(declaration_variable());
} else if(peek(Token(TokenType::IDENTIFIER, "", "", line))) {
_for->stmt_l = std::move(ret_stmt());
}
// taken by var_decl();
// consume(Token(TokenType::SEMICOLON, ";", "", line), std::unique_ptr<ParserException>(new ParserException("Expected ';' after for first statement")));

// second ;
auto expr = expression();
_for->expr = std::move(expr);
consume(Token(TokenType::SEMICOLON, ";", "", line), std::unique_ptr<ParserException>(new ParserException("Expected ';' after for second statement")));

// third ;
if(peek(Token(TokenType::IDENTIFIER, "", "", line))) {
_for->stmt_r = std::move(ret_stmt());
}
consume(Token(TokenType::RIGHT_PAREN, ")", "", line), std::unique_ptr<ParserException>(new ParserException("Expected ')' after for")));

if (match({Token(TokenType::LEFT_BRACE, "{", "", line)})) {
_for->blk = std::move(block());
} else {
_for->stmt_o = std::move(ret_stmt());
}

return _for;
}

#pragma mark - Program / Block Parsing
Expand Down Expand Up @@ -344,7 +385,10 @@ namespace rift

while (!atEnd()) {
if (consume (Token(TokenType::VAR, "", "", line))) {
decls->push_back(declaration_variable());
auto test = declaration_variable();
decls->emplace_back(std::move(test)); // GIVING ME UB
} else if (consume (Token(TokenType::FOR, "", "", line))) {
decls->push_back(for_());
} else if(match({Token(TokenType::LEFT_BRACE, "{", "", line)})) {
decls->push_back(block());
} else {
Expand Down
1 change: 1 addition & 0 deletions lib/utils/literals.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ namespace rift

std::string castString(const Token& tok, bool err) {
any val = tok.getLiteral();

if (val.type() == typeid(std::string)) {
return std::any_cast<std::string>(val);
} else if (val.type() == typeid(char*)) {
Expand Down

0 comments on commit 2322f32

Please sign in to comment.