aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/elna/boot/ast.h36
-rw-r--r--include/elna/boot/name_analysis.h9
-rw-r--r--include/elna/boot/symbol.h24
-rw-r--r--include/elna/boot/validation.h2
-rw-r--r--include/elna/gcc/elna-generic.h2
5 files changed, 72 insertions, 1 deletions
diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h
index ffc57de..4eea412 100644
--- a/include/elna/boot/ast.h
+++ b/include/elna/boot/ast.h
@@ -148,6 +148,8 @@ namespace elna::boot
template<literal_type T>
class literal;
class defer_statement;
+ class block_statement;
+ class break_statement;
class empty_statement;
/**
@@ -171,6 +173,8 @@ namespace elna::boot
virtual void visit(repeat_statement *) = 0;
virtual void visit(for_statement *) = 0;
virtual void visit(defer_statement *) = 0;
+ virtual void visit(block_statement *) = 0;
+ virtual void visit(break_statement *) = 0;
virtual void visit(case_statement *) = 0;
virtual void visit(empty_statement *) = 0;
virtual void visit(unit *) = 0;
@@ -223,6 +227,8 @@ namespace elna::boot
[[noreturn]] void visit(repeat_statement *) override;
[[noreturn]] void visit(for_statement *) override;
[[noreturn]] void visit(defer_statement *) override;
+ [[noreturn]] void visit(block_statement *) override;
+ [[noreturn]] void visit(break_statement *) override;
[[noreturn]] void visit(empty_statement *) override;
[[noreturn]] void visit(case_statement *) override;
[[noreturn]] void visit(procedure_call *) override;
@@ -271,6 +277,8 @@ namespace elna::boot
void visit(repeat_statement *statement) override;
void visit(for_statement *statement) override;
void visit(defer_statement *statement) override;
+ void visit(block_statement *statement) override;
+ void visit(break_statement *) override;
void visit(empty_statement *) override;
void visit(case_statement *statement) override;
void visit(procedure_call *call) override;
@@ -1104,6 +1112,34 @@ namespace elna::boot
~defer_statement() override;
};
+ /**
+ * Named block a break-statement can jump out of.
+ */
+ class block_statement : public statement
+ {
+ public:
+ const identifier name;
+ const std::vector<statement *> statements;
+
+ block_statement(const source_position position, identifier&& name,
+ std::vector<statement *>&& statements);
+ void accept(parser_visitor *visitor) override;
+
+ ~block_statement() override;
+ };
+
+ /**
+ * Jump to the end of the named block.
+ */
+ class break_statement : public statement
+ {
+ public:
+ const identifier label;
+
+ break_statement(const source_position position, identifier&& label);
+ void accept(parser_visitor *visitor) override;
+ };
+
class empty_statement : public statement
{
public:
diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h
index eff122b..67cd713 100644
--- a/include/elna/boot/name_analysis.h
+++ b/include/elna/boot/name_analysis.h
@@ -43,7 +43,10 @@ namespace elna::boot
undeclared_type,
undeclared_trait,
undeclared_symbol,
- not_a_type
+ undeclared_label,
+ not_a_type,
+ not_a_label,
+ break_leaves_defer
};
struct redefinition
{
@@ -208,6 +211,8 @@ namespace elna::boot
symbol_bag& bag;
evaluator constant_evaluator;
std::filesystem::path module_file;
+ /// Number of defer bodies the visited statement stands in.
+ std::size_t defer_depth{ 0 };
resolving_visitor(symbol_bag& bag, const target_info& target,
const std::filesystem::path& module_path);
@@ -310,6 +315,8 @@ namespace elna::boot
void visit(while_statement *statement) override;
void visit(repeat_statement *statement) override;
void visit(defer_statement *statement) override;
+ void visit(block_statement *statement) override;
+ void visit(break_statement *statement) override;
void visit(empty_statement *) override;
void visit(case_statement *statement) override;
diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h
index 08292bc..5bbe2c6 100644
--- a/include/elna/boot/symbol.h
+++ b/include/elna/boot/symbol.h
@@ -271,6 +271,7 @@ namespace elna::boot
class type_info;
class procedure_info;
class variable_info;
+ class label_info;
class info : public std::enable_shared_from_this<info>
{
@@ -285,6 +286,7 @@ namespace elna::boot
virtual std::shared_ptr<type_info> is_type();
virtual std::shared_ptr<procedure_info> is_procedure();
virtual std::shared_ptr<variable_info> is_variable();
+ virtual std::shared_ptr<label_info> is_label();
};
/**
@@ -501,6 +503,28 @@ namespace elna::boot
std::shared_ptr<variable_info> is_variable() override;
};
+ /**
+ * Named block a break-statement can jump to.
+ */
+ class label_info : public info
+ {
+ public:
+ /**
+ * Constructs a label symbol information.
+ *
+ * \param defer_depth Number of defer bodies enclosing the block.
+ */
+ explicit label_info(std::size_t defer_depth);
+
+ std::shared_ptr<label_info> is_label() override;
+
+ /*
+ * A break may not leave the defer body it stands in, so a label
+ * declared outside that body is not a valid target.
+ */
+ const std::size_t defer_depth;
+ };
+
std::shared_ptr<symbol_table> builtin_symbol_table(const target_info& target);
/**
diff --git a/include/elna/boot/validation.h b/include/elna/boot/validation.h
index 8598ada..87e0b18 100644
--- a/include/elna/boot/validation.h
+++ b/include/elna/boot/validation.h
@@ -65,6 +65,8 @@ namespace elna::boot
void visit(repeat_statement *statement) override;
void visit(for_statement *statement) override;
void visit(defer_statement *statement) override;
+ void visit(block_statement *statement) override;
+ void visit(break_statement *) override;
void visit(empty_statement *) override;
void visit(procedure_call *) override;
};
diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h
index dde883a..b05a8f9 100644
--- a/include/elna/gcc/elna-generic.h
+++ b/include/elna/gcc/elna-generic.h
@@ -103,6 +103,8 @@ namespace elna::gcc
void visit(boot::for_statement *statement) override;
void visit(boot::while_statement *statement) override;
void visit(boot::defer_statement *statement) override;
+ void visit(boot::block_statement *statement) override;
+ void visit(boot::break_statement *statement) override;
void visit(boot::empty_statement *) override;
void visit(boot::case_statement *statement) override;
};