Add procedure type expression
This commit is contained in:
parent
ff9169a98c
commit
18857e1a88
2
Rakefile
2
Rakefile
@ -49,7 +49,7 @@ namespace :boot do
|
|||||||
"--build=#{options.build}",
|
"--build=#{options.build}",
|
||||||
"--host=#{options.build}"
|
"--host=#{options.build}"
|
||||||
]
|
]
|
||||||
flags = '-O2 -fPIC -I/opt/homebrew/Cellar/flex/2.6.4_2/include'
|
flags = '-O0 -g -fPIC -I/opt/homebrew/Cellar/flex/2.6.4_2/include'
|
||||||
env = {
|
env = {
|
||||||
'CC' => options.gcc,
|
'CC' => options.gcc,
|
||||||
'CXX' => options.gxx,
|
'CXX' => options.gxx,
|
||||||
|
131
boot/ast.cc
131
boot/ast.cc
@ -32,13 +32,10 @@ namespace boot
|
|||||||
|
|
||||||
void empty_visitor::visit(procedure_definition *definition)
|
void empty_visitor::visit(procedure_definition *definition)
|
||||||
{
|
{
|
||||||
for (auto parameter : definition->parameters)
|
definition->heading().accept(this);
|
||||||
|
if (definition->body != nullptr)
|
||||||
{
|
{
|
||||||
parameter->accept(this);
|
definition->body->accept(this);
|
||||||
}
|
|
||||||
if (definition->body() != nullptr)
|
|
||||||
{
|
|
||||||
definition->body()->accept(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,6 +179,18 @@ namespace boot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void empty_visitor::visit(procedure_type *expression)
|
||||||
|
{
|
||||||
|
for (auto parameter : expression->parameters)
|
||||||
|
{
|
||||||
|
parameter->accept(this);
|
||||||
|
}
|
||||||
|
if (expression->return_type != nullptr)
|
||||||
|
{
|
||||||
|
expression->return_type->accept(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(variable_expression *)
|
void empty_visitor::visit(variable_expression *)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -255,27 +264,32 @@ namespace boot
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
basic_type *top_type::is_basic()
|
std::shared_ptr<basic_type> top_type::is_basic()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
array_type *top_type::is_array()
|
std::shared_ptr<array_type> top_type::is_array()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
record_type *top_type::is_record()
|
std::shared_ptr<record_type> top_type::is_record()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
union_type *top_type::is_union()
|
std::shared_ptr<union_type> top_type::is_union()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer_type *top_type::is_pointer()
|
std::shared_ptr<pointer_type> top_type::is_pointer()
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<procedure_type> top_type::is_procedure()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -295,9 +309,9 @@ namespace boot
|
|||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
basic_type *basic_type::is_basic()
|
std::shared_ptr<basic_type> basic_type::is_basic()
|
||||||
{
|
{
|
||||||
return this;
|
return std::static_pointer_cast<basic_type>(shared_from_this());
|
||||||
}
|
}
|
||||||
|
|
||||||
array_type::array_type(const struct position position, std::shared_ptr<top_type> base, const std::uint32_t size)
|
array_type::array_type(const struct position position, std::shared_ptr<top_type> base, const std::uint32_t size)
|
||||||
@ -315,9 +329,9 @@ namespace boot
|
|||||||
return *m_base;
|
return *m_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
array_type*array_type::is_array()
|
std::shared_ptr<array_type> array_type::is_array()
|
||||||
{
|
{
|
||||||
return this;
|
return std::static_pointer_cast<array_type>(shared_from_this());
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer_type::pointer_type(const struct position position, std::shared_ptr<top_type> base)
|
pointer_type::pointer_type(const struct position position, std::shared_ptr<top_type> base)
|
||||||
@ -335,18 +349,13 @@ namespace boot
|
|||||||
return *m_base;
|
return *m_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer_type *pointer_type::is_pointer()
|
std::shared_ptr<pointer_type> pointer_type::is_pointer()
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
composite_type::composite_type(const struct position position, fields_t&& fields)
|
|
||||||
: top_type(position), fields(std::move(fields))
|
|
||||||
{
|
{
|
||||||
|
return std::static_pointer_cast<pointer_type>(shared_from_this());
|
||||||
}
|
}
|
||||||
|
|
||||||
record_type::record_type(const struct position position, fields_t&& fields)
|
record_type::record_type(const struct position position, fields_t&& fields)
|
||||||
: composite_type(position, std::move(fields))
|
: top_type(position), fields(std::move(fields))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,19 +364,19 @@ namespace boot
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
record_type *record_type::is_record()
|
std::shared_ptr<record_type> record_type::is_record()
|
||||||
{
|
{
|
||||||
return this;
|
return std::static_pointer_cast<record_type>(shared_from_this());
|
||||||
}
|
}
|
||||||
|
|
||||||
union_type::union_type(const struct position position, fields_t&& fields)
|
union_type::union_type(const struct position position, fields_t&& fields)
|
||||||
: composite_type(position, std::move(fields))
|
: top_type(position), fields(std::move(fields))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
union_type *union_type::is_union()
|
std::shared_ptr<union_type> union_type::is_union()
|
||||||
{
|
{
|
||||||
return this;
|
return std::static_pointer_cast<union_type>(shared_from_this());
|
||||||
}
|
}
|
||||||
|
|
||||||
void union_type::accept(parser_visitor *visitor)
|
void union_type::accept(parser_visitor *visitor)
|
||||||
@ -417,15 +426,37 @@ namespace boot
|
|||||||
delete m_body;
|
delete m_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
|
procedure_type::procedure_type(const struct position position, std::shared_ptr<top_type> return_type)
|
||||||
const bool exported, std::shared_ptr<top_type> return_type)
|
: top_type(position), return_type(return_type), no_return(false)
|
||||||
: definition(position, identifier, exported), m_return_type(return_type), no_return{ false }
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
procedure_type::procedure_type(const struct position position, no_return_t)
|
||||||
|
: top_type(position), return_type(nullptr), no_return(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void procedure_type::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<procedure_type> procedure_type::is_procedure()
|
||||||
|
{
|
||||||
|
return std::static_pointer_cast<procedure_type>(shared_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
|
procedure_type::~procedure_type()
|
||||||
|
{
|
||||||
|
for (auto parameter : this->parameters)
|
||||||
|
{
|
||||||
|
delete parameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
|
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
|
||||||
const bool exported, no_return_t)
|
const bool exported, std::shared_ptr<procedure_type> heading, block *body)
|
||||||
: definition(position, identifier, exported), m_return_type(nullptr), no_return{ true }
|
: definition(position, identifier, exported), m_heading(heading), body(body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,32 +465,14 @@ namespace boot
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
block *procedure_definition::body()
|
procedure_type& procedure_definition::heading()
|
||||||
{
|
{
|
||||||
return m_body;
|
return *m_heading;
|
||||||
}
|
|
||||||
|
|
||||||
procedure_definition *procedure_definition::add_body(block *procedure_body)
|
|
||||||
{
|
|
||||||
m_body = procedure_body;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<top_type> procedure_definition::return_type()
|
|
||||||
{
|
|
||||||
return m_return_type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
procedure_definition::~procedure_definition()
|
procedure_definition::~procedure_definition()
|
||||||
{
|
{
|
||||||
if (m_body != nullptr)
|
delete body;
|
||||||
{
|
|
||||||
delete m_body;
|
|
||||||
}
|
|
||||||
for (auto parameter : parameters)
|
|
||||||
{
|
|
||||||
delete parameter;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type_definition::type_definition(const struct position position, const std::string& identifier,
|
type_definition::type_definition(const struct position position, const std::string& identifier,
|
||||||
@ -846,10 +859,7 @@ namespace boot
|
|||||||
|
|
||||||
return_statement::~return_statement()
|
return_statement::~return_statement()
|
||||||
{
|
{
|
||||||
if (m_return_expression != nullptr)
|
delete m_return_expression;
|
||||||
{
|
|
||||||
delete m_return_expression;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void assign_statement::accept(parser_visitor *visitor)
|
void assign_statement::accept(parser_visitor *visitor)
|
||||||
@ -926,10 +936,7 @@ namespace boot
|
|||||||
{
|
{
|
||||||
delete branch;
|
delete branch;
|
||||||
}
|
}
|
||||||
if (m_alternative != nullptr)
|
delete m_alternative;
|
||||||
{
|
|
||||||
delete m_alternative;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while_statement::while_statement(const struct position position, conditional_statements *body)
|
while_statement::while_statement(const struct position position, conditional_statements *body)
|
||||||
|
@ -111,7 +111,8 @@ along with GCC; see the file COPYING3. If not see
|
|||||||
%type <elna::boot::return_statement *> return_statement;
|
%type <elna::boot::return_statement *> return_statement;
|
||||||
%type <elna::boot::statement *> statement;
|
%type <elna::boot::statement *> statement;
|
||||||
%type <std::vector<elna::boot::statement *>> statements optional_statements;
|
%type <std::vector<elna::boot::statement *>> statements optional_statements;
|
||||||
%type <elna::boot::procedure_definition *> procedure_definition procedure_heading;
|
%type <elna::boot::procedure_definition *> procedure_definition;
|
||||||
|
%type <std::shared_ptr<elna::boot::procedure_type>> procedure_heading;
|
||||||
%type <std::vector<elna::boot::procedure_definition *>> procedure_definitions procedure_part;
|
%type <std::vector<elna::boot::procedure_definition *>> procedure_definitions procedure_part;
|
||||||
%type <elna::boot::type_definition *> type_definition;
|
%type <elna::boot::type_definition *> type_definition;
|
||||||
%type <std::vector<elna::boot::type_definition *>> type_definitions type_part;
|
%type <std::vector<elna::boot::type_definition *>> type_definitions type_part;
|
||||||
@ -162,27 +163,30 @@ identifier_definitions:
|
|||||||
}
|
}
|
||||||
| identifier_definition { $$.emplace_back(std::move($1)); }
|
| identifier_definition { $$.emplace_back(std::move($1)); }
|
||||||
procedure_heading:
|
procedure_heading:
|
||||||
PROCEDURE identifier_definition formal_parameter_list SEMICOLON
|
formal_parameter_list
|
||||||
{
|
{
|
||||||
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1),
|
$$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1));
|
||||||
$2.first, $2.second);
|
std::swap($1, $$->parameters);
|
||||||
std::swap($3, $$->parameters);
|
|
||||||
}
|
}
|
||||||
| PROCEDURE identifier_definition formal_parameter_list ARROW EXCLAMATION SEMICOLON
|
| formal_parameter_list ARROW EXCLAMATION
|
||||||
{
|
{
|
||||||
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1),
|
$$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1), elna::boot::no_return);
|
||||||
$2.first, $2.second, elna::boot::procedure_definition::no_return_t{});
|
std::swap($1, $$->parameters);
|
||||||
std::swap($3, $$->parameters);
|
|
||||||
}
|
}
|
||||||
| PROCEDURE identifier_definition formal_parameter_list ARROW type_expression SEMICOLON
|
| formal_parameter_list ARROW type_expression
|
||||||
{
|
{
|
||||||
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1),
|
$$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1), $3);
|
||||||
$2.first, $2.second, $5);
|
std::swap($1, $$->parameters);
|
||||||
std::swap($3, $$->parameters);
|
|
||||||
}
|
}
|
||||||
procedure_definition:
|
procedure_definition:
|
||||||
procedure_heading block { $$ = $1->add_body($2); }
|
PROCEDURE identifier_definition procedure_heading SEMICOLON block
|
||||||
| procedure_heading EXTERN { $$ = $1; }
|
{
|
||||||
|
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), $2.first, $2.second, $3, $5);
|
||||||
|
}
|
||||||
|
| PROCEDURE identifier_definition procedure_heading SEMICOLON EXTERN
|
||||||
|
{
|
||||||
|
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), $2.first, $2.second, $3);
|
||||||
|
}
|
||||||
procedure_definitions:
|
procedure_definitions:
|
||||||
procedure_definition procedure_definitions
|
procedure_definition procedure_definitions
|
||||||
{
|
{
|
||||||
@ -467,6 +471,10 @@ type_expression:
|
|||||||
{
|
{
|
||||||
$$ = std::make_shared<elna::boot::union_type>(elna::boot::make_position(@1), std::move($2));
|
$$ = std::make_shared<elna::boot::union_type>(elna::boot::make_position(@1), std::move($2));
|
||||||
}
|
}
|
||||||
|
| PROCEDURE procedure_heading
|
||||||
|
{
|
||||||
|
$$ = $2;
|
||||||
|
}
|
||||||
| IDENTIFIER
|
| IDENTIFIER
|
||||||
{
|
{
|
||||||
$$ = std::make_shared<elna::boot::basic_type>(elna::boot::make_position(@1), $1);
|
$$ = std::make_shared<elna::boot::basic_type>(elna::boot::make_position(@1), $1);
|
||||||
|
@ -86,7 +86,7 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
std::string output = "proc(";
|
std::string output = "proc(";
|
||||||
tree parameter_type = TYPE_ARG_TYPES(type);
|
tree parameter_type = TYPE_ARG_TYPES(type);
|
||||||
while (parameter_type != NULL_TREE)
|
while (TREE_VALUE(parameter_type) != void_type_node)
|
||||||
{
|
{
|
||||||
output += print_type(TREE_VALUE(parameter_type));
|
output += print_type(TREE_VALUE(parameter_type));
|
||||||
parameter_type = TREE_CHAIN(parameter_type);
|
parameter_type = TREE_CHAIN(parameter_type);
|
||||||
|
@ -242,27 +242,17 @@ namespace gcc
|
|||||||
|
|
||||||
void generic_visitor::visit(boot::procedure_definition *definition)
|
void generic_visitor::visit(boot::procedure_definition *definition)
|
||||||
{
|
{
|
||||||
std::vector<tree> parameter_types(definition->parameters.size());
|
tree declaration_type = build_type(definition->heading());
|
||||||
|
|
||||||
for (std::size_t i = 0; i < definition->parameters.size(); ++i)
|
|
||||||
{
|
|
||||||
parameter_types[i] = build_type(definition->parameters.at(i)->variable_type());
|
|
||||||
}
|
|
||||||
tree return_type = definition->return_type() == nullptr
|
|
||||||
? void_type_node
|
|
||||||
: build_type(*definition->return_type());
|
|
||||||
tree declaration_type = build_function_type_array(return_type,
|
|
||||||
definition->parameters.size(), parameter_types.data());
|
|
||||||
tree fndecl = build_fn_decl(definition->identifier.c_str(), declaration_type);
|
tree fndecl = build_fn_decl(definition->identifier.c_str(), declaration_type);
|
||||||
this->symbol_map->enter(definition->identifier, fndecl);
|
this->symbol_map->enter(definition->identifier, fndecl);
|
||||||
|
|
||||||
if (definition->no_return)
|
if (definition->heading().no_return)
|
||||||
{
|
{
|
||||||
TREE_THIS_VOLATILE(fndecl) = 1;
|
TREE_THIS_VOLATILE(fndecl) = 1;
|
||||||
}
|
}
|
||||||
if (definition->body() != nullptr)
|
if (definition->body != nullptr)
|
||||||
{
|
{
|
||||||
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, return_type);
|
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, TREE_TYPE(declaration_type));
|
||||||
DECL_CONTEXT(resdecl) = fndecl;
|
DECL_CONTEXT(resdecl) = fndecl;
|
||||||
DECL_RESULT(fndecl) = resdecl;
|
DECL_RESULT(fndecl) = resdecl;
|
||||||
|
|
||||||
@ -272,27 +262,29 @@ namespace gcc
|
|||||||
enter_scope();
|
enter_scope();
|
||||||
}
|
}
|
||||||
tree argument_chain = NULL_TREE;
|
tree argument_chain = NULL_TREE;
|
||||||
for (std::size_t i = 0; i < definition->parameters.size(); ++i)
|
function_args_iterator parameter_type;
|
||||||
|
function_args_iter_init(¶meter_type, declaration_type);
|
||||||
|
|
||||||
|
for (const boot::variable_declaration *parameter : definition->heading().parameters)
|
||||||
{
|
{
|
||||||
auto parameter = definition->parameters.at(i);
|
|
||||||
|
|
||||||
tree declaration_tree = build_decl(get_location(¶meter->position()), PARM_DECL,
|
tree declaration_tree = build_decl(get_location(¶meter->position()), PARM_DECL,
|
||||||
get_identifier(parameter->identifier.c_str()), parameter_types[i]);
|
get_identifier(parameter->identifier.c_str()), function_args_iter_cond(¶meter_type));
|
||||||
DECL_CONTEXT(declaration_tree) = fndecl;
|
DECL_CONTEXT(declaration_tree) = fndecl;
|
||||||
DECL_ARG_TYPE(declaration_tree) = parameter_types[i];
|
DECL_ARG_TYPE(declaration_tree) = function_args_iter_cond(¶meter_type);
|
||||||
|
|
||||||
if (definition->body() != nullptr)
|
if (definition->body != nullptr)
|
||||||
{
|
{
|
||||||
this->symbol_map->enter(parameter->identifier, declaration_tree);
|
this->symbol_map->enter(parameter->identifier, declaration_tree);
|
||||||
}
|
}
|
||||||
argument_chain = chainon(argument_chain, declaration_tree);
|
argument_chain = chainon(argument_chain, declaration_tree);
|
||||||
|
function_args_iter_next(¶meter_type);
|
||||||
}
|
}
|
||||||
DECL_ARGUMENTS(fndecl) = argument_chain;
|
DECL_ARGUMENTS(fndecl) = argument_chain;
|
||||||
TREE_PUBLIC(fndecl) = definition->exported;
|
TREE_PUBLIC(fndecl) = definition->exported;
|
||||||
|
|
||||||
if (definition->body() != nullptr)
|
if (definition->body != nullptr)
|
||||||
{
|
{
|
||||||
definition->body()->accept(this);
|
definition->body->accept(this);
|
||||||
tree mapping = leave_scope();
|
tree mapping = leave_scope();
|
||||||
|
|
||||||
BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl;
|
BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl;
|
||||||
@ -749,7 +741,7 @@ namespace gcc
|
|||||||
|
|
||||||
tree generic_visitor::build_type(boot::top_type& type)
|
tree generic_visitor::build_type(boot::top_type& type)
|
||||||
{
|
{
|
||||||
if (boot::basic_type *basic_type = type.is_basic())
|
if (std::shared_ptr<boot::basic_type> basic_type = type.is_basic())
|
||||||
{
|
{
|
||||||
tree symbol = this->lookup(basic_type->base_name());
|
tree symbol = this->lookup(basic_type->base_name());
|
||||||
|
|
||||||
@ -762,7 +754,7 @@ namespace gcc
|
|||||||
|
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
else if (boot::array_type *array_type = type.is_array())
|
else if (std::shared_ptr<boot::array_type> array_type = type.is_array())
|
||||||
{
|
{
|
||||||
tree lower_bound = build_int_cst_type(integer_type_node, 0);
|
tree lower_bound = build_int_cst_type(integer_type_node, 0);
|
||||||
tree upper_bound = build_int_cst_type(integer_type_node, array_type->size);
|
tree upper_bound = build_int_cst_type(integer_type_node, array_type->size);
|
||||||
@ -776,7 +768,7 @@ namespace gcc
|
|||||||
|
|
||||||
return build_array_type(base_type, range_type);
|
return build_array_type(base_type, range_type);
|
||||||
}
|
}
|
||||||
else if (boot::pointer_type *pointer_type = type.is_pointer())
|
else if (std::shared_ptr<boot::pointer_type> pointer_type = type.is_pointer())
|
||||||
{
|
{
|
||||||
tree base_type = build_type(pointer_type->base());
|
tree base_type = build_type(pointer_type->base());
|
||||||
|
|
||||||
@ -786,7 +778,7 @@ namespace gcc
|
|||||||
}
|
}
|
||||||
return build_pointer_type_for_mode(base_type, VOIDmode, true);
|
return build_pointer_type_for_mode(base_type, VOIDmode, true);
|
||||||
}
|
}
|
||||||
else if (boot::record_type *record_type = type.is_record())
|
else if (std::shared_ptr<boot::record_type> record_type = type.is_record())
|
||||||
{
|
{
|
||||||
std::set<std::string> field_names;
|
std::set<std::string> field_names;
|
||||||
tree record_type_node = make_node(RECORD_TYPE);
|
tree record_type_node = make_node(RECORD_TYPE);
|
||||||
@ -813,7 +805,7 @@ namespace gcc
|
|||||||
|
|
||||||
return record_type_node;
|
return record_type_node;
|
||||||
}
|
}
|
||||||
else if (boot::union_type *union_type = type.is_union())
|
else if (std::shared_ptr<boot::union_type> union_type = type.is_union())
|
||||||
{
|
{
|
||||||
std::set<std::string> field_names;
|
std::set<std::string> field_names;
|
||||||
tree union_type_node = make_node(UNION_TYPE);
|
tree union_type_node = make_node(UNION_TYPE);
|
||||||
@ -840,6 +832,21 @@ namespace gcc
|
|||||||
|
|
||||||
return union_type_node;
|
return union_type_node;
|
||||||
}
|
}
|
||||||
|
else if (std::shared_ptr<boot::procedure_type> procedure_type = type.is_procedure())
|
||||||
|
{
|
||||||
|
std::vector<tree> parameter_types(procedure_type->parameters.size());
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < procedure_type->parameters.size(); ++i)
|
||||||
|
{
|
||||||
|
parameter_types[i] = build_type(procedure_type->parameters.at(i)->variable_type());
|
||||||
|
}
|
||||||
|
tree return_type = procedure_type->return_type == nullptr
|
||||||
|
? void_type_node
|
||||||
|
: build_type(*procedure_type->return_type);
|
||||||
|
|
||||||
|
return build_function_type_array(return_type,
|
||||||
|
procedure_type->parameters.size(), parameter_types.data());
|
||||||
|
}
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -889,9 +896,15 @@ namespace gcc
|
|||||||
"variable '%s' not declared in the current scope",
|
"variable '%s' not declared in the current scope",
|
||||||
expression->name().c_str());
|
expression->name().c_str());
|
||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
this->current_expression = symbol;
|
else if (TREE_CODE(symbol) == FUNCTION_DECL)
|
||||||
|
{
|
||||||
|
this->current_expression = build1(ADDR_EXPR, build_pointer_type(TREE_TYPE(symbol)), symbol);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->current_expression = symbol;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::array_access_expression *expression)
|
void generic_visitor::visit(boot::array_access_expression *expression)
|
||||||
|
@ -75,6 +75,7 @@ namespace boot
|
|||||||
class pointer_type;
|
class pointer_type;
|
||||||
class record_type;
|
class record_type;
|
||||||
class union_type;
|
class union_type;
|
||||||
|
class procedure_type;
|
||||||
class variable_expression;
|
class variable_expression;
|
||||||
class array_access_expression;
|
class array_access_expression;
|
||||||
class field_access_expression;
|
class field_access_expression;
|
||||||
@ -110,6 +111,7 @@ namespace boot
|
|||||||
virtual void visit(pointer_type *) = 0;
|
virtual void visit(pointer_type *) = 0;
|
||||||
virtual void visit(record_type *) = 0;
|
virtual void visit(record_type *) = 0;
|
||||||
virtual void visit(union_type *) = 0;
|
virtual void visit(union_type *) = 0;
|
||||||
|
virtual void visit(procedure_type *) = 0;
|
||||||
virtual void visit(variable_expression *) = 0;
|
virtual void visit(variable_expression *) = 0;
|
||||||
virtual void visit(array_access_expression *) = 0;
|
virtual void visit(array_access_expression *) = 0;
|
||||||
virtual void visit(field_access_expression *is_field_access) = 0;
|
virtual void visit(field_access_expression *is_field_access) = 0;
|
||||||
@ -150,6 +152,7 @@ namespace boot
|
|||||||
virtual void visit(pointer_type *) override;
|
virtual void visit(pointer_type *) override;
|
||||||
virtual void visit(record_type *expression) override;
|
virtual void visit(record_type *expression) override;
|
||||||
virtual void visit(union_type *expression) override;
|
virtual void visit(union_type *expression) override;
|
||||||
|
virtual void visit(procedure_type *expression) override;
|
||||||
virtual void visit(variable_expression *) override;
|
virtual void visit(variable_expression *) override;
|
||||||
virtual void visit(array_access_expression *expression) override;
|
virtual void visit(array_access_expression *expression) override;
|
||||||
virtual void visit(field_access_expression *expression) override;
|
virtual void visit(field_access_expression *expression) override;
|
||||||
@ -220,14 +223,15 @@ namespace boot
|
|||||||
/**
|
/**
|
||||||
* Some type expression.
|
* Some type expression.
|
||||||
*/
|
*/
|
||||||
class top_type : public node
|
class top_type : public node, public std::enable_shared_from_this<top_type>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual basic_type *is_basic();
|
virtual std::shared_ptr<basic_type> is_basic();
|
||||||
virtual array_type *is_array();
|
virtual std::shared_ptr<array_type> is_array();
|
||||||
virtual pointer_type *is_pointer();
|
virtual std::shared_ptr<pointer_type> is_pointer();
|
||||||
virtual record_type *is_record();
|
virtual std::shared_ptr<record_type> is_record();
|
||||||
virtual union_type *is_union();
|
virtual std::shared_ptr<union_type> is_union();
|
||||||
|
virtual std::shared_ptr<procedure_type> is_procedure();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
top_type(const struct position position);
|
top_type(const struct position position);
|
||||||
@ -250,7 +254,7 @@ namespace boot
|
|||||||
|
|
||||||
const std::string& base_name();
|
const std::string& base_name();
|
||||||
|
|
||||||
basic_type *is_basic() override;
|
std::shared_ptr<basic_type> is_basic() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class array_type : public top_type
|
class array_type : public top_type
|
||||||
@ -265,7 +269,7 @@ namespace boot
|
|||||||
|
|
||||||
top_type& base();
|
top_type& base();
|
||||||
|
|
||||||
array_type *is_array() override;
|
std::shared_ptr<array_type> is_array() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class pointer_type : public top_type
|
class pointer_type : public top_type
|
||||||
@ -278,37 +282,32 @@ namespace boot
|
|||||||
|
|
||||||
top_type& base();
|
top_type& base();
|
||||||
|
|
||||||
pointer_type *is_pointer() override;
|
std::shared_ptr<pointer_type> is_pointer() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
using field_t = std::pair<std::string, std::shared_ptr<top_type>>;
|
using field_t = std::pair<std::string, std::shared_ptr<top_type>>;
|
||||||
using fields_t = std::vector<field_t>;
|
using fields_t = std::vector<field_t>;
|
||||||
|
|
||||||
class composite_type : public top_type
|
class record_type : public top_type
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
composite_type(const struct position position, fields_t&& fields);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
fields_t fields;
|
fields_t fields;
|
||||||
};
|
|
||||||
|
|
||||||
class record_type : public composite_type
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
record_type(const struct position position, fields_t&& fields);
|
record_type(const struct position position, fields_t&& fields);
|
||||||
|
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
record_type *is_record() override;
|
std::shared_ptr<record_type> is_record() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class union_type : public composite_type
|
class union_type : public top_type
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
fields_t fields;
|
||||||
|
|
||||||
union_type(const struct position position, fields_t&& fields);
|
union_type(const struct position position, fields_t&& fields);
|
||||||
|
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
union_type *is_union() override;
|
std::shared_ptr<union_type> is_union() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -357,31 +356,48 @@ namespace boot
|
|||||||
virtual ~constant_definition() override;
|
virtual ~constant_definition() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tags a procedure type as never returning.
|
||||||
|
*/
|
||||||
|
struct no_return_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
constexpr no_return_t no_return{};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Procedure type.
|
||||||
|
*/
|
||||||
|
class procedure_type : public top_type
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const std::shared_ptr<top_type> return_type;
|
||||||
|
const bool no_return;
|
||||||
|
std::vector<variable_declaration *> parameters;
|
||||||
|
|
||||||
|
procedure_type(const struct position position, std::shared_ptr<top_type> return_type = nullptr);
|
||||||
|
procedure_type(const struct position position, no_return_t);
|
||||||
|
|
||||||
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
std::shared_ptr<procedure_type> is_procedure() override;
|
||||||
|
|
||||||
|
virtual ~procedure_type() override;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Procedure definition.
|
* Procedure definition.
|
||||||
*/
|
*/
|
||||||
class procedure_definition : public definition
|
class procedure_definition : public definition
|
||||||
{
|
{
|
||||||
std::shared_ptr<top_type> m_return_type{ nullptr };
|
std::shared_ptr<procedure_type> m_heading;
|
||||||
block *m_body{ nullptr };
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct no_return_t
|
block *const body;
|
||||||
{
|
|
||||||
};
|
|
||||||
const bool no_return{ false };
|
|
||||||
std::vector<variable_declaration *> parameters;
|
|
||||||
|
|
||||||
procedure_definition(const struct position position, const std::string& identifier,
|
procedure_definition(const struct position position, const std::string& identifier,
|
||||||
const bool exported, std::shared_ptr<top_type> return_type = nullptr);
|
const bool exported, std::shared_ptr<procedure_type> heading, block *body = nullptr);
|
||||||
procedure_definition(const struct position position, const std::string& identifier,
|
|
||||||
const bool exported, no_return_t);
|
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
std::shared_ptr<top_type> return_type();
|
procedure_type& heading();
|
||||||
|
|
||||||
block *body();
|
|
||||||
procedure_definition *add_body(block *procedure_body);
|
|
||||||
|
|
||||||
virtual ~procedure_definition() override;
|
virtual ~procedure_definition() override;
|
||||||
};
|
};
|
||||||
|
13
source.elna
13
source.elna
@ -891,6 +891,19 @@ begin
|
|||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
proc f();
|
||||||
begin
|
begin
|
||||||
|
write_s("In f\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
proc g();
|
||||||
|
var x: ^proc()
|
||||||
|
begin
|
||||||
|
x := cast(f: ^proc())
|
||||||
|
(* x() *)
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
g()
|
||||||
exit(process(cast(count: Int), cast(parameters: ^^Char)))
|
exit(process(cast(count: Int), cast(parameters: ^^Char)))
|
||||||
end.
|
end.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user