Skip to content

Commit

Permalink
mut issues
Browse files Browse the repository at this point in the history
  • Loading branch information
amanuel2 committed Jun 28, 2024
1 parent 2322f32 commit 7e3ef4c
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 40 deletions.
2 changes: 1 addition & 1 deletion include/ast/decl.hh
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ namespace rift
class DeclVar: public Decl
{
public:
DeclVar(const Token&identifier): identifier(identifier), expr(nullptr) {};
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
4 changes: 3 additions & 1 deletion include/ast/env.hh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
// #include <absl/container/flat_hash_map.h>
#include <scanner/tokens.hh>
#include <unordered_map>
#include <unordered_set>
#include <iostream>

using Token = rift::scanner::Token;
Expand Down Expand Up @@ -71,12 +72,13 @@ namespace rift
Environment(Environment *child) : child(child) {}
~Environment() = default;
Token getEnv(const str_t& name) const;
void setEnv(const str_t& name, const Token& value);
void setEnv(const str_t& name, const Token& value, bool is_const);
void printState();
Environment *child;
protected:
// absl::flat_hash_map<str_t, rift::scanner::Token> values;
std::unordered_map<str_t, rift::scanner::Token> values = {};
std::unordered_set<str_t> const_keys = {};
};
}
}
6 changes: 4 additions & 2 deletions include/ast/parser.hh
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ namespace rift
/// @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 mut x = 1; mut! x = 5;
std::unique_ptr<DeclVar> declaration_variable(bool mut);

/// @example while(true) print("hi");
std::unique_ptr<For> for_();
Expand All @@ -100,6 +100,8 @@ namespace rift
void synchronize();
/// @brief returns any statements that might be executed
std::unique_ptr<Stmt> ret_stmt();
/// @brief returns any declarations that might be executed
vec_prog ret_decl();
};

class ParserException : public ReaderException
Expand Down
4 changes: 2 additions & 2 deletions include/scanner/scanner.hh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include <stdlib.h>
// #include <map>

#include <unordered_map>
#include <map>
#include <vector>

using namespace rift::reader;
Expand All @@ -37,7 +37,7 @@ namespace rift
{
std::shared_ptr<std::vector<char>> source;
std::vector<Token> tokens;
std::unordered_map<std::string, Type> keywords;
std::map<str_t, Type, std::greater<str_t> > keywords;

Scanner(std::shared_ptr<std::vector<char>> source);
~Scanner(){}
Expand Down
4 changes: 3 additions & 1 deletion include/scanner/tokens.hh
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ namespace rift

// Literals
IDENTIFIER,
C_IDENTIFIER,
STRINGLITERAL,
NUMERICLITERAL,

Expand All @@ -80,6 +81,7 @@ namespace rift
THIS,
TRUE,
VAR,
CONST,
WHILE,

IGNORE,
Expand Down Expand Up @@ -130,7 +132,7 @@ namespace rift
<< ", Line=" << token.line << ")"*/;
return os;
}
bool operator==(const Token &token);
bool operator==(const Token &token) const;

std::any getLiteral() const;
};
Expand Down
11 changes: 8 additions & 3 deletions lib/ast/env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,17 @@ namespace rift
return values.at(name);
}

void Environment::setEnv(const str_t& name, const Token& value)
void Environment::setEnv(const str_t& name, const Token& value, bool is_const)
{
if (!values.contains(name) && child != nullptr) {
child->setEnv(name, value);
child->setEnv(name, value, is_const);
} else {
values[name] = value;
if (values.contains(name) && const_keys.contains(name)) {
error::report(0, "Environment", "Cannot reassign a constant variable", values.at(name), std::exception());
} else {
values[name] = value;
if (is_const) const_keys.insert(name);
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions lib/ast/eval.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ namespace rift
Token Visitor::visit_assign(const Assign& expr) const
{
auto name = castString(expr.name);
env::getInstance().setEnv(name, expr.value->accept(*this));
env::getInstance().setEnv(name, expr.value->accept(*this), expr.name.type == TokenType::C_IDENTIFIER);
return env::getInstance().getEnv(name);;
}

Expand Down Expand Up @@ -363,7 +363,7 @@ namespace rift
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);
env::getInstance().setEnv(decl.identifier.lexeme, niltok, decl.identifier.type == TokenType::C_IDENTIFIER);
toks.push_back(niltok);
}
return toks;
Expand Down
61 changes: 35 additions & 26 deletions lib/ast/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -295,28 +295,31 @@ namespace rift
return std::make_unique<DeclStmt>(std::move(stmt));
}

std::unique_ptr<DeclVar> Parser::declaration_variable()
std::unique_ptr<DeclVar> Parser::declaration_variable(bool mut)
{
// make sure there is an identifier
auto tok_t = mut ? TokenType::IDENTIFIER : TokenType::C_IDENTIFIER;
auto idt = consume(Token(TokenType::IDENTIFIER, "", "", line), std::unique_ptr<ParserException>(new ParserException("Expected variable name")));
prevance();
// make sure the identifier is not already declared
/// @note this is just a check, the actual declaration is done in the evaluator
/// this also checks if any outer block has already declared this variable
if (env::getInstance().getEnv(castString(idt)) != Token())
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);
env::getInstance().setEnv(castString(idt), idt, idt.type == TokenType::C_IDENTIFIER);

