diff --git a/boot/dependency.cc b/boot/dependency.cc
new file mode 100644
index 0000000..9811422
--- /dev/null
+++ b/boot/dependency.cc
@@ -0,0 +1,62 @@
+/* Dependency graph analysis.
+ 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
+. */
+
+#include "elna/boot/dependency.h"
+
+#include "elna/boot/driver.h"
+#include "parser.hh"
+
+namespace elna::boot
+{
+ dependency_graph::dependency_graph()
+ {
+ }
+
+ dependency_graph::dependency_graph(error_list&& errors)
+ : m_errors(std::move(errors))
+ {
+ }
+
+ bool dependency_graph::has_errors() const
+ {
+ return !errors().empty();
+ }
+
+ const error_list& dependency_graph::errors() const
+ {
+ return m_errors;
+ }
+
+ dependency_graph read_sources(std::istream& entry_point, const char *entry_path)
+ {
+ driver parse_driver{ entry_path };
+ lexer tokenizer(entry_point);
+ yy::parser parser(tokenizer, parse_driver);
+
+ if (parser())
+ {
+ return dependency_graph(std::move(parse_driver.errors()));
+ }
+ else
+ {
+ dependency_graph outcome;
+ outcome.modules.emplace_back(std::move(parse_driver.tree));
+
+ return outcome;
+ }
+ }
+}
diff --git a/gcc/Make-lang.in b/gcc/Make-lang.in
index 3159853..a3e6d85 100644
--- a/gcc/Make-lang.in
+++ b/gcc/Make-lang.in
@@ -43,6 +43,7 @@ elna_OBJS = \
elna/elna-tree.o \
elna/elna-builtins.o \
elna/ast.o \
+ elna/dependency.o \
elna/driver.o \
elna/lexer.o \
elna/parser.o \
diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc
index a2dee33..7774e1c 100644
--- a/gcc/elna-generic.cc
+++ b/gcc/elna-generic.cc
@@ -100,7 +100,7 @@ namespace elna::gcc
}
std::deque> do_semantic_analysis(const char *path,
- std::unique_ptr& ast, std::shared_ptr info_table,
+ const std::unique_ptr& ast, std::shared_ptr info_table,
std::shared_ptr symbols, std::unordered_map& unresolved)
{
boot::declaration_visitor declaration_visitor(path, info_table);
diff --git a/gcc/elna1.cc b/gcc/elna1.cc
index 8ea613a..bcd3df5 100644
--- a/gcc/elna1.cc
+++ b/gcc/elna1.cc
@@ -29,12 +29,11 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks-def.h"
#include
-#include "elna/boot/driver.h"
+#include "elna/boot/dependency.h"
#include "elna/gcc/elna-tree.h"
#include "elna/gcc/elna-generic.h"
#include "elna/gcc/elna-diagnostic.h"
#include "elna/gcc/elna-builtins.h"
-#include "parser.hh"
tree elna_global_trees[ELNA_TI_MAX];
hash_map *elna_global_decls = nullptr;
@@ -71,33 +70,34 @@ static void elna_parse_file(const char *filename)
{
fatal_error(UNKNOWN_LOCATION, "cannot open filename %s: %m", filename);
}
+ elna::boot::dependency_graph outcome = elna::boot::read_sources(file, filename);
- elna::boot::driver driver{ filename };
- elna::boot::lexer lexer(file);
- yy::parser parser(lexer, driver);
+ std::shared_ptr info_table = elna::boot::builtin_symbol_table();
+ std::shared_ptr symbol_table = elna::gcc::builtin_symbol_table();
linemap_add(line_table, LC_ENTER, 0, filename, 1);
- if (parser())
+ if (outcome.has_errors())
{
- elna::gcc::report_errors(driver.errors());
+ elna::gcc::report_errors(outcome.errors());
}
else
{
- std::shared_ptr info_table = elna::boot::builtin_symbol_table();
- std::shared_ptr symbol_table = elna::gcc::builtin_symbol_table();
- std::unordered_map unresolved;
-
- auto semantic_errors = elna::gcc::do_semantic_analysis(filename, driver.tree,
- info_table, symbol_table, unresolved);
-
- if (semantic_errors.empty())
+ for (const std::unique_ptr& module_tree : outcome.modules)
{
- elna::gcc::generic_visitor generic_visitor{ symbol_table, std::move(unresolved) };
- generic_visitor.visit(driver.tree.get());
- }
- else
- {
- elna::gcc::report_errors(semantic_errors);
+ std::unordered_map unresolved;
+
+ auto semantic_errors = elna::gcc::do_semantic_analysis(filename, module_tree,
+ info_table, symbol_table, unresolved);
+
+ if (semantic_errors.empty())
+ {
+ elna::gcc::generic_visitor generic_visitor{ symbol_table, std::move(unresolved) };
+ generic_visitor.visit(module_tree.get());
+ }
+ else
+ {
+ elna::gcc::report_errors(semantic_errors);
+ }
}
}
linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
diff --git a/include/elna/boot/dependency.h b/include/elna/boot/dependency.h
new file mode 100644
index 0000000..64ed7dd
--- /dev/null
+++ b/include/elna/boot/dependency.h
@@ -0,0 +1,41 @@
+/* Dependency graph analysis.
+ 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
+. */
+
+#pragma once
+
+#include
+#include "elna/boot/result.h"
+#include "elna/boot/ast.h"
+
+namespace elna::boot
+{
+ class dependency_graph
+ {
+ error_list m_errors;
+
+ public:
+ std::vector> modules;
+
+ bool has_errors() const;
+ const error_list& errors() const;
+
+ dependency_graph();
+ explicit dependency_graph(error_list&& errors);
+ };
+
+ dependency_graph read_sources(std::istream& entry_point, const char *entry_path);
+}
diff --git a/include/elna/boot/result.h b/include/elna/boot/result.h
index b4ac13b..acf4a4f 100644
--- a/include/elna/boot/result.h
+++ b/include/elna/boot/result.h
@@ -61,17 +61,19 @@ namespace elna::boot
std::size_t column() const;
};
+ using error_list = typename std::deque>;
+
class error_container
{
protected:
- std::deque> m_errors;
+ error_list m_errors;
error_container(const char *input_file);
public:
const char *input_file;
- std::deque>& errors();
+ error_list& errors();
template
void add_error(Args... arguments)
@@ -102,5 +104,4 @@ namespace elna::boot
T proper_type{};
bool no_return{ false };
};
-
}
diff --git a/include/elna/boot/semantic.h b/include/elna/boot/semantic.h
index 5eafae9..f398f65 100644
--- a/include/elna/boot/semantic.h
+++ b/include/elna/boot/semantic.h
@@ -15,6 +15,8 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
. */
+#pragma once
+
#include
#include
#include
diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h
index 69e4b44..968238b 100644
--- a/include/elna/gcc/elna-generic.h
+++ b/include/elna/gcc/elna-generic.h
@@ -34,7 +34,7 @@ along with GCC; see the file COPYING3. If not see
namespace elna::gcc
{
std::deque> do_semantic_analysis(const char *path,
- std::unique_ptr& ast, std::shared_ptr info_table,
+ const std::unique_ptr& ast, std::shared_ptr info_table,
std::shared_ptr symbols, std::unordered_map& unresolved);
tree handle_symbol(const std::string& symbol_name, std::shared_ptr reference,
std::shared_ptr symbols, std::unordered_map& unresolved,