HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
skeleton_node.hpp
1// Copyright Take Vos 2020-2022.
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 hi::inline v1 {
15
17 using statement_vector = typename std::vector<std::unique_ptr<skeleton_node>>;
18
19 parse_location location;
20
21 skeleton_node(parse_location location) : location(std::move(location)) {}
22
23 virtual ~skeleton_node() {}
24
27 [[nodiscard]] virtual bool append(std::unique_ptr<skeleton_node> x) noexcept
28 {
29 return false;
30 }
31
34 [[nodiscard]] virtual bool should_left_align() const noexcept
35 {
36 return true;
37 }
38
41 virtual void left_align() noexcept {}
42
43 [[nodiscard]] virtual bool found_elif(parse_location _location, std::unique_ptr<formula_node> expression) noexcept
44 {
45 return false;
46 }
47 [[nodiscard]] virtual bool found_else(parse_location _location) noexcept
48 {
49 return false;
50 }
51 [[nodiscard]] virtual bool found_while(parse_location _location, std::unique_ptr<formula_node> expression) noexcept
52 {
53 return false;
54 }
55
56 virtual void post_process(formula_post_process_context &context) {}
57
66 [[nodiscard]] virtual datum evaluate(formula_evaluation_context &context)
67 {
69 }
70
71 [[nodiscard]] std::string evaluate_output(formula_evaluation_context &context)
72 {
73 auto tmp = evaluate(context);
74 if (tmp.is_break()) {
75 throw operation_error(std::format("{}: Found #break not inside a loop statement.", location));
76
77 } else if (tmp.is_continue()) {
78 throw operation_error(std::format("{}: Found #continue not inside a loop statement.", location));
79
80 } else if (tmp.is_undefined()) {
81 return std::move(context.output);
82
83 } else {
84 throw operation_error(std::format("{}: Found #return not inside a function.", location));
85 }
86 }
87
88 [[nodiscard]] std::string evaluate_output()
89 {
90 auto context = formula_evaluation_context{};
91 return evaluate_output(context);
92 }
93
94 [[nodiscard]] virtual std::string string() const noexcept
95 {
96 return "<skeleton_node>";
97 }
98
99 [[nodiscard]] friend std::string to_string(skeleton_node const &lhs) noexcept
100 {
101 return lhs.string();
102 }
103
104 friend std::ostream &operator<<(std::ostream &lhs, skeleton_node const &rhs)
105 {
106 return lhs << to_string(rhs);
107 }
108
109 static void append_child(statement_vector &children, std::unique_ptr<skeleton_node> new_child)
110 {
111 if (ssize(children) > 0 && new_child->should_left_align()) {
112 children.back()->left_align();
113 }
114 children.push_back(std::move(new_child));
115 }
116
117 [[nodiscard]] static datum evaluate_formula_without_output(
118 formula_evaluation_context &context,
119 formula_node const &expression,
120 parse_location const &location)
121 {
122 try {
123 return expression.evaluate_without_output(context);
124
125 } catch (std::exception const &e) {
126 throw operation_error(std::format("{}: Could not evaluate.\n{}", location, e.what()));
127 }
128 }
129
130 [[nodiscard]] static datum
131 evaluate_expression(formula_evaluation_context &context, formula_node const &expression, parse_location const &location)
132 {
133 try {
134 return expression.evaluate(context);
135
136 } catch (std::exception const &e) {
137 throw operation_error(std::format("{}: Could not evaluate expression.\n{}", location, e.what()));
138 }
139 }
140
141 static void
142 post_process_expression(formula_post_process_context &context, formula_node &expression, parse_location const &location)
143 {
144 try {
145 return expression.post_process(context);
146
147 } catch (std::exception const &e) {
148 throw operation_error(std::format("{}: Could not post-process expression.\n{}", location, e.what()));
149 }
150 }
151
152 [[nodiscard]] static datum evaluate_children(formula_evaluation_context &context, statement_vector const &children)
153 {
154 for (hilet &child : children) {
155 hilet tmp = child->evaluate(context);
156 if (!tmp.is_undefined()) {
157 return tmp;
158 }
159 }
160 return {};
161 }
162};
163
164} // namespace hi::inline v1
#define hi_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:279
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:13
A dynamic data type.
Definition datum.hpp:223
Definition formula_evaluation_context.hpp:15
Definition parse_location.hpp:18
Definition skeleton_node.hpp:16
virtual bool append(std::unique_ptr< skeleton_node > x) noexcept
Append a template-piece to the current template.
Definition skeleton_node.hpp:27
virtual datum evaluate(formula_evaluation_context &context)
Evaluate the template.
Definition skeleton_node.hpp:66
virtual void left_align() noexcept
Remove any trailing spaces or tabs after a new-line.
Definition skeleton_node.hpp:41
virtual bool should_left_align() const noexcept
Should any spaces on the left side of a statement be removed?
Definition skeleton_node.hpp:34
T move(T... args)
T to_string(T... args)
T what(T... args)