Skip to content

Commit

Permalink
var done
Browse files Browse the repository at this point in the history
  • Loading branch information
amanuel2 committed Jun 25, 2024
1 parent 73e3f00 commit ee3d82d
Show file tree
Hide file tree
Showing 10 changed files with 59 additions and 30 deletions.
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
include_directories(${gmock_SOURCE_DIR}/include ${gmock_SOURCE_DIR})

# Google {Abseil}
add_subdirectory(external/abseil)
# add_compile_definitions(ABSL_USE_GOOGLE_DEFAULT_NAMESPACE)
# add_subdirectory(external/abseil)
# find_package(absl REQUIRED)
# include_directories(${abseil_SOURCE_DIR})
# target_link_libraries(riftlang absl::base absl::synchronization absl::strings)
5 changes: 2 additions & 3 deletions include/ast/decl.hh
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ namespace rift
friend class Visitor;
friend class DeclStmt;
friend class DeclVar;
protected:
rift::ast::Environment env = {};
};

class DeclStmt: public Decl
Expand All @@ -52,7 +50,7 @@ namespace rift
class DeclVar: public Decl
{
public:
DeclVar(const Token &identifier): identifier(identifier) {};
DeclVar(const Token &identifier, std::unique_ptr<Expr> expr): identifier(identifier), expr(std::move(expr)) {};
Token accept(const Visitor &visitor) const override { return visitor.visit_decl_var(*this); }

#pragma clang diagnostic push
Expand All @@ -62,6 +60,7 @@ namespace rift
#pragma clang diagnostic pop

const Token& identifier;
std::unique_ptr<Expr> expr;
};
}
}
15 changes: 11 additions & 4 deletions include/ast/env.hh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
// #include "../../external/abseil/absl/container/flat_hash_map.h"
// #include <absl/container/flat_hash_map.h>
#include <scanner/tokens.hh>
#include <map>
#include <unordered_map>
#include <iostream>

using Token = rift::scanner::Token;
Expand All @@ -30,14 +30,21 @@ namespace rift
class Environment
{
public:
Environment() = default;
~Environment() = default;

static Environment& getInstance() {
static Environment instance;
return instance;
}
Token getEnv(const str_t& name) const;
void setEnv(const str_t& name, const Token& value);
protected:
// absl::flat_hash_map<str_t, rift::scanner::Token> values;
std::unordered_map<str_t, rift::scanner::Token> values = {};
Environment(Environment &other) = delete;
Environment &operator=(const Environment &other) = delete;

private:
Environment() = default;
~Environment() = default;
};
}
}
3 changes: 1 addition & 2 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,10 @@ add_executable(
${SOURCES}
)

find_package(absl REQUIRED)
target_compile_options(riftlang PRIVATE -Wno-gcc-compat)
target_compile_definitions(riftlang PRIVATE ABSL_USES_STD_ANY=1)

target_link_libraries(riftlang absl::base absl::strings absl::hash absl::algorithm absl::memory absl::flat_hash_map absl::container_common absl::container_memory)
# target_link_libraries(riftlang absl::base absl::strings absl::hash absl::algorithm absl::memory absl::flat_hash_map absl::container_common absl::container_memory)

add_library(riftlib STATIC ${SOURCES})

Expand Down
11 changes: 7 additions & 4 deletions lib/ast/env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,20 @@ namespace rift
{
Token Environment::getEnv(const str_t& name) const
{
// if(tok == Token())
// rift::error::runTimeError("🛑 Undefined variable '" + name + "'");
// }
for (const auto& [key, value] : values) {
std::cout << key << " => " << value.to_string() << std::endl;
}
if (!values.contains(name)) {
return Token();
}
return values.at("env");
return values.at(name);
}

void Environment::setEnv(const str_t& name, const Token& value)
{
if (values.contains(name)) {
std::cout << "🟡 [line " << value.line << "] Warn: Variable '" << name << "' already defined." << std::endl;
}
values[name] = value;
}
}
Expand Down
15 changes: 6 additions & 9 deletions lib/ast/eval.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <ast/eval.hh>
#include <error/error.hh>
#include <utils/macros.hh>
#include <ast/env.hh>

namespace rift
{
Expand Down Expand Up @@ -59,10 +60,10 @@ namespace rift

Token Visitor::visit_assign(const Assign& expr) const
{
Token val = expr.value->accept(*this);
auto name = castString(expr.name);
expr.env.assign(name, val);
return val;
auto tok = rift::ast::Environment::getInstance().getEnv(name);
rift::ast::Environment::getInstance().setEnv(name, expr.value->accept(*this));
return tok;
}

Token Visitor::visit_binary(const Binary& expr) const
Expand Down Expand Up @@ -243,12 +244,8 @@ namespace rift

Token Visitor::visit_decl_var(const DeclVar& decl) const
{
auto name = castString(decl.identifier);
auto tok = decl.env.getEnv(name);
if(tok == Token())
rift::error::runTimeError("🛑 Undefined variable '" + name + "'");
return tok;
// check performed in parser, undefined variables are CT errors
return decl.expr->accept(*this);
}

}
}
31 changes: 24 additions & 7 deletions lib/ast/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include <error/error.hh>
#include <memory>
#include <ast/prgm.hh>
#include <ast/env.hh>
#include <utils/literals.hh>

