Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Scopes #38

Merged
merged 4 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions include/ast/passes/define.h → include/ast/passes/def_ref.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
#include "ast/symbol/symbol.h"
#include "ast/symbol/symbol_table.h"

class Define : public Pass {
class DefRef : public Pass {
private:
shared_ptr<SymbolTable> symbol_table;
bool is_builtin(std::string name);

public:
explicit Define(shared_ptr<SymbolTable> symbol_table);
explicit DefRef(shared_ptr<SymbolTable> symbol_table);
void visit_block(shared_ptr<ast::Block>) override;
void visit_declaration(shared_ptr<ast::Declaration>) override;
void visit_parameter(shared_ptr<ast::Parameter>) override;
void visit_function(shared_ptr<ast::Function>) override;
void visit_variable(shared_ptr<ast::Variable>) override;
void visit_call(shared_ptr<ast::Call>) override;
};
17 changes: 0 additions & 17 deletions include/ast/passes/reference.h

This file was deleted.

3 changes: 1 addition & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ set(
"${CMAKE_CURRENT_SOURCE_DIR}/ast/symbol/function_symbol.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ast/ast.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ast/passes/pass.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ast/passes/define.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ast/passes/reference.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ast/passes/def_ref.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ast/passes/type_check.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ast/passes/builtin.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/shared/type.cpp"
Expand Down
23 changes: 13 additions & 10 deletions src/ast/ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,13 +260,15 @@ void ast::Function::xml(int level) {
<< type->get_name() << "\" name=\"" << name << "\" ref_name=\""
<< ref_name << "\">\n";

std::cout << std::string((level + 1) * 4, ' ') << "<parameters>\n";
for (const auto& param : params) {
param->xml(level + 2);
if (params.size() > 0) {
std::cout << std::string((level + 1) * 4, ' ') << "<parameters>\n";
for (const auto& param : params) {
param->xml(level + 2);
}
std::cout << std::string((level + 1) * 4, ' ') << "</parameters>\n";
}
std::cout << std::string((level + 1) * 4, ' ') << "</parameters>\n";
body->xml(level + 1);

body->xml(level + 1);
std::cout << std::string(level * 4, ' ') << "</function>\n";
}

Expand Down Expand Up @@ -294,16 +296,17 @@ std::string ast::Call::get_name() {
}

void ast::Call::xml(int level) {
std::cout << std::string(level * 4, ' ') << "<call name=\"" << this->name
<< "\" ref_name=\"" << this->function->get_ref_name()
<< "\" type=\"" << this->type->get_name() << "\">\n";
std::string ref = function ? function->get_ref_name() : "(unset)";
std::cout << std::string(level * 4, ' ') << "<call name=\"" << name
<< "\" ref_name=\"" << ref << "\" type=\"" << type->get_name()
<< "\">\n";

if (arguments.size() > 0) {
std::cout << std::string((level + 1) * 4, ' ') << "<args>\n";
std::cout << std::string((level + 1) * 4, ' ') << "<arguments>\n";
for (auto const& a : arguments) {
a->xml(level + 2);
}
std::cout << std::string((level + 1) * 4, ' ') << "</args>\n";
std::cout << std::string((level + 1) * 4, ' ') << "</arguments>\n";
}

std::cout << std::string(level * 4, ' ') << "</call>\n";
Expand Down
13 changes: 8 additions & 5 deletions src/ast/builder.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <any>
#include <stdexcept>
#include <vector>

Expand All @@ -6,8 +7,10 @@
#include "ast/builder.h"
#include "shared/context.h"

using std::any_cast;

#define cast_node(a, b) \
(dynamic_pointer_cast<a>(std::any_cast<shared_ptr<ast::Node>>(b)))
(dynamic_pointer_cast<a>(any_cast<shared_ptr<ast::Node>>(b)))
#define to_node(a) static_cast<shared_ptr<ast::Node>>(a)

Builder::Builder(shared_ptr<SymbolTable> symbol_table) {
Expand Down Expand Up @@ -147,7 +150,7 @@ std::any Builder::visitIdentifier(FusionParser::IdentifierContext* ctx) {

std::any Builder::visitBlock(FusionParser::BlockContext* ctx) {
Token* token = ctx->L_CURLY()->getSymbol();
auto block = std::make_shared<ast::Block>(token);
auto block = make_shared<ast::Block>(token);

for (auto const& s : ctx->statement()) {
shared_ptr<ast::Node> node = cast_node(ast::Node, visit(s));
Expand All @@ -163,16 +166,16 @@ std::any Builder::visitVariable(FusionParser::VariableContext* ctx) {
std::string name = ctx->ID()->getText();

ast::Qualifier qualifier =
std::any_cast<ast::Qualifier>(visit(ctx->qualifier()));
TypePtr type = std::any_cast<TypePtr>(visit(ctx->type()));
any_cast<ast::Qualifier>(visit(ctx->qualifier()));
TypePtr type = any_cast<TypePtr>(visit(ctx->type()));

auto var = make_shared<ast::Variable>(qualifier, type, name, token);
return to_node(var);
}

std::any Builder::visitFunction(FusionParser::FunctionContext* ctx) {
Token* token = ctx->FUNCTION()->getSymbol();
TypePtr type = std::any_cast<TypePtr>(visit(ctx->type()));
TypePtr type = any_cast<TypePtr>(visit(ctx->type()));
std::string name = ctx->ID()->getText();
auto block = cast_node(ast::Block, visit(ctx->block()));

Expand Down
116 changes: 116 additions & 0 deletions src/ast/passes/def_ref.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#include "ast/passes/def_ref.h"
#include "ast/ast.h"
#include "ast/symbol/function_symbol.h"
#include "errors.h"

DefRef::DefRef(shared_ptr<SymbolTable> symbol_table) : Pass("DefRef") {
this->symbol_table = symbol_table;
}

void DefRef::visit_block(shared_ptr<ast::Block> node) {
symbol_table->push();
for (const auto& node : node->nodes) {
visit(node);
}
symbol_table->pop();
}

void DefRef::visit_declaration(shared_ptr<ast::Declaration> node) {
if (symbol_table->resolve_local(node->var->get_name()).has_value()) {
throw SymbolError(
node->token->getLine(),
"variable " + node->var->get_name() + " already defined");
}

shared_ptr<ast::Variable> var = node->var;
shared_ptr<VariableSymbol> sym = make_shared<VariableSymbol>(var);

symbol_table->define(sym);

visit(node->expr);
}

void DefRef::visit_parameter(shared_ptr<ast::Parameter> node) {
shared_ptr<ast::Variable> var = node->var;
if (symbol_table->resolve_local(var->get_name()).has_value()) {
throw SymbolError(
node->token->getLine(),
"parameter " + node->var->get_name() + " already defined");
}

shared_ptr<VariableSymbol> sym = make_shared<VariableSymbol>(var);
symbol_table->define(sym);
}

void DefRef::visit_function(shared_ptr<ast::Function> node) {
if (symbol_table->resolve_bottom(name).has_value()) {
throw SymbolError(node->token->getLine(),
"function " + node->get_name() + " already defined");
}

shared_ptr<FunctionSymbol> sym =
std::make_shared<FunctionSymbol>(node, symbol_table->current_scope);
symbol_table->define(sym);

symbol_table->push();
for (const auto& param : node->params) {
visit(param);
}

symbol_table->push();
visit(node->body);
symbol_table->pop();
symbol_table->pop();
}

void DefRef::visit_variable(shared_ptr<ast::Variable> node) {
std::optional<SymbolPtr> var = symbol_table->resolve(node->get_name());
size_t line = node->token->getLine();
if (!var.has_value()) {
throw SymbolError(line,
"use of undefined variable: " + node->get_name());
}

shared_ptr<VariableSymbol> vs =
dynamic_pointer_cast<VariableSymbol>(var.value());
if (vs == nullptr) {
throw SymbolError(line, node->get_name() + " is not a variable");
}

node->set_type(vs->variable->get_type());
node->set_qualifier(vs->variable->get_qualifier());
node->set_ref_name(vs->variable->get_ref_name());
}

void DefRef::visit_call(shared_ptr<ast::Call> node) {
for (const auto& arg : node->arguments) {
visit(arg);
}

std::string name = node->get_name();
if (is_builtin(name) && node->arguments.size() > 0) {
name += "_" + node->arguments[0]->get_type()->get_name();
}

std::optional<SymbolPtr> var = symbol_table->resolve(name);
size_t line = node->token->getLine();
if (!var.has_value()) {
throw SymbolError(line, "called undefined function: " + name);
}

shared_ptr<FunctionSymbol> vs =
dynamic_pointer_cast<FunctionSymbol>(var.value());
if (vs == nullptr) {
throw SymbolError(line, node->get_name() + " is not a function");
}

node->set_function(vs->function);
}

bool DefRef::is_builtin(std::string name) {
if (name == "print" || name == "println") {
return true;
}

return false;
}
48 changes: 0 additions & 48 deletions src/ast/passes/define.cpp

This file was deleted.

6 changes: 2 additions & 4 deletions src/ast/passes/pass.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#include "ast/passes/pass.h"
#include "ast/ast.h"
#include "ast/passes/builtin.h"
#include "ast/passes/define.h"
#include "ast/passes/reference.h"
#include "ast/passes/def_ref.h"
#include "ast/passes/type_check.h"

constexpr bool debug = false;
Expand All @@ -14,8 +13,7 @@ constexpr bool debug = false;
void Pass::run_passes(std::shared_ptr<ast::Block> ast,
shared_ptr<SymbolTable> symtab) {
std::vector<std::shared_ptr<Pass>> passes = {
std::make_shared<Define>(symtab),
std::make_shared<Reference>(symtab),
std::make_shared<DefRef>(symtab),
std::make_shared<TypeCheck>(),
std::make_shared<Builtin>(symtab),
};
Expand Down
55 changes: 0 additions & 55 deletions src/ast/passes/reference.cpp

This file was deleted.

Loading
Loading