aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/elna/boot/ast.h21
-rw-r--r--include/elna/boot/driver.h2
-rw-r--r--include/elna/boot/evaluator.h28
-rw-r--r--include/elna/boot/name_analysis.h22
-rw-r--r--include/elna/boot/result.h46
-rw-r--r--include/elna/boot/symbol.h12
-rw-r--r--include/elna/boot/type_check.h8
-rw-r--r--include/elna/boot/validation.h20
8 files changed, 119 insertions, 40 deletions
diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h
index 996c58a..1ea17fb 100644
--- a/include/elna/boot/ast.h
+++ b/include/elna/boot/ast.h
@@ -17,7 +17,6 @@ along with GCC; see the file COPYING3. If not see
#pragma once
-#include <cstdint>
#include <memory>
#include <string>
#include <vector>
@@ -316,18 +315,19 @@ namespace elna::boot
class array_type_expression : public type_expression
{
type_expression *m_base;
+ expression *m_dimensions;
public:
- const std::uint32_t size;
array_type_expression(const source_position position,
- type_expression *base, const std::uint32_t size);
+ type_expression *base, expression *dimensions);
~array_type_expression() override;
void accept(parser_visitor *visitor) override;
array_type_expression *is_array() override;
- type_expression& base();
+ type_expression& base() const;
+ expression& dimensions() const;
};
class slice_type_expression : public type_expression
@@ -415,7 +415,7 @@ namespace elna::boot
{
public:
const identifier type_name;
- std::vector<field_initializer> field_initializers;
+ const std::vector<field_initializer> field_initializers;
record_constructor_expression(const source_position position,
identifier&& type_name,
@@ -426,17 +426,18 @@ namespace elna::boot
class array_constructor_expression : public expression
{
+ array_type_expression *m_element_type;
+
public:
- const std::uint32_t size;
- type_expression *const m_element_type;
- std::vector<expression *> elements;
+ const std::vector<expression *> elements;
array_constructor_expression(const source_position position,
- std::uint32_t size, type_expression *element_type,
- std::vector<expression *>&& elements);
+ array_type_expression *element_type, std::vector<expression *>&& elements);
void accept(parser_visitor *visitor) override;
array_constructor_expression *is_array_constructor() override;
+ array_type_expression& array_type() const;
+
~array_constructor_expression() override;
};
diff --git a/include/elna/boot/driver.h b/include/elna/boot/driver.h
index 34a8c99..60d40fb 100644
--- a/include/elna/boot/driver.h
+++ b/include/elna/boot/driver.h
@@ -35,7 +35,7 @@ namespace elna::boot
std::string what() const override;
};
- class driver : public error_container
+ class driver final : public error_container
{
public:
std::unique_ptr<unit> tree;
diff --git a/include/elna/boot/evaluator.h b/include/elna/boot/evaluator.h
index 84bd5ab..0d1a7c8 100644
--- a/include/elna/boot/evaluator.h
+++ b/include/elna/boot/evaluator.h
@@ -22,9 +22,35 @@ along with GCC; see the file COPYING3. If not see
#include <memory>
#include <optional>
+#include <variant>
namespace elna::boot
{
+ class non_constant_expression_error final : public error
+ {
+ public:
+ struct initializer
+ {
+ std::vector<identifier> identifiers;
+ };
+ struct case_label
+ {
+ };
+ struct array_dimensions
+ {
+ type array_type;
+ };
+ using payload_type = std::variant<initializer, case_label, array_dimensions>;
+
+ non_constant_expression_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;
+ };
+
std::optional<type_properties> get_type_properties(const type& subject, const target_info& target);
/**
@@ -53,7 +79,6 @@ namespace elna::boot
std::optional<constant_value> evaluate_named(named_expression& subject);
std::optional<constant_value> evaluate_array_access(array_access_expression& subject);
std::optional<constant_value> evaluate_field_access(field_access_expression& subject);
- std::optional<std::size_t> evaluate_index(expression& subject);
std::optional<constant_value> evaluate_slicing(slicing_expression& subject);
std::optional<constant_value> evaluate_unary(unary_expression& subject);
std::optional<constant_value> evaluate_binary(binary_expression& subject);
@@ -62,6 +87,7 @@ namespace elna::boot
std::optional<std::size_t> evaluate_traits_alignment(const type& subject);
public:
+ std::optional<std::size_t> evaluate_index(expression& subject);
std::optional<constant_value> evaluate_traits(traits_expression& subject);
explicit evaluator(symbol_bag& bag, const target_info& target);
diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h
index 996c357..f6663ea 100644
--- a/include/elna/boot/name_analysis.h
+++ b/include/elna/boot/name_analysis.h
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see
#include "elna/boot/ast.h"
#include "elna/boot/result.h"
#include "elna/boot/symbol.h"
+#include "elna/boot/evaluator.h"
#include <string>
#include <memory>
@@ -32,7 +33,7 @@ namespace elna::boot
* Error declaring or using a symbol (undeclared, redefinition,
* local export).
*/
- class declaration_error : public error
+ class declaration_error final : public error
{
public:
enum class kind { undeclared_type, undeclared_trait, undeclared_symbol, local_export };
@@ -56,7 +57,7 @@ namespace elna::boot
* \c const qualifier used incorrectly — wrong position or
* duplicate.
*/
- class const_qualifier_error : public error
+ class const_qualifier_error final : public error
{
public:
enum class kind { array_position, duplicate };
@@ -72,7 +73,7 @@ namespace elna::boot
/**
* Error accessing or defining a member of a record or enumeration.
*/
- class member_error : public error
+ class member_error final : public error
{
public:
enum class kind { not_found, field_on_type };
@@ -94,6 +95,17 @@ namespace elna::boot
payload_type payload;
};
+ class not_initialized_error final : public error
+ {
+ std::vector<identifier> identifiers;
+
+ public:
+ not_initialized_error(const source_position position, std::vector<identifier> identifiers);
+
+ std::string what() const override;
+ std::optional<std::pair<std::string, source_position>> note() const override;
+ };
+
/**
* Origin of a field in a composite type.
*/
@@ -109,8 +121,8 @@ namespace elna::boot
class name_analysis_visitor final : public walking_visitor, public error_container
{
type current_type;
-
symbol_bag bag;
+ evaluator constant_evaluator;
std::pair<procedure_type, std::vector<std::string>> build_procedure(
procedure_type_expression& expression);
@@ -125,7 +137,7 @@ namespace elna::boot
const type& element_type);
public:
- name_analysis_visitor(symbol_bag bag);
+ name_analysis_visitor(symbol_bag bag, const target_info& target);
void visit(array_type_expression *expression) override;
void visit(slice_type_expression *expression) override;
diff --git a/include/elna/boot/result.h b/include/elna/boot/result.h
index 36be8ee..3d01eb2 100644
--- a/include/elna/boot/result.h
+++ b/include/elna/boot/result.h
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include <string>
#include <deque>
#include <memory>
+#include <numeric>
#include <optional>
#include <utility>
#include <variant>
@@ -158,6 +159,8 @@ namespace elna::boot
const std::string& name() const;
const source_position& position() const;
+ std::string to_string() const;
+
bool operator==(const identifier& that) const;
bool operator==(std::string_view that) const;
@@ -181,6 +184,44 @@ namespace elna::boot
};
/**
+ * Checks whether the givn object can be converted to a string using
+ * the .to_string() method.
+ */
+ template<typename T>
+ concept has_to_string = requires(const T& stringable) {
+ { stringable.to_string() } -> std::convertible_to<std::string>;
+ };
+
+ /**
+ * Extracts identifiers (name and position) from identifier definitions and
+ * returns them in an allocated vector.
+ *
+ * \param identifiers Identifier definitions.
+ * \return Extracted identifiers.
+ */
+ std::vector<identifier> extract_identifiers(const std::vector<identifier_definition>& identifiers);
+
+ /**
+ * Joins an array of string-convertable objects (with a .t_string() method)
+ * into a delimiter separated list.
+ *
+ * \tparam T Array element type.
+ * \param identifiers Identifier array.
+ * \param delimiter List delimiter.
+ * \return Comma separted list.
+ */
+ template<has_to_string T>
+ std::string join(const std::vector<T>& identifiers, std::string_view delimiter = ", ")
+ {
+ return std::accumulate(std::next(identifiers.begin()), identifiers.end(),
+ identifiers.front().to_string(),
+ [delimiter](const std::string& accumulator, const T& next) -> std::string {
+ return accumulator + std::string(delimiter) + next.to_string();
+ }
+ );
+ }
+
+ /**
* Checks whether \p T is a signed, std::int*_t type.
*
* \tparam T The examined type.
@@ -271,6 +312,11 @@ namespace elna::boot
std::string to_string(const std::uint8_t base = 10U) const;
/**
+ * \return Whether the stored value is a negative integer.
+ */
+ bool is_negative() const;
+
+ /**
* Exports the stored value as a host \c std::ptrdiff_t.
*
* \return The converted value, or \c std::nullopt if out of range.
diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h
index 5000ab8..bd07a7e 100644
--- a/include/elna/boot/symbol.h
+++ b/include/elna/boot/symbol.h
@@ -494,11 +494,17 @@ namespace elna::boot
*/
void add_import(const symbol_bag& bag);
- private:
/**
- * Returns a reduced symbol table with exported symbols, computed lazily
- * and cached.
+ * Tells whether the current scope is the module global scope.
+ *
+ * The module scope is not the top-level scope, it's parent is the
+ * scope containing builtins.
+ *
+ * \return Whether the current scope is the global scope.
*/
+ bool is_global() const;
+
+ private:
std::shared_ptr<symbol_table> exported_symbols() const;
mutable std::shared_ptr<symbol_table> m_exported;
diff --git a/include/elna/boot/type_check.h b/include/elna/boot/type_check.h
index 82f0092..93e891a 100644
--- a/include/elna/boot/type_check.h
+++ b/include/elna/boot/type_check.h
@@ -30,7 +30,7 @@ namespace elna::boot
/**
* Expected type does not match the actual type of an expression.
*/
- class type_mismatch_error : public error
+ class type_mismatch_error final : public error
{
public:
struct expected_type
@@ -90,7 +90,7 @@ namespace elna::boot
/**
* Cyclic type declaration.
*/
- class cyclic_declaration_error : public error
+ class cyclic_declaration_error final : public error
{
std::vector<std::string> cycle;
@@ -104,7 +104,7 @@ namespace elna::boot
* Argument count in a procedure call or array constructor doesn't match
* the expected number of parameters or elements.
*/
- class argument_count_error : public error
+ class argument_count_error final : public error
{
std::size_t expected;
std::size_t actual;
@@ -119,7 +119,7 @@ namespace elna::boot
/**
* A trait invocation is invalid.
*/
- class trait_error : public error
+ class trait_error final : public error
{
public:
struct argument_count
diff --git a/include/elna/boot/validation.h b/include/elna/boot/validation.h
index c11a652..4a256fa 100644
--- a/include/elna/boot/validation.h
+++ b/include/elna/boot/validation.h
@@ -27,30 +27,20 @@ namespace elna::boot
/**
* Validation error.
*/
- class validation_error : public error
+ class validation_error final : public error
{
public:
- struct non_constant_initializer
- {
- std::vector<identifier> identifiers;
- };
struct duplicate_case
{
source_position first;
};
- struct non_constant_case_label
- {
- };
- using payload_type = std::variant<non_constant_initializer, duplicate_case, non_constant_case_label>;
+ using payload_type = std::variant<duplicate_case>;
validation_error(const source_position position, payload_type payload);
std::string what() const override;
std::optional<std::pair<std::string, source_position>> note() const override;
- static validation_error non_constant_initializer_error(const source_position position,
- const std::vector<identifier_definition>& identifiers);
-
private:
payload_type payload;
};
@@ -58,19 +48,17 @@ namespace elna::boot
/**
* Validates:
* - case label uniqueness
- * - Initializer constness.
*/
class validation_visitor final : public walking_visitor, public error_container
{
symbol_bag& bag;
- const target_info& target;
evaluator constant_evaluator;
public:
validation_visitor(symbol_bag& bag, const target_info& target);
- void visit(variable_declaration* declaration) override;
- void visit(procedure_declaration* declaration) override;
+ void visit(unit *unit) override;
+ void visit(procedure_declaration *declaration) override;
void visit(case_statement *statement) override;
};
}