using namespace rift::scanner;

Expand Down Expand Up @@ -52,8 +54,14 @@ namespace rift
return std::unique_ptr<Literal>(new Literal(peekPrev(1)));
if (match({Token(TokenType::STRINGLITERAL, "", "", line)}))
return std::unique_ptr<Literal>(new Literal(Token(peekPrev(1))));
if (match({Token(TokenType::IDENTIFIER, "", "", line)}))
if (match({Token(TokenType::IDENTIFIER, "", "", line)})) {
/// @note rhs identifier undeclared
auto idt = peekPrev(1);
if (rift::ast::Environment::getInstance().getEnv(castString(idt)) == Token()) {
rift::error::report(line, "primary", "🛑 Undefined variable '" + castString(idt) + "' at line: " + castNumberString(idt.line), idt, ParserException("Undefined variable '" + castString(idt) + "'"));
}
return std::unique_ptr<Literal>(new Literal(Token(peekPrev(1))));
}

if (match({Token(TokenType::LEFT_PAREN, "(", "", line)})) {
auto expr = expression();
Expand Down Expand Up @@ -150,6 +158,10 @@ namespace rift
consume(Token(TokenType::EQUAL, "=", "", line), std::unique_ptr<ParserException>(new ParserException("Expected '=' after variable name")));
auto expr = assignment();
if (expr == nullptr) rift::error::report(line, "assignment", "Expected expression after variable name", peekPrev(), ParserException("Expected expression after variable name"));

// assignemnt operator expects lhs to be already declared
if (rift::ast::Environment::getInstance().getEnv(castString(idt)) == Token())
rift::error::report(line, "assignment", "🛑 Undefined variable '" + castString(idt) + "' at line: " + castNumberString(idt.line), idt, ParserException("Undefined variable '" + castString(idt) + "'"));
return std::unique_ptr<Assign>(new Assign(idt, std::move(expr)));
}

Expand Down Expand Up @@ -195,12 +207,17 @@ namespace rift

std::unique_ptr<DeclVar> Parser::declaration_variable()
{
// auto idt = consume(Token(TokenType::IDENTIFIER, "", "", line), std::unique_ptr<ParserException>(new ParserException("Expected variable name")));
// consume(Token(TokenType::EQUAL, "=", "", line), std::unique_ptr<ParserException>(new ParserException("Expected '=' after variable name")));
// consume(Token(TokenType::SEMICOLON, ";", "", line), std::unique_ptr<ParserException>(new ParserException("Expected ';' after variable declaration")));
// auto val = consume(Token(TokenType::NUMERICLITERAL, "", "", line), std::unique_ptr<ParserException>(new ParserException("Expected number after variable declaration")));
// return std::make_unique<DeclVar>(idt);
return nullptr;
// make sure there is an 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
if (rift::ast::Environment::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"));
rift::ast::Environment::getInstance().setEnv(castString(idt), Token(TokenType::NIL, "nil", "", 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));
}

#pragma mark - Program Parsing
Expand Down
1 change: 1 addition & 0 deletions lib/error/error.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace rift
{
std::cout << "⛔️ Runtime Error: " << msg << std::endl;
runtimeErrorOccured = true;
exit(1);
}
}
}
1 change: 1 addition & 0 deletions lib/scanner/scanner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ namespace rift
void Scanner::identifier() {
while (isAlphaNumeric(advance()));
std::string text = std::string(source->begin()+start, source->begin()+curr);
text.erase(std::remove_if(text.begin(), text.end(), ::isspace), text.end());
if (keywords.find(text)!= keywords.end()) {
addToken(keywords.at(text));
} else {
Expand Down
3 changes: 3 additions & 0 deletions lib/scanner/tokens.cc
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,10 @@ std::any Token::getLiteral() const
{
if (type == STRINGLITERAL) {
return std::any{std::string(lexeme)};
} else if (type == IDENTIFIER) {
return std::any{std::string(lexeme)};
}

if (isInteger(lexeme.c_str()))
return std::any{std::stoi(lexeme.c_str())};
if (isUnsignedInteger(lexeme.c_str()))
Expand Down

0 comments on commit ee3d82d

Please sign in to comment.