22 ssize_t output_disable_count = 0;
33 loop_info(
ssize_t count,
ssize_t size) : count(), size(), first(), last()
37 this->first = count == 0;
40 this->last = count == (size - 1);
48 formula_evaluation_context() noexcept = default;
54 if (output_disable_count == 0) {
72 hi_assert(new_size > 0);
74 output.resize(new_size);
77 void enable_output() noexcept
79 hi_assert(output_disable_count > 0);
80 output_disable_count--;
83 void disable_output() noexcept
85 output_disable_count++;
93 void loop_pop() noexcept
95 hi_assert(ssize(loop_stack) > 0);
96 loop_stack.pop_back();
101 local_stack.emplace_back();
107 hi_assert(local_stack.size() > 0);
108 local_stack.pop_back();
112 [[nodiscard]]
bool has_locals() const noexcept
114 return local_stack.size() > 0;
117 scope
const &locals()
const
119 hi_assert(has_locals());
120 return local_stack.back();
125 hi_assert(has_locals());
126 return local_stack.back();
129 [[nodiscard]] datum
const &loop_get(std::string_view name)
const
131 hi_assert(name.size() > 0);
132 if (name.back() ==
'$') {
133 throw operation_error(std::format(
"Invalid loop variable '{}'", name));
136 std::string_view short_name = name.substr(1);
137 auto i = loop_stack.crbegin();
139 while (short_name[0] ==
'$') {
140 if (i == loop_stack.crend() || holds_alternative<std::monostate>(i->count)) {
141 throw operation_error(std::format(
"Accessing loop variable {} while not in loop", name));
144 short_name = short_name.substr(1);
148 if (short_name ==
"i" || short_name ==
"count") {
150 }
else if (short_name ==
"first") {
152 }
else if (short_name ==
"size" || short_name ==
"length") {
153 if (holds_alternative<std::monostate>(i->size)) {
154 throw operation_error(std::format(
"Accessing loop variable {} only available in #for loops", name));
157 }
else if (short_name ==
"last") {
158 if (holds_alternative<std::monostate>(i->last)) {
159 throw operation_error(std::format(
"Accessing loop variable {} only available in #for loops", name));
163 throw operation_error(std::format(
"Unknown loop variable {}", name));
167 [[nodiscard]] datum
const &get(std::string
const &name)
const
169 hi_assert(name.
size() > 0);
171 if (name[0] ==
'$') {
172 return loop_get(name);
176 hilet i = locals().find(name);
177 if (i != locals().
end()) {
182 hilet j = globals.find(name);
183 if (j != globals.end()) {
187 throw operation_error(std::format(
"Could not find {} in local or global scope.", name));
190 [[nodiscard]] datum &get(std::string
const &name)
192 hi_assert(name.
size() > 0);
195 hilet i = locals().find(name);
196 if (i != locals().
end()) {
201 hilet j = globals.find(name);
202 if (j != globals.end()) {
206 throw operation_error(std::format(
"Could not find {} in local or global scope.", name));
210 void set_local(std::string
const &name, T &&value)
216 void set_global(std::string
const &name, T &&value)
221 datum &set(std::string
const &name, datum
const &value)
224 return locals()[name] = value;
226 return globals[name] = value;