HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
skeleton_node.hpp
1// Copyright Take Vos 2020.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "../formula/formula.hpp"
8#include "../strings.hpp"
9#include "../algorithm.hpp"
10#include <memory>
11#include <string_view>
12#include <optional>
13
14namespace tt {
15
17 using statement_vector = typename std::vector<std::unique_ptr<skeleton_node>>;
18
19 parse_location location;
20
22 location(std::move(location)) {}
23
24 virtual ~skeleton_node() {}
25
28 [[nodiscard]] virtual bool append(std::unique_ptr<skeleton_node> x) noexcept { return false; }
29
32 [[nodiscard]] virtual bool should_left_align() const noexcept { return true; }
33
36 virtual void left_align() noexcept {}
37
38 [[nodiscard]] virtual bool found_elif(parse_location _location, std::unique_ptr<formula_node> expression) noexcept { return false; }
39 [[nodiscard]] virtual bool found_else(parse_location _location) noexcept { return false;}
40 [[nodiscard]] virtual bool found_while(parse_location _location, std::unique_ptr<formula_node> expression) noexcept { return false; }
41
42 virtual void post_process(formula_post_process_context &context) {}
43
52 [[nodiscard]] virtual datum evaluate(formula_evaluation_context &context) {
53 tt_no_default();
54 }
55
56 [[nodiscard]] std::string evaluate_output(formula_evaluation_context &context) {
57 auto tmp = evaluate(context);
58 if (tmp.is_break()) {
59 tt_error_info().set<"parse_location">(location);
60 throw operation_error("Found #break not inside a loop statement.");
61
62 } else if (tmp.is_continue()) {
63 tt_error_info().set<"parse_location">(location);
64 throw operation_error("Found #continue not inside a loop statement.");
65
66 } else if (tmp.is_undefined()) {
67 return std::move(context.output);
68
69 } else {
70 tt_error_info().set<"parse_location">(location);
71 throw operation_error("Found #return not inside a function.");
72 }
73 }
74
75 [[nodiscard]] std::string evaluate_output() {
76 auto context = formula_evaluation_context{};
77 return evaluate_output(context);
78 }
79
80 [[nodiscard]] virtual std::string string() const noexcept {
81 return "<skeleton_node>";
82 }
83
84 [[nodiscard]] friend std::string to_string(skeleton_node const &lhs) noexcept {
85 return lhs.string();
86 }
87
88 friend std::ostream &operator<<(std::ostream &lhs, skeleton_node const &rhs) {
89 return lhs << to_string(rhs);
90 }
91
92 static void append_child(statement_vector &children, std::unique_ptr<skeleton_node> new_child) {
93 if (std::ssize(children) > 0 && new_child->should_left_align()) {
94 children.back()->left_align();
95 }
96 children.push_back(std::move(new_child));
97 }
98
99 [[nodiscard]] static datum evaluate_formula_without_output(formula_evaluation_context &context, formula_node const &expression, parse_location const &location) {
100 try {
101 return expression.evaluate_without_output(context);
102
103 } catch (...) {
104 auto error_location = location;
105 if (ttlet evaluation_location = error_info::peek<parse_location, "parse_location">()) {
106 error_location += *evaluation_location;
107 }
108 error_info(true).set<"parse_location">(error_location);
109 throw;
110 }
111 }
112
113 [[nodiscard]] static datum evaluate_expression(formula_evaluation_context &context, formula_node const &expression, parse_location const &location) {
114 try {
115 return expression.evaluate(context);
116
117 } catch (...) {
118 auto error_location = location;
119 if (ttlet evaluation_location = error_info::peek<parse_location, "parse_location">()) {
120 error_location += *evaluation_location;
121 }
122 error_info(true).set<"parse_location">(error_location);
123 throw;
124 }
125 }
126
127 static void post_process_expression(formula_post_process_context &context, formula_node &expression, parse_location const &location) {
128 try {
129 return expression.post_process(context);
130
131 } catch (...) {
132 auto error_location = location;
133 if (ttlet evaluation_location = error_info::peek<parse_location, "parse_location">()) {
134 error_location += *evaluation_location;
135 }
136 error_info(true).set<"parse_location">(error_location);
137 throw;
138 }
139 }
140
141
142 [[nodiscard]] static datum evaluate_children(formula_evaluation_context &context, statement_vector const &children) {
143 for (ttlet &child: children) {
144 ttlet tmp = child->evaluate(context);
145 if (!tmp.is_undefined()) {
146 return tmp;
147 }
148 }
149 return {};
150 }
151};
152
153}
Exception thrown during execution of a dynamic operation.
Definition exception.hpp:37
Definition formula_evaluation_context.hpp:16
Definition parse_location.hpp:16
Definition skeleton_node.hpp:16
virtual datum evaluate(formula_evaluation_context &context)
Evaluate the template.
Definition skeleton_node.hpp:52
virtual void left_align() noexcept
Remove any trailing spaces or tabs after a new-line.
Definition skeleton_node.hpp:36
virtual bool append(std::unique_ptr< skeleton_node > x) noexcept
Append a template-piece to the current template.
Definition skeleton_node.hpp:28
virtual bool should_left_align() const noexcept
Should any spaces on the left side of a statement be removed?
Definition skeleton_node.hpp:32
T move(T... args)