Add semantic passes
This commit is contained in:
@ -1,7 +1,8 @@
|
||||
#include "elna/source/ast.hpp"
|
||||
#include <stdexcept>
|
||||
#include "elna/source/ast.h"
|
||||
|
||||
namespace elna::source
|
||||
namespace elna
|
||||
{
|
||||
namespace source
|
||||
{
|
||||
void empty_visitor::visit(declaration *declaration)
|
||||
{
|
||||
@ -69,7 +70,7 @@ namespace elna::source
|
||||
|
||||
void empty_visitor::visit(program *program)
|
||||
{
|
||||
visit(dynamic_cast<block *>(program));
|
||||
visit(reinterpret_cast<block *>(program));
|
||||
}
|
||||
|
||||
void empty_visitor::visit(binary_expression *expression)
|
||||
@ -368,7 +369,7 @@ namespace elna::source
|
||||
this->m_operator = binary_operator::greater_equal;
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("Invalid binary operator");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -405,7 +406,7 @@ namespace elna::source
|
||||
this->m_operator = unary_operator::dereference;
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("Invalid unary operator");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -522,3 +523,4 @@ namespace elna::source
|
||||
return *m_body;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
#include "elna/source/driver.hpp"
|
||||
#include "elna/source/driver.h"
|
||||
|
||||
namespace elna::source
|
||||
namespace elna
|
||||
{
|
||||
namespace source
|
||||
{
|
||||
position make_position(const yy::location& location)
|
||||
{
|
||||
@ -36,3 +38,4 @@ namespace elna::source
|
||||
return m_errors;
|
||||
}
|
||||
}
|
||||
}
|
@ -3,10 +3,10 @@
|
||||
#define YY_USER_ACTION this->location.columns(yyleng);
|
||||
|
||||
#include <sstream>
|
||||
#include "parser.hpp"
|
||||
#include "parser.hh"
|
||||
|
||||
#undef YY_DECL
|
||||
#define YY_DECL yy::parser::symbol_type elna::source::lexer::lex()
|
||||
#define YY_DECL yy::parser::symbol_type elna::source::lexer::lex(elna::source::driver& driver)
|
||||
#define yyterminate() return yy::parser::make_YYEOF(this->location)
|
||||
%}
|
||||
|
||||
@ -126,6 +126,6 @@ false {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "Illegal character 0x" << std::hex << static_cast<unsigned int>(yytext[0]);
|
||||
throw yy::parser::syntax_error(this->location, ss.str());
|
||||
driver.error(this->location, ss.str());
|
||||
}
|
||||
%%
|
||||
|
@ -4,7 +4,7 @@
|
||||
%code requires {
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include "elna/source/driver.hpp"
|
||||
#include "elna/source/driver.h"
|
||||
|
||||
#if !defined(yyFlexLexerOnce)
|
||||
#include <FlexLexer.h>
|
||||
@ -30,7 +30,7 @@
|
||||
{
|
||||
}
|
||||
|
||||
yy::parser::symbol_type lex();
|
||||
yy::parser::symbol_type lex(elna::source::driver& driver);
|
||||
};
|
||||
|
||||
}
|
||||
@ -39,10 +39,9 @@
|
||||
%define api.token.raw
|
||||
%define api.token.constructor
|
||||
%define api.value.type variant
|
||||
%define parse.assert
|
||||
|
||||
%parse-param {elna::source::lexer& lexer}
|
||||
%parse-param {elna::source::driver& driver}
|
||||
%param {elna::source::driver& driver}
|
||||
%locations
|
||||
|
||||
%header
|
||||
@ -58,7 +57,6 @@
|
||||
%token IF THEN WHILE DO
|
||||
%token CONST VAR PROCEDURE
|
||||
%token BEGIN_BLOCK END_BLOCK
|
||||
%token TRUE FALSE
|
||||
%token LEFT_PAREN RIGHT_PAREN SEMICOLON DOT COMMA
|
||||
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
|
||||
%token PLUS MINUS MULTIPLICATION DIVISION
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "elna/source/result.hpp"
|
||||
#include "elna/source/result.h"
|
||||
|
||||
namespace elna::source
|
||||
namespace elna
|
||||
{
|
||||
namespace source
|
||||
{
|
||||
error::error(const std::filesystem::path& path, const position position)
|
||||
: m_position(position), m_path(path)
|
||||
@ -33,8 +35,8 @@ namespace elna::source
|
||||
return "Name '" + name + "' was already defined";
|
||||
}
|
||||
|
||||
type_mismatch::type_mismatch(std::shared_ptr<const type> got, operation kind, const std::filesystem::path& path,
|
||||
const struct position position)
|
||||
type_mismatch::type_mismatch(std::shared_ptr<const type> got, operation kind,
|
||||
const std::filesystem::path& path, const struct position position)
|
||||
: error(path, position), kind(kind), got(got)
|
||||
{
|
||||
}
|
||||
@ -44,3 +46,4 @@ namespace elna::source
|
||||
return "Type cannot be used here.";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
#include "elna/source/semantic.hpp"
|
||||
#include "elna/source/result.hpp"
|
||||
#include "elna/source/semantic.h"
|
||||
#include "elna/source/result.h"
|
||||
#include <cstdlib>
|
||||
|
||||
namespace elna::source
|
||||
namespace elna
|
||||
{
|
||||
namespace source
|
||||
{
|
||||
name_analysis_visitor::name_analysis_visitor(std::shared_ptr<symbol_table> table,
|
||||
const std::filesystem::path& filename, const std::size_t target_pointer_size)
|
||||
@ -12,15 +14,14 @@ namespace elna::source
|
||||
|
||||
void name_analysis_visitor::visit(constant_definition *definition)
|
||||
{
|
||||
auto constant_type = std::make_shared<const class type>(int_type);
|
||||
auto constant_type = std::make_shared<const class primitive_type>(int_type);
|
||||
this->table->enter(definition->identifier(),
|
||||
std::make_shared<constant_info>(constant_type, definition->body().number()));
|
||||
}
|
||||
|
||||
std::shared_ptr<const type> name_analysis_visitor::convert_declaration_type(const type_expression& ast_type) const
|
||||
{
|
||||
auto variable_type = std::dynamic_pointer_cast<type_info>(table->lookup(ast_type.base()))
|
||||
->type();
|
||||
auto variable_type = table->lookup(ast_type.base())->is_type_info()->type();
|
||||
std::shared_ptr<type> declaration_type;
|
||||
|
||||
if (ast_type.is_pointer())
|
||||
@ -33,11 +34,11 @@ namespace elna::source
|
||||
}
|
||||
}
|
||||
|
||||
void name_analysis_visitor::visit(declaration *declaration)
|
||||
void name_analysis_visitor::visit(declaration *declarationx)
|
||||
{
|
||||
std::shared_ptr<const type> declaration_type = convert_declaration_type(declaration->type());
|
||||
std::shared_ptr<const type> declaration_type = convert_declaration_type(declarationx->type());
|
||||
|
||||
this->table->enter(declaration->identifier(),
|
||||
this->table->enter(declarationx->identifier(),
|
||||
std::make_shared<variable_info>(declaration_type));
|
||||
}
|
||||
|
||||
@ -87,12 +88,12 @@ namespace elna::source
|
||||
{
|
||||
auto declaration_info = this->table->lookup(declaration->identifier());
|
||||
|
||||
if (auto variable = std::dynamic_pointer_cast<variable_info>(declaration_info))
|
||||
if (auto variable = declaration_info->is_variable_info())
|
||||
{
|
||||
this->local_offset -= sizeof(std::int32_t);
|
||||
variable->offset = this->local_offset;
|
||||
}
|
||||
else if (auto parameter = std::dynamic_pointer_cast<parameter_info>(declaration_info))
|
||||
else if (auto parameter = declaration_info->is_parameter_info())
|
||||
{
|
||||
parameter->offset = this->argument_offset;
|
||||
this->argument_offset += sizeof(std::int32_t);
|
||||
@ -105,7 +106,7 @@ namespace elna::source
|
||||
this->argument_offset = 0;
|
||||
|
||||
empty_visitor::visit(program);
|
||||
std::dynamic_pointer_cast<procedure_info>(table->lookup("_start"))->local_stack_size =
|
||||
table->lookup("_start")->is_procedure_info()->local_stack_size =
|
||||
std::abs(this->local_offset);
|
||||
}
|
||||
|
||||
@ -113,7 +114,7 @@ namespace elna::source
|
||||
{
|
||||
this->local_offset = 0;
|
||||
this->argument_offset = 0;
|
||||
auto info = std::dynamic_pointer_cast<procedure_info>(this->table->lookup(procedure->identifier()));
|
||||
auto info = this->table->lookup(procedure->identifier())->is_procedure_info();
|
||||
this->table = info->scope();
|
||||
|
||||
empty_visitor::visit(procedure);
|
||||
@ -125,7 +126,7 @@ namespace elna::source
|
||||
|
||||
void allocator_visitor::visit(call_statement *statement)
|
||||
{
|
||||
auto call_info = std::dynamic_pointer_cast<intrinsic_info>(this->table->lookup(statement->name()));
|
||||
auto call_info = this->table->lookup(statement->name())->is_intrinsic_info();
|
||||
|
||||
this->argument_offset = std::max(static_cast<std::size_t>(this->argument_offset),
|
||||
call_info->parameter_stack_size());
|
||||
@ -141,17 +142,14 @@ namespace elna::source
|
||||
{
|
||||
for (auto& definition : program->definitions())
|
||||
{
|
||||
if (dynamic_cast<procedure_definition *>(definition.get()) != nullptr)
|
||||
{
|
||||
definition->accept(this);
|
||||
}
|
||||
definition->accept(this);
|
||||
}
|
||||
program->body().accept(this);
|
||||
}
|
||||
|
||||
void type_analysis_visitor::visit(procedure_definition *procedure)
|
||||
{
|
||||
auto info = std::dynamic_pointer_cast<procedure_info>(this->table->lookup(procedure->identifier()));
|
||||
auto info = this->table->lookup(procedure->identifier())->is_procedure_info();
|
||||
this->table = info->scope();
|
||||
|
||||
procedure->body().accept(this);
|
||||
@ -161,17 +159,17 @@ namespace elna::source
|
||||
|
||||
void type_analysis_visitor::visit(integer_literal *literal)
|
||||
{
|
||||
literal->data_type = std::dynamic_pointer_cast<type_info>(table->lookup("Int"))->type();
|
||||
literal->data_type = table->lookup("Int")->is_type_info()->type();
|
||||
}
|
||||
|
||||
void type_analysis_visitor::visit(boolean_literal *literal)
|
||||
{
|
||||
literal->data_type = std::dynamic_pointer_cast<type_info>(table->lookup("Boolean"))->type();
|
||||
literal->data_type = table->lookup("Boolean")->is_type_info()->type();
|
||||
}
|
||||
|
||||
void type_analysis_visitor::visit(variable_expression *expression)
|
||||
{
|
||||
expression->data_type = std::dynamic_pointer_cast<typed_info>(table->lookup(expression->name()))->type();
|
||||
expression->data_type = table->lookup(expression->name())->is_typed_info()->type();
|
||||
}
|
||||
|
||||
void type_analysis_visitor::visit(unary_expression *expression)
|
||||
@ -187,9 +185,9 @@ namespace elna::source
|
||||
case unary_operator::dereference:
|
||||
auto operand_type = expression->operand().data_type;
|
||||
|
||||
if (auto referenced_type = std::dynamic_pointer_cast<const pointer_type>(operand_type))
|
||||
if (operand_type->is_pointer_type() != nullptr)
|
||||
{
|
||||
expression->data_type = referenced_type;
|
||||
expression->data_type = operand_type;
|
||||
}
|
||||
else if (operand_type != nullptr)
|
||||
{
|
||||
@ -217,18 +215,16 @@ namespace elna::source
|
||||
case binary_operator::greater_equal:
|
||||
if (expression->lhs().data_type != nullptr && expression->rhs().data_type != nullptr)
|
||||
{
|
||||
auto lhs_type = std::dynamic_pointer_cast<const primitive_type>(expression->lhs().data_type);
|
||||
auto rhs_type = std::dynamic_pointer_cast<const primitive_type>(expression->rhs().data_type);
|
||||
|
||||
std::unique_ptr<type_mismatch> new_error;
|
||||
if (lhs_type == nullptr || *lhs_type != int_type)
|
||||
|
||||
if (*expression->lhs().data_type != int_type)
|
||||
{
|
||||
new_error = std::make_unique<type_mismatch>(lhs_type,
|
||||
new_error = std::make_unique<type_mismatch>(expression->lhs().data_type,
|
||||
type_mismatch::operation::arithmetic, this->filename, expression->lhs().position());
|
||||
}
|
||||
if (rhs_type == nullptr || *rhs_type != int_type)
|
||||
if (*expression->rhs().data_type != int_type)
|
||||
{
|
||||
new_error = std::make_unique<type_mismatch>(rhs_type,
|
||||
new_error = std::make_unique<type_mismatch>(expression->rhs().data_type,
|
||||
type_mismatch::operation::arithmetic, this->filename, expression->rhs().position());
|
||||
}
|
||||
if (new_error != nullptr)
|
||||
@ -253,7 +249,7 @@ namespace elna::source
|
||||
|
||||
void type_analysis_visitor::visit(call_statement *statement)
|
||||
{
|
||||
auto call_info = std::dynamic_pointer_cast<intrinsic_info>(this->table->lookup(statement->name()));
|
||||
auto call_info = this->table->lookup(statement->name())->is_intrinsic_info();
|
||||
|
||||
std::size_t i{ 0 };
|
||||
for (const auto& argument : statement->arguments())
|
||||
@ -280,7 +276,7 @@ namespace elna::source
|
||||
void type_analysis_visitor::visit(while_statement *statement)
|
||||
{
|
||||
statement->prerequisite().accept(this);
|
||||
auto condition_type = std::dynamic_pointer_cast<const primitive_type>(statement->prerequisite().data_type);
|
||||
auto condition_type = statement->prerequisite().data_type;
|
||||
|
||||
if (condition_type != nullptr && *condition_type != boolean_type)
|
||||
{
|
||||
@ -294,7 +290,7 @@ namespace elna::source
|
||||
void type_analysis_visitor::visit(if_statement *statement)
|
||||
{
|
||||
statement->prerequisite().accept(this);
|
||||
auto condition_type = std::dynamic_pointer_cast<const primitive_type>(statement->prerequisite().data_type);
|
||||
auto condition_type = statement->prerequisite().data_type;
|
||||
|
||||
if (condition_type != nullptr && *condition_type != boolean_type)
|
||||
{
|
||||
@ -308,7 +304,7 @@ namespace elna::source
|
||||
void type_analysis_visitor::visit(assign_statement *statement)
|
||||
{
|
||||
statement->rvalue().accept(this);
|
||||
auto lvalue_info = std::dynamic_pointer_cast<typed_info>(this->table->lookup(statement->lvalue()));
|
||||
auto lvalue_info = this->table->lookup(statement->lvalue())->is_typed_info();
|
||||
|
||||
if (statement->rvalue().data_type != nullptr && lvalue_info->type() == statement->rvalue().data_type)
|
||||
{
|
||||
@ -323,3 +319,4 @@ namespace elna::source
|
||||
return m_errors;
|
||||
}
|
||||
}
|
||||
}
|
230
source/symbol_table.cc
Normal file
230
source/symbol_table.cc
Normal file
@ -0,0 +1,230 @@
|
||||
#include "elna/source/types.h"
|
||||
#include "elna/source/symbol_table.h"
|
||||
|
||||
namespace elna
|
||||
{
|
||||
namespace source
|
||||
{
|
||||
symbol_table::symbol_table(std::shared_ptr<symbol_table> scope)
|
||||
: outer_scope(scope)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<info> symbol_table::lookup(const std::string& name)
|
||||
{
|
||||
auto entry = entries.find(name);
|
||||
|
||||
if (entry != entries.cend())
|
||||
{
|
||||
return entry->second;
|
||||
}
|
||||
if (this->outer_scope != nullptr)
|
||||
{
|
||||
return this->outer_scope->lookup(name);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void symbol_table::enter(const std::string& name, std::shared_ptr<info> entry)
|
||||
{
|
||||
entries.insert({ name, entry });
|
||||
}
|
||||
|
||||
std::shared_ptr<symbol_table> symbol_table::scope()
|
||||
{
|
||||
return this->outer_scope;
|
||||
}
|
||||
|
||||
info::~info()
|
||||
{
|
||||
}
|
||||
|
||||
type_info *info::is_type_info() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
typed_info *info::is_typed_info() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
constant_info *info::is_constant_info() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
variable_info *info::is_variable_info() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
parameter_info *info::is_parameter_info() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
intrinsic_info *info::is_intrinsic_info() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
procedure_info *info::is_procedure_info() noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
info::info()
|
||||
{
|
||||
}
|
||||
|
||||
type_info::type_info(std::shared_ptr<class type> type)
|
||||
: info(), m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
type_info::~type_info()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<const class type> type_info::type() const noexcept
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
type_info *type_info::is_type_info() noexcept
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
typed_info::typed_info(std::shared_ptr<const class type> type)
|
||||
: m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
typed_info::~typed_info()
|
||||
{
|
||||
}
|
||||
|
||||
typed_info *typed_info::is_typed_info() noexcept
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
std::shared_ptr<const class type> typed_info::type() const noexcept
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
constant_info::constant_info(const std::shared_ptr<const class type> type, const std::int32_t value)
|
||||
: typed_info(type), m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
constant_info *constant_info::is_constant_info() noexcept
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
std::int32_t constant_info::value() const noexcept
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
variable_info::variable_info(std::shared_ptr<const class type> type)
|
||||
: typed_info(type)
|
||||
{
|
||||
}
|
||||
|
||||
variable_info *variable_info::is_variable_info() noexcept
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
parameter_info::parameter_info(std::shared_ptr<const class type> type)
|
||||
: typed_info(type)
|
||||
{
|
||||
}
|
||||
|
||||
parameter_info *parameter_info::is_parameter_info() noexcept
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
intrinsic_info::intrinsic_info(const class procedure_type& type)
|
||||
: m_type(std::make_shared<procedure_type>(type))
|
||||
{
|
||||
}
|
||||
|
||||
intrinsic_info::~intrinsic_info()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<const class procedure_type> intrinsic_info::type() const noexcept
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
std::size_t intrinsic_info::parameter_stack_size() const noexcept
|
||||
{
|
||||
return type()->arguments.size() * sizeof(std::int32_t);
|
||||
}
|
||||
|
||||
intrinsic_info *intrinsic_info::is_intrinsic_info() noexcept
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
procedure_info::procedure_info(const class procedure_type& type, std::shared_ptr<symbol_table> outer_scope)
|
||||
: intrinsic_info(type), local_table(std::make_shared<symbol_table>(outer_scope))
|
||||
{
|
||||
}
|
||||
|
||||
procedure_info::~procedure_info()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<symbol_table> procedure_info::scope()
|
||||
{
|
||||
return local_table;
|
||||
}
|
||||
|
||||
std::size_t procedure_info::stack_size() const noexcept
|
||||
{
|
||||
return local_stack_size + argument_stack_size;
|
||||
}
|
||||
|
||||
procedure_info *procedure_info::is_procedure_info() noexcept
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
constexpr std::size_t pointer_size = 4;
|
||||
|
||||
std::shared_ptr<source::symbol_table> add_builtin_symbols()
|
||||
{
|
||||
source::symbol_table result;
|
||||
std::vector<std::shared_ptr<const source::type>> intrinsic_arguments;
|
||||
|
||||
auto prim = boolean_type;
|
||||
auto boolean_info = std::make_shared<type_info>(std::make_shared<primitive_type>(boolean_type));
|
||||
auto int_info = std::make_shared<source::type_info>(std::make_shared<primitive_type>(int_type));
|
||||
result.enter("Boolean", boolean_info);
|
||||
result.enter("Int", int_info);
|
||||
|
||||
intrinsic_arguments.push_back(int_info->type());
|
||||
auto writei = std::make_shared<source::intrinsic_info>(
|
||||
source::procedure_type{ intrinsic_arguments, pointer_size });
|
||||
result.enter("writei", writei);
|
||||
intrinsic_arguments.clear();
|
||||
|
||||
intrinsic_arguments.push_back(boolean_info->type());
|
||||
auto writeb = std::make_shared<source::intrinsic_info>(
|
||||
source::procedure_type{ intrinsic_arguments, pointer_size });
|
||||
result.enter("writeb", writeb);
|
||||
intrinsic_arguments.clear();
|
||||
|
||||
return std::make_shared<source::symbol_table>(std::move(result));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,129 +0,0 @@
|
||||
#include "elna/source/types.hpp"
|
||||
#include "elna/source/symbol_table.hpp"
|
||||
|
||||
namespace elna::source
|
||||
{
|
||||
symbol_table::symbol_table(std::shared_ptr<symbol_table> scope)
|
||||
: outer_scope(scope)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<info> symbol_table::lookup(const std::string& name)
|
||||
{
|
||||
auto entry = entries.find(name);
|
||||
|
||||
if (entry != entries.cend())
|
||||
{
|
||||
return entry->second;
|
||||
}
|
||||
if (this->outer_scope != nullptr)
|
||||
{
|
||||
return this->outer_scope->lookup(name);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void symbol_table::enter(const std::string& name, std::shared_ptr<info> entry)
|
||||
{
|
||||
entries.insert_or_assign(name, entry);
|
||||
}
|
||||
|
||||
std::shared_ptr<symbol_table> symbol_table::scope()
|
||||
{
|
||||
return this->outer_scope;
|
||||
}
|
||||
|
||||
info::~info()
|
||||
{
|
||||
}
|
||||
|
||||
info::info()
|
||||
{
|
||||
}
|
||||
|
||||
type_info::type_info(const class type& type)
|
||||
: info(), m_type(std::make_shared<class type>(type))
|
||||
{
|
||||
}
|
||||
|
||||
type_info::~type_info()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<const class type> type_info::type() const noexcept
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
typed_info::typed_info(std::shared_ptr<const class type> type)
|
||||
: m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
typed_info::~typed_info()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<const class type> typed_info::type() const noexcept
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
constant_info::constant_info(const std::shared_ptr<const class type> type, const std::int32_t value)
|
||||
: typed_info(type), m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
std::int32_t constant_info::value() const noexcept
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
variable_info::variable_info(std::shared_ptr<const class type> type)
|
||||
: typed_info(type)
|
||||
{
|
||||
}
|
||||
|
||||
parameter_info::parameter_info(std::shared_ptr<const class type> type)
|
||||
: typed_info(type)
|
||||
{
|
||||
}
|
||||
|
||||
intrinsic_info::intrinsic_info(const class procedure_type& type)
|
||||
: m_type(std::make_shared<procedure_type>(type))
|
||||
{
|
||||
}
|
||||
|
||||
intrinsic_info::~intrinsic_info()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<const class procedure_type> intrinsic_info::type() const noexcept
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
std::size_t intrinsic_info::parameter_stack_size() const noexcept
|
||||
{
|
||||
return type()->arguments.size() * sizeof(std::int32_t);
|
||||
}
|
||||
|
||||
procedure_info::procedure_info(const class procedure_type& type, std::shared_ptr<symbol_table> outer_scope)
|
||||
: intrinsic_info(type), local_table(std::make_shared<symbol_table>(outer_scope))
|
||||
{
|
||||
}
|
||||
|
||||
procedure_info::~procedure_info()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<symbol_table> procedure_info::scope()
|
||||
{
|
||||
return local_table;
|
||||
}
|
||||
|
||||
std::size_t procedure_info::stack_size() const noexcept
|
||||
{
|
||||
return local_stack_size + argument_stack_size;
|
||||
}
|
||||
}
|
80
source/types.cc
Normal file
80
source/types.cc
Normal file
@ -0,0 +1,80 @@
|
||||
#include <elna/source/types.h>
|
||||
|
||||
namespace elna
|
||||
{
|
||||
namespace source
|
||||
{
|
||||
type::type(const std::size_t byte_size)
|
||||
: byte_size(byte_size)
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t type::size() const noexcept
|
||||
{
|
||||
return this->byte_size;
|
||||
}
|
||||
|
||||
const pointer_type *type::is_pointer_type() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
primitive_type::primitive_type(const std::string& type_name, const std::size_t byte_size)
|
||||
: type(byte_size), m_type_name(type_name)
|
||||
{
|
||||
}
|
||||
|
||||
std::string primitive_type::type_name() const
|
||||
{
|
||||
return m_type_name;
|
||||
}
|
||||
|
||||
pointer_type::pointer_type(std::shared_ptr<const type> base_type, const std::size_t byte_size)
|
||||
: type(byte_size), base_type(base_type)
|
||||
{
|
||||
}
|
||||
|
||||
const pointer_type *pointer_type::is_pointer_type() const
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
std::string pointer_type::type_name() const
|
||||
{
|
||||
return '^' + base_type->type_name();
|
||||
}
|
||||
|
||||
procedure_type::procedure_type(std::vector<std::shared_ptr<const type>> arguments, const std::size_t byte_size)
|
||||
: arguments(std::move(arguments)), type(byte_size)
|
||||
{
|
||||
}
|
||||
|
||||
std::string procedure_type::type_name() const
|
||||
{
|
||||
std::string result{ "proc(" };
|
||||
for (const auto& argument : arguments)
|
||||
{
|
||||
result += argument->type_name() + ',';
|
||||
}
|
||||
result.at(result.size() - 1) = ')';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool operator==(const type& lhs, const type& rhs) noexcept
|
||||
{
|
||||
auto lhs_type = lhs.type_name();
|
||||
auto rhs_type = rhs.type_name();
|
||||
|
||||
return lhs_type == rhs_type;
|
||||
}
|
||||
|
||||
bool operator!=(const type& lhs, const type& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
const primitive_type boolean_type{ "Boolean", 1 };
|
||||
const primitive_type int_type{ "Int", 4 };
|
||||
}
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
#include <elna/source/types.hpp>
|
||||
|
||||
namespace elna::source
|
||||
{
|
||||
type::type(const std::size_t byte_size)
|
||||
: byte_size(byte_size)
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t type::size() const noexcept
|
||||
{
|
||||
return this->byte_size;
|
||||
}
|
||||
|
||||
primitive_type::primitive_type(const std::string& type_name, const std::size_t byte_size)
|
||||
: type(byte_size), type_name(type_name)
|
||||
{
|
||||
}
|
||||
|
||||
bool primitive_type::operator==(const primitive_type& that) const noexcept
|
||||
{
|
||||
return this->type_name == that.type_name;
|
||||
}
|
||||
|
||||
bool primitive_type::operator!=(const primitive_type& that) const noexcept
|
||||
{
|
||||
return this->type_name != that.type_name;
|
||||
}
|
||||
|
||||
pointer_type::pointer_type(std::shared_ptr<const type> base_type, const std::size_t byte_size)
|
||||
: type(byte_size), base_type(base_type)
|
||||
{
|
||||
}
|
||||
|
||||
bool pointer_type::operator==(const pointer_type& that) const noexcept
|
||||
{
|
||||
return this->base_type == that.base_type;
|
||||
}
|
||||
|
||||
bool pointer_type::operator!=(const pointer_type& that) const noexcept
|
||||
{
|
||||
return this->base_type != that.base_type;
|
||||
}
|
||||
|
||||
procedure_type::procedure_type(std::vector<std::shared_ptr<const type>> arguments, const std::size_t byte_size)
|
||||
: arguments(std::move(arguments)), type(byte_size)
|
||||
{
|
||||
}
|
||||
|
||||
bool procedure_type::operator==(const procedure_type &that) const noexcept
|
||||
{
|
||||
return this->arguments == that.arguments;
|
||||
}
|
||||
|
||||
bool procedure_type::operator!=(const procedure_type &that) const noexcept
|
||||
{
|
||||
return this->arguments != that.arguments;
|
||||
}
|
||||
|
||||
bool operator==(const type& lhs, const type& rhs) noexcept
|
||||
{
|
||||
{
|
||||
auto lhs_type = dynamic_cast<const primitive_type *>(&lhs);
|
||||
auto rhs_type = dynamic_cast<const primitive_type *>(&rhs);
|
||||
|
||||
if (lhs_type != nullptr && rhs_type != nullptr)
|
||||
{
|
||||
return *lhs_type == *rhs_type;
|
||||
}
|
||||
}
|
||||
{
|
||||
auto lhs_type = dynamic_cast<const pointer_type *>(&lhs);
|
||||
auto rhs_type = dynamic_cast<const pointer_type *>(&rhs);
|
||||
|
||||
if (lhs_type != nullptr && rhs_type != nullptr)
|
||||
{
|
||||
return *lhs_type == *rhs_type;
|
||||
}
|
||||
}
|
||||
{
|
||||
auto lhs_type = dynamic_cast<const procedure_type *>(&lhs);
|
||||
auto rhs_type = dynamic_cast<const procedure_type *>(&rhs);
|
||||
|
||||
if (lhs_type != nullptr && rhs_type != nullptr)
|
||||
{
|
||||
return *lhs_type == *rhs_type;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator!=(const type& lhs, const type& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user