Add second GENERIC visitor
This commit is contained in:
parent
c5930285bf
commit
8dc02047df
104
Rakefile
104
Rakefile
@ -76,107 +76,3 @@ file (TMP + 'elna').to_path => ['source.elna']
|
||||
file (TMP + 'elna').to_path => [(HOST_INSTALL + 'bin/gelna').to_path] do |task|
|
||||
sh (HOST_INSTALL + 'bin/gelna').to_path, '-o', task.name, task.prerequisites.first
|
||||
end
|
||||
|
||||
namespace :cross do
|
||||
desc 'Build cross toolchain'
|
||||
task :init, [:target] do |_, args|
|
||||
args.with_defaults target: 'riscv32-unknown-linux-gnu'
|
||||
|
||||
options = find_build_target GCC_VERSION, args[:target]
|
||||
env = {
|
||||
'PATH' => "#{options.rootfs.realpath + 'bin'}:#{ENV['PATH']}"
|
||||
}
|
||||
sh env, 'riscv32-unknown-linux-gnu-gcc',
|
||||
'-ffreestanding', '-static',
|
||||
'-o', (options.tools + 'init').to_path,
|
||||
'tools/init.c'
|
||||
end
|
||||
end
|
||||
|
||||
namespace :test do
|
||||
test_sources = FileList['tests/vm/*.elna', 'tests/vm/*.s']
|
||||
compiler = TMP + 'bin/elna'
|
||||
object_directory = TMP + 'riscv/tests'
|
||||
root_directory = TMP + 'riscv/root'
|
||||
executable_directory = root_directory + 'tests'
|
||||
expectation_directory = root_directory + 'expectations'
|
||||
init = TMP + 'riscv/root/init'
|
||||
builtin = TMP + 'riscv/builtin.o'
|
||||
|
||||
directory root_directory
|
||||
directory object_directory
|
||||
directory executable_directory
|
||||
directory expectation_directory
|
||||
|
||||
file builtin => ['tools/builtin.s', object_directory] do |task|
|
||||
sh AS, '-o', task.name, task.prerequisites.first
|
||||
end
|
||||
|
||||
test_files = test_sources.flat_map do |test_source|
|
||||
test_basename = File.basename(test_source, '.*')
|
||||
test_object = object_directory + test_basename.ext('.o')
|
||||
|
||||
file test_object => [test_source, object_directory] do |task|
|
||||
case File.extname(task.prerequisites.first)
|
||||
when '.s'
|
||||
sh AS, '-mno-relax', '-o', task.name, task.prerequisites.first
|
||||
when '.elna'
|
||||
sh compiler, '--output', task.name, task.prerequisites.first
|
||||
else
|
||||
raise "Unknown source file extension #{task.prerequisites.first}"
|
||||
end
|
||||
end
|
||||
test_executable = executable_directory + test_basename
|
||||
|
||||
file test_executable => [test_object, executable_directory, builtin] do |task|
|
||||
objects = task.prerequisites.filter { |prerequisite| File.file? prerequisite }
|
||||
|
||||
sh LINKER, '-o', test_executable.to_path, *objects
|
||||
end
|
||||
expectation_name = test_basename.ext '.txt'
|
||||
source_expectation = "tests/expectations/#{expectation_name}"
|
||||
target_expectation = expectation_directory + expectation_name
|
||||
|
||||
file target_expectation => [source_expectation, expectation_directory] do
|
||||
cp source_expectation, target_expectation
|
||||
end
|
||||
|
||||
[test_executable, target_expectation]
|
||||
end
|
||||
|
||||
file init => [root_directory] do |task|
|
||||
cp (TMP + 'tools/init'), task.name
|
||||
end
|
||||
# Directories should come first.
|
||||
test_files.unshift executable_directory, expectation_directory, init
|
||||
|
||||
file (TMP + 'riscv/root.cpio') => test_files do |task|
|
||||
root_files = task.prerequisites
|
||||
.map { |prerequisite| Pathname.new(prerequisite).relative_path_from(root_directory).to_path }
|
||||
|
||||
File.open task.name, 'wb' do |cpio_file|
|
||||
cpio_options = {
|
||||
chdir: root_directory.to_path
|
||||
}
|
||||
cpio_stream = Open3.popen2 'cpio', '-o', '--format=newc', cpio_options do |stdin, stdout, wait_thread|
|
||||
stdin.write root_files.join("\n")
|
||||
stdin.close
|
||||
stdout.each { |chunk| cpio_file.write chunk }
|
||||
wait_thread.value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
task :vm => (TMP + 'riscv/root.cpio') do |task|
|
||||
kernels = FileList.glob(TMP + 'tools/linux-*/arch/riscv/boot/Image')
|
||||
|
||||
sh 'qemu-system-riscv32',
|
||||
'-nographic',
|
||||
'-M', 'virt',
|
||||
'-bios', 'default',
|
||||
'-kernel', kernels.first,
|
||||
'-append', 'quiet panic=1',
|
||||
'-initrd', task.prerequisites.first,
|
||||
'-no-reboot'
|
||||
end
|
||||
end
|
||||
|
300
boot/ast.cc
300
boot/ast.cc
@ -191,6 +191,10 @@ namespace boot
|
||||
{
|
||||
}
|
||||
|
||||
node::~node()
|
||||
{
|
||||
}
|
||||
|
||||
const struct position& node::position() const
|
||||
{
|
||||
return this->source_position;
|
||||
@ -200,10 +204,145 @@ namespace boot
|
||||
{
|
||||
}
|
||||
|
||||
statement::~statement()
|
||||
{
|
||||
}
|
||||
|
||||
assign_statement *statement::is_assign()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if_statement *statement::is_if()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
while_statement *statement::is_while()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return_statement *statement::is_return()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
defer_statement *statement::is_defer()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
procedure_call *statement::is_call_statement()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void statement::accept(parser_visitor *visitor)
|
||||
{
|
||||
if (assign_statement *node = is_assign())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (if_statement *node = is_if())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (while_statement *node = is_while())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (return_statement *node = is_return())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (defer_statement *node = is_defer())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (procedure_call *node = is_call_statement())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
expression::expression()
|
||||
{
|
||||
}
|
||||
|
||||
expression::~expression()
|
||||
{
|
||||
}
|
||||
|
||||
cast_expression *expression::is_cast()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
traits_expression *expression::is_traits()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
binary_expression *expression::is_binary()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unary_expression *expression::is_unary()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
designator_expression *expression::is_designator()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
procedure_call *expression::is_call_expression()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
literal *expression::is_literal()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
if (cast_expression *node = is_cast())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (traits_expression *node = is_traits())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (binary_expression *node = is_binary())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (unary_expression *node = is_unary())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (designator_expression *node = is_designator())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (procedure_call *node = is_call_expression())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (literal *node = is_literal())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
type_expression::type_expression(const struct position position)
|
||||
: node(position)
|
||||
{
|
||||
@ -239,6 +378,35 @@ namespace boot
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void type_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
if (std::shared_ptr<primitive_type_expression> node = is_primitive())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (std::shared_ptr<array_type_expression> node = is_array())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (std::shared_ptr<pointer_type_expression> node = is_pointer())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (std::shared_ptr<record_type_expression> node = is_record())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (std::shared_ptr<union_type_expression> node = is_union())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (std::shared_ptr<procedure_type_expression> node = is_procedure())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
primitive_type_expression::primitive_type_expression(const struct position position, const std::string& name)
|
||||
: type_expression(position), name(name)
|
||||
{
|
||||
@ -486,6 +654,47 @@ namespace boot
|
||||
{
|
||||
}
|
||||
|
||||
literal *literal::is_literal()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void literal::accept(parser_visitor *visitor)
|
||||
{
|
||||
if (number_literal<std::int32_t> *node = is_int())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (number_literal<std::uint32_t> *node = is_word())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (number_literal<double> *node = is_float())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (number_literal<bool> *node = is_bool())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (number_literal<unsigned char> *node = is_char())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (number_literal<std::nullptr_t> *node = is_nil())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else if (number_literal<std::string> *node = is_string())
|
||||
{
|
||||
return node->accept(visitor);
|
||||
}
|
||||
else
|
||||
{
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
defer_statement::defer_statement(const struct position position)
|
||||
: node(position)
|
||||
{
|
||||
@ -496,6 +705,11 @@ namespace boot
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
defer_statement *defer_statement::is_defer()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
defer_statement::~defer_statement()
|
||||
{
|
||||
for (statement *body_statement : statements)
|
||||
@ -508,6 +722,36 @@ namespace boot
|
||||
{
|
||||
}
|
||||
|
||||
designator_expression::~designator_expression()
|
||||
{
|
||||
}
|
||||
|
||||
designator_expression *designator_expression::is_designator()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void designator_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
if (variable_expression *node = is_variable())
|
||||
{
|
||||
return visitor->visit(node);
|
||||
}
|
||||
else if (array_access_expression *node = is_array_access())
|
||||
{
|
||||
return visitor->visit(node);
|
||||
}
|
||||
else if (field_access_expression *node = is_field_access())
|
||||
{
|
||||
return visitor->visit(node);
|
||||
}
|
||||
else if (dereference_expression *node = is_dereference())
|
||||
{
|
||||
return visitor->visit(node);
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
variable_expression::variable_expression(const struct position position, const std::string& name)
|
||||
: node(position), name(name)
|
||||
{
|
||||
@ -623,6 +867,11 @@ namespace boot
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
binary_expression *binary_expression::is_binary()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
expression& binary_expression::lhs()
|
||||
{
|
||||
return *m_lhs;
|
||||
@ -655,6 +904,11 @@ namespace boot
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
unary_expression *unary_expression::is_unary()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
expression& unary_expression::operand()
|
||||
{
|
||||
return *m_operand;
|
||||
@ -680,6 +934,16 @@ namespace boot
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
procedure_call *procedure_call::is_call_statement()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
procedure_call *procedure_call::is_call_expression()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
designator_expression& procedure_call::callable()
|
||||
{
|
||||
return *m_callable;
|
||||
@ -705,6 +969,11 @@ namespace boot
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
cast_expression *cast_expression::is_cast()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
type_expression& cast_expression::target()
|
||||
{
|
||||
return *m_target;
|
||||
@ -731,6 +1000,11 @@ namespace boot
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
traits_expression *traits_expression::is_traits()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
type_expression& traits_expression::type()
|
||||
{
|
||||
return *m_type;
|
||||
@ -765,6 +1039,11 @@ namespace boot
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
return_statement *return_statement::is_return()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
expression *return_statement::return_expression()
|
||||
{
|
||||
return m_return_expression;
|
||||
@ -775,15 +1054,20 @@ namespace boot
|
||||
delete m_return_expression;
|
||||
}
|
||||
|
||||
assign_statement::assign_statement(const struct position position, designator_expression *lvalue,
|
||||
expression *rvalue)
|
||||
: node(position), m_lvalue(lvalue), m_rvalue(rvalue)
|
||||
{
|
||||
}
|
||||
|
||||
void assign_statement::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
assign_statement::assign_statement(const struct position position, designator_expression *lvalue,
|
||||
expression *rvalue)
|
||||
: node(position), m_lvalue(lvalue), m_rvalue(rvalue)
|
||||
assign_statement *assign_statement::is_assign()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
variable_expression *designator_expression::is_variable()
|
||||
@ -832,6 +1116,11 @@ namespace boot
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
if_statement *if_statement::is_if()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
conditional_statements& if_statement::body()
|
||||
{
|
||||
return *m_body;
|
||||
@ -862,6 +1151,11 @@ namespace boot
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
while_statement *while_statement::is_while()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
conditional_statements& while_statement::body()
|
||||
{
|
||||
return *m_body;
|
||||
|
@ -1,33 +0,0 @@
|
||||
/* Semantic analysis visitors.
|
||||
Copyright (C) 2025 Free Software Foundation, Inc.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "elna/boot/semantic.h"
|
||||
|
||||
namespace elna
|
||||
{
|
||||
namespace boot
|
||||
{
|
||||
declaration_visitor::declaration_visitor(std::shared_ptr<symbol_table> table)
|
||||
: table(table)
|
||||
{
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(program *program)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/* Symbol definitions.
|
||||
Copyright (C) 2025 Free Software Foundation, Inc.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "elna/boot/symbol.h"
|
||||
|
||||
namespace elna
|
||||
{
|
||||
namespace boot
|
||||
{
|
||||
type::~type()
|
||||
{
|
||||
}
|
||||
|
||||
info::~info()
|
||||
{
|
||||
}
|
||||
|
||||
type_info::type_info(const std::string& name)
|
||||
: name(name)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -46,8 +46,6 @@ elna_OBJS = \
|
||||
elna/driver.o \
|
||||
elna/lexer.o \
|
||||
elna/parser.o \
|
||||
elna/semantic.o \
|
||||
elna/symbol.o \
|
||||
elna/result.o \
|
||||
$(END)
|
||||
|
||||
|
@ -38,9 +38,73 @@ namespace elna
|
||||
{
|
||||
namespace gcc
|
||||
{
|
||||
declaration_visitor::declaration_visitor(std::shared_ptr<symbol_table> symbol_table)
|
||||
: symbols(symbol_table)
|
||||
{
|
||||
this->unresolved.insert({ "Int", std::make_shared<type>(elna_int_type_node) });
|
||||
this->unresolved.insert({ "Word", std::make_shared<type>(elna_word_type_node) });
|
||||
this->unresolved.insert({ "Char", std::make_shared<type>(elna_char_type_node) });
|
||||
this->unresolved.insert({ "Bool", std::make_shared<type>(elna_bool_type_node) });
|
||||
this->unresolved.insert({ "Byte", std::make_shared<type>(elna_byte_type_node) });
|
||||
this->unresolved.insert({ "Float", std::make_shared<type>(elna_float_type_node) });
|
||||
this->unresolved.insert({ "String", std::make_shared<type>(elna_string_type_node) });
|
||||
}
|
||||
|
||||
tree get_inner_alias(const type& t)
|
||||
{
|
||||
if (t.reference == nullptr)
|
||||
{
|
||||
return t.resolved;
|
||||
}
|
||||
else
|
||||
{
|
||||
return get_inner_alias(*t.reference);
|
||||
}
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(boot::program *program)
|
||||
{
|
||||
for (boot::type_definition *const type : program->types)
|
||||
{
|
||||
type->accept(this);
|
||||
}
|
||||
for (boot::type_definition *const type : program->types)
|
||||
{
|
||||
auto unresolved_declaration = this->unresolved.at(type->identifier);
|
||||
|
||||
if (auto alias_node = type->body().is_primitive())
|
||||
{
|
||||
auto unresolved_alias = this->unresolved.find(alias_node->name);
|
||||
|
||||
if (unresolved_alias != this->unresolved.end())
|
||||
{
|
||||
unresolved_declaration->reference = unresolved_alias->second;
|
||||
}
|
||||
}
|
||||
else if (auto alias_node = type->body().is_record())
|
||||
{
|
||||
unresolved_declaration->resolved = make_node(RECORD_TYPE);
|
||||
}
|
||||
else if (auto alias_node = type->body().is_union())
|
||||
{
|
||||
unresolved_declaration->resolved = make_node(UNION_TYPE);
|
||||
}
|
||||
}
|
||||
for (auto unresolved : this->unresolved)
|
||||
{
|
||||
auto inner_alias = get_inner_alias(unresolved.second);
|
||||
this->symbols->enter(unresolved.first, inner_alias);
|
||||
}
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(boot::type_definition *definition)
|
||||
{
|
||||
this->unresolved.insert({ definition->identifier, std::make_shared<type>() });
|
||||
}
|
||||
|
||||
generic_visitor::generic_visitor(std::shared_ptr<symbol_table> symbol_table)
|
||||
{
|
||||
this->symbol_map = symbol_table;
|
||||
this->symbols = symbol_table;
|
||||
}
|
||||
|
||||
void generic_visitor::build_procedure_call(location_t call_location,
|
||||
@ -180,23 +244,6 @@ namespace gcc
|
||||
constant->accept(this);
|
||||
}
|
||||
for (boot::type_definition *const type : program->types)
|
||||
{
|
||||
tree type_node = NULL_TREE;
|
||||
|
||||
if (type->body().is_record())
|
||||
{
|
||||
type_node = make_node(RECORD_TYPE);
|
||||
}
|
||||
else if (type->body().is_union())
|
||||
{
|
||||
type_node = make_node(UNION_TYPE);
|
||||
}
|
||||
if (type_node != NULL_TREE)
|
||||
{
|
||||
this->symbol_map->enter(type->identifier, type_node);
|
||||
}
|
||||
}
|
||||
for (boot::type_definition *const type : program->types)
|
||||
{
|
||||
type->accept(this);
|
||||
}
|
||||
@ -229,7 +276,7 @@ namespace gcc
|
||||
DECL_CONTEXT(declaration_tree) = fndecl;
|
||||
DECL_ARG_TYPE(declaration_tree) = TREE_VALUE(parameter_type);
|
||||
|
||||
this->symbol_map->enter(argument_name, declaration_tree);
|
||||
this->symbols->enter(argument_name, declaration_tree);
|
||||
DECL_ARGUMENTS(fndecl) = chainon(DECL_ARGUMENTS(fndecl), declaration_tree);
|
||||
parameter_type = TREE_CHAIN(parameter_type);
|
||||
}
|
||||
@ -269,7 +316,7 @@ namespace gcc
|
||||
{
|
||||
tree declaration_type = build_procedure_type(definition->heading());
|
||||
tree fndecl = build_fn_decl(definition->identifier.c_str(), declaration_type);
|
||||
this->symbol_map->enter(definition->identifier, fndecl);
|
||||
this->symbols->enter(definition->identifier, fndecl);
|
||||
|
||||
if (definition->heading().no_return)
|
||||
{
|
||||
@ -299,7 +346,7 @@ namespace gcc
|
||||
|
||||
if (definition->body != nullptr)
|
||||
{
|
||||
this->symbol_map->enter(parameter->identifier, declaration_tree);
|
||||
this->symbols->enter(parameter->identifier, declaration_tree);
|
||||
}
|
||||
argument_chain = chainon(argument_chain, declaration_tree);
|
||||
function_args_iter_next(¶meter_type);
|
||||
@ -332,7 +379,7 @@ namespace gcc
|
||||
|
||||
void generic_visitor::enter_scope()
|
||||
{
|
||||
this->symbol_map = std::make_shared<symbol_table>(this->symbol_map);
|
||||
this->symbols = std::make_shared<symbol_table>(this->symbols);
|
||||
|
||||
// Chain the binding levels.
|
||||
struct binding_level *new_level = ggc_cleared_alloc<binding_level>();
|
||||
@ -352,7 +399,7 @@ namespace gcc
|
||||
BLOCK_SUPERCONTEXT(it) = new_block;
|
||||
}
|
||||
tree bind_expr = build3(BIND_EXPR, void_type_node, variables, chain_defer(), new_block);
|
||||
this->symbol_map = this->symbol_map->scope();
|
||||
this->symbols = this->symbols->scope();
|
||||
|
||||
f_binding_level = f_binding_level->level_chain;
|
||||
|
||||
@ -365,35 +412,7 @@ namespace gcc
|
||||
|
||||
tree generic_visitor::lookup(const std::string& name)
|
||||
{
|
||||
if (name == "Int")
|
||||
{
|
||||
return elna_int_type_node;
|
||||
}
|
||||
if (name == "Word")
|
||||
{
|
||||
return elna_word_type_node;
|
||||
}
|
||||
if (name == "Char")
|
||||
{
|
||||
return elna_char_type_node;
|
||||
}
|
||||
if (name == "Bool")
|
||||
{
|
||||
return elna_bool_type_node;
|
||||
}
|
||||
if (name == "Byte")
|
||||
{
|
||||
return elna_byte_type_node;
|
||||
}
|
||||
if (name == "Float")
|
||||
{
|
||||
return elna_float_type_node;
|
||||
}
|
||||
if (name == "String")
|
||||
{
|
||||
return elna_string_type_node;
|
||||
}
|
||||
return this->symbol_map->lookup(name);
|
||||
return this->symbols->lookup(name);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::number_literal<std::int32_t> *literal)
|
||||
@ -720,7 +739,7 @@ namespace gcc
|
||||
|
||||
tree definition_tree = build_decl(definition_location, CONST_DECL,
|
||||
get_identifier(definition->identifier.c_str()), TREE_TYPE(this->current_expression));
|
||||
auto result = this->symbol_map->enter(definition->identifier, definition_tree);
|
||||
auto result = this->symbols->enter(definition->identifier, definition_tree);
|
||||
|
||||
if (result)
|
||||
{
|
||||
@ -748,12 +767,12 @@ namespace gcc
|
||||
void generic_visitor::visit(boot::type_definition *definition)
|
||||
{
|
||||
location_t definition_location = get_location(&definition->position());
|
||||
this->current_expression = this->symbol_map->lookup(definition->identifier);
|
||||
this->current_expression = lookup(definition->identifier);
|
||||
definition->body().accept(this);
|
||||
|
||||
tree definition_tree = build_decl(definition_location, TYPE_DECL,
|
||||
get_identifier(definition->identifier.c_str()), this->current_expression);
|
||||
auto result = this->symbol_map->enter(definition->identifier, this->current_expression);
|
||||
auto result = this->symbols->enter(definition->identifier, this->current_expression);
|
||||
|
||||
/* if (result)
|
||||
{ */
|
||||
@ -798,7 +817,7 @@ namespace gcc
|
||||
location_t declaration_location = get_location(&declaration->position());
|
||||
tree declaration_tree = build_decl(declaration_location, VAR_DECL,
|
||||
get_identifier(declaration->identifier.c_str()), this->current_expression);
|
||||
bool result = this->symbol_map->enter(declaration->identifier, declaration_tree);
|
||||
bool result = this->symbols->enter(declaration->identifier, declaration_tree);
|
||||
|
||||
if (is_pointer_type(this->current_expression))
|
||||
{
|
||||
@ -829,7 +848,7 @@ namespace gcc
|
||||
|
||||
void generic_visitor::visit(boot::variable_expression *expression)
|
||||
{
|
||||
auto symbol = this->lookup(expression->name);
|
||||
auto symbol = lookup(expression->name);
|
||||
|
||||
if (symbol == NULL_TREE)
|
||||
{
|
||||
@ -1122,9 +1141,9 @@ namespace gcc
|
||||
|
||||
void generic_visitor::visit(boot::primitive_type_expression *type)
|
||||
{
|
||||
tree symbol = this->lookup(type->name);
|
||||
tree symbol = lookup(type->name);
|
||||
|
||||
if (symbol == NULL_TREE && TYPE_P(symbol))
|
||||
if (symbol == NULL_TREE || !TYPE_P(symbol))
|
||||
{
|
||||
error_at(get_location(&type->position()),
|
||||
"type '%s' not declared", type->name.c_str());
|
||||
|
@ -30,7 +30,6 @@ along with GCC; see the file COPYING3. If not see
|
||||
|
||||
#include <fstream>
|
||||
#include "elna/boot/driver.h"
|
||||
#include "elna/boot/semantic.h"
|
||||
#include "elna/gcc/elna-tree.h"
|
||||
#include "elna/gcc/elna-generic.h"
|
||||
#include "elna/gcc/elna-diagnostic.h"
|
||||
@ -89,8 +88,10 @@ static void elna_parse_file(const char *filename)
|
||||
}
|
||||
else
|
||||
{
|
||||
elna::boot::declaration_visitor declaration_visitor{ std::make_shared<elna::boot::symbol_table>() };
|
||||
elna::gcc::generic_visitor generic_visitor{ std::make_shared<elna::gcc::symbol_table>() };
|
||||
std::shared_ptr<elna::gcc::symbol_table> symbol_table = std::make_shared<elna::gcc::symbol_table>();
|
||||
|
||||
elna::gcc::declaration_visitor declaration_visitor{ symbol_table };
|
||||
elna::gcc::generic_visitor generic_visitor{ symbol_table };
|
||||
|
||||
declaration_visitor.visit(driver.tree.get());
|
||||
generic_visitor.visit(driver.tree.get());
|
||||
|
@ -79,6 +79,8 @@ namespace boot
|
||||
class array_access_expression;
|
||||
class field_access_expression;
|
||||
class dereference_expression;
|
||||
class designator_expression;
|
||||
class literal;
|
||||
template<typename T>
|
||||
class number_literal;
|
||||
class defer_statement;
|
||||
@ -132,9 +134,9 @@ namespace boot
|
||||
virtual void visit(constant_definition *) override;
|
||||
virtual void visit(procedure_definition *) override;
|
||||
virtual void visit(type_definition *) override;
|
||||
virtual void visit(traits_expression *) override;
|
||||
virtual void visit(procedure_call *) override;
|
||||
virtual void visit(cast_expression *) override;
|
||||
virtual void visit(traits_expression *) override;
|
||||
virtual void visit(assign_statement *) override;
|
||||
virtual void visit(if_statement *) override;
|
||||
virtual void visit(while_statement *) override;
|
||||
@ -177,8 +179,7 @@ namespace boot
|
||||
explicit node(const position position);
|
||||
|
||||
public:
|
||||
virtual ~node() = default;
|
||||
virtual void accept(parser_visitor *) = 0;
|
||||
virtual ~node() = 0;
|
||||
|
||||
/**
|
||||
* \return Node position in the source code.
|
||||
@ -188,12 +189,35 @@ namespace boot
|
||||
|
||||
class statement : public virtual node
|
||||
{
|
||||
public:
|
||||
virtual assign_statement *is_assign();
|
||||
virtual if_statement *is_if();
|
||||
virtual while_statement *is_while();
|
||||
virtual return_statement *is_return();
|
||||
virtual defer_statement *is_defer();
|
||||
virtual procedure_call *is_call_statement();
|
||||
|
||||
void accept(parser_visitor *visitor);
|
||||
~statement() = 0;
|
||||
|
||||
protected:
|
||||
statement();
|
||||
};
|
||||
|
||||
class expression : public virtual node
|
||||
{
|
||||
public:
|
||||
virtual cast_expression *is_cast();
|
||||
virtual traits_expression *is_traits();
|
||||
virtual binary_expression *is_binary();
|
||||
virtual unary_expression *is_unary();
|
||||
virtual designator_expression *is_designator();
|
||||
virtual procedure_call *is_call_expression();
|
||||
virtual literal *is_literal();
|
||||
|
||||
void accept(parser_visitor *visitor);
|
||||
~expression() = 0;
|
||||
|
||||
protected:
|
||||
expression();
|
||||
};
|
||||
@ -224,6 +248,8 @@ namespace boot
|
||||
virtual std::shared_ptr<union_type_expression> is_union();
|
||||
virtual std::shared_ptr<procedure_type_expression> is_procedure();
|
||||
|
||||
void accept(parser_visitor *visitor);
|
||||
|
||||
protected:
|
||||
type_expression(const struct position position);
|
||||
};
|
||||
@ -237,7 +263,7 @@ namespace boot
|
||||
const std::string name;
|
||||
|
||||
primitive_type_expression(const struct position position, const std::string& name);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
std::shared_ptr<primitive_type_expression> is_primitive() override;
|
||||
};
|
||||
|
||||
@ -250,7 +276,7 @@ namespace boot
|
||||
|
||||
array_type_expression(const struct position position,
|
||||
std::shared_ptr<type_expression> base, const std::uint32_t size);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
std::shared_ptr<array_type_expression> is_array() override;
|
||||
|
||||
type_expression& base();
|
||||
@ -262,7 +288,7 @@ namespace boot
|
||||
|
||||
public:
|
||||
pointer_type_expression(const struct position position, std::shared_ptr<type_expression> base);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
std::shared_ptr<pointer_type_expression> is_pointer() override;
|
||||
|
||||
type_expression& base();
|
||||
@ -278,7 +304,7 @@ namespace boot
|
||||
|
||||
record_type_expression(const struct position position, fields_t&& fields);
|
||||
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
std::shared_ptr<record_type_expression> is_record() override;
|
||||
};
|
||||
|
||||
@ -289,7 +315,7 @@ namespace boot
|
||||
|
||||
union_type_expression(const struct position position, fields_t&& fields);
|
||||
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
std::shared_ptr<union_type_expression> is_union() override;
|
||||
};
|
||||
|
||||
@ -303,7 +329,7 @@ namespace boot
|
||||
public:
|
||||
variable_declaration(const struct position position, const std::string& identifier,
|
||||
std::shared_ptr<type_expression> type, const bool exported = false);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
|
||||
type_expression& variable_type();
|
||||
};
|
||||
@ -313,6 +339,18 @@ namespace boot
|
||||
*/
|
||||
class literal : public expression
|
||||
{
|
||||
public:
|
||||
virtual number_literal<std::int32_t> *is_int() = 0;
|
||||
virtual number_literal<std::uint32_t> *is_word() = 0;
|
||||
virtual number_literal<double> *is_float() = 0;
|
||||
virtual number_literal<bool> *is_bool() = 0;
|
||||
virtual number_literal<unsigned char> *is_char() = 0;
|
||||
virtual number_literal<std::nullptr_t> *is_nil() = 0;
|
||||
virtual number_literal<std::string> *is_string() = 0;
|
||||
|
||||
literal *is_literal() override;
|
||||
void accept(parser_visitor *visitor);
|
||||
|
||||
protected:
|
||||
literal();
|
||||
};
|
||||
@ -332,7 +370,7 @@ namespace boot
|
||||
*/
|
||||
constant_definition(const struct position position, const std::string& identifier,
|
||||
const bool exported, literal *body);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
|
||||
literal& body();
|
||||
|
||||
@ -361,7 +399,7 @@ namespace boot
|
||||
std::shared_ptr<type_expression> return_type = nullptr);
|
||||
procedure_type_expression(const struct position position, no_return_t);
|
||||
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
std::shared_ptr<procedure_type_expression> is_procedure() override;
|
||||
|
||||
virtual ~procedure_type_expression() override;
|
||||
@ -379,7 +417,7 @@ namespace boot
|
||||
|
||||
procedure_definition(const struct position position, const std::string& identifier,
|
||||
const bool exported, std::shared_ptr<procedure_type_expression> heading, block *body = nullptr);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
|
||||
procedure_type_expression& heading();
|
||||
|
||||
@ -396,7 +434,7 @@ namespace boot
|
||||
public:
|
||||
type_definition(const struct position position, const std::string& identifier,
|
||||
const bool exported, std::shared_ptr<type_expression> expression);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
|
||||
type_expression& body();
|
||||
};
|
||||
@ -411,7 +449,8 @@ namespace boot
|
||||
|
||||
public:
|
||||
cast_expression(const struct position position, std::shared_ptr<type_expression> target, expression *value);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
cast_expression *is_cast() override;
|
||||
|
||||
type_expression& target();
|
||||
expression& value();
|
||||
@ -428,7 +467,8 @@ namespace boot
|
||||
|
||||
traits_expression(const struct position position, const std::string& name,
|
||||
std::shared_ptr<type_expression> type);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
traits_expression *is_traits() override;
|
||||
|
||||
type_expression& type();
|
||||
};
|
||||
@ -456,7 +496,8 @@ namespace boot
|
||||
|
||||
public:
|
||||
return_statement(const struct position position, expression *return_expression);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
virtual return_statement *is_return() override;
|
||||
|
||||
expression *return_expression();
|
||||
|
||||
@ -471,6 +512,10 @@ namespace boot
|
||||
virtual field_access_expression *is_field_access();
|
||||
virtual dereference_expression *is_dereference();
|
||||
|
||||
designator_expression *is_designator() override;
|
||||
void accept(parser_visitor *visitor);
|
||||
~designator_expression() = 0;
|
||||
|
||||
protected:
|
||||
designator_expression();
|
||||
};
|
||||
@ -481,7 +526,7 @@ namespace boot
|
||||
const std::string name;
|
||||
|
||||
variable_expression(const struct position position, const std::string& name);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
|
||||
variable_expression *is_variable() override;
|
||||
};
|
||||
@ -493,7 +538,7 @@ namespace boot
|
||||
|
||||
public:
|
||||
array_access_expression(const struct position position, expression *base, expression *index);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
|
||||
expression& base();
|
||||
expression& index();
|
||||
@ -511,7 +556,7 @@ namespace boot
|
||||
public:
|
||||
field_access_expression(const struct position position, expression *base,
|
||||
const std::string& field);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
|
||||
expression& base();
|
||||
std::string& field();
|
||||
@ -527,7 +572,7 @@ namespace boot
|
||||
|
||||
public:
|
||||
dereference_expression(const struct position position, expression *base);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
|
||||
expression& base();
|
||||
|
||||
@ -547,7 +592,9 @@ namespace boot
|
||||
std::vector<expression *> arguments;
|
||||
|
||||
procedure_call(const struct position position, designator_expression *callable);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
virtual procedure_call *is_call_statement() override;
|
||||
virtual procedure_call *is_call_expression() override;
|
||||
|
||||
designator_expression& callable();
|
||||
|
||||
@ -567,12 +614,13 @@ namespace boot
|
||||
*/
|
||||
assign_statement(const struct position position, designator_expression *lvalue,
|
||||
expression *rvalue);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
|
||||
designator_expression& lvalue();
|
||||
expression& rvalue();
|
||||
|
||||
virtual ~assign_statement() override;
|
||||
assign_statement *is_assign() override;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -588,7 +636,8 @@ namespace boot
|
||||
|
||||
if_statement(const struct position position, conditional_statements *body,
|
||||
std::vector<statement *> *alternative = nullptr);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
virtual if_statement *is_if() override;
|
||||
|
||||
conditional_statements& body();
|
||||
std::vector<statement *> *alternative();
|
||||
@ -606,7 +655,8 @@ namespace boot
|
||||
public:
|
||||
std::vector<conditional_statements *> branches;
|
||||
while_statement(const struct position position, conditional_statements *body);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
while_statement *is_while() override;
|
||||
|
||||
conditional_statements& body();
|
||||
|
||||
@ -621,7 +671,7 @@ namespace boot
|
||||
std::vector<statement *> body;
|
||||
|
||||
block(const struct position position);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
|
||||
virtual ~block() override;
|
||||
};
|
||||
@ -633,7 +683,7 @@ namespace boot
|
||||
std::vector<procedure_definition *> procedures;
|
||||
|
||||
program(const struct position position);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
|
||||
virtual ~program() override;
|
||||
};
|
||||
@ -649,7 +699,91 @@ namespace boot
|
||||
{
|
||||
}
|
||||
|
||||
virtual void accept(parser_visitor *visitor) override
|
||||
number_literal<std::int32_t> *is_int() override
|
||||
{
|
||||
if (std::is_same<T, std::int32_t>::value)
|
||||
{
|
||||
return reinterpret_cast<number_literal<std::int32_t> *>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
number_literal<std::uint32_t> *is_word() override
|
||||
{
|
||||
if (std::is_same<T, std::uint32_t>::value)
|
||||
{
|
||||
return reinterpret_cast<number_literal<std::uint32_t> *>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
number_literal<double> *is_float() override
|
||||
{
|
||||
if (std::is_same<T, double>::value)
|
||||
{
|
||||
return reinterpret_cast<number_literal<double> *>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
number_literal<bool> *is_bool() override
|
||||
{
|
||||
if (std::is_same<T, bool>::value)
|
||||
{
|
||||
return reinterpret_cast<number_literal<bool> *>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
number_literal<unsigned char> *is_char() override
|
||||
{
|
||||
if (std::is_same<T, unsigned char>::value)
|
||||
{
|
||||
return reinterpret_cast<number_literal<unsigned char> *>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
number_literal<std::nullptr_t> *is_nil() override
|
||||
{
|
||||
if (std::is_same<T, std::nullptr_t>::value)
|
||||
{
|
||||
return reinterpret_cast<number_literal<std::nullptr_t> *>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
number_literal<std::string> *is_string() override
|
||||
{
|
||||
if (std::is_same<T, std::string>::value)
|
||||
{
|
||||
return reinterpret_cast<number_literal<std::string> *>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
@ -661,7 +795,8 @@ namespace boot
|
||||
std::vector<statement *> statements;
|
||||
|
||||
defer_statement(const struct position position);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
defer_statement *is_defer() override;
|
||||
|
||||
virtual ~defer_statement() override;
|
||||
};
|
||||
@ -676,7 +811,9 @@ namespace boot
|
||||
binary_expression(const struct position position, expression *lhs,
|
||||
expression *rhs, const binary_operator operation);
|
||||
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
binary_expression *is_binary() override;
|
||||
|
||||
expression& lhs();
|
||||
expression& rhs();
|
||||
binary_operator operation() const;
|
||||
@ -693,7 +830,9 @@ namespace boot
|
||||
unary_expression(const struct position position, expression *operand,
|
||||
const unary_operator operation);
|
||||
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
void accept(parser_visitor *visitor);
|
||||
unary_expression *is_unary() override;
|
||||
|
||||
expression& operand();
|
||||
unary_operator operation() const;
|
||||
|
||||
|
@ -1,37 +0,0 @@
|
||||
/* Semantic analysis visitors.
|
||||
Copyright (C) 2025 Free Software Foundation, Inc.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "elna/boot/ast.h"
|
||||
#include "elna/boot/symbol.h"
|
||||
|
||||
namespace elna
|
||||
{
|
||||
namespace boot
|
||||
{
|
||||
class declaration_visitor : public empty_visitor
|
||||
{
|
||||
std::shared_ptr<symbol_table> table;
|
||||
|
||||
public:
|
||||
declaration_visitor(std::shared_ptr<symbol_table> table);
|
||||
|
||||
void visit(program *program) override;
|
||||
};
|
||||
}
|
||||
}
|
@ -26,32 +26,6 @@ namespace elna
|
||||
{
|
||||
namespace boot
|
||||
{
|
||||
class info
|
||||
{
|
||||
public:
|
||||
virtual ~info() = 0;
|
||||
|
||||
protected:
|
||||
info() = default;
|
||||
};
|
||||
|
||||
class type
|
||||
{
|
||||
public:
|
||||
virtual ~type() = 0;
|
||||
|
||||
protected:
|
||||
type() = default;
|
||||
};
|
||||
|
||||
class type_info : public info, public type
|
||||
{
|
||||
public:
|
||||
const std::string name;
|
||||
|
||||
type_info(const std::string& name);
|
||||
};
|
||||
|
||||
/**
|
||||
* Symbol table.
|
||||
*/
|
||||
@ -146,7 +120,5 @@ namespace boot
|
||||
return this->outer_scope;
|
||||
}
|
||||
};
|
||||
|
||||
using symbol_table = symbol_map<std::shared_ptr<info>, std::nullptr_t, nullptr>;
|
||||
}
|
||||
}
|
||||
|
@ -27,17 +27,39 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "tree.h"
|
||||
#include "tree-iterator.h"
|
||||
|
||||
#include <forward_list>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
namespace elna
|
||||
{
|
||||
namespace gcc
|
||||
{
|
||||
struct type
|
||||
{
|
||||
type() {}
|
||||
type(tree resolved): resolved(resolved) {}
|
||||
type(std::shared_ptr<type> reference): reference(reference) {}
|
||||
|
||||
tree resolved{ NULL_TREE };
|
||||
std::shared_ptr<type> reference;
|
||||
};
|
||||
|
||||
class declaration_visitor final : public boot::empty_visitor
|
||||
{
|
||||
std::shared_ptr<symbol_table> symbols;
|
||||
std::unordered_map<std::string, std::shared_ptr<type>> unresolved;
|
||||
|
||||
public:
|
||||
declaration_visitor(std::shared_ptr<symbol_table> symbol_table);
|
||||
|
||||
void visit(boot::program *program) override;
|
||||
void visit(boot::type_definition *definition) override;
|
||||
};
|
||||
|
||||
class generic_visitor final : public boot::empty_visitor
|
||||
{
|
||||
tree current_expression{ NULL_TREE };
|
||||
std::shared_ptr<symbol_table> symbol_map;
|
||||
std::shared_ptr<symbol_table> symbols;
|
||||
|
||||
tree build_label_decl(const char *name, location_t loc);
|
||||
tree build_procedure_type(boot::procedure_type_expression& type);
|
||||
|
@ -6,9 +6,6 @@ require 'uri'
|
||||
require 'net/http'
|
||||
require 'open3'
|
||||
|
||||
LINKER = 'build/rootfs/riscv32-unknown-linux-gnu/bin/ld'
|
||||
AS = 'build/rootfs/riscv32-unknown-linux-gnu/bin/as'
|
||||
|
||||
TMP = Pathname.new('./build')
|
||||
|
||||
class BuildTarget
|
||||
|
Loading…
x
Reference in New Issue
Block a user