20 ssize_t output_disable_count = 0;
35 this->first = count == 0;
38 this->last = count == (size - 1);
50 void write(
std::string_view text) noexcept
52 if (output_disable_count == 0) {
70 hi_assert(new_size > 0);
71 hi_assert(new_size <= output_size());
72 output.resize(new_size);
75 void enable_output() noexcept
77 hi_assert(output_disable_count > 0);
78 output_disable_count--;
81 void disable_output() noexcept
83 output_disable_count++;
86 void loop_push(ssize_t count = -1, ssize_t size = -1) noexcept
91 void loop_pop() noexcept
93 hi_assert(ssize(loop_stack) > 0);
105 hi_assert(local_stack.
size() > 0);
110 [[nodiscard]]
bool has_locals() const noexcept
112 return local_stack.
size() > 0;
115 scope
const &locals()
const
117 hi_axiom(has_locals());
118 return local_stack.
back();
123 hi_axiom(has_locals());
124 return local_stack.
back();
127 [[nodiscard]] datum
const &loop_get(std::string_view name)
const
129 hi_axiom(name.size() > 0);
130 if (name.back() ==
'$') {
131 throw operation_error(std::format(
"Invalid loop variable '{}'", name));
134 std::string_view short_name = name.substr(1);
137 while (short_name[0] ==
'$') {
138 if (i == loop_stack.
crend() || holds_alternative<std::monostate>(i->count)) {
139 throw operation_error(std::format(
"Accessing loop variable {} while not in loop", name));
142 short_name = short_name.substr(1);
146 if (short_name ==
"i" || short_name ==
"count") {
148 }
else if (short_name ==
"first") {
150 }
else if (short_name ==
"size" || short_name ==
"length") {
151 if (holds_alternative<std::monostate>(i->size)) {
152 throw operation_error(std::format(
"Accessing loop variable {} only available in #for loops", name));
155 }
else if (short_name ==
"last") {
156 if (holds_alternative<std::monostate>(i->last)) {
157 throw operation_error(std::format(
"Accessing loop variable {} only available in #for loops", name));
161 throw operation_error(std::format(
"Unknown loop variable {}", name));
165 [[nodiscard]] datum
const &get(
std::string const &name)
const
167 hi_assert(name.
size() > 0);
169 if (name[0] ==
'$') {
170 return loop_get(name);
174 hilet i = locals().find(name);
175 if (i != locals().
end()) {
181 if (j != globals.
end()) {
185 throw operation_error(std::format(
"Could not find {} in local or global scope.", name));
190 hi_assert(name.
size() > 0);
193 hilet i = locals().find(name);
194 if (i != locals().
end()) {
200 if (j != globals.
end()) {
204 throw operation_error(std::format(
"Could not find {} in local or global scope.", name));
210 locals()[name] = std::forward<T>(value);
214 void set_global(
std::string const &name, T &&value)
216 globals[name] = std::forward<T>(value);
219 datum &set(
std::string const &name, datum
const &value)
222 return locals()[name] = value;
224 return globals[name] = value;