aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/elna/boot/ast.h32
-rw-r--r--include/elna/boot/name_analysis.h98
-rw-r--r--include/elna/boot/type_check.h14
-rw-r--r--include/elna/gcc/elna-generic.h2
-rw-r--r--include/elna/gcc/elna-tree.h1
-rw-r--r--include/elna/gcc/elna1.h7
6 files changed, 80 insertions, 74 deletions
diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h
index 6080155..b50eb75 100644
--- a/include/elna/boot/ast.h
+++ b/include/elna/boot/ast.h
@@ -75,6 +75,7 @@ namespace elna::boot
class if_statement;
class import_declaration;
class while_statement;
+ class for_statement;
class case_statement;
class traits_expression;
class unit;
@@ -117,6 +118,7 @@ namespace elna::boot
virtual void visit(if_statement *) = 0;
virtual void visit(import_declaration *) = 0;
virtual void visit(while_statement *) = 0;
+ virtual void visit(for_statement *) = 0;
virtual void visit(defer_statement *) = 0;
virtual void visit(case_statement *) = 0;
virtual void visit(empty_statement *) = 0;
@@ -164,6 +166,7 @@ namespace elna::boot
[[noreturn]] void visit(if_statement *) override;
[[noreturn]] void visit(import_declaration *) override;
[[noreturn]] void visit(while_statement *) override;
+ [[noreturn]] void visit(for_statement *) override;
[[noreturn]] void visit(defer_statement *) override;
[[noreturn]] void visit(empty_statement *) override;
[[noreturn]] void visit(case_statement *) override;
@@ -210,6 +213,7 @@ namespace elna::boot
void visit(if_statement *) override;
void visit(import_declaration *) override;
void visit(while_statement *statement) override;
+ void visit(for_statement *statement) override;
void visit(defer_statement *statement) override;
void visit(empty_statement *) override;
void visit(case_statement *statement) override;
@@ -819,6 +823,34 @@ namespace elna::boot
~while_statement() override;
};
+ /**
+ * for-statement.
+ */
+ class for_statement : public statement
+ {
+ expression *m_initial_value;
+ expression *m_final_value;
+
+ public:
+ const identifier control_variable;
+ const std::vector<statement *> body;
+ expression *const step;
+ std::shared_ptr<symbol_table> symbols;
+
+ for_statement(const source_position position, identifier&& control_variable,
+ expression *initial_value, expression *final_value,
+ std::vector<statement *>&& body, expression *step = nullptr);
+ ~for_statement() override;
+
+ void accept(parser_visitor *visitor) override;
+
+ expression& initial_value();
+ expression& final_value();
+ };
+
+ /**
+ * Stores module-level definitions.
+ */
class unit : public node, public procedure_body
{
public:
diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h
index 5afe102..d18b813 100644
--- a/include/elna/boot/name_analysis.h
+++ b/include/elna/boot/name_analysis.h
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
#include <memory>
#include <map>
#include <optional>
+#include <variant>
#include "elna/boot/ast.h"
#include "elna/boot/result.h"
@@ -29,102 +30,60 @@ along with GCC; see the file COPYING3. If not see
namespace elna::boot
{
/**
- * Error declaring a symbol.
+ * Error declaring or using a symbol (undeclared, redefinition,
+ * local export).
*/
- class declaration_error : public error
+ class symbol_error : public error
{
public:
- enum class kind
- {
- undeclared,
- local_export
- };
+ struct undeclared { std::string name; };
+ struct local_export { std::string name; };
+ struct redefinition { std::string name; std::optional<source_position> original; };
+ using payload_type = std::variant<undeclared, local_export, redefinition>;
- declaration_error(const kind error_kind,
- const boot::identifier& identifier);
+ symbol_error(const source_position position, payload_type payload);
std::string what() const override;
+ std::optional<std::pair<std::string, source_position>> note() const override;
private:
- std::string identifier;
- kind error_kind;
+ payload_type payload;
};
/**
- * Attempted to redefine a name that is already in use in the
- * current scope.
+ * \c const qualifier used incorrectly — wrong position or
+ * duplicate.
*/
- class redefinition_error : public error
+ class const_qualifier_error : public error
{
- std::string identifier;
- std::optional<source_position> original;
-
public:
- redefinition_error(const boot::identifier& identifier,
- std::optional<source_position> original);
-
- std::string what() const override;
+ enum class kind { array_position, duplicate };
- std::optional<std::pair<std::string, source_position>> note() const override;
- };
-
- /**
- * Array size before \c const is not valid — only \c const [n]T is
- * accepted, not \c [n]const T.
- */
- class const_array_error : public error
- {
- public:
- explicit const_array_error(const source_position position);
+ const_qualifier_error(const source_position position, kind error_kind);
std::string what() const override;
- };
-
- /**
- * Direct \c const \c const T is not valid — write it once.
- * Merging through an alias is fine (C++ rule).
- */
- class double_const_error : public error
- {
- public:
- explicit double_const_error(const source_position position);
- std::string what() const override;
+ private:
+ kind error_kind;
};
/**
- * Access to a field that does not exist in the given type.
+ * Error accessing or defining a member of a record or enumeration.
*/
- class field_not_found_error : public error
+ class member_error : public error
{
- std::string field_name;
- type composite_type;
-
public:
- field_not_found_error(const identifier& field_name,
- type composite_type);
+ struct not_found { std::string name; type composite; };
+ struct duplicate { std::string name; type aggregate; std::optional<source_position> original; std::optional<std::string> base; };
+ using payload_type = std::variant<not_found, duplicate>;
- std::string what() const override;
- };
-
- /**
- * Field with the same name is already declared in this type.
- */
- class duplicate_member_error : public error
- {
- std::string member_name;
- type aggregate;
- std::optional<source_position> original;
- std::optional<std::string> base_name;
-
- public:
- duplicate_member_error(const boot::identifier& member_name,
- type aggregate, std::optional<source_position> original = std::nullopt,
- std::optional<std::string> base_name = std::nullopt);
+ member_error(const source_position position, payload_type payload);
std::string what() const override;
-
std::optional<std::pair<std::string, source_position>> note() const override;
+
+ private:
+ payload_type payload;
};
/**
@@ -200,6 +159,9 @@ namespace elna::boot
void visit(array_access_expression *expression) override;
void visit(field_access_expression *expression) override;
void visit(dereference_expression *expression) override;
+
+ void visit(for_statement *statement) override;
+
void visit(literal<std::int32_t> *literal) override;
void visit(literal<std::uint32_t> *literal) override;
void visit(literal<double> *literal) override;
diff --git a/include/elna/boot/type_check.h b/include/elna/boot/type_check.h
index 1680077..5fdc5cb 100644
--- a/include/elna/boot/type_check.h
+++ b/include/elna/boot/type_check.h
@@ -165,6 +165,19 @@ namespace elna::boot
};
/**
+ * FOR loop variable must be \c Int or \c Word.
+ */
+ class for_loop_type_error : public error
+ {
+ type actual;
+
+ public:
+ for_loop_type_error(const source_position position, type actual);
+
+ std::string what() const override;
+ };
+
+ /**
* Chain of responsibility for type compatibility checks.
*
* Populate \c ctx with pre-resolved types, then call \c run().
@@ -231,6 +244,7 @@ namespace elna::boot
void visit(record_type_expression *expression) override;
void visit(procedure_call *call) override;
void visit(case_statement *statement) override;
+ void visit(for_statement *statement) override;
void visit(record_constructor_expression *expression) override;
void visit(array_constructor_expression *expression) override;
void visit(slicing_expression *expression) override;
diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h
index 04b91fb..de95a7e 100644
--- a/include/elna/gcc/elna-generic.h
+++ b/include/elna/gcc/elna-generic.h
@@ -89,7 +89,7 @@ namespace elna::gcc
void visit(boot::slicing_expression *expression) override;
void visit(boot::assign_statement *statement) override;
void visit(boot::if_statement *statement) override;
- void visit(boot::import_declaration *) override;
+ void visit(boot::for_statement *statement) override;
void visit(boot::while_statement *statement) override;
void visit(boot::defer_statement *statement) override;
void visit(boot::empty_statement *) override;
diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h
index d826f25..1d48b00 100644
--- a/include/elna/gcc/elna-tree.h
+++ b/include/elna/gcc/elna-tree.h
@@ -66,7 +66,6 @@ namespace elna::gcc
tree find_field_by_name(location_t expression_location, tree type, const std::string& field_name);
tree build_static_array_type(tree type, const std::uint64_t size);
tree build_enumeration_type(const std::vector<std::string>& members);
- tree build_label_decl(const char *name, location_t loc);
tree extract_constant(tree expression);
diff --git a/include/elna/gcc/elna1.h b/include/elna/gcc/elna1.h
index b05cdf2..34cf091 100644
--- a/include/elna/gcc/elna1.h
+++ b/include/elna/gcc/elna1.h
@@ -73,16 +73,15 @@ struct GTY ((chain_next ("%h.level_chain"))) binding_level
// Defer statement coupled with statements following it.
vec<defer_scope, va_gc> *defers;
+
+ // Variables local to a block.
+ tree names;
};
struct GTY (()) language_function
{
- // Local variables and constants.
- tree names;
-
// Lexical scope.
struct binding_level *binding_level;
};
#define f_binding_level DECL_STRUCT_FUNCTION(current_function_decl)->language->binding_level
-#define f_names DECL_STRUCT_FUNCTION(current_function_decl)->language->names