20 ssize_t output_disable_count = 0;
32 count(), size(), first(), last()
36 this->first = count == 0;
39 this->last = count == (size - 1);
51 void write(std::string_view text)
noexcept {
52 if (output_disable_count == 0) {
61 return std::ssize(output);
68 tt_assert(new_size > 0);
70 output.resize(new_size);
73 void enable_output() noexcept {
74 tt_assert(output_disable_count > 0);
75 output_disable_count--;
78 void disable_output() noexcept {
79 output_disable_count++;
82 void loop_push(ssize_t count = -1, ssize_t size = -1) noexcept {
86 void loop_pop() noexcept {
87 tt_assert(std::ssize(loop_stack) > 0);
97 tt_assert(local_stack.
size() > 0);
102 [[nodiscard]]
bool has_locals() const noexcept {
103 return local_stack.
size() > 0;
106 scope
const& locals()
const {
107 tt_axiom(has_locals());
108 return local_stack.
back();
112 tt_axiom(has_locals());
113 return local_stack.
back();
116 [[nodiscard]] datum
const &loop_get(std::string_view name)
const {
117 tt_axiom(name.size() > 0);
118 if (name.back() ==
'$') {
119 throw operation_error(fmt::format(
"Invalid loop variable '{}'", name));
122 std::string_view short_name = name.substr(1);
125 while (short_name[0] ==
'$') {
126 if (i == loop_stack.
crend() || i->count.is_undefined()) {
127 throw operation_error(fmt::format(
"Accessing loop variable {} while not in loop", name));
130 short_name = short_name.substr(1);
134 if (short_name ==
"i" || short_name ==
"count") {
136 }
else if (short_name ==
"first") {
138 }
else if (short_name ==
"size" || short_name ==
"length") {
139 if (i->size.is_undefined()) {
140 throw operation_error(fmt::format(
"Accessing loop variable {} only available in #for loops", name));
143 }
else if (short_name ==
"last") {
144 if (i->last.is_undefined()) {
145 throw operation_error(fmt::format(
"Accessing loop variable {} only available in #for loops", name));
149 throw operation_error(fmt::format(
"Unknown loop variable {}", name));
153 [[nodiscard]] datum
const& get(
std::string const &name)
const {
154 tt_assert(name.
size() > 0);
156 if (name[0] ==
'$') {
157 return loop_get(name);
161 ttlet i = locals().
find(name);
162 if (i != locals().
end()) {
167 ttlet j = globals.
find(name);
168 if (j != globals.
end()) {
172 throw operation_error(fmt::format(
"Could not find {} in local or global scope.", name));
175 [[nodiscard]] datum &get(
std::string const &name) {
176 tt_assert(name.
size() > 0);
179 ttlet i = locals().
find(name);
180 if (i != locals().
end()) {
185 ttlet j = globals.
find(name);
186 if (j != globals.
end()) {
190 throw operation_error(fmt::format(
"Could not find {} in local or global scope.", name));
194 void set_local(
std::string const &name, T &&value) {
195 locals()[name] = std::forward<T>(value);
199 void set_global(
std::string const& name, T &&value) {
200 globals[name] = std::forward<T>(value);
203 datum &set(
std::string const &name, datum
const &value) {
205 return locals()[name] = value;
207 return globals[name] = value;