if(peekNext() == Token(TokenType::EQUAL, "=", "", line)) {
auto expr = assignment();
consume(Token(TokenType::SEMICOLON, ";", "", line), std::unique_ptr<ParserException>(new ParserException("Expected ';' after variable assignment")));
idt.type = tok_t;
return std::make_unique<DeclVar>(idt, std::move(expr));
} else if (!mut) {
rift::error::report(line, "declaration_variable", "🛑 Constants must be defined", idt, ParserException("Constants must be defined"));
}

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);
return std::unique_ptr<DeclVar>(new DeclVar(Token(tok_t, idt.lexeme, idt.literal, idt.line)));
}

std::unique_ptr<For> Parser::for_()
Expand All @@ -326,7 +329,9 @@ namespace rift

// first ;
if (match({Token(TokenType::VAR, "", "", line)})) {
_for->decl = std::move(declaration_variable());
_for->decl = std::move(declaration_variable(true));
} else if (match({Token(TokenType::CONST, "", "", line)})) {
_for->decl = std::move(declaration_variable(false));
} else if(peek(Token(TokenType::IDENTIFIER, "", "", line))) {
_for->stmt_l = std::move(ret_stmt());
}
Expand All @@ -339,9 +344,8 @@ namespace rift
consume(Token(TokenType::SEMICOLON, ";", "", line), std::unique_ptr<ParserException>(new ParserException("Expected ';' after for second statement")));

// third ;
if(peek(Token(TokenType::IDENTIFIER, "", "", line))) {
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)})) {
Expand All @@ -355,21 +359,34 @@ namespace rift

#pragma mark - Program / Block Parsing

vec_prog Parser::ret_decl()
{
vec_prog decls = std::make_unique<std::vector<std::unique_ptr<Decl>>>();
if (consume (Token(TokenType::VAR, "", "", line))) {
auto test = declaration_variable(true);
decls->emplace_back(std::move(test));
} else if (consume (Token(TokenType::CONST, "", "", line))) {
auto test = declaration_variable(false);
decls->emplace_back(std::move(test));
} else if (consume (Token(TokenType::FOR, "", "", line))) {
decls->emplace_back(for_());
} else if(match({Token(TokenType::LEFT_BRACE, "{", "", line)})) {
auto inner_decls = std::move(block()->decls);
decls->insert(decls->end(), std::make_move_iterator(inner_decls->begin()), std::make_move_iterator(inner_decls->end()));
} else {
decls->emplace_back(declaration_statement());
}
return decls;
}

std::unique_ptr<Block> Parser::block()
{
vec_prog decls = std::make_unique<std::vector<std::unique_ptr<Decl>>>();

env::addChild();
while (!atEnd() && !peek(Token(TokenType::RIGHT_BRACE, "}", "", line))) {
if (match({Token(TokenType::LEFT_BRACE, "{", "", line)})) {
auto inner_decls = std::move(block()->decls);
decls->insert(decls->end(), std::make_move_iterator(inner_decls->begin()), std::make_move_iterator(inner_decls->end()));
} else if (consume (Token(TokenType::VAR, "", "", line))) {
auto decl = declaration_variable();
decls->push_back(std::move(decl));
} else {
decls->push_back(declaration_statement());
}
auto inner = ret_decl();
decls->insert(decls->end(), std::make_move_iterator(inner->begin()), std::make_move_iterator(inner->end()));
}
env::removeChild();

Expand All @@ -384,16 +401,8 @@ namespace rift
vec_prog decls = std::make_unique<std::vector<std::unique_ptr<Decl>>>();

while (!atEnd()) {
if (consume (Token(TokenType::VAR, "", "", line))) {
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 {
decls->push_back(declaration_statement());
}
auto inner = ret_decl();
decls->insert(decls->end(), std::make_move_iterator(inner->begin()), std::make_move_iterator(inner->end()));
}

return std::unique_ptr<Program>(new Program(std::move(decls)));
Expand Down
3 changes: 2 additions & 1 deletion lib/scanner/scanner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace rift
this->source = source;
this->tokens = std::vector<Token>();

keywords = std::unordered_map<std::string, Type>();
keywords = {};
keywords["and"] = Type::LOG_AND;
keywords["class"] = Type::CLASS;
keywords["false"] = Type::FALSE;
Expand All @@ -48,6 +48,7 @@ namespace rift
keywords["super"] = Type::SUPER;
keywords["this"] = Type::THIS;
keywords["true"] = Type::TRUE;
keywords["mut!"] = Type::CONST;
keywords["mut"] = Type::VAR;
keywords["while"] = Type::WHILE;
}
Expand Down
4 changes: 3 additions & 1 deletion lib/scanner/tokens.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ std::string Token::convertTypeString(TokenType type) {
case THIS: return "THIS";
case TRUE: return "TRUE";
case VAR: return "VAR";
case CONST: return "CONST";
case WHILE: return "WHILE";
case C_IDENTIFIER: return "C_IDENTIFIER";
case IGNORE: return "IGNORE";
case EOFF: return "EOFF";
}
Expand Down Expand Up @@ -209,7 +211,7 @@ std::any Token::getLiteral() const

#pragma mark - Operators

bool Token::operator==(const Token &token)
bool Token::operator==(const Token &token) const
{
return this->type == token.type;
}

0 comments on commit 7e3ef4c

Please sign in to comment.