Support one hardcoded import
This commit is contained in:
@ -17,46 +17,67 @@ along with GCC; see the file COPYING3. If not see
|
||||
|
||||
#include "elna/boot/dependency.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
|
||||
#include "elna/boot/driver.h"
|
||||
#include "elna/boot/semantic.h"
|
||||
#include "parser.hh"
|
||||
|
||||
namespace elna::boot
|
||||
{
|
||||
dependency_graph::dependency_graph()
|
||||
dependency::dependency(const char *path)
|
||||
: error_container(path)
|
||||
{
|
||||
}
|
||||
|
||||
dependency_graph::dependency_graph(error_list&& errors)
|
||||
: m_errors(std::move(errors))
|
||||
{
|
||||
}
|
||||
|
||||
bool dependency_graph::has_errors() const
|
||||
{
|
||||
return !errors().empty();
|
||||
}
|
||||
|
||||
const error_list& dependency_graph::errors() const
|
||||
{
|
||||
return m_errors;
|
||||
}
|
||||
|
||||
dependency_graph read_sources(std::istream& entry_point, const char *entry_path)
|
||||
dependency read_sources(std::istream& entry_point, const char *entry_path)
|
||||
{
|
||||
driver parse_driver{ entry_path };
|
||||
lexer tokenizer(entry_point);
|
||||
yy::parser parser(tokenizer, parse_driver);
|
||||
|
||||
dependency outcome{ entry_path };
|
||||
if (parser())
|
||||
{
|
||||
return dependency_graph(std::move(parse_driver.errors()));
|
||||
std::swap(outcome.errors(), parse_driver.errors());
|
||||
return outcome;
|
||||
}
|
||||
else
|
||||
{
|
||||
dependency_graph outcome;
|
||||
outcome.modules.emplace_back(std::move(parse_driver.tree));
|
||||
|
||||
return outcome;
|
||||
std::swap(outcome.tree, parse_driver.tree);
|
||||
}
|
||||
declaration_visitor declaration_visitor(entry_path);
|
||||
outcome.tree->accept(&declaration_visitor);
|
||||
|
||||
if (!declaration_visitor.errors().empty())
|
||||
{
|
||||
std::swap(outcome.errors(), parse_driver.errors());
|
||||
}
|
||||
outcome.unresolved = declaration_visitor.unresolved;
|
||||
|
||||
return outcome;
|
||||
}
|
||||
|
||||
std::filesystem::path build_path(const std::vector<std::string>& segments)
|
||||
{
|
||||
std::filesystem::path result;
|
||||
std::vector<std::string>::const_iterator segment_iterator = std::cbegin(segments);
|
||||
|
||||
if (segment_iterator == std::cend(segments))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
result = *segment_iterator;
|
||||
|
||||
++segment_iterator;
|
||||
for (; segment_iterator != std::cend(segments); ++segment_iterator)
|
||||
{
|
||||
result /= *segment_iterator;
|
||||
}
|
||||
result.replace_extension(".elna");
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ program:
|
||||
}
|
||||
| "module" ";" import_part constant_part type_part variable_part procedure_part "end" "."
|
||||
{
|
||||
auto tree = new boot::program(boot::make_position(@1));
|
||||
auto tree = new boot::unit(boot::make_position(@1));
|
||||
|
||||
std::swap(tree->imports, $3);
|
||||
std::swap(tree->constants, $4);
|
||||
|
@ -43,4 +43,9 @@ namespace elna::boot
|
||||
{
|
||||
return m_errors;
|
||||
}
|
||||
|
||||
bool error_container::has_errors() const
|
||||
{
|
||||
return !m_errors.empty();
|
||||
}
|
||||
}
|
||||
|
@ -74,9 +74,8 @@ namespace elna::boot
|
||||
return message;
|
||||
}
|
||||
|
||||
name_analysis_visitor::name_analysis_visitor(const char *path, std::shared_ptr<symbol_table> symbols,
|
||||
std::unordered_map<std::string, std::shared_ptr<alias_type>>&& unresolved)
|
||||
: error_container(path), symbols(symbols), unresolved(std::move(unresolved))
|
||||
name_analysis_visitor::name_analysis_visitor(const char *path, symbol_bag bag)
|
||||
: error_container(path), bag(bag)
|
||||
{
|
||||
}
|
||||
|
||||
@ -120,20 +119,20 @@ namespace elna::boot
|
||||
void name_analysis_visitor::visit(type_declaration *definition)
|
||||
{
|
||||
definition->body().accept(this);
|
||||
auto unresolved_declaration = this->unresolved.at(definition->identifier.identifier);
|
||||
auto unresolved_declaration = this->bag.unresolved.at(definition->identifier.identifier);
|
||||
|
||||
unresolved_declaration->reference = this->current_type;
|
||||
}
|
||||
|
||||
void name_analysis_visitor::visit(named_type_expression *type_expression)
|
||||
{
|
||||
auto unresolved_alias = this->unresolved.find(type_expression->name);
|
||||
auto unresolved_alias = this->bag.unresolved.find(type_expression->name);
|
||||
|
||||
if (unresolved_alias != this->unresolved.end())
|
||||
if (unresolved_alias != this->bag.unresolved.end())
|
||||
{
|
||||
this->current_type = type(unresolved_alias->second);
|
||||
}
|
||||
else if (auto from_symbol_table = this->symbols->lookup(type_expression->name))
|
||||
else if (auto from_symbol_table = this->bag.lookup(type_expression->name))
|
||||
{
|
||||
this->current_type = from_symbol_table->is_type()->symbol;
|
||||
}
|
||||
@ -214,28 +213,24 @@ namespace elna::boot
|
||||
{
|
||||
declaration->variable_type().accept(this);
|
||||
|
||||
this->symbols->enter(declaration->identifier.identifier,
|
||||
std::make_shared<variable_info>(this->current_type));
|
||||
this->bag.enter(declaration->identifier.identifier, std::make_shared<variable_info>(this->current_type));
|
||||
}
|
||||
|
||||
void name_analysis_visitor::visit(constant_declaration *definition)
|
||||
{
|
||||
definition->body().accept(this);
|
||||
|
||||
this->symbols->enter(definition->identifier.identifier,
|
||||
std::make_shared<constant_info>(this->current_literal));
|
||||
this->bag.enter(definition->identifier.identifier, std::make_shared<constant_info>(this->current_literal));
|
||||
}
|
||||
|
||||
void name_analysis_visitor::visit(procedure_declaration *definition)
|
||||
{
|
||||
std::shared_ptr<procedure_info> info;
|
||||
auto heading = build_procedure(definition->heading());
|
||||
|
||||
if (definition->body.has_value())
|
||||
{
|
||||
info = std::make_shared<procedure_info>(build_procedure(definition->heading()),
|
||||
definition->parameter_names, this->symbols);
|
||||
|
||||
this->symbols = info->symbols;
|
||||
info = std::make_shared<procedure_info>(heading, definition->parameter_names, this->bag.enter());
|
||||
|
||||
for (constant_declaration *const constant : definition->body.value().constants())
|
||||
{
|
||||
@ -249,14 +244,13 @@ namespace elna::boot
|
||||
{
|
||||
statement->accept(this);
|
||||
}
|
||||
this->symbols = this->symbols->scope();
|
||||
this->bag.leave();
|
||||
}
|
||||
else
|
||||
{
|
||||
info = std::make_shared<procedure_info>(build_procedure(definition->heading()),
|
||||
definition->parameter_names);
|
||||
info = std::make_shared<procedure_info>(heading, definition->parameter_names);
|
||||
}
|
||||
this->symbols->enter(definition->identifier.identifier, info);
|
||||
this->bag.enter(definition->identifier.identifier, info);
|
||||
}
|
||||
|
||||
void name_analysis_visitor::visit(assign_statement *statement)
|
||||
@ -379,14 +373,14 @@ namespace elna::boot
|
||||
{
|
||||
type->accept(this);
|
||||
}
|
||||
for (auto& unresolved : this->unresolved)
|
||||
for (auto& unresolved : this->bag.unresolved)
|
||||
{
|
||||
std::vector<std::string> path;
|
||||
|
||||
if (check_unresolved_symbol(unresolved.second, path))
|
||||
{
|
||||
auto info = std::make_shared<type_info>(type_info(type(unresolved.second)));
|
||||
this->symbols->enter(std::move(unresolved.first), info);
|
||||
this->bag.enter(unresolved.first, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -313,13 +313,9 @@ namespace elna::boot
|
||||
}
|
||||
|
||||
procedure_info::procedure_info(const procedure_type symbol, const std::vector<std::string> names,
|
||||
std::shared_ptr<symbol_table> parent_table)
|
||||
: symbol(symbol), names(names)
|
||||
std::shared_ptr<symbol_table> scope)
|
||||
: symbol(symbol), names(names), symbols(scope)
|
||||
{
|
||||
if (parent_table != nullptr)
|
||||
{
|
||||
this->symbols = std::make_shared<symbol_table>(parent_table);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<procedure_info> procedure_info::is_procedure()
|
||||
@ -361,4 +357,57 @@ namespace elna::boot
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
symbol_bag::symbol_bag()
|
||||
{
|
||||
this->symbols = std::make_shared<symbol_table>();
|
||||
}
|
||||
|
||||
symbol_bag::symbol_bag(forward_table&& unresolved, std::shared_ptr<symbol_table> symbols)
|
||||
: symbols(symbols), unresolved(unresolved)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<info> symbol_bag::lookup(const std::string& name)
|
||||
{
|
||||
for (auto import_bag : this->imports)
|
||||
{
|
||||
if (auto result = import_bag->lookup(name))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return this->symbols->lookup(name);
|
||||
}
|
||||
|
||||
bool symbol_bag::enter(const std::string& name, std::shared_ptr<info> entry)
|
||||
{
|
||||
return this->symbols->enter(name, entry);
|
||||
}
|
||||
|
||||
std::shared_ptr<symbol_table> symbol_bag::enter()
|
||||
{
|
||||
this->symbols = std::make_shared<symbol_table>(this->symbols);
|
||||
return this->symbols;
|
||||
}
|
||||
|
||||
void symbol_bag::enter(std::shared_ptr<symbol_table> child)
|
||||
{
|
||||
this->symbols = child;
|
||||
}
|
||||
|
||||
void symbol_bag::leave()
|
||||
{
|
||||
this->symbols = this->symbols->scope();
|
||||
}
|
||||
|
||||
void symbol_bag::add_import(std::shared_ptr<symbol_table> table)
|
||||
{
|
||||
this->imports.push_front(table);
|
||||
}
|
||||
|
||||
void symbol_bag::add_import(const symbol_bag& bag)
|
||||
{
|
||||
add_import(bag.symbols);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user