Project Alice
Loading...
Searching...
No Matches
fif.hpp
Go to the documentation of this file.
1#pragma once
2#include "unordered_dense.h"
3#include <vector>
4#include <optional>
5#include <variant>
6#include "stdint.h"
7#include <string>
8#include <string_view>
9#include <assert.h>
10#include <charconv>
11#include <span>
12#include <limits>
13
14#ifdef _WIN64
15#define USE_LLVM
16#else
17#endif
18
19#ifdef USE_LLVM
20
21#include "llvm-c/Core.h"
22#include "llvm-c/Types.h"
23#include "llvm-c/LLJIT.h"
24#include "llvm-c/LLJITUtils.h"
25#include "llvm-c/Analysis.h"
26#include "llvm-c/Error.h"
28#include "llvm-c/Orc.h"
29#include "llvm-c/OrcEE.h"
30#include "llvm-c/Linker.h"
31#include "llvm-c/lto.h"
32#include "llvm-c/Support.h"
33#include "llvm-c/Target.h"
36
37#ifdef _WIN64
38#define NATIVE_CC LLVMCallConv::LLVMWin64CallConv
39#else
40#define NATIVE_CC LLVMCallConv::LLVMX8664SysVCallConv
41#endif
42
43#endif
44namespace fif {
45
46enum class stack_type {
50};
51
53 using is_avalanching = void;
54 using is_transparent = void;
55
57 }
58 auto operator()(std::string_view sv) const noexcept -> uint64_t {
59 return ankerl::unordered_dense::detail::wyhash::hash(sv.data(), sv.size());
60 }
61 auto operator()(std::unique_ptr<char[]> const& str) const noexcept -> uint64_t {
62 return ankerl::unordered_dense::detail::wyhash::hash(str.get(), std::string_view{ str.get() }.size());
63 }
64};
66 using is_transparent = void;
67
68
70 }
71
72 bool operator()(std::unique_ptr<char[]> const& l, std::unique_ptr<char[]> const& r) const noexcept {
73 return std::string_view{ l.get() } == std::string_view{ r.get() };
74 }
75 bool operator()(std::unique_ptr<char[]> const& l, std::string_view r) const noexcept {
76 return std::string_view{ l.get() } == r;
77 }
78 bool operator()(std::string_view r, std::unique_ptr<char[]> const& l) const noexcept {
79 return std::string_view{ l.get() } == r;
80 }
81 bool operator()(std::unique_ptr<char[]> const& l, std::string const& r) const noexcept {
82 return std::string_view{ l.get() } == r;
83 }
84 bool operator()(std::string const& r, std::unique_ptr<char[]> const& l) const noexcept {
85 return std::string_view{ l.get() } == r;
86 }
87};
88
89#ifdef USE_LLVM
90#else
91#define LLVMValueRef void*
92#define LLVMBasicBlockRef void*
93#define LLVMTypeRef void*
94#endif
95
97protected:
98 std::vector<int32_t> main_types;
99 std::vector<int32_t> return_types;
100public:
101 size_t min_main_depth = 0;
103
104 void mark_used_from_main(size_t count) {
105 min_main_depth = std::min(std::max(main_types.size(), count) - count, min_main_depth);
106 }
107 void mark_used_from_return(size_t count) {
108 min_return_depth = std::min(std::max(return_types.size(), count) - count, min_return_depth);
109 }
110
111 state_stack() = default;
113 state_stack(const state_stack&) = default;
114 virtual ~state_stack() = default;
115
116 virtual void pop_main() = 0;
117 virtual void pop_return() = 0;
118 virtual int64_t main_data(size_t index) const = 0;
119 virtual int64_t return_data(size_t index) const = 0;
120 virtual LLVMValueRef main_ex(size_t index) const = 0;
121 virtual LLVMValueRef return_ex(size_t index) const = 0;
122 virtual int64_t main_data_back(size_t index) const = 0;
123 virtual int64_t return_data_back(size_t index) const = 0;
124 virtual LLVMValueRef main_ex_back(size_t index) const = 0;
125 virtual LLVMValueRef return_ex_back(size_t index) const = 0;
126 virtual void set_main_data(size_t index, int64_t value) = 0;
127 virtual void set_return_data(size_t index, int64_t value) = 0;
128 virtual void set_main_ex(size_t index, LLVMValueRef value) = 0;
129 virtual void set_return_ex(size_t index, LLVMValueRef value) = 0;
130 virtual void set_main_data_back(size_t index, int64_t value) = 0;
131 virtual void set_return_data_back(size_t index, int64_t value) = 0;
132 virtual void set_main_ex_back(size_t index, LLVMValueRef value) = 0;
133 virtual void set_return_ex_back(size_t index, LLVMValueRef value) = 0;
134 virtual stack_type get_type() const = 0;
135 virtual void move_into(state_stack&& other) = 0;
136 virtual void copy_into(state_stack const& other) = 0;
137 virtual void push_back_main(int32_t type, int64_t data, LLVMValueRef expr) = 0;
138 virtual void push_back_return(int32_t type, int64_t data, LLVMValueRef expr) = 0;
139 virtual std::unique_ptr< state_stack> copy() const = 0;
140 virtual void resize(size_t main_sz, size_t return_sz) = 0;
141
142 size_t main_size() const {
143 return main_types.size();
144 }
145 size_t return_size()const {
146 return return_types.size();
147 }
148 int32_t main_type(size_t index) const {
149 return std::abs(main_types[index]);
150 }
151 int32_t return_type(size_t index) const {
152 return std::abs(return_types[index]);
153 }
154 int32_t main_type_back(size_t index) const {
155 return std::abs(main_types[main_types.size() - (index + 1)]);
156 }
157 int32_t return_type_back(size_t index) const {
158 return std::abs(return_types[return_types.size() - (index + 1)]);
159 }
160 void set_main_type(size_t index, int32_t type) {
161 main_types[index] = type;
162 min_main_depth = std::min(min_main_depth, index);
163 }
164 void set_return_type(size_t index, int32_t type) {
165 return_types[index] = type;
166 min_return_depth = std::min(min_return_depth, index);
167 }
168 void set_main_type_back(size_t index, int32_t type) {
169 main_types[main_types.size() - (index + 1)] = type;
170 min_main_depth = std::min(min_main_depth, main_types.size() - (index + 1));
171 }
172 void set_return_type_back(size_t index, int32_t type) {
173 return_types[return_types.size() - (index + 1)] = type;
174 min_return_depth = std::min(min_return_depth, return_types.size() - (index + 1));
175 }
176};
177
178class llvm_stack : public state_stack {
179public:
180 std::vector<LLVMValueRef> main_exs;
181 std::vector<LLVMValueRef> return_exs;
182
183 virtual void pop_main() override {
184 if(main_exs.empty())
185 return;
186 main_exs.pop_back();
187 main_types.pop_back();
188 min_main_depth = std::min(min_main_depth, main_types.size());
189 }
190 virtual void pop_return() override {
191 if(return_exs.empty())
192 return;
193 return_exs.pop_back();
194 return_types.pop_back();
196 }
197 virtual void resize(size_t main_sz, size_t return_sz) override {
198 min_return_depth = std::min(min_return_depth, return_sz);
199 min_main_depth = std::min(min_main_depth, main_sz);
200 return_types.resize(return_sz);
201 return_exs.resize(return_sz);
202 main_types.resize(main_sz);
203 main_exs.resize(main_sz);
204 }
205 virtual int64_t main_data(size_t index) const override {
206 return 0;
207 }
208 virtual int64_t return_data(size_t index) const override {
209 return 0;
210 }
211 virtual LLVMValueRef main_ex(size_t index) const override {
212 return main_exs[index];
213 }
214 virtual LLVMValueRef return_ex(size_t index) const override {
215 return return_exs[index];
216 }
217 virtual int64_t main_data_back(size_t index)const override {
218 return 0;
219 }
220 virtual int64_t return_data_back(size_t index)const override {
221 return 0;
222 }
223 virtual LLVMValueRef main_ex_back(size_t index)const override {
224 return main_exs[main_exs.size() - (index + 1)];
225 }
226 virtual LLVMValueRef return_ex_back(size_t index) const override {
227 return return_exs[return_exs.size() - (index + 1)];
228 }
229 virtual void set_main_data(size_t index, int64_t value) override {
230 min_main_depth = std::min(min_main_depth, index);
231 }
232 virtual void set_return_data(size_t index, int64_t value)override {
233 min_return_depth = std::min(min_return_depth, index);
234 }
235 virtual void set_main_ex(size_t index, LLVMValueRef value) override {
236 main_exs[index] = value;
237 min_main_depth = std::min(min_main_depth, index);
238 }
239 virtual void set_return_ex(size_t index, LLVMValueRef value) override {
240 return_exs[index] = value;
241 min_return_depth = std::min(min_return_depth, index);
242 }
243 virtual void set_main_data_back(size_t index, int64_t value)override {
244 min_main_depth = std::min(min_main_depth, main_types.size() - (index + 1));
245 }
246 virtual void set_return_data_back(size_t index, int64_t value) override {
247 min_return_depth = std::min(min_return_depth, return_types.size() - (index + 1));
248 }
249 virtual void set_main_ex_back(size_t index, LLVMValueRef value)override {
250 main_exs[main_exs.size() - (index + 1)] = value;
251 min_main_depth = std::min(min_main_depth, main_types.size() - (index + 1));
252 }
253 virtual void set_return_ex_back(size_t index, LLVMValueRef value)override {
254 return_exs[return_exs.size() - (index + 1)] = value;
255 min_return_depth = std::min(min_return_depth, return_types.size() - (index + 1));
256 }
257 virtual stack_type get_type() const override {
259 }
260 virtual void move_into(state_stack&& other)override {
261 if(other.get_type() != stack_type::llvm_compiler)
262 std::abort();
263
264 llvm_stack&& o = static_cast<llvm_stack&&>(other);
265 main_exs = std::move(o.main_exs);
266 return_exs = std::move(o.return_exs);
267 main_types = std::move(o.main_types);
268 return_types = std::move(o.return_types);
271 }
272 virtual void copy_into(state_stack const& other)override {
273 if(other.get_type() != stack_type::llvm_compiler)
274 std::abort();
275
276 llvm_stack const& o = static_cast<llvm_stack const&>(other);
277 main_exs = o.main_exs;
283 }
284 virtual void push_back_main(int32_t type, int64_t data, LLVMValueRef expr)override {
285 main_exs.push_back(expr);
286 main_types.push_back(type);
287 }
288 virtual void push_back_return(int32_t type, int64_t data, LLVMValueRef expr)override {
289 return_exs.push_back(expr);
290 return_types.push_back(type);
291 }
292 virtual std::unique_ptr<state_stack> copy() const override {
293 auto temp_new = std::make_unique<llvm_stack>(*this);
294 temp_new->min_main_depth = main_types.size();
295 temp_new->min_return_depth = return_types.size();
296 return temp_new;
297 }
298};
299
300class type_stack : public state_stack {
301public:
302 virtual void pop_main() override {
303 if(main_types.empty())
304 return;
305 main_types.pop_back();
306 min_main_depth = std::min(min_main_depth, main_types.size());
307 }
308 virtual void pop_return()override {
309 if(return_types.empty())
310 return;
311 return_types.pop_back();
313 }
314 virtual void resize(size_t main_sz, size_t return_sz) override {
315 min_return_depth = std::min(min_return_depth, return_sz);
316 min_main_depth = std::min(min_main_depth, main_sz);
317 return_types.resize(return_sz);
318 main_types.resize(main_sz);
319 }
320 virtual int64_t main_data(size_t index) const override {
321 return 0;
322 }
323 virtual int64_t return_data(size_t index) const override {
324 return 0;
325 }
326 virtual LLVMValueRef main_ex(size_t index) const override {
327 return nullptr;
328 }
329 virtual LLVMValueRef return_ex(size_t index) const override {
330 return nullptr;
331 }
332 virtual int64_t main_data_back(size_t index)const override {
333 return 0;
334 }
335 virtual int64_t return_data_back(size_t index)const override {
336 return 0;
337 }
338 virtual LLVMValueRef main_ex_back(size_t index)const override {
339 return nullptr;
340 }
341 virtual LLVMValueRef return_ex_back(size_t index) const override {
342 return nullptr;
343 }
344 virtual stack_type get_type() const override {
346 }
347 virtual void set_main_data(size_t index, int64_t value)override {
348 min_main_depth = std::min(min_main_depth, index);
349 }
350 virtual void set_return_data(size_t index, int64_t value) override {
351 min_return_depth = std::min(min_return_depth, index);
352 }
353 virtual void set_main_ex(size_t index, LLVMValueRef value) override {
354 min_main_depth = std::min(min_main_depth, index);
355 }
356 virtual void set_return_ex(size_t index, LLVMValueRef value)override {
357 min_return_depth = std::min(min_return_depth, index);
358 }
359 virtual void set_main_data_back(size_t index, int64_t value) override {
360 min_main_depth = std::min(min_main_depth, main_types.size() - (index + 1));
361 }
362 virtual void set_return_data_back(size_t index, int64_t value) override {
363 min_return_depth = std::min(min_return_depth, return_types.size() - (index + 1));
364 }
365 virtual void set_main_ex_back(size_t index, LLVMValueRef value) override {
366 min_main_depth = std::min(min_main_depth, main_types.size() - (index + 1));
367 }
368 virtual void set_return_ex_back(size_t index, LLVMValueRef value) override {
369 min_return_depth = std::min(min_return_depth, return_types.size() - (index + 1));
370 }
371 virtual void move_into(state_stack&& other) override {
372 if(other.get_type() != stack_type::bytecode_compiler)
373 std::abort();
374
375 type_stack&& o = static_cast<type_stack&&>(other);
376 main_types = std::move(o.main_types);
377 return_types = std::move(o.return_types);
380 }
381 virtual void copy_into(state_stack const& other) override {
382 if(other.get_type() != stack_type::bytecode_compiler)
383 std::abort();
384
385 type_stack const& o = static_cast<type_stack const&>(other);
390 }
391 virtual void push_back_main(int32_t type, int64_t data, LLVMValueRef expr) override {
392 main_types.push_back(type);
393 }
394 virtual void push_back_return(int32_t type, int64_t data, LLVMValueRef expr) override {
395 return_types.push_back(type);
396 }
397 virtual std::unique_ptr<state_stack> copy() const override {
398 auto temp_new = std::make_unique<type_stack>(*this);
399 temp_new->min_main_depth = main_types.size();
400 temp_new->min_return_depth = return_types.size();
401 return temp_new;
402 }
403};
404
405
406class environment;
407struct type;
408
409using fif_call = int32_t * (*)(state_stack&, int32_t*, environment*);
410
412 std::vector<int32_t> compiled_bytecode;
414 int32_t stack_types_start = 0;
415 int32_t stack_types_count = 0;
417 bool being_compiled = false;
420};
421
424 int32_t stack_types_start = 0;
425 int32_t stack_types_count = 0;
426};
427
428using word_types = std::variant<interpreted_word_instance, compiled_word_instance>;
429
430struct word {
431 std::vector<int32_t> instances;
432 std::string source;
433 int32_t specialization_of = -1;
434 int32_t stack_types_start = 0;
435 int32_t stack_types_count = 0;
436 bool treat_as_base = false;
437 bool immediate = false;
438 bool being_typechecked = false;
439};
440
442 return r;
443}
444
445#ifdef USE_LLVM
446using llvm_zero_expr = LLVMValueRef (*)(LLVMContextRef, int32_t t, environment*);
447#endif
448using interpreter_zero_expr = int64_t(*)(int32_t t, environment*);
449using interpreted_new = int64_t(*)();
450
451struct type {
452 static constexpr uint32_t FLAG_REFCOUNTED = 0x00000001;
453 static constexpr uint32_t FLAG_SINGLE_MEMBER = 0x00000002;
454 static constexpr uint32_t FLAG_TEMPLATE = 0x00000004;
455
456#ifdef USE_LLVM
457 LLVMTypeRef llvm_type = nullptr;
458 llvm_zero_expr zero_constant = nullptr;
459#else
460 void* llvm_type = nullptr;
461 void* zero_constant = nullptr;
462#endif
464
465 int32_t type_slots = 0;
466 int32_t non_member_types = 0;
469
471
472 bool refcounted_type() const {
473 return (flags & FLAG_REFCOUNTED) != 0;
474 }
475 bool single_member_struct() const {
476 return (flags & FLAG_SINGLE_MEMBER) != 0;
477 }
478 bool is_struct_template() const {
479 return (flags & FLAG_TEMPLATE) != 0;
480 }
481};
482
483constexpr inline int32_t fif_i32 = 0;
484constexpr inline int32_t fif_f32 = 1;
485constexpr inline int32_t fif_bool = 2;
486constexpr inline int32_t fif_type = 3;
487constexpr inline int32_t fif_i64 = 4;
488constexpr inline int32_t fif_f64 = 5;
489constexpr inline int32_t fif_u32 = 6;
490constexpr inline int32_t fif_u64 = 7;
491constexpr inline int32_t fif_i16 = 8;
492constexpr inline int32_t fif_u16 = 9;
493constexpr inline int32_t fif_i8 = 10;
494constexpr inline int32_t fif_u8 = 11;
495constexpr inline int32_t fif_nil = 12;
496constexpr inline int32_t fif_ptr = 13;
497constexpr inline int32_t fif_opaque_ptr = 14;
498constexpr inline int32_t fif_struct = 15;
499
500class environment;
501
503public:
504 ankerl::unordered_dense::map<std::string, int32_t> words;
505 ankerl::unordered_dense::map<std::string, int32_t> types;
506 std::vector<word> word_array;
507 std::vector<type> type_array;
508 std::vector<word_types> all_instances;
509 std::vector<int32_t> all_compiled;
510 std::vector<int32_t> all_stack_types;
511
512#ifdef USE_LLVM
513 void ready_llvm_types(LLVMContextRef llvm_context) {
514 type_array[fif_i32].llvm_type = LLVMInt32TypeInContext(llvm_context);
515 type_array[fif_i32].zero_constant = +[](LLVMContextRef c, int32_t t, environment*) {
516 return LLVMConstInt(LLVMInt32TypeInContext(c), 0, true);
517 };
518 type_array[fif_type].llvm_type = LLVMInt32TypeInContext(llvm_context);
519 type_array[fif_type].zero_constant = +[](LLVMContextRef c, int32_t t, environment*) {
520 return LLVMConstInt(LLVMInt32TypeInContext(c), 0, true);
521 };
522 type_array[fif_f32].llvm_type = LLVMFloatTypeInContext(llvm_context);
523 type_array[fif_f32].zero_constant = +[](LLVMContextRef c, int32_t t, environment*) {
525 };
526 type_array[fif_i64].llvm_type = LLVMInt64TypeInContext(llvm_context);
527 type_array[fif_i64].zero_constant = +[](LLVMContextRef c, int32_t t, environment*) {
528 return LLVMConstInt(LLVMInt64TypeInContext(c), 0, true);
529 };
530 type_array[fif_f64].llvm_type = LLVMDoubleTypeInContext(llvm_context);
531 type_array[fif_f64].zero_constant = +[](LLVMContextRef c, int32_t t, environment*) {
533 };
534 type_array[fif_bool].llvm_type = LLVMInt1TypeInContext(llvm_context);
535 type_array[fif_bool].zero_constant = +[](LLVMContextRef c, int32_t t, environment*) {
536 return LLVMConstInt(LLVMInt1TypeInContext(c), 0, true);
537 };
538 type_array[fif_u32].llvm_type = LLVMInt32TypeInContext(llvm_context);
539 type_array[fif_u32].zero_constant = +[](LLVMContextRef c, int32_t t, environment*) {
540 return LLVMConstInt(LLVMInt32TypeInContext(c), 0, false);
541 };
542 type_array[fif_u64].llvm_type = LLVMInt64TypeInContext(llvm_context);
543 type_array[fif_u64].zero_constant = +[](LLVMContextRef c, int32_t t, environment*) {
544 return LLVMConstInt(LLVMInt64TypeInContext(c), 0, false);
545 };
546 type_array[fif_u16].llvm_type = LLVMInt16TypeInContext(llvm_context);
547 type_array[fif_u16].zero_constant = +[](LLVMContextRef c, int32_t t, environment*) {
548 return LLVMConstInt(LLVMInt16TypeInContext(c), 0, false);
549 };
550 type_array[fif_u8].llvm_type = LLVMInt8TypeInContext(llvm_context);
551 type_array[fif_u8].zero_constant = +[](LLVMContextRef c, int32_t t, environment*) {
552 return LLVMConstInt(LLVMInt8TypeInContext(c), 0, false);
553 };
554 type_array[fif_i16].llvm_type = LLVMInt16TypeInContext(llvm_context);
555 type_array[fif_i16].zero_constant = +[](LLVMContextRef c, int32_t t, environment*) {
556 return LLVMConstInt(LLVMInt16TypeInContext(c), 0, true);
557 };
558 type_array[fif_i8].llvm_type = LLVMInt8TypeInContext(llvm_context);
559 type_array[fif_i8].zero_constant = +[](LLVMContextRef c, int32_t t, environment*) {
560 return LLVMConstInt(LLVMInt8TypeInContext(c), 0, true);
561 };
562 type_array[fif_nil].llvm_type = LLVMVoidTypeInContext(llvm_context);
563 type_array[fif_nil].zero_constant = +[](LLVMContextRef c, int32_t t, environment*) {
565 };
566 type_array[fif_ptr].llvm_type = LLVMPointerTypeInContext(llvm_context, 0);
567 type_array[fif_ptr].zero_constant = +[](LLVMContextRef c, int32_t t, environment*) {
569 };
570 type_array[fif_opaque_ptr].llvm_type = LLVMPointerTypeInContext(llvm_context, 0);
571 type_array[fif_opaque_ptr].zero_constant = +[](LLVMContextRef c, int32_t t, environment*) {
573 };
574 type_array[fif_struct].llvm_type = LLVMVoidTypeInContext(llvm_context);
575 type_array[fif_struct].zero_constant = +[](LLVMContextRef c, int32_t t, environment*) {
577 };
578 }
579#endif
581 types.insert_or_assign(std::string("i32"), fif_i32);
582 type_array.push_back(type{ nullptr, nullptr, nullptr, 0, 0, 0, 0 });
583 types.insert_or_assign(std::string("f32"), fif_f32);
584 type_array.push_back(type{ nullptr, nullptr, nullptr, 0, 0, 0, 0 });
585 types.insert_or_assign(std::string("bool"), fif_bool);
586 type_array.push_back(type{ nullptr, nullptr, nullptr, 0, 0, 0, 0 });
587 types.insert_or_assign(std::string("type"), fif_type);
588 type_array.push_back(type{ nullptr, nullptr, nullptr, 0, 0, 0, 0 });
589 types.insert_or_assign(std::string("i64"), fif_i64);
590 type_array.push_back(type{ nullptr, nullptr, nullptr, 0, 0, 0, 0 });
591 types.insert_or_assign(std::string("f64"), fif_f64);
592 type_array.push_back(type{ nullptr, nullptr, nullptr, 0, 0, 0, 0 });
593 types.insert_or_assign(std::string("u32"), fif_u32);
594 type_array.push_back(type{ nullptr, nullptr, nullptr, 0, 0, 0, 0 });
595 types.insert_or_assign(std::string("u64"), fif_u64);
596 type_array.push_back(type{ nullptr, nullptr, nullptr, 0, 0, 0, 0 });
597 types.insert_or_assign(std::string("i16"), fif_i16);
598 type_array.push_back(type{ nullptr, nullptr, nullptr, 0, 0, 0, 0 });
599 types.insert_or_assign(std::string("u16"), fif_u16);
600 type_array.push_back(type{ nullptr, nullptr, nullptr, 0, 0, 0, 0 });
601 types.insert_or_assign(std::string("i8"), fif_i8);
602 type_array.push_back(type{ nullptr, nullptr, nullptr, 0, 0, 0, 0 });
603 types.insert_or_assign(std::string("u8"), fif_u8);
604 type_array.push_back(type{ nullptr, nullptr, nullptr, 0, 0, 0, 0 });
605 types.insert_or_assign(std::string("nil"), fif_nil);
606 type_array.push_back(type{ nullptr, nullptr, nullptr, 0, 0, 0, 0 });
607 types.insert_or_assign(std::string("ptr"), fif_ptr);
608 type_array.push_back(type{ nullptr, nullptr, nullptr, 1, 0, 0, 0 });
609 types.insert_or_assign(std::string("opaque_ptr"), fif_nil);
610 type_array.push_back(type{ nullptr, nullptr, nullptr, 0, 0, 0, 0 });
611 types.insert_or_assign(std::string("struct"), fif_struct);
612 type_array.push_back(type{ nullptr, nullptr, nullptr, 0, 0, 0, 0 });
613 }
614};
615
616
619};
620
621class compiler_state;
622
626 int32_t stack_consumed = 0;
627 int32_t rstack_consumed = 0;
628};
629
630struct var_data {
631 int64_t data; // only in interpreter mode -- first so that we can treat the address as the data addres
632 LLVMValueRef alloc; // only in llvm mode
633 int32_t type;
634};
635struct let_data {
636 int64_t data; // only in interpreter mode
637 LLVMValueRef expression; // only in llvm mode
638 int32_t type;
639};
640
642protected:
644public:
646
647 virtual ~opaque_compiler_data() = default;
650 }
652 return parent ? parent->llvm_function() : nullptr;
653 }
655 return parent ? parent->llvm_block() : nullptr;
656 }
657 virtual int32_t word_id() {
658 return parent ? parent->word_id() : -1;
659 }
660 virtual int32_t instance_id() {
661 return parent ? parent->instance_id() : -1;
662 }
663 virtual std::vector<int32_t>* bytecode_compilation_progress() {
664 return parent ? parent->bytecode_compilation_progress() : nullptr;
665 }
666 virtual ankerl::unordered_dense::map<uint64_t, typecheck_3_record>* typecheck_record() {
667 return parent ? parent->typecheck_record() : nullptr;
668 }
670 return parent ? parent->working_state() : nullptr;
671 }
672 virtual void set_working_state(std::unique_ptr<state_stack> p) {
673 if(parent)
674 parent->set_working_state(std::move(p));
675 }
676 virtual bool finish(environment& env) {
677 return true;
678 }
679 virtual var_data* get_var(std::string const& name) {
680 return parent ? parent->get_var(name) : nullptr;
681 }
682 virtual let_data* get_let(std::string const& name) {
683 return parent ? parent->get_let(name) : nullptr;
684 }
685 virtual var_data* create_var(std::string const& name, int32_t type) {
686 return parent ? parent->create_var(name, type) : nullptr;
687 }
688 virtual let_data* create_let(std::string const& name, int32_t type, int64_t data, LLVMValueRef expression) {
689 return parent ? parent->create_let(name, type, data, expression) : nullptr;
690 }
691 virtual std::vector<int32_t>* type_substitutions() {
692 return parent ? parent->type_substitutions() : nullptr;
693 }
694};
695
696
698public:
699 std::unique_ptr<opaque_compiler_data> data;
700};
701
702enum class fif_mode {
703 interpreting = 0,
705 compiling_llvm = 2,
706 terminated = 3,
707 error = 4,
714};
715
718}
722}
725}
729 return m;
730}
738 return m;
739}
741 std::string name;
742 void* ptr = nullptr;
743};
745public:
746 ankerl::unordered_dense::set<std::unique_ptr<char[]>, indirect_string_hash, indirect_string_eq> string_constants;
747 std::vector<LLVMValueRef> exported_functions;
748 std::vector<import_item> imported_functions;
749#ifdef USE_LLVM
750 LLVMOrcThreadSafeContextRef llvm_ts_context = nullptr;
751 LLVMContextRef llvm_context = nullptr;
752 LLVMModuleRef llvm_module = nullptr;
753 LLVMBuilderRef llvm_builder = nullptr;
754 LLVMTargetRef llvm_target = nullptr;
755 LLVMTargetMachineRef llvm_target_machine = nullptr;
756 LLVMTargetDataRef llvm_target_data = nullptr;
757 LLVMOrcLLJITRef llvm_jit = nullptr;
758 char* llvm_target_triple = nullptr;
759 char* llvm_target_cpu = nullptr;
760 char* llvm_target_cpu_features = nullptr;
761#endif
763
764 std::vector<std::unique_ptr<opaque_compiler_data>> compiler_stack;
765 std::vector<std::string_view> source_stack;
766
768 std::function<void(std::string_view)> report_error = [](std::string_view) { std::abort(); };
769
770 environment();
772#ifdef USE_LLVM
773 LLVMDisposeMessage(llvm_target_triple);
774 LLVMDisposeMessage(llvm_target_cpu);
775 LLVMDisposeMessage(llvm_target_cpu_features);
776
777 if(llvm_jit)
778 LLVMOrcDisposeLLJIT(llvm_jit);
779 if(llvm_target_data)
780 LLVMDisposeTargetData(llvm_target_data);
781 if(llvm_target_machine)
782 LLVMDisposeTargetMachine(llvm_target_machine);
783 if(llvm_builder)
784 LLVMDisposeBuilder(llvm_builder);
785 if(llvm_module)
786 LLVMDisposeModule(llvm_module);
787 if(llvm_ts_context)
788 LLVMOrcDisposeThreadSafeContext(llvm_ts_context);
789#endif
790 }
791
792 std::string_view get_string_constant(std::string_view data) {
793 if(auto it = string_constants.find(data); it != string_constants.end()) {
794 return std::string_view{ it->get() };
795 }
796 std::unique_ptr<char[]> temp = std::unique_ptr<char[]>(new char[data.length() + 1 ]);
797 memcpy(temp.get(), data.data(), data.length());
798 temp.get()[data.length()] = 0;
799 auto data_ptr = temp.get();
800 string_constants.insert(std::move(temp));
801 return std::string_view{ data_ptr };
802 }
803};
804
806public:
807 ankerl::unordered_dense::map<std::string, std::unique_ptr<var_data>> global_vars;
808 ankerl::unordered_dense::map<std::string, std::unique_ptr<let_data>> global_lets;
811 }
812
813 virtual control_structure get_type() override {
815 }
816
817 var_data* get_global_var(std::string const& name) {
818 if(auto it = global_vars.find(name); it != global_vars.end()) {
819 return it->second.get();
820 }
821 return nullptr;
822 }
823 var_data* create_global_var(std::string const& name, int32_t type) {
824 if(auto it = global_vars.find(name); it != global_vars.end()) {
825 if(it->second->type == type)
826 return it->second.get();
827 else
828 return nullptr;
829 }
830 auto added = global_vars.insert_or_assign(name, std::make_unique<var_data>());
831 added.first->second->type = type;
832 added.first->second->data = 0;
833#ifdef USE_LLVM
834 added.first->second->alloc = LLVMAddGlobal(env.llvm_module, env.dict.type_array[type].llvm_type, name.c_str());
835 LLVMSetInitializer(added.first->second->alloc, env.dict.type_array[type].zero_constant(env.llvm_context, type, &env));
836#endif
837 return added.first->second.get();
838 }
839 let_data* get_global_let(std::string const& name) {
840 if(auto it = global_lets.find(name); it != global_lets.end()) {
841 return it->second.get();
842 }
843 return nullptr;
844 }
845 let_data* create_global_let(std::string const& name, int32_t type, int64_t data, LLVMValueRef expression) {
846 if(auto it = global_lets.find(name); it != global_lets.end()) {
847 return nullptr;
848 }
849 auto added = global_lets.insert_or_assign(name, std::make_unique<let_data>());
850 added.first->second->type = type;
851 added.first->second->data = data;
852 added.first->second->expression = expression;
853 if(auto it = global_lets.find(name); it != global_lets.end()) {
854 return it->second.get();
855 }
856 return nullptr;
857 }
858};
859
861#ifdef USE_LLVM
862 llvm_ts_context = LLVMOrcCreateNewThreadSafeContext();
863 llvm_context = LLVMOrcThreadSafeContextGetContext(llvm_ts_context);
864 llvm_module = LLVMModuleCreateWithNameInContext("module_main", llvm_context);
865 llvm_builder = LLVMCreateBuilderInContext(llvm_context);
866
867 LLVMInitializeNativeTarget();
868 LLVMInitializeNativeAsmPrinter();
869
870 llvm_target = LLVMGetFirstTarget();
871 llvm_target_triple = LLVMGetDefaultTargetTriple();
872 llvm_target_cpu = LLVMGetHostCPUName();
873 llvm_target_cpu_features = LLVMGetHostCPUFeatures();
874
875 llvm_target_machine = LLVMCreateTargetMachine(llvm_target, llvm_target_triple, llvm_target_cpu, llvm_target_cpu_features, LLVMCodeGenOptLevel::LLVMCodeGenLevelAggressive, LLVMRelocMode::LLVMRelocDefault, LLVMCodeModel::LLVMCodeModelJITDefault);
876
877 LLVMSetTarget(llvm_module, llvm_target_triple);
878 llvm_target_data = LLVMCreateTargetDataLayout(llvm_target_machine);
879 LLVMSetModuleDataLayout(llvm_module, llvm_target_data);
880
881 dict.ready_llvm_types(llvm_context);
882#endif
883
884 compiler_stack.push_back(std::make_unique<compiler_globals_layer>(nullptr, *this));
885}
886
888public:
889 std::vector<int64_t> main_datas;
890 std::vector<int64_t> return_datas;
891
893
894 virtual void pop_main() override {
895 if(main_datas.empty())
896 return;
897
898 main_datas.pop_back();
899 main_types.pop_back();
900
901 min_main_depth = std::min(min_main_depth, main_types.size());
902 }
903 virtual void pop_return() override {
904 if(return_datas.empty())
905 return;
906
907 return_datas.pop_back();
908 return_types.pop_back();
909
911 }
912 virtual void resize(size_t main_sz, size_t return_sz) override {
913 min_return_depth = std::min(min_return_depth, return_sz);
914 min_main_depth = std::min(min_main_depth, main_sz);
915
916 return_types.resize(return_sz);
917 return_datas.resize(return_sz);
918 main_types.resize(main_sz);
919 main_datas.resize(main_sz);
920 }
921 virtual int64_t main_data(size_t index) const override {
922 return main_datas[index];
923 }
924 virtual int64_t return_data(size_t index) const override {
925 return return_datas[index];
926 }
927 virtual LLVMValueRef main_ex(size_t index) const override {
928 return nullptr;
929 }
930 virtual LLVMValueRef return_ex(size_t index) const override {
931 return nullptr;
932 }
933 virtual int64_t main_data_back(size_t index)const override {
934 return main_datas[main_datas.size() - (index + 1)];
935 }
936 virtual int64_t return_data_back(size_t index)const override {
937 return return_datas[return_datas.size() - (index + 1)];
938 }
939 virtual LLVMValueRef main_ex_back(size_t index)const override {
940 return nullptr;
941 }
942 virtual LLVMValueRef return_ex_back(size_t index) const override {
943 return nullptr;
944 }
945 virtual void set_main_data(size_t index, int64_t value) override {
946 main_datas[index] = value;
947 min_main_depth = std::min(min_main_depth, index);
948 }
949 virtual void set_return_data(size_t index, int64_t value) override {
950 return_datas[index] = value;
951 min_return_depth = std::min(min_return_depth, index);
952 }
953 virtual void set_main_ex(size_t index, LLVMValueRef value)override {
954 min_main_depth = std::min(min_main_depth, index);
955 }
956 virtual void set_return_ex(size_t index, LLVMValueRef value)override {
957 min_return_depth = std::min(min_return_depth, index);
958 }
959 virtual void set_main_data_back(size_t index, int64_t value) override {
960 main_datas[main_datas.size() - (index + 1)] = value;
961 min_main_depth = std::min(min_main_depth, main_datas.size() - (index + 1));
962 }
963 virtual void set_return_data_back(size_t index, int64_t value) override {
964 return_datas[return_datas.size() - (index + 1)] = value;
965 min_return_depth = std::min(min_return_depth, return_datas.size() - (index + 1));
966 }
967 virtual void set_main_ex_back(size_t index, LLVMValueRef value) override {
968 min_main_depth = std::min(min_main_depth, main_datas.size() - (index + 1));
969 }
970 virtual void set_return_ex_back(size_t index, LLVMValueRef value) override {
971 min_return_depth = std::min(min_return_depth, return_datas.size() - (index + 1));
972 }
973 virtual stack_type get_type() const override {
975 }
976 virtual void move_into(state_stack&& other) override {
977 if(other.get_type() != stack_type::interpreter_stack)
978 std::abort();
979
980 interpreter_stack&& o = static_cast<interpreter_stack&&>(other);
981 main_datas = std::move(o.main_datas);
982 return_datas = std::move(o.return_datas);
983 main_types = std::move(o.main_types);
984 return_types = std::move(o.return_types);
987 o.main_datas.clear();
988 o.return_datas.clear();
989 o.main_types.clear();
990 o.return_types.clear();
991 }
992 virtual void copy_into(state_stack const& other) override {
993 if(other.get_type() != stack_type::interpreter_stack)
994 std::abort();
995 interpreter_stack const& o = static_cast<interpreter_stack const&>(other);
1002 }
1003 virtual void push_back_main(int32_t type, int64_t data, LLVMValueRef expr) override {
1004 main_datas.push_back(data);
1005 main_types.push_back(type);
1006 }
1007 virtual void push_back_return(int32_t type, int64_t data, LLVMValueRef expr) override {
1008 return_datas.push_back(data);
1009 return_types.push_back(type);
1010 }
1011 virtual std::unique_ptr<state_stack> copy() const override {
1012 auto temp_new = std::make_unique< interpreter_stack>(*this);
1013 temp_new->min_main_depth = main_types.size();
1014 temp_new->min_return_depth = return_types.size();
1015 return temp_new;
1016 }
1017};
1018
1019inline std::string word_name_from_id(int32_t w, environment const& e) {
1020 for(auto& p : e.dict.words) {
1021 if(p.second == w)
1022 return p.first;
1023 }
1024 return "@unknown (" + std::to_string(w) + ")";
1025}
1026
1027inline int32_t* illegal_interpretation(state_stack& s, int32_t* p, environment* e) {
1028 e->report_error("attempted to perform an illegal operation under interpretation");
1029 e->mode = fif_mode::error;
1030 return nullptr;
1031}
1032
1034 bool matched = false;
1035 int32_t stack_consumed = 0;
1037};
1039 int32_t type = 0;
1041};
1042
1043
1044inline bool is_positive_integer(char const* start, char const* end) {
1045 if(start == end)
1046 return false;
1047 while(start < end) {
1048 if(!isdigit(*start))
1049 return false;
1050 ++start;
1051 }
1052 return true;
1053}
1054
1055inline bool is_integer(char const* start, char const* end) {
1056 if(start == end)
1057 return false;
1058 if(*start == '-')
1059 return is_positive_integer(start + 1, end);
1060 else
1061 return is_positive_integer(start, end);
1062}
1063
1064inline bool is_positive_fp(char const* start, char const* end) {
1065 auto const decimal = std::find(start, end, '.');
1066 if(decimal == end) {
1067 return is_positive_integer(start, end);
1068 } else if(decimal == start) {
1069 return is_positive_integer(decimal + 1, end);
1070 } else {
1071 return is_positive_integer(start, decimal) && (decimal + 1 == end || is_positive_integer(decimal + 1, end));
1072 }
1073}
1074
1075inline bool is_fp(char const* start, char const* end) {
1076 if(start == end)
1077 return false;
1078 if(*start == '-')
1079 return is_positive_fp(start + 1, end);
1080 else
1081 return is_positive_fp(start, end);
1082}
1083
1084inline double pow_10(int n) {
1085 static double const e[] = {// 1e-0...1e308: 309 * 8 bytes = 2472 bytes
1086 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18,
1087 1e+19, 1e+20, 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35,
1088 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52,
1089 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69,
1090 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86,
1091 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, 1e+101, 1e+102, 1e+103,
1092 1e+104, 1e+105, 1e+106, 1e+107, 1e+108, 1e+109, 1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116, 1e+117, 1e+118,
1093 1e+119, 1e+120, 1e+121, 1e+122, 1e+123, 1e+124, 1e+125, 1e+126, 1e+127, 1e+128, 1e+129, 1e+130, 1e+131, 1e+132, 1e+133,
1094 1e+134, 1e+135, 1e+136, 1e+137, 1e+138, 1e+139, 1e+140, 1e+141, 1e+142, 1e+143, 1e+144, 1e+145, 1e+146, 1e+147, 1e+148,
1095 1e+149, 1e+150, 1e+151, 1e+152, 1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159, 1e+160, 1e+161, 1e+162, 1e+163,
1096 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169, 1e+170, 1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178,
1097 1e+179, 1e+180, 1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188, 1e+189, 1e+190, 1e+191, 1e+192, 1e+193,
1098 1e+194, 1e+195, 1e+196, 1e+197, 1e+198, 1e+199, 1e+200, 1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206, 1e+207, 1e+208,
1099 1e+209, 1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215, 1e+216, 1e+217, 1e+218, 1e+219, 1e+220, 1e+221, 1e+222, 1e+223,
1100 1e+224, 1e+225, 1e+226, 1e+227, 1e+228, 1e+229, 1e+230, 1e+231, 1e+232, 1e+233, 1e+234, 1e+235, 1e+236, 1e+237, 1e+238,
1101 1e+239, 1e+240, 1e+241, 1e+242, 1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249, 1e+250, 1e+251, 1e+252, 1e+253,
1102 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259, 1e+260, 1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268,
1103 1e+269, 1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278, 1e+279, 1e+280, 1e+281, 1e+282, 1e+283,
1104 1e+284, 1e+285, 1e+286, 1e+287, 1e+288, 1e+289, 1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296, 1e+297, 1e+298,
1105 1e+299, 1e+300, 1e+301, 1e+302, 1e+303, 1e+304, 1e+305, 1e+306, 1e+307, 1e+308 };
1106 return e[n];
1107}
1108
1109inline bool float_from_chars(char const* start, char const* end, float& float_out) { // returns true on success
1110 // first read the chars into an int, keeping track of the magnitude
1111 // multiply by a pow of 10
1112
1113 int32_t magnitude = 0;
1114 int64_t accumulated = 0;
1115 bool after_decimal = false;
1116
1117 if(start == end) {
1118 float_out = 0.0f;
1119 return true;
1120 }
1121
1122 bool is_negative = false;
1123 if(*start == '-') {
1124 is_negative = true;
1125 ++start;
1126 } else if(*start == '+') {
1127 ++start;
1128 }
1129
1130 for(; start < end; ++start) {
1131 if(*start >= '0' && *start <= '9') {
1132 accumulated = accumulated * 10 + (*start - '0');
1133 magnitude += int32_t(after_decimal);
1134 } else if(*start == '.') {
1135 after_decimal = true;
1136 } else {
1137 // maybe check for non space and throw an error?
1138 }
1139 }
1140 if(!is_negative) {
1141 if(magnitude > 0)
1142 float_out = float(double(accumulated) / pow_10(magnitude));
1143 else
1144 float_out = float(accumulated);
1145 } else {
1146 if(magnitude > 0)
1147 float_out = -float(double(accumulated) / pow_10(magnitude));
1148 else
1149 float_out = -float(accumulated);
1150 }
1151 return true;
1152}
1153
1154inline int32_t parse_int(std::string_view content) {
1155 int32_t rvalue = 0;
1156 auto result = std::from_chars(content.data(), content.data() + content.length(), rvalue);
1157 if(result.ec == std::errc::invalid_argument) {
1158 return 0;
1159 }
1160 return rvalue;
1161}
1162inline float parse_float(std::string_view content) {
1163 float rvalue = 0.0f;
1164 if(!float_from_chars(content.data(), content.data() + content.length(), rvalue)) {
1165 return 0.0f;
1166 }
1167 return rvalue;
1168}
1170 bool match_result = false;
1172};
1173
1174inline type_match resolve_span_type(std::span<int32_t const> tlist, std::vector<int32_t> const& type_subs, environment& env);
1175inline variable_match_result fill_in_variable_types(int32_t source_type, std::span<int32_t const> match_span, std::vector<int32_t>& type_subs, environment& env);
1176
1177#ifdef USE_LLVM
1178inline LLVMValueRef struct_zero_constant(LLVMContextRef c, int32_t t, environment* e) {
1179 std::vector<LLVMValueRef> zvals;
1180 for(int32_t j = 1; j < e->dict.type_array[t].decomposed_types_count; ++j) {
1181 auto st = e->dict.all_stack_types[e->dict.type_array[t].decomposed_types_start + j];
1182 zvals.push_back(e->dict.type_array[st].zero_constant(c, st, e));
1183 }
1184 return LLVMConstNamedStruct(e->dict.type_array[t].llvm_type, zvals.data(), uint32_t(zvals.size()));
1185}
1186#endif
1187
1188inline int32_t interepreter_size(int32_t type, environment& env) {
1189 if(env.dict.type_array[type].decomposed_types_count == 0)
1190 return 8;
1191 auto main_type = env.dict.all_stack_types[env.dict.type_array[type].decomposed_types_start];
1192 return 8 * (env.dict.type_array[type].decomposed_types_count - 1 - env.dict.type_array[main_type].non_member_types);
1193}
1194
1195inline int32_t struct_child_count(int32_t type, environment& env) {
1196 if(env.dict.type_array[type].decomposed_types_count == 0)
1197 return 0;
1198 auto main_type = env.dict.all_stack_types[env.dict.type_array[type].decomposed_types_start];
1199 return (env.dict.type_array[type].decomposed_types_count - 1 - env.dict.type_array[main_type].non_member_types);
1200}
1201
1202inline int64_t interpreter_struct_zero_constant(int32_t t, environment* e) {
1203 if(e->dict.type_array[t].single_member_struct()) {
1204 auto child_index = e->dict.type_array[t].decomposed_types_start + 1 + 0;
1205 auto child_type = e->dict.all_stack_types[child_index];
1206 if(e->dict.type_array[child_type].interpreter_zero)
1207 return e->dict.type_array[child_type].interpreter_zero(child_type, e);
1208 else
1209 return 0;
1210 } else {
1211 auto bytes = interepreter_size(t, *e);
1212 auto mem = (char*)malloc(bytes);
1213 memset(mem, 0, bytes);
1214 return (int64_t)mem;
1215 }
1216}
1217
1218inline uint32_t next_encoded_stack_type(std::span<int32_t const> desc) {
1219 if(desc.size() == 0)
1220 return 0;
1221 if(desc.size() == 1)
1222 return 1;
1223 if(desc[1] != std::numeric_limits<int32_t>::max())
1224 return 1;
1225 uint32_t i = 2;
1226 while(i < desc.size() && desc[i] != -1) {
1227 i += next_encoded_stack_type(desc.subspan(i));
1228 }
1229 if(i < desc.size() && desc[i] == -1)
1230 ++i;
1231 return i;
1232}
1233
1234inline int32_t instantiate_templated_struct_full(int32_t template_base, std::vector<int32_t> const& final_subtype_list, environment& env) {
1235
1236 auto desc = std::span<int32_t const>(env.dict.all_stack_types.data() + env.dict.type_array[template_base].decomposed_types_start, size_t(env.dict.type_array[template_base].decomposed_types_count));
1237
1238 uint32_t match_pos = 0;
1239 uint32_t mem_count = 0;
1240 std::vector<int32_t> type_subs_out;
1241 while(match_pos < desc.size()) {
1242 if(mem_count > final_subtype_list.size()) {
1243 env.report_error("attempted to instantiate a struct template with the wrong number of members");
1244 env.mode = fif_mode::error;
1245 return -1;
1246 }
1247
1248 auto mr = fill_in_variable_types(final_subtype_list[mem_count], desc.subspan(match_pos), type_subs_out, env);
1249 if(!mr.match_result) {
1250 env.report_error("attempted to instantiate a struct template with types that do not match its definition");
1251 env.mode = fif_mode::error;
1252 return -1;
1253 }
1254
1255 match_pos += next_encoded_stack_type(desc.subspan(match_pos));
1256 ++mem_count;
1257 }
1258 if(mem_count < final_subtype_list.size()) {
1259 env.report_error("attempted to instantiate a struct template with the wrong number of members");
1260 env.mode = fif_mode::error;
1261 return -1;
1262 }
1263
1264 for(uint32_t i = 0; i < env.dict.type_array.size(); ++i) {
1265 if(env.dict.type_array[i].decomposed_types_count == int32_t(final_subtype_list.size() + 1)) {
1266 auto ta_start = env.dict.type_array[i].decomposed_types_start;
1267 bool match = env.dict.all_stack_types[ta_start] == template_base;
1268
1269 for(uint32_t j = 0; match && j < final_subtype_list.size(); ++j) {
1270 if(env.dict.all_stack_types[ta_start + j + 1] != final_subtype_list[j]) {
1271 match = false;
1272 }
1273 }
1274
1275 if(match)
1276 return int32_t(i);
1277 }
1278 }
1279
1280 int32_t new_type = int32_t(env.dict.type_array.size());
1281 env.dict.type_array.emplace_back();
1282
1283 std::vector<LLVMTypeRef> ctypes;
1284 for(uint32_t j = 0; j < final_subtype_list.size(); ++j) {
1285 ctypes.push_back(env.dict.type_array[final_subtype_list[j]].llvm_type);
1286 }
1287 for(int32_t j = 0; j < env.dict.type_array[template_base].non_member_types; ++j)
1288 ctypes.pop_back();
1289
1290 if(ctypes.size() != 1) {
1291 std::string autoname = "struct#" + std::to_string(env.dict.type_array.size());
1292#ifdef USE_LLVM
1293 auto ty = LLVMStructCreateNamed(env.llvm_context, autoname.c_str());
1294 LLVMStructSetBody(ty, ctypes.data(), uint32_t(ctypes.size()), false);
1295 env.dict.type_array.back().llvm_type = ty;
1296 env.dict.type_array.back().zero_constant = struct_zero_constant;
1297#endif
1298 env.dict.type_array.back().interpreter_zero = interpreter_struct_zero_constant;
1299 } else {
1300#ifdef USE_LLVM
1301 env.dict.type_array.back().llvm_type = ctypes[0];
1302 env.dict.type_array.back().zero_constant = env.dict.type_array[final_subtype_list[0]].zero_constant;
1303#endif
1304 env.dict.type_array.back().interpreter_zero = env.dict.type_array[final_subtype_list[0]].interpreter_zero;
1305 }
1306
1307 env.dict.type_array.back().decomposed_types_count = uint32_t(final_subtype_list.size() + 1);
1308 env.dict.type_array.back().decomposed_types_start = uint32_t(env.dict.all_stack_types.size());
1309
1310 if(ctypes.size() == 1)
1311 env.dict.type_array.back().flags |= type::FLAG_SINGLE_MEMBER;
1312
1313 env.dict.type_array.back().flags &= ~(type::FLAG_TEMPLATE);
1314 env.dict.type_array.back().flags |= type::FLAG_REFCOUNTED;
1315 env.dict.type_array.back().type_slots = 0;
1316 env.dict.all_stack_types.push_back(template_base);
1317 env.dict.all_stack_types.insert(env.dict.all_stack_types.end(), final_subtype_list.begin(), final_subtype_list.end());
1318
1319 return new_type;
1320}
1321
1322inline int32_t instantiate_templated_struct(int32_t template_base, std::vector<int32_t> const& subtypes, environment& env) {
1323 std::vector<int32_t> final_subtype_list;
1324 final_subtype_list.push_back(template_base);
1325
1326 auto desc = std::span<int32_t const>(env.dict.all_stack_types.data() + env.dict.type_array[template_base].decomposed_types_start, size_t(env.dict.type_array[template_base].decomposed_types_count));
1327
1328 uint32_t match_pos = 0;
1329 while(match_pos < desc.size()) {
1330 auto mresult = resolve_span_type(desc.subspan(match_pos), subtypes, env);
1331 match_pos += mresult.end_match_pos;
1332 final_subtype_list.push_back(mresult.type);
1333 }
1334
1335 for(uint32_t i = 0; i < env.dict.type_array.size(); ++i) {
1336 if(env.dict.type_array[i].decomposed_types_count == int32_t(final_subtype_list.size())) {
1337 auto ta_start = env.dict.type_array[i].decomposed_types_start;
1338 bool match = true;
1339
1340 for(uint32_t j = 0; j < final_subtype_list.size(); ++j) {
1341 if(env.dict.all_stack_types[ta_start + j] != final_subtype_list[j]) {
1342 match = false;
1343 break;
1344 }
1345 }
1346
1347 if(match)
1348 return int32_t(i);
1349 }
1350 }
1351
1352 int32_t new_type = int32_t(env.dict.type_array.size());
1353 env.dict.type_array.emplace_back();
1354
1355 std::vector<LLVMTypeRef> ctypes;
1356 for(uint32_t j = 1; j < final_subtype_list.size(); ++j) {
1357 ctypes.push_back(env.dict.type_array[final_subtype_list[j]].llvm_type);
1358 }
1359 for(int32_t j = 0; j < env.dict.type_array[template_base].non_member_types; ++j)
1360 ctypes.pop_back();
1361
1362 if(ctypes.size() != 1) {
1363 std::string autoname = "struct#" + std::to_string(env.dict.type_array.size());
1364#ifdef USE_LLVM
1365 auto ty = LLVMStructCreateNamed(env.llvm_context, autoname.c_str());
1366 LLVMStructSetBody(ty, ctypes.data(), uint32_t(ctypes.size()), false);
1367 env.dict.type_array.back().llvm_type = ty;
1368 env.dict.type_array.back().zero_constant = struct_zero_constant;
1369#endif
1370 env.dict.type_array.back().interpreter_zero = interpreter_struct_zero_constant;
1371 } else {
1372#ifdef USE_LLVM
1373 env.dict.type_array.back().llvm_type = ctypes[0];
1374 env.dict.type_array.back().zero_constant = env.dict.type_array[final_subtype_list[0]].zero_constant;
1375#endif
1376 env.dict.type_array.back().interpreter_zero = env.dict.type_array[final_subtype_list[0]].interpreter_zero;
1377 }
1378 env.dict.type_array.back().decomposed_types_count = uint32_t(final_subtype_list.size());
1379 env.dict.type_array.back().decomposed_types_start = uint32_t(env.dict.all_stack_types.size());
1380
1381 env.dict.type_array.back().flags &= ~(type::FLAG_TEMPLATE);
1382 env.dict.type_array.back().flags |= type::FLAG_REFCOUNTED;
1383 if(ctypes.size() == 1)
1384 env.dict.type_array.back().flags |= type::FLAG_SINGLE_MEMBER;
1385
1386 env.dict.type_array.back().type_slots = 0;
1387 env.dict.all_stack_types.insert(env.dict.all_stack_types.end(), final_subtype_list.begin(), final_subtype_list.end());
1388
1389 return new_type;
1390}
1391
1392inline int32_t make_struct_type(std::string_view name, std::span<int32_t const> subtypes, std::vector<std::string_view> const& member_names, environment& env, int32_t template_types, int32_t extra_count) {
1393
1394 int32_t new_type = int32_t(env.dict.type_array.size());
1395 env.dict.type_array.emplace_back();
1396 env.dict.types.insert_or_assign(std::string(name), new_type);
1397
1398 if(template_types == 0 && extra_count == 0) {
1399 std::vector<LLVMTypeRef> ctypes;
1400 for(uint32_t j = 0; j < subtypes.size(); ++j) {
1401 ctypes.push_back(env.dict.type_array[subtypes[j]].llvm_type);
1402 }
1403 if(ctypes.size() != 1) {
1404 std::string autoname = "struct#" + std::to_string(env.dict.type_array.size());
1405#ifdef USE_LLVM
1406 auto ty = LLVMStructCreateNamed(env.llvm_context, autoname.c_str());
1407 LLVMStructSetBody(ty, ctypes.data(), uint32_t(ctypes.size()), false);
1408 env.dict.type_array.back().llvm_type = ty;
1409 env.dict.type_array.back().zero_constant = struct_zero_constant;
1410#endif
1411 env.dict.type_array.back().interpreter_zero = interpreter_struct_zero_constant;
1412 } else {
1413#ifdef USE_LLVM
1414 env.dict.type_array.back().llvm_type = ctypes[0];
1415 env.dict.type_array.back().zero_constant = env.dict.type_array[subtypes[0]].zero_constant;
1416#endif
1417 env.dict.type_array.back().interpreter_zero = env.dict.type_array[subtypes[0]].interpreter_zero;
1418 }
1419 } else {
1420#ifdef USE_LLVM
1421 env.dict.type_array.back().llvm_type = LLVMVoidTypeInContext(env.llvm_context);
1422 env.dict.type_array.back().zero_constant = struct_zero_constant;
1423#endif
1424 env.dict.type_array.back().interpreter_zero = interpreter_struct_zero_constant;
1425 env.dict.type_array.back().non_member_types = extra_count;
1426 }
1427
1428 env.dict.type_array.back().decomposed_types_count = uint32_t(subtypes.size() + (template_types + extra_count == 0 ? 1 : extra_count));
1429 env.dict.type_array.back().decomposed_types_start = uint32_t(env.dict.all_stack_types.size());
1430
1431 auto add_child_types = [&]() {
1432 if(template_types + extra_count > 0) {
1433 env.dict.all_stack_types.push_back(std::numeric_limits<int32_t>::max());
1434 env.dict.all_stack_types.insert(env.dict.all_stack_types.end(), subtypes.begin(), subtypes.end());
1435 for(int32_t e = 0; e < extra_count; ++e) {
1436 env.dict.all_stack_types.push_back(-(template_types + e + 2));
1437 }
1438 env.dict.all_stack_types.push_back(-1);
1439 }
1440 };
1441
1442
1443 if(template_types + extra_count > 0)
1444 env.dict.type_array.back().flags |= type::FLAG_TEMPLATE;
1445 else
1446 env.dict.type_array.back().flags &= ~(type::FLAG_TEMPLATE);
1447
1448 if(subtypes.size() == 1)
1449 env.dict.type_array.back().flags |= type::FLAG_SINGLE_MEMBER;
1450
1451 env.dict.type_array.back().flags |= type::FLAG_REFCOUNTED;
1452 env.dict.type_array.back().type_slots = template_types + extra_count;
1453 if(template_types + extra_count == 0)
1454 env.dict.all_stack_types.push_back(fif_struct);
1455 env.dict.all_stack_types.insert(env.dict.all_stack_types.end(), subtypes.begin(), subtypes.end());
1456 for(int32_t e = 0; e < extra_count; ++e) {
1457 env.dict.all_stack_types.push_back(-(template_types + e + 2));
1458 }
1459
1460 int32_t start_types = int32_t(env.dict.all_stack_types.size());
1461 env.dict.all_stack_types.push_back(new_type);
1462 add_child_types();
1463 int32_t end_zero = int32_t(env.dict.all_stack_types.size());
1464 env.dict.all_stack_types.push_back(-1);
1465 env.dict.all_stack_types.push_back(new_type);
1466 add_child_types();
1467 int32_t end_one = int32_t(env.dict.all_stack_types.size());
1468 env.dict.all_stack_types.push_back(new_type);
1469 add_child_types();
1470
1471 int32_t end_two = int32_t(env.dict.all_stack_types.size());
1472
1473 auto bury_word = [&](std::string const& name, int32_t id) {
1474 int32_t start_word = 0;
1475 int32_t preceding_word = -1;
1476 if(auto it = env.dict.words.find(name); it != env.dict.words.end()) {
1477 start_word = it->second;
1478 } else {
1479 env.dict.words.insert_or_assign(name, id);
1480 return;
1481 }
1482 while(env.dict.word_array[start_word].specialization_of != -1) {
1483 preceding_word = start_word;
1484 start_word = env.dict.word_array[start_word].specialization_of;
1485 }
1486 if(preceding_word == -1) {
1487 env.dict.words.insert_or_assign(name, id);
1488 env.dict.word_array[id].specialization_of = start_word;
1489 assert(id != start_word);
1490 } else {
1491 env.dict.word_array[preceding_word].specialization_of = id;
1492 env.dict.word_array[id].specialization_of = start_word;
1493 assert(id != start_word);
1494 }
1495 };
1496
1497 {
1498 env.dict.word_array.emplace_back();
1499 env.dict.word_array.back().source = std::string("struct-map2 copy");
1500 env.dict.word_array.back().stack_types_start = start_types;
1501 env.dict.word_array.back().stack_types_count = end_two - start_types;
1502 env.dict.word_array.back().treat_as_base = true;
1503 bury_word("copy", int32_t(env.dict.word_array.size() - 1));
1504 }
1505 {
1506 env.dict.word_array.emplace_back();
1507 env.dict.word_array.back().source = std::string("struct-map2 dup");
1508 env.dict.word_array.back().stack_types_start = start_types;
1509 env.dict.word_array.back().stack_types_count = end_two - start_types;
1510 env.dict.word_array.back().treat_as_base = true;
1511 bury_word("dup", int32_t(env.dict.word_array.size() - 1));
1512 }
1513 {
1514 env.dict.word_array.emplace_back();
1515 env.dict.word_array.back().source = std::string("struct-map1 init");
1516 env.dict.word_array.back().stack_types_start = start_types;
1517 env.dict.word_array.back().stack_types_count = end_one - start_types;
1518 env.dict.word_array.back().treat_as_base = true;
1519 bury_word("init", int32_t(env.dict.word_array.size() - 1));
1520 }
1521 {
1522 env.dict.word_array.emplace_back();
1523 env.dict.word_array.back().source = std::string("struct-map0 drop");
1524 env.dict.word_array.back().stack_types_start = start_types;
1525 env.dict.word_array.back().stack_types_count = end_zero - start_types;
1526 env.dict.word_array.back().treat_as_base = true;
1527 bury_word("drop", int32_t(env.dict.word_array.size() - 1));
1528 }
1529
1530 uint32_t index = 0;
1531 auto desc = subtypes;
1532 while(desc.size() > 0) {
1533 auto next = next_encoded_stack_type(desc);
1534
1535 {
1536 int32_t start_types_i = int32_t(env.dict.all_stack_types.size());
1537 env.dict.all_stack_types.push_back(new_type);
1538 add_child_types();
1539 env.dict.all_stack_types.push_back(-1);
1540 for(uint32_t j = 0; j < next; ++j)
1541 env.dict.all_stack_types.push_back(desc[j]);
1542 int32_t end_types_i = int32_t(env.dict.all_stack_types.size());
1543
1544 env.dict.word_array.emplace_back();
1545 env.dict.word_array.back().source = std::string("forth.extract ") + std::to_string(index);
1546 env.dict.word_array.back().stack_types_start = start_types_i;
1547 env.dict.word_array.back().stack_types_count = end_types_i - start_types_i;
1548 env.dict.word_array.back().treat_as_base = true;
1549
1550 bury_word(std::string(".") + std::string{ member_names[index] }, int32_t(env.dict.word_array.size() - 1));
1551 }
1552 {
1553 int32_t start_types_i = int32_t(env.dict.all_stack_types.size());
1554 env.dict.all_stack_types.push_back(new_type);
1555 add_child_types();
1556 env.dict.all_stack_types.push_back(-1);
1557 env.dict.all_stack_types.push_back(new_type);
1558 add_child_types();
1559 for(uint32_t j = 0; j < next; ++j)
1560 env.dict.all_stack_types.push_back(desc[j]);
1561 int32_t end_types_i = int32_t(env.dict.all_stack_types.size());
1562
1563 env.dict.word_array.emplace_back();
1564 env.dict.word_array.back().source = std::string("forth.extract-copy ") + std::to_string(index);
1565 env.dict.word_array.back().stack_types_start = start_types_i;
1566 env.dict.word_array.back().stack_types_count = end_types_i - start_types_i;
1567 env.dict.word_array.back().treat_as_base = true;
1568
1569 bury_word(std::string(".") + std::string{ member_names[index] } + "@", int32_t(env.dict.word_array.size() - 1));
1570 }
1571 {
1572 int32_t start_types_i = int32_t(env.dict.all_stack_types.size());
1573 env.dict.all_stack_types.push_back(new_type);
1574 add_child_types();
1575 for(uint32_t j = 0; j < next; ++j)
1576 env.dict.all_stack_types.push_back(desc[j]);
1577 env.dict.all_stack_types.push_back(-1);
1578 env.dict.all_stack_types.push_back(new_type);
1579 add_child_types();
1580 int32_t end_types_i = int32_t(env.dict.all_stack_types.size());
1581
1582 env.dict.word_array.emplace_back();
1583 env.dict.word_array.back().source = std::string("forth.insert ") + std::to_string(index);
1584 env.dict.word_array.back().stack_types_start = start_types_i;
1585 env.dict.word_array.back().stack_types_count = end_types_i - start_types_i;
1586 env.dict.word_array.back().treat_as_base = true;
1587
1588 bury_word(std::string(".") + std::string{ member_names[index] } + "!", int32_t(env.dict.word_array.size() - 1));
1589 }
1590 {
1591 int32_t start_types_i = int32_t(env.dict.all_stack_types.size());
1592 env.dict.all_stack_types.push_back(fif_ptr);
1593 env.dict.all_stack_types.push_back(std::numeric_limits<int32_t>::max());
1594 env.dict.all_stack_types.push_back(new_type);
1595 add_child_types();
1596 env.dict.all_stack_types.push_back(-1);
1597 env.dict.all_stack_types.push_back(-1);
1598 env.dict.all_stack_types.push_back(fif_ptr);
1599 env.dict.all_stack_types.push_back(std::numeric_limits<int32_t>::max());
1600 for(uint32_t j = 0; j < next; ++j)
1601 env.dict.all_stack_types.push_back(desc[j]);
1602 env.dict.all_stack_types.push_back(-1);
1603 int32_t end_types_i = int32_t(env.dict.all_stack_types.size());
1604
1605 env.dict.word_array.emplace_back();
1606 env.dict.word_array.back().source = std::string("forth.gep ") + std::to_string(index);
1607 env.dict.word_array.back().stack_types_start = start_types_i;
1608 env.dict.word_array.back().stack_types_count = end_types_i - start_types_i;
1609 env.dict.word_array.back().treat_as_base = true;
1610
1611 bury_word(std::string(".") + std::string{ member_names[index] }, int32_t(env.dict.word_array.size() - 1));
1612 }
1613
1614 ++index;
1615 desc = desc.subspan(next);
1616 }
1617
1618 return new_type;
1619}
1620
1621inline type_match internal_resolve_type(std::string_view text, environment& env, std::vector<int32_t>* type_subs) {
1622 uint32_t mt_end = 0;
1623 if(text.starts_with("ptr(nil)")) {
1624 return type_match{ fif_opaque_ptr, 8 };
1625 }
1626 for(; mt_end < text.size(); ++mt_end) {
1627 if(text[mt_end] == '(' || text[mt_end] == ')' || text[mt_end] == ',')
1628 break;
1629 }
1630
1631 if(text.size() > 0 && text[0] == '$') {
1632 if(is_integer(text.data() + 1, text.data() + mt_end)) {
1633 auto v = parse_int(text.substr(1));
1634 if(type_subs && v >= 0 && size_t(v) < type_subs->size()) {
1635 return type_match{ (*type_subs)[v], mt_end };
1636 }
1637 return type_match{ fif_nil, mt_end };
1638 }
1639 }
1640 if(text.substr(0, mt_end) == "struct") { // prevent "generic" struct matching
1641 return type_match{ -1, uint32_t(text.length()) };
1642 }
1643 if(auto it = env.dict.types.find(std::string(text.substr(0, mt_end))); it != env.dict.types.end()) {
1644 if(mt_end >= text.size() || text[mt_end] == ',' || text[mt_end] == ')') { // case: plain type
1645 return type_match{ it->second, mt_end };
1646 }
1647 //followed by type list
1648 ++mt_end;
1649 std::vector<int32_t> subtypes;
1650 while(mt_end < text.size() && text[mt_end] != ')') {
1651 auto sub_match = internal_resolve_type(text.substr(mt_end), env, type_subs);
1652 subtypes.push_back(sub_match.type);
1653 mt_end += sub_match.end_match_pos;
1654 if(mt_end < text.size() && text[mt_end] == ',')
1655 ++mt_end;
1656 }
1657 if(mt_end < text.size() && text[mt_end] == ')')
1658 ++mt_end;
1659
1660 if(env.dict.type_array[it->second].type_slots != int32_t(subtypes.size())) {
1661 env.report_error("attempted to instantiate a type with the wrong number of parameters");
1662 env.mode = fif_mode::error;
1663 return type_match{ -1, mt_end };
1664 } else if(env.dict.type_array[it->second].is_struct_template()) {
1665 return type_match{ instantiate_templated_struct(it->second, subtypes, env), mt_end };
1666 } else {
1667 for(uint32_t i = 0; i < env.dict.type_array.size(); ++i) {
1668 if(env.dict.type_array[i].decomposed_types_count == int32_t(1 + subtypes.size())) {
1669 auto ta_start = env.dict.type_array[i].decomposed_types_start;
1670 if(env.dict.all_stack_types[ta_start] == it->second) {
1671 bool match = true;
1672 for(uint32_t j = 0; j < subtypes.size(); ++j) {
1673 if(env.dict.all_stack_types[ta_start + 1 + j] != subtypes[j]) {
1674 match = false;
1675 break;
1676 }
1677 }
1678
1679 if(match) {
1680 return type_match{ int32_t(i), mt_end };
1681 }
1682 }
1683 }
1684 }
1685
1686 int32_t new_type = int32_t(env.dict.type_array.size());
1687 env.dict.type_array.emplace_back();
1688 env.dict.type_array.back().llvm_type = env.dict.type_array[it->second].llvm_type;
1689 env.dict.type_array.back().decomposed_types_count = uint32_t(1 + subtypes.size());
1690 env.dict.type_array.back().decomposed_types_start = uint32_t(env.dict.all_stack_types.size());
1691 env.dict.type_array.back().flags = env.dict.type_array[it->second].flags;
1692 env.dict.type_array.back().zero_constant = env.dict.type_array[it->second].zero_constant;
1693 env.dict.type_array.back().type_slots = 0;
1694
1695 env.dict.all_stack_types.push_back(it->second);
1696 for(auto t : subtypes) {
1697 env.dict.all_stack_types.push_back(t);
1698 }
1699
1700 return type_match{ new_type, mt_end };
1701 }
1702 }
1703
1704 return type_match{ -1, mt_end };
1705}
1706
1707inline int32_t resolve_type(std::string_view text, environment& env, std::vector<int32_t>* type_subs) {
1708 return internal_resolve_type(text, env, type_subs).type;
1709}
1710
1712 std::vector<int32_t> type_array;
1714 int32_t max_variable = -1;
1715};
1716
1718 uint32_t mt_end = 0;
1720
1721 if(text.starts_with("ptr(nil)")) {
1722 r.type_array.push_back(fif_opaque_ptr);
1723 r.end_match_pos = 8;
1724 return r;
1725 }
1726 for(; mt_end < text.size(); ++mt_end) {
1727 if(text[mt_end] == '(' || text[mt_end] == ')' || text[mt_end] == ',')
1728 break;
1729 }
1730
1731 if(text.size() > 0 && text[0] == '$') {
1732 if(is_integer(text.data() + 1, text.data() + mt_end)) {
1733 auto v = parse_int(text.substr(1));
1734 r.max_variable = std::max(r.max_variable, v);
1735 r.type_array.push_back( -(v + 2) );
1736 r.end_match_pos = mt_end;
1737 return r;
1738 }
1739 }
1740 if(auto it = env.dict.types.find(std::string(text.substr(0, mt_end))); it != env.dict.types.end()) {
1741 r.type_array.push_back(it->second);
1742 if(mt_end >= text.size() || text[mt_end] == ',' || text[mt_end] == ')') { // case: plain type
1743 r.end_match_pos = mt_end;
1744 return r;
1745 }
1746 //followed by type list
1747 ++mt_end;
1748 r.type_array.push_back(std::numeric_limits<int32_t>::max());
1749 if((env.dict.type_array[it->second].flags & type::FLAG_TEMPLATE) != 0) {
1750 std::vector<type_span_gen_result> sub_matches;
1751 while(mt_end < text.size() && text[mt_end] != ')') {
1752 auto sub_match = internal_generate_type(text.substr(mt_end), env);
1753 r.max_variable = std::max(r.max_variable, sub_match.max_variable);
1754 sub_matches.push_back(std::move(sub_match));
1755 mt_end += sub_match.end_match_pos;
1756 if(mt_end < text.size() && text[mt_end] == ',')
1757 ++mt_end;
1758 }
1759 auto desc = std::span<int32_t const>(env.dict.all_stack_types.data() + env.dict.type_array[it->second].decomposed_types_start, size_t(env.dict.type_array[it->second].decomposed_types_count));
1760 for(auto v : desc) {
1761 if(v < -1) {
1762 auto index = -(v + 2);
1763 if(size_t(index) < sub_matches.size()) {
1764 r.type_array.insert(r.type_array.end(), sub_matches[index].type_array.begin(), sub_matches[index].type_array.end());
1765 } else {
1766 r.type_array.push_back(fif_nil);
1767 }
1768 } else {
1769 r.type_array.push_back(v);
1770 }
1771 }
1772
1773 } else {
1774 while(mt_end < text.size() && text[mt_end] != ')') {
1775 auto sub_match = internal_generate_type(text.substr(mt_end), env);
1776 r.type_array.insert(r.type_array.end(), sub_match.type_array.begin(), sub_match.type_array.end());
1777 r.max_variable = std::max(r.max_variable, sub_match.max_variable);
1778 mt_end += sub_match.end_match_pos;
1779 if(mt_end < text.size() && text[mt_end] == ',')
1780 ++mt_end;
1781 }
1782 }
1783 r.type_array.push_back(-1);
1784 if(mt_end < text.size() && text[mt_end] == ')')
1785 ++mt_end;
1786 }
1787 r.end_match_pos = mt_end;
1788 if(r.max_variable == -1) {
1789 std::vector<int32_t> type_subs;
1790 auto resolved_type = resolve_span_type(std::span<int32_t const>(r.type_array.begin(), r.type_array.end()), type_subs, env);
1791 r.type_array.clear();
1792 r.type_array.push_back(resolved_type.type);
1793 }
1794 return r;
1795}
1796
1797inline type_match resolve_span_type(std::span<int32_t const> tlist, std::vector<int32_t> const& type_subs, environment& env) {
1798
1799 auto make_sub = [&](int32_t type_in) {
1800 if(type_in < -1) {
1801 auto slot = -(type_in + 2);
1802 if(slot < int32_t(type_subs.size()))
1803 return type_subs[slot];
1804 return -1;
1805 }
1806 return type_in;
1807 };
1808
1809 if(tlist.size() == 0) {
1810 return type_match{ -1, 0 };
1811 }
1812 if(tlist.size() == 1) {
1813 return type_match{ make_sub(tlist[0]), 1 };
1814 }
1815 if(tlist[1] != std::numeric_limits<int32_t>::max()) {
1816 return type_match{ make_sub(tlist[0]), 1 };
1817 }
1818 int32_t base_type = tlist[0];
1819 assert(base_type >= 0);
1820 uint32_t mt_end = 2;
1821
1822 //followed by type list
1823 std::vector<int32_t> subtypes;
1824 while(mt_end < tlist.size() && tlist[mt_end] != -1) {
1825 auto sub_match = resolve_span_type(tlist.subspan(mt_end), type_subs, env);
1826 subtypes.push_back(sub_match.type);
1827 mt_end += sub_match.end_match_pos;
1828 }
1829 if(mt_end < tlist.size() && tlist[mt_end] == -1)
1830 ++mt_end;
1831
1832
1833 if(base_type == fif_ptr && !subtypes.empty() && subtypes[0] == fif_nil) {
1834 return type_match{ fif_opaque_ptr, mt_end };
1835 } else if(env.dict.type_array[base_type].is_struct_template()) {
1836 return type_match{ instantiate_templated_struct_full(base_type, subtypes, env), mt_end };
1837 } else {
1838 for(uint32_t i = 0; i < env.dict.type_array.size(); ++i) {
1839 if(env.dict.type_array[i].decomposed_types_count == int32_t(1 + subtypes.size())) {
1840 auto ta_start = env.dict.type_array[i].decomposed_types_start;
1841 if(env.dict.all_stack_types[ta_start] == base_type) {
1842 bool match = true;
1843 for(uint32_t j = 0; j < subtypes.size(); ++j) {
1844 if(env.dict.all_stack_types[ta_start + 1 + j] != subtypes[j]) {
1845 match = false;
1846 break;
1847 }
1848 }
1849
1850 if(match) {
1851 return type_match{ int32_t(i), mt_end };
1852 }
1853 }
1854 }
1855 }
1856
1857 int32_t new_type = int32_t(env.dict.type_array.size());
1858 env.dict.type_array.emplace_back();
1859
1860 env.dict.type_array.back().llvm_type = env.dict.type_array[base_type].llvm_type;
1861 env.dict.type_array.back().decomposed_types_count = uint32_t(1 + subtypes.size());
1862 env.dict.type_array.back().decomposed_types_start = uint32_t(env.dict.all_stack_types.size());
1863 env.dict.type_array.back().zero_constant = env.dict.type_array[base_type].zero_constant;
1864 env.dict.type_array.back().flags = env.dict.type_array[base_type].flags;
1865 env.dict.type_array.back().type_slots = 0;
1866
1867 env.dict.all_stack_types.push_back(base_type);
1868 for(auto t : subtypes) {
1869 env.dict.all_stack_types.push_back(t);
1870 }
1871
1872 return type_match{ new_type, mt_end };
1873 }
1874}
1875
1876inline variable_match_result fill_in_variable_types(int32_t source_type, std::span<int32_t const> match_span, std::vector<int32_t>& type_subs, environment& env) {
1877 if(match_span.size() == 0)
1878 return variable_match_result{ true, 0 };
1879
1880 auto match_to_slot = [&](int32_t matching_type, int32_t matching_against) {
1881 if(matching_type < -1) {
1882 auto slot = -(matching_type + 2);
1883 if(slot >= int32_t(type_subs.size())) {
1884 type_subs.resize(size_t(slot + 1), -2);
1885 type_subs[slot] = matching_against;
1886 return true;
1887 } else if(type_subs[slot] == -2 || type_subs[slot] == matching_against) {
1888 type_subs[slot] = matching_against;
1889 return true;
1890 } else {
1891 return false;
1892 }
1893 } else {
1894 return matching_type == matching_against;
1895 }
1896 };
1897
1898 if(match_span.size() == 1) {
1899 return variable_match_result{ match_to_slot(match_span[0], source_type), 1 };
1900 }
1901
1902 if(match_span[1] != std::numeric_limits<int32_t>::max()) {
1903 return variable_match_result{ match_to_slot(match_span[0], source_type), 1 };
1904 }
1905
1906 uint32_t sub_offset = 2;
1907
1908 std::span<const int32_t> destructured_source{ };
1909 if(source_type >= 0) {
1910 auto const& t = env.dict.type_array[source_type];
1911 destructured_source = std::span<const int32_t>(env.dict.all_stack_types.data() + t.decomposed_types_start, size_t(t.decomposed_types_count));
1912 }
1913
1914 bool result = destructured_source.size() > 0 ? match_to_slot(match_span[0], destructured_source[0]) : false;
1915 uint32_t dest_offset = 1;
1916 while(sub_offset < match_span.size() && match_span[sub_offset] != -1) {
1917 auto dmatch = dest_offset < destructured_source.size() ? destructured_source[dest_offset] : -1;
1918 auto sub_result = fill_in_variable_types(dmatch, match_span.subspan(sub_offset), type_subs, env);
1919 sub_offset += sub_result.match_end;
1920 result &= sub_result.match_result;
1921 ++dest_offset;
1922 }
1923 if(dest_offset < destructured_source.size())
1924 result = false;
1925 if(sub_offset < match_span.size() && match_span[sub_offset] == -1)
1926 ++sub_offset;
1927
1928 return variable_match_result{ result, sub_offset };
1929}
1930
1931inline type_match_result match_stack_description(std::span<int32_t const> desc, state_stack& ts, environment& env, std::vector<int32_t>& type_subs) { // ret: true if function matched
1932 int32_t match_position = 0;
1933 // stack matching
1934
1935 auto const ssize = int32_t(ts.main_size());
1936 int32_t consumed_stack_cells = 0;
1937 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
1938 if(consumed_stack_cells >= ssize)
1939 return type_match_result{ false, 0, 0 };
1940 auto match_result = fill_in_variable_types(ts.main_type_back(size_t(consumed_stack_cells)), desc.subspan(match_position), type_subs, env);
1941 if(!match_result.match_result)
1942 return type_match_result{ false, 0, 0 };
1943 match_position += match_result.match_end;
1944 ++consumed_stack_cells;
1945 }
1946
1947 ++match_position; // skip -1
1948
1949 // skip over output stack
1950 int32_t first_output_stack = match_position;
1951 //int32_t output_stack_types = 0;
1952 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
1953 match_position += next_encoded_stack_type(desc.subspan(match_position));
1954 //++output_stack_types;
1955 }
1956 //int32_t last_output_stack = match_position;
1957 ++match_position; // skip -1
1958
1959 // return stack matching
1960 auto const rsize = int32_t(ts.return_size());
1961 int32_t consumed_rstack_cells = 0;
1962 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
1963 if(consumed_rstack_cells >= rsize)
1964 return type_match_result{ false, 0, 0 };
1965 auto match_result = fill_in_variable_types(ts.return_type_back(size_t(consumed_rstack_cells)), desc.subspan(match_position), type_subs, env);
1966 if(!match_result.match_result)
1967 return type_match_result{ false, 0, 0 };
1968 match_position += match_result.match_end;
1969 ++consumed_rstack_cells;
1970 }
1971
1972 ++match_position; // skip -1
1973
1974 // output ret stack
1975 //int32_t ret_added = 0;
1976 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
1977 auto result = resolve_span_type(desc.subspan(match_position), type_subs, env);
1978 match_position += result.end_match_pos;
1979 //++ret_added;
1980 }
1981
1982 return type_match_result{ true, consumed_stack_cells, consumed_rstack_cells };
1983}
1984
1985
1986inline void apply_stack_description(std::span<int32_t const> desc, state_stack& ts, environment& env) { // ret: true if function matched
1987 int32_t match_position = 0;
1988 // stack matching
1989
1990 std::vector<int32_t> type_subs;
1991
1992 auto const ssize = int32_t(ts.main_size());
1993 int32_t consumed_stack_cells = 0;
1994 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
1995 if(consumed_stack_cells >= ssize)
1996 return;
1997 auto match_result = fill_in_variable_types(ts.main_type_back(consumed_stack_cells), desc.subspan(match_position), type_subs, env);
1998 if(!match_result.match_result)
1999 return;
2000 match_position += match_result.match_end;
2001 ++consumed_stack_cells;
2002 }
2003
2004 ++match_position; // skip -1
2005
2006 // skip over output stack
2007 int32_t first_output_stack = match_position;
2008 //int32_t output_stack_types = 0;
2009 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2010 match_position += next_encoded_stack_type(desc.subspan(match_position));
2011 //++output_stack_types;
2012 }
2013 //int32_t last_output_stack = match_position;
2014 ++match_position; // skip -1
2015
2016 // return stack matching
2017 auto const rsize = int32_t(ts.return_size());
2018 int32_t consumed_rstack_cells = 0;
2019 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2020 if(consumed_rstack_cells >= rsize)
2021 return;
2022 auto match_result = fill_in_variable_types(ts.return_type_back(consumed_rstack_cells), desc.subspan(match_position), type_subs, env);
2023 if(!match_result.match_result)
2024 return;
2025 match_position += match_result.match_end;
2026 ++consumed_rstack_cells;
2027 }
2028
2029 ++match_position; // skip -1
2030
2031 // drop consumed types
2032 ts.resize(ssize - consumed_stack_cells, rsize - consumed_rstack_cells);
2033
2034 // add returned stack types
2035 while(first_output_stack < int32_t(desc.size()) && desc[first_output_stack] != -1) {
2036 auto result = resolve_span_type(desc.subspan(first_output_stack), type_subs, env);
2037 first_output_stack += result.end_match_pos;
2038 ts.push_back_main(result.type, 0, nullptr);
2039 }
2040
2041 // output ret stack
2042 // add new types
2043 //int32_t ret_added = 0;
2044 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2045 auto result = resolve_span_type(desc.subspan(match_position), type_subs, env);
2046 ts.push_back_return(result.type, 0, nullptr);
2047 match_position += result.end_match_pos;
2048 //++ret_added;
2049 }
2050}
2051
2052
2054 int32_t stack;
2055 int32_t rstack;
2056};
2057inline stack_consumption get_stack_consumption(int32_t word, int32_t alternative, environment& env) {
2058 int32_t count_desc = 0;
2059 int32_t desc_offset = 0;
2060 if(std::holds_alternative<interpreted_word_instance>(env.dict.all_instances[alternative])) {
2061 count_desc = std::get<interpreted_word_instance>(env.dict.all_instances[alternative]).stack_types_count;
2062 desc_offset = std::get<interpreted_word_instance>(env.dict.all_instances[alternative]).stack_types_start;
2063 } else if(std::holds_alternative<compiled_word_instance>(env.dict.all_instances[alternative])) {
2064 count_desc = std::get<compiled_word_instance>(env.dict.all_instances[alternative]).stack_types_count;
2065 desc_offset = std::get<compiled_word_instance>(env.dict.all_instances[alternative]).stack_types_start;
2066 }
2067
2068 std::span<const int> desc = std::span<const int>(env.dict.all_stack_types.data() + desc_offset, size_t(count_desc));
2069
2070 int32_t match_position = 0;
2071 // stack matching
2072
2073 int32_t consumed_stack_cells = 0;
2074 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2075 match_position += next_encoded_stack_type(desc.subspan(match_position));
2076 ++consumed_stack_cells;
2077 }
2078
2079 ++match_position; // skip -1
2080
2081 // skip over output stack
2082 int32_t first_output_stack = match_position;
2083 //int32_t output_stack_types = 0;
2084 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2085 match_position += next_encoded_stack_type(desc.subspan(match_position));
2086 //++output_stack_types;
2087 }
2088
2089 ++match_position; // skip -1
2090
2091 // return stack matching
2092
2093 int32_t consumed_rstack_cells = 0;
2094 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2095 match_position += next_encoded_stack_type(desc.subspan(match_position));
2096 ++consumed_rstack_cells;
2097 }
2098
2099 return stack_consumption{ consumed_stack_cells, consumed_rstack_cells };
2100}
2101
2103 bool matched = false;
2104 int32_t stack_consumed = 0;
2106 int32_t word_index = 0;
2108};
2109
2110inline word_match_result match_word(word const& w, state_stack& ts, std::vector<word_types> const& all_instances, std::vector<int32_t> const& all_stack_types, environment& env) {
2111 std::vector<int32_t> type_subs;
2112 for(uint32_t i = 0; i < w.instances.size(); ++i) {
2113 if(std::holds_alternative<interpreted_word_instance>(all_instances[w.instances[i]])) {
2114 interpreted_word_instance const& s = std::get<interpreted_word_instance>(all_instances[w.instances[i]]);
2115 auto mr = match_stack_description(std::span<int32_t const>(all_stack_types.data() + s.stack_types_start, size_t(s.stack_types_count)), ts, env, type_subs);
2116 if(mr.matched) {
2117 return word_match_result{ mr.matched, mr.stack_consumed, mr.ret_stack_consumed, w.instances[i], 0 };
2118 }
2119 type_subs.clear();
2120 } else if(std::holds_alternative<compiled_word_instance>(all_instances[w.instances[i]])) {
2121 compiled_word_instance const& s = std::get<compiled_word_instance>(all_instances[w.instances[i]]);
2122 auto mr = match_stack_description(std::span<int32_t const>(all_stack_types.data() + s.stack_types_start, size_t(s.stack_types_count)), ts, env, type_subs);
2123 if(mr.matched) {
2124 return word_match_result{ mr.matched, mr.stack_consumed, mr.ret_stack_consumed, w.instances[i], 0 };
2125 }
2126 type_subs.clear();
2127 }
2128 }
2129 return word_match_result{ false, 0, 0, 0, 0 };
2130}
2131
2132inline std::string_view read_word(std::string_view source, uint32_t& read_position) {
2133 uint32_t first_non_space = read_position;
2134 while(first_non_space < source.length() && (source[first_non_space] == ' ' || source[first_non_space] == '\t'))
2135 ++first_non_space;
2136
2137 auto word_end = first_non_space;
2138 while(word_end < source.length() && source[word_end] != ' ' && source[word_end] != '\t')
2139 ++word_end;
2140
2141 read_position = word_end;
2142
2143 return source.substr(first_non_space, word_end - first_non_space);
2144}
2145
2147 int32_t* ptr = wi.compiled_bytecode.data();
2148 while(ptr) {
2149 fif_call fn = nullptr;
2150 memcpy(&fn, ptr, 8);
2151 ptr = fn(ss, ptr, &env);
2152#ifdef HEAP_CHECKS
2153 assert(_CrtCheckMemory());
2154#endif
2155 }
2156}
2158 wi.implementation(ss, nullptr, &env);
2159}
2160inline void execute_fif_word(state_stack& ss, int32_t* ptr, environment& env) {
2161 while(ptr) {
2162 fif_call fn = nullptr;
2163 memcpy(&fn, ptr, 8);
2164 ptr = fn(ss, ptr, &env);
2165#ifdef HEAP_CHECKS
2166 assert(_CrtCheckMemory());
2167#endif
2168 }
2169}
2170
2171inline int32_t* immediate_i32(state_stack& s, int32_t* p, environment*) {
2172 int32_t data = 0;
2173 memcpy(&data, p + 2, 4);
2174 s.push_back_main(fif_i32, data, nullptr);
2175 return p + 3;
2176}
2177inline int32_t* immediate_f32(state_stack& s, int32_t* p, environment*) {
2178 int64_t data = 0;
2179 memcpy(&data, p + 2, 4);
2180 s.push_back_main(fif_f32, data, nullptr);
2181 return p + 3;
2182}
2183inline int32_t* immediate_bool(state_stack& s, int32_t* p, environment*) {
2184 int32_t data = 0;
2185 memcpy(&data, p + 2, 4);
2186 s.push_back_main(fif_bool, data, nullptr);
2187 return p + 3;
2188}
2189inline void do_immediate_i32(state_stack& s, int32_t value, environment* e) {
2191 return;
2192
2193 auto compile_bytes = e->compiler_stack.back()->bytecode_compilation_progress();
2194 if(compile_bytes && e->mode == fif_mode::compiling_bytecode) {
2195 fif_call imm = immediate_i32;
2196 uint64_t imm_bytes = 0;
2197 memcpy(&imm_bytes, &imm, 8);
2198 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
2199 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
2200 compile_bytes->push_back(value);
2201 }
2202 LLVMValueRef val = nullptr;
2203#ifdef USE_LLVM
2204 if(e->mode == fif_mode::compiling_llvm) {
2205 val = LLVMConstInt(LLVMInt32TypeInContext(e->llvm_context), uint32_t(value), true);
2206 }
2207#endif
2208 s.push_back_main(fif_i32, value, val);
2209}
2210inline int32_t* immediate_type(state_stack& s, int32_t* p, environment*) {
2211 int32_t data = 0;
2212 memcpy(&data, p + 2, 4);
2213 s.push_back_main(fif_type, data, nullptr);
2214 return p + 3;
2215}
2216inline void do_immediate_type(state_stack& s, int32_t value, environment* e) {
2218 return;
2219
2220 auto compile_bytes = e->compiler_stack.back()->bytecode_compilation_progress();
2221 if(compile_bytes && e->mode == fif_mode::compiling_bytecode) {
2223 uint64_t imm_bytes = 0;
2224 memcpy(&imm_bytes, &imm, 8);
2225 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
2226 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
2227 compile_bytes->push_back(value);
2228 }
2229 LLVMValueRef val = nullptr;
2230#ifdef USE_LLVM
2231 if(e->mode == fif_mode::compiling_llvm) {
2232 val = LLVMConstInt(LLVMInt32TypeInContext(e->llvm_context), uint32_t(value), true);
2233 }
2234#endif
2235 s.push_back_main(fif_type, value, val);
2236}
2237inline void do_immediate_bool(state_stack& s, bool value, environment* e) {
2239 return;
2240
2241 auto compile_bytes = e->compiler_stack.back()->bytecode_compilation_progress();
2242 if(compile_bytes && e->mode == fif_mode::compiling_bytecode) {
2244 uint64_t imm_bytes = 0;
2245 memcpy(&imm_bytes, &imm, 8);
2246 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
2247 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
2248 compile_bytes->push_back(int32_t(value));
2249 }
2250 LLVMValueRef val = nullptr;
2251#ifdef USE_LLVM
2252 if(e->mode == fif_mode::compiling_llvm) {
2253 val = LLVMConstInt(LLVMInt1TypeInContext(e->llvm_context), uint32_t(value), true);
2254 }
2255#endif
2256 s.push_back_main(fif_bool, int64_t(value), val);
2257}
2258inline void do_immediate_f32(state_stack& s, float value, environment* e) {
2260 return;
2261
2262 int32_t v4 = 0;
2263 int64_t v8 = 0;
2264 memcpy(&v4, &value, 4);
2265 memcpy(&v8, &value, 4);
2266
2267 auto compile_bytes = e->compiler_stack.back()->bytecode_compilation_progress();
2268 if(compile_bytes && e->mode == fif_mode::compiling_bytecode) {
2269 fif_call imm = immediate_f32;
2270 uint64_t imm_bytes = 0;
2271 memcpy(&imm_bytes, &imm, 8);
2272 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
2273 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
2274 compile_bytes->push_back(v4);
2275 }
2276 LLVMValueRef val = nullptr;
2277#ifdef USE_LLVM
2278 if(e->mode == fif_mode::compiling_llvm) {
2279 val = LLVMConstReal(LLVMFloatTypeInContext(e->llvm_context), value);
2280 }
2281#endif
2282 s.push_back_main(fif_f32, v8, val);
2283}
2284inline int32_t* function_return(state_stack& s, int32_t* p, environment*) {
2285 return nullptr;
2286}
2287
2289 std::string_view content;
2290 bool is_string = false;
2291};
2292
2293inline void execute_fif_word(parse_result word, environment& env, bool ignore_specializations);
2294
2295#ifdef USE_LLVM
2296inline LLVMTypeRef llvm_function_type_from_desc(environment& env, std::span<int32_t const> desc) {
2297 std::vector<LLVMTypeRef> parameter_group;
2298 std::vector<LLVMTypeRef> returns_group;
2299
2300 /*
2301 * NOTE: function assumes that description is fully resolved
2302 */
2303
2304 int32_t match_position = 0;
2305 // stack matching
2306
2307 //int32_t consumed_stack_cells = 0;
2308 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2309 parameter_group.push_back(env.dict.type_array[desc[match_position]].llvm_type);
2310 ++match_position;
2311 //++consumed_stack_cells;
2312 }
2313
2314 ++match_position; // skip -1
2315
2316 // output stack
2317 int32_t first_output_stack = match_position;
2318 //int32_t output_stack_types = 0;
2319 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2320 returns_group.push_back(env.dict.type_array[desc[match_position]].llvm_type);
2321 ++match_position;
2322 //++output_stack_types;
2323 }
2324 ++match_position; // skip -1
2325
2326 // return stack matching
2327 //int32_t consumed_rstack_cells = 0;
2328 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2329 parameter_group.push_back(env.dict.type_array[desc[match_position]].llvm_type);
2330 ++match_position;
2331 //++consumed_rstack_cells;
2332 }
2333
2334 ++match_position; // skip -1
2335
2336 // output ret stack
2337 //int32_t ret_added = 0;
2338 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2339 returns_group.push_back(env.dict.type_array[desc[match_position]].llvm_type);
2340 ++match_position;
2341 //++ret_added;
2342 }
2343
2344 LLVMTypeRef ret_type = nullptr;
2345 if(returns_group.size() == 0) {
2346 ret_type = LLVMVoidTypeInContext(env.llvm_context);
2347 } else if(returns_group.size() == 1) {
2348 ret_type = returns_group[0];
2349 } else {
2350 ret_type = LLVMStructTypeInContext(env.llvm_context, returns_group.data(), uint32_t(returns_group.size()), false);
2351 }
2352 return LLVMFunctionType(ret_type, parameter_group.data(), uint32_t(parameter_group.size()), false);
2353}
2354
2355inline void llvm_make_function_parameters(environment& env, LLVMValueRef fn, state_stack& ws, std::span<int32_t const> desc) {
2356
2357 /*
2358 * NOTE: function assumes that description is fully resolved
2359 */
2360
2361 int32_t match_position = 0;
2362 // stack matching
2363
2364 int32_t consumed_stack_cells = 0;
2365 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2366 ws.set_main_ex_back(consumed_stack_cells, LLVMGetParam(fn, uint32_t(consumed_stack_cells)));
2367 ++match_position;
2368 ++consumed_stack_cells;
2369 }
2370
2371 ++match_position; // skip -1
2372
2373 // output stack
2374 int32_t first_output_stack = match_position;
2375 //int32_t output_stack_types = 0;
2376 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2377 ++match_position;
2378 //++output_stack_types;
2379 }
2380 ++match_position; // skip -1
2381
2382 // return stack matching
2383 int32_t consumed_rstack_cells = 0;
2384 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2385 ws.set_return_ex_back(consumed_rstack_cells, LLVMGetParam(fn, uint32_t(consumed_stack_cells + consumed_stack_cells)));
2386 ++match_position;
2387 ++consumed_rstack_cells;
2388 }
2389
2390 ++match_position; // skip -1
2391
2392 // output ret stack
2393 //int32_t ret_added = 0;
2394 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2395 ++match_position;
2396 //++ret_added;
2397 }
2398}
2399
2400struct brief_fn_return {
2401 LLVMTypeRef composite_type = nullptr;
2402 int32_t num_stack_values;
2403 int32_t num_rstack_values;
2404 bool is_struct_type;
2405};
2406
2407inline brief_fn_return llvm_function_return_type_from_desc(environment& env, std::span<int32_t const> desc) {
2408 std::vector<LLVMTypeRef> returns_group;
2409
2410 /*
2411 * NOTE: function assumes that description is fully resolved
2412 */
2413
2414 int32_t match_position = 0;
2415 // stack matching
2416
2417 //int32_t consumed_stack_cells = 0;
2418 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2419 //parameter_group.push_back(env.dict.type_array[desc[match_position]].llvm_type);
2420 ++match_position;
2421 //++consumed_stack_cells;
2422 }
2423
2424 ++match_position; // skip -1
2425
2426 // output stack
2427 int32_t first_output_stack = match_position;
2428 int32_t output_stack_types = 0;
2429 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2430 returns_group.push_back(env.dict.type_array[desc[match_position]].llvm_type);
2431 ++match_position;
2432 ++output_stack_types;
2433 }
2434 ++match_position; // skip -1
2435
2436 // return stack matching
2437 //int32_t consumed_rstack_cells = 0;
2438 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2439 //parameter_group.push_back(env.dict.type_array[desc[match_position]].llvm_type);
2440 ++match_position;
2441 //++consumed_rstack_cells;
2442 }
2443
2444 ++match_position; // skip -1
2445
2446 // output ret stack
2447 int32_t ret_added = 0;
2448 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2449 returns_group.push_back(env.dict.type_array[desc[match_position]].llvm_type);
2450 ++match_position;
2451 ++ret_added;
2452 }
2453
2454 LLVMTypeRef ret_type = nullptr;
2455 if(returns_group.size() == 0) {
2456 // leave as nullptr
2457 } else if(returns_group.size() == 1) {
2458 ret_type = returns_group[0];
2459 } else {
2460 ret_type = LLVMStructTypeInContext(env.llvm_context, returns_group.data(), uint32_t(returns_group.size()), false);
2461 }
2462 return brief_fn_return{ ret_type , output_stack_types, ret_added, returns_group.size() > 1};
2463}
2464
2465inline void llvm_make_function_return(environment& env, std::span<int32_t const> desc) {
2466 auto rsummary = llvm_function_return_type_from_desc( env, desc);
2467
2468 if(rsummary.composite_type == nullptr) {
2469 LLVMBuildRetVoid(env.llvm_builder);
2470 return;
2471 }
2472 if(rsummary.is_struct_type == false) {
2473 if(rsummary.num_stack_values == 0) {
2474 LLVMBuildRet(env.llvm_builder, env.compiler_stack.back()->working_state()->return_ex_back(0));
2475 return;
2476 } else if(rsummary.num_rstack_values == 0) {
2477 LLVMBuildRet(env.llvm_builder, env.compiler_stack.back()->working_state()->main_ex_back(0));
2478 return;
2479 } else {
2480 assert(false);
2481 }
2482 }
2483
2484 auto rstruct = LLVMGetUndef(rsummary.composite_type);
2485 uint32_t insert_index = 0;
2486
2487 for(int32_t i = rsummary.num_stack_values - 1; i >= 0; --i) {
2488 rstruct = LLVMBuildInsertValue(env.llvm_builder, rstruct, env.compiler_stack.back()->working_state()->main_ex_back(i), insert_index, "");
2489 ++insert_index;
2490 }
2491 for(int32_t i = rsummary.num_rstack_values - 1; i >= 0; --i) {
2492 rstruct = LLVMBuildInsertValue(env.llvm_builder, rstruct, env.compiler_stack.back()->working_state()->return_ex_back(i), insert_index, "");
2493 ++insert_index;
2494 }
2495 LLVMBuildRet(env.llvm_builder, rstruct);
2496 // LLVMBuildAggregateRet(env.llvm_builder, LLVMValueRef * RetVals, unsigned N);
2497}
2498
2499inline void llvm_make_function_call(environment& env, LLVMValueRef fn, std::span<int32_t const> desc) {
2500 std::vector<LLVMValueRef> params;
2501
2502 {
2503 int32_t match_position = 0;
2504 // stack matching
2505
2506 //int32_t consumed_stack_cells = 0;
2507 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2508 params.push_back(env.compiler_stack.back()->working_state()->main_ex_back(0));
2509 env.compiler_stack.back()->working_state()->pop_main();
2510 ++match_position;
2511 //++consumed_stack_cells;
2512 }
2513
2514 ++match_position; // skip -1
2515
2516 // output stack
2517 int32_t first_output_stack = match_position;
2518 //int32_t output_stack_types = 0;
2519 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2520 //returns_group.push_back(env.dict.type_array[desc[match_position]].llvm_type.llvm_type);
2521 ++match_position;
2522 //++output_stack_types;
2523 }
2524 ++match_position; // skip -1
2525
2526 // return stack matching
2527 //int32_t consumed_rstack_cells = 0;
2528 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2529 params.push_back(env.compiler_stack.back()->working_state()->return_ex_back(0));
2530 env.compiler_stack.back()->working_state()->pop_return();
2531 ++match_position;
2532 //++consumed_rstack_cells;
2533 }
2534 }
2535
2536 assert(fn);
2537 auto retvalue = LLVMBuildCall2(env.llvm_builder, llvm_function_type_from_desc(env, desc), fn, params.data(), uint32_t(params.size()), "");
2538 LLVMSetInstructionCallConv(retvalue, LLVMCallConv::LLVMFastCallConv);
2539 auto rsummary = llvm_function_return_type_from_desc(env, desc);
2540
2541 if(rsummary.composite_type == nullptr) {
2542 return;
2543 }
2544
2545 {
2546 uint32_t extract_index = 0;
2547 int32_t match_position = 0;
2548 // stack matching
2549
2550 //int32_t consumed_stack_cells = 0;
2551 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2552 //parameter_group.push_back(env.dict.type_array[desc[match_position]].llvm_type);
2553 ++match_position;
2554 //++consumed_stack_cells;
2555 }
2556
2557 ++match_position; // skip -1
2558
2559 // output stack
2560 int32_t first_output_stack = match_position;
2561 //int32_t output_stack_types = 0;
2562 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2563 if(rsummary.is_struct_type == false) { // single return value
2564 env.compiler_stack.back()->working_state()->push_back_main(desc[match_position], 0, retvalue);
2565 } else {
2566 env.compiler_stack.back()->working_state()->push_back_main(desc[match_position], 0, LLVMBuildExtractValue(env.llvm_builder, retvalue, extract_index, ""));
2567 }
2568 ++extract_index;
2569 ++match_position;
2570 //++output_stack_types;
2571 }
2572 ++match_position; // skip -1
2573
2574 // return stack matching
2575 //int32_t consumed_rstack_cells = 0;
2576 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2577 //parameter_group.push_back(env.dict.type_array[desc[match_position]].llvm_type);
2578 ++match_position;
2579 //++consumed_rstack_cells;
2580 }
2581
2582 ++match_position; // skip -1
2583
2584 // output ret stack
2585 //int32_t ret_added = 0;
2586 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
2587 if(rsummary.is_struct_type == false) { // single return value
2588 env.compiler_stack.back()->working_state()->push_back_return(desc[match_position], 0, retvalue);
2589 } else {
2590 env.compiler_stack.back()->working_state()->push_back_return(desc[match_position], 0, LLVMBuildExtractValue(env.llvm_builder, retvalue, extract_index, ""));
2591 }
2592 ++extract_index;
2593 ++match_position;
2594 //++ret_added;
2595 }
2596 }
2597}
2598#endif
2599
2600inline std::vector<int32_t> expand_stack_description(state_stack& initial_stack_state, std::span<const int32_t> desc, int32_t stack_consumed, int32_t rstack_consumed);
2601inline bool compare_stack_description(std::span<const int32_t> a, std::span<const int32_t> b);
2602
2604public:
2605 ankerl::unordered_dense::map<std::string, std::unique_ptr<var_data>> vars;
2606 ankerl::unordered_dense::map<std::string, std::unique_ptr<let_data>> lets;
2608 const bool llvm_mode;
2609
2611 }
2612
2613 virtual var_data* get_var(std::string const& name)override {
2614 if(auto it = vars.find(name); it != vars.end()) {
2615 return it->second.get();
2616 }
2617 return parent->get_var(name);
2618 }
2619 virtual var_data* create_var(std::string const& name, int32_t type)override {
2620 if(auto it = lets.find(name); it != lets.end()) {
2621 return nullptr;
2622 }
2623 if(auto it = vars.find(name); it != vars.end()) {
2624 return nullptr;
2625 }
2626
2627 auto added = vars.insert_or_assign(name, std::make_unique<var_data>());
2628 added.first->second->type = type;
2629 added.first->second->data = 0;
2630#ifdef USE_LLVM
2631 added.first->second->alloc = llvm_mode ? LLVMBuildAlloca(env.llvm_builder, env.dict.type_array[type].llvm_type, name.c_str()) : nullptr;
2632#endif
2633 return added.first->second.get();
2634 }
2635 virtual let_data* get_let(std::string const& name) override {
2636 if(auto it = lets.find(name); it != lets.end()) {
2637 return it->second.get();
2638 }
2639 return parent->get_let(name);
2640 }
2641 virtual let_data* create_let(std::string const& name, int32_t type, int64_t data, LLVMValueRef expression)override {
2642 if(auto it = lets.find(name); it != lets.end()) {
2643 return nullptr;
2644 }
2645 if(auto it = vars.find(name); it != vars.end()) {
2646 return nullptr;
2647 }
2648 auto added = lets.insert_or_assign(name, std::make_unique<let_data>());
2649 added.first->second->type = type;
2650 added.first->second->data = data;
2651 added.first->second->expression = expression;
2652 if(auto it = lets.find(name); it != lets.end()) {
2653 return it->second.get();
2654 }
2655 return nullptr;
2656 }
2657
2659 auto* ws = env.compiler_stack.back()->working_state();
2660 for(auto& l : vars) {
2661 if(env.dict.type_array[l.second->type].flags != 0) {
2662#ifdef USE_LLVM
2663 auto iresult = LLVMBuildLoad2(env.llvm_builder, env.dict.type_array[l.second->type].llvm_type, l.second->alloc, "");
2664#else
2665 void* iresult = nullptr;
2666#endif
2667 ws->push_back_main(l.second->type, l.second->data, iresult);
2668 execute_fif_word(fif::parse_result{ "drop", false }, env, false);
2669 }
2670 }
2671 for(auto& l : lets) {
2672 if(env.dict.type_array[l.second->type].flags != 0) {
2673 ws->push_back_main(l.second->type, l.second->data, l.second->expression);
2674 execute_fif_word(fif::parse_result{ "drop", false }, env, false);
2675 }
2676 }
2677 vars.clear();
2678 lets.clear();
2679 }
2680};
2681
2683public:
2684 std::unique_ptr<state_stack> initial_state;
2685 std::unique_ptr<state_stack> iworking_state;
2686 std::vector<int32_t> compiled_bytes;
2687 std::vector<int32_t> type_subs;
2690 int32_t for_word = -1;
2691 int32_t for_instance = -1;
2692
2693
2695
2696 initial_state = entry_state.copy();
2697 iworking_state = entry_state.copy();
2698
2699 if(for_word == -1) {
2700 env.report_error("attempted to compile a function for an anonymous word");
2702 return;
2703 }
2704
2705
2707 env.dict.word_array[for_word].being_typechecked = true;
2709 assert(for_instance != -1);
2710 std::get<interpreted_word_instance>(env.dict.all_instances[for_instance]).being_compiled = true;
2711 }
2712
2714 assert(for_instance != -1);
2715 auto fn_desc = std::span<int32_t const>(env.dict.all_stack_types.data() + std::get<interpreted_word_instance>(env.dict.all_instances[for_instance]).stack_types_start, std::get<interpreted_word_instance>(env.dict.all_instances[for_instance]).stack_types_count);
2716
2717#ifdef USE_LLVM
2718 if(!std::get<interpreted_word_instance>(env.dict.all_instances[for_instance]).llvm_function) {
2719 auto fn_string_name = word_name_from_id(for_word, env) + "#" + std::to_string(for_instance);
2720 auto fn_type = llvm_function_type_from_desc(env, fn_desc);
2721 std::get<interpreted_word_instance>(env.dict.all_instances[for_instance]).llvm_function = LLVMAddFunction(env.llvm_module, fn_string_name.c_str(), fn_type);
2722 }
2723#endif
2724 auto compiled_fn = std::get<interpreted_word_instance>(env.dict.all_instances[for_instance]).llvm_function;
2725 llvm_fn = compiled_fn;
2726
2727#ifdef USE_LLVM
2728 if(std::get<interpreted_word_instance>(env.dict.all_instances[for_instance]).is_imported_function)
2729 LLVMSetFunctionCallConv(compiled_fn, NATIVE_CC);
2730 else
2731 LLVMSetFunctionCallConv(compiled_fn, LLVMCallConv::LLVMFastCallConv);
2732
2733 LLVMSetLinkage(compiled_fn, LLVMLinkage::LLVMPrivateLinkage);
2734 auto entry_block = LLVMAppendBasicBlockInContext(env.llvm_context, compiled_fn, "fn_entry_point");
2735 LLVMPositionBuilderAtEnd(env.llvm_builder, entry_block);
2736 llvm_make_function_parameters(env, compiled_fn, *iworking_state, fn_desc);
2737
2738 current_block = entry_block;
2739#endif
2740 }
2741
2742 }
2743 virtual std::vector<int32_t>* type_substitutions()override {
2744 return &type_subs;
2745 }
2746 virtual control_structure get_type()override {
2748 }
2749 virtual LLVMValueRef llvm_function()override {
2750 return llvm_fn;
2751 }
2752 virtual LLVMBasicBlockRef* llvm_block() override {
2753 return &current_block;
2754 }
2755 virtual int32_t word_id()override {
2756 return for_word;
2757 }
2758 virtual int32_t instance_id()override {
2759 return for_instance;
2760 }
2761 virtual std::vector<int32_t>* bytecode_compilation_progress()override {
2762 return &compiled_bytes;
2763 }
2764 virtual ankerl::unordered_dense::map<uint64_t, typecheck_3_record>* typecheck_record()override {
2765 return parent ? parent->typecheck_record() : nullptr;
2766 }
2767 virtual state_stack* working_state()override {
2768 return iworking_state.get();
2769 }
2770 virtual void set_working_state(std::unique_ptr<state_stack> p) override {
2771 iworking_state = std::move(p);
2772 }
2773 virtual bool finish(environment&)override {
2774 int32_t stack_consumed = int32_t(initial_state->main_size()) - int32_t(iworking_state->min_main_depth);
2775 int32_t rstack_consumed = int32_t(initial_state->return_size()) - int32_t(iworking_state->min_return_depth);
2776 int32_t stack_added = int32_t(iworking_state->main_size()) - int32_t(iworking_state->min_main_depth);
2777 int32_t rstack_added = int32_t(iworking_state->return_size()) - int32_t(iworking_state->min_return_depth);
2778 assert(stack_added >= 0);
2779 assert(rstack_added >= 0);
2780 assert(stack_consumed >= 0);
2781 assert(rstack_consumed >= 0);
2782
2785
2787 auto& current_stack = *iworking_state;
2788
2789 temp.stack_types_start = int32_t(env.dict.all_stack_types.size());
2790 {
2791 for(int32_t i = 0; i < stack_consumed; ++i) {
2792 env.dict.all_stack_types.push_back(initial_state->main_type_back(i));
2793 }
2794 }
2795 int32_t skipped = 0;
2796 if(stack_added > 0) {
2797 env.dict.all_stack_types.push_back(-1);
2798 for(int32_t i = 1; i <= stack_added; ++i) {
2799 env.dict.all_stack_types.push_back(current_stack.main_type_back(stack_added - i));
2800 }
2801 } else {
2802 ++skipped;
2803 }
2804 if(rstack_consumed > 0) {
2805 for(; skipped > 0; --skipped)
2806 env.dict.all_stack_types.push_back(-1);
2807 env.dict.all_stack_types.push_back(-1);
2808 for(int32_t i = 0; i < rstack_consumed; ++i) {
2809 env.dict.all_stack_types.push_back(initial_state->return_type_back(i));
2810 }
2811 } else {
2812 ++skipped;
2813 }
2814 if(rstack_added > 0) {
2815 for(; skipped > 0; --skipped)
2816 env.dict.all_stack_types.push_back(-1);
2817 env.dict.all_stack_types.push_back(-1);
2818 for(int32_t i = 1; i <= rstack_added; ++i) {
2819 env.dict.all_stack_types.push_back(current_stack.return_type_back(rstack_added - i));
2820 }
2821 }
2822 temp.stack_types_count = int32_t(env.dict.all_stack_types.size()) - temp.stack_types_start;
2823 temp.typechecking_level = 1;
2824
2825 if(for_instance == -1) {
2826 w.instances.push_back(int32_t(env.dict.all_instances.size()));
2827 env.dict.all_instances.push_back(std::move(temp));
2828 } else if(std::get<interpreted_word_instance>(env.dict.all_instances[for_instance]).typechecking_level == 0) {
2829 env.dict.all_instances[for_instance] = std::move(temp);
2830 }
2831
2832 env.dict.word_array[for_word].being_typechecked = false;
2833 } else if(env.mode == fif_mode::typechecking_lvl_2) {
2834 if(for_instance == -1) {
2835 env.report_error("tried to level 2 typecheck a word without an instance");
2837 return true;
2838 }
2839 interpreted_word_instance& wi = std::get<interpreted_word_instance>(env.dict.all_instances[for_instance]);
2840 std::span<const int32_t> existing_description = std::span<const int32_t>(env.dict.all_stack_types.data() + wi.stack_types_start, size_t(wi.stack_types_count));
2841 auto revised_description = expand_stack_description(*initial_state, existing_description, stack_consumed, rstack_consumed);
2842
2843 if(!compare_stack_description(existing_description, std::span<const int32_t>(revised_description.data(), revised_description.size()))) {
2844 wi.stack_types_start = int32_t(env.dict.all_stack_types.size());
2845 wi.stack_types_count = int32_t(revised_description.size());
2846 env.dict.all_stack_types.insert(env.dict.all_stack_types.end(), revised_description.begin(), revised_description.end());
2847 }
2848
2849 wi.typechecking_level = std::max(wi.typechecking_level, 2);
2850 env.dict.word_array[for_word].being_typechecked = false;
2851 } else if(env.mode == fif_mode::typechecking_lvl_3) {
2852 // no alterations -- handled explicitly by invoking lvl 3
2853 env.dict.word_array[for_word].being_typechecked = false;
2854 } else if(env.mode == fif_mode::compiling_bytecode) {
2855 if(for_instance == -1) {
2856 env.report_error("tried to compile a word without an instance");
2858 return true;
2859 }
2860
2862 uint64_t imm_bytes = 0;
2863 memcpy(&imm_bytes, &imm, 8);
2864 compiled_bytes.push_back(int32_t(imm_bytes & 0xFFFFFFFF));
2865 compiled_bytes.push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
2866
2867 interpreted_word_instance& wi = std::get<interpreted_word_instance>(env.dict.all_instances[for_instance]);
2868 wi.compiled_bytecode = std::move(compiled_bytes);
2869
2870 if(for_instance != -1)
2871 std::get<interpreted_word_instance>(env.dict.all_instances[for_instance]).being_compiled = false;
2872 } else if(env.mode == fif_mode::compiling_llvm) {
2873#ifdef USE_LLVM
2874 if(for_instance == -1) {
2875 env.report_error("tried to compile a word without an instance");
2877 return true;
2878 }
2879
2880 release_locals();
2881
2882 interpreted_word_instance& wi = std::get<interpreted_word_instance>(env.dict.all_instances[for_instance]);
2883 std::span<const int32_t> existing_description = std::span<const int32_t>(env.dict.all_stack_types.data() + wi.stack_types_start, size_t(wi.stack_types_count));
2884 llvm_make_function_return(env, existing_description);
2885 wi.llvm_compilation_finished = true;
2886
2887 if(LLVMVerifyFunction(wi.llvm_function, LLVMVerifierFailureAction::LLVMPrintMessageAction)) {
2888
2889 std::string mod_contents = LLVMPrintModuleToString(env.llvm_module);
2890
2891 char* message = nullptr;
2892 LLVMVerifyModule(env.llvm_module, LLVMReturnStatusAction, &message);
2893
2894 env.report_error("LLVM verification of function failed");
2896 return true;
2897 }
2898
2899 if(for_instance != -1)
2900 std::get<interpreted_word_instance>(env.dict.all_instances[for_instance]).being_compiled = false;
2901#endif
2902 } else if(typechecking_failed(env.mode)) {
2903 env.dict.word_array[for_word].being_typechecked = false;
2904 return true;
2905 } else {
2906 env.report_error("reached end of compilation in unexpected mode");
2908 return true;
2909 }
2910 return true;
2911 }
2912};
2913
2915public:
2917 }
2918 virtual bool finish(environment&) override {
2920 return true;
2921 }
2922 virtual control_structure get_type() override {
2924 }
2925};
2926inline int32_t* call_function(state_stack& s, int32_t* p, environment* env) {
2927 int32_t* jump_target = nullptr;
2928 memcpy(&jump_target, p + 2, 8);
2929 env->compiler_stack.push_back(std::make_unique<runtime_function_scope>(env->compiler_stack.back().get(), *env));
2930 execute_fif_word(s, jump_target, *env);
2931 env->compiler_stack.back()->finish(*env);
2932 env->compiler_stack.pop_back();
2933 return p + 4;
2934}
2935inline int32_t* call_function_indirect(state_stack& s, int32_t* p, environment* env) {
2936 auto instance = *(p + 2);
2937 env->compiler_stack.push_back(std::make_unique<runtime_function_scope>(env->compiler_stack.back().get(), *env));
2938 execute_fif_word(std::get<interpreted_word_instance>(env->dict.all_instances[instance]), s, *env);
2939 env->compiler_stack.back()->finish(*env);
2940 env->compiler_stack.pop_back();
2941 return p + 3;
2942}
2943inline int32_t* enter_scope(state_stack& s, int32_t* p, environment* env) {
2944 env->compiler_stack.push_back(std::make_unique<runtime_function_scope>(env->compiler_stack.back().get(), *env));
2945 return p + 2;
2946}
2947inline int32_t* leave_scope(state_stack& s, int32_t* p, environment* env) {
2948 env->compiler_stack.back()->finish(*env);
2949 env->compiler_stack.pop_back();
2950 return p + 2;
2951}
2952
2954public:
2958
2960 [&]() {
2961 for(auto i = env.compiler_stack.size(); i-- > 0; ) {
2962 if(env.compiler_stack[i]->get_type() == control_structure::mode_switch) {
2963 mode_switch_scope* p = static_cast<mode_switch_scope*>(env.compiler_stack[i].get());
2964 if(p->running_mode == running_mode) {
2965 ++i;
2966 for(; i < env.compiler_stack.size(); ++i) {
2967 if(env.compiler_stack[i]->get_type() == control_structure::mode_switch) {
2968 interpreted_link = env.compiler_stack[i - 1].get();
2969 return;
2970 }
2971 }
2972 interpreted_link = env.compiler_stack[env.compiler_stack.size() - 1].get();
2973 return;
2974 }
2975 }
2976 }
2977 }();
2978 entry_mode = env.mode;
2979 env.mode = running_mode;
2980 }
2981
2982 virtual control_structure get_type()override {
2984 }
2985 virtual ankerl::unordered_dense::map<uint64_t, typecheck_3_record>* typecheck_record() override {
2986 return parent ? parent->typecheck_record() : nullptr;
2987 }
2988 virtual state_stack* working_state() override {
2989 return interpreted_link ? interpreted_link->working_state() : nullptr;
2990 }
2991 virtual var_data* get_var(std::string const& name) override {
2992 return interpreted_link ? interpreted_link->get_var(name) : nullptr;
2993 }
2994 virtual var_data* create_var(std::string const& name, int32_t type) override {
2995 return interpreted_link ? interpreted_link->create_var(name, type) : nullptr;
2996 }
2997 virtual let_data* get_let(std::string const& name) override {
2998 return interpreted_link ? interpreted_link->get_let(name) : nullptr;
2999 }
3000 virtual let_data* create_let(std::string const& name, int32_t type, int64_t data, LLVMValueRef expression)override {
3001 return interpreted_link ? interpreted_link->create_let(name, type, data, expression) : nullptr;
3002 }
3003 virtual void set_working_state(std::unique_ptr<state_stack> p)override {
3005 interpreted_link->set_working_state(std::move(p));
3006 }
3007 virtual bool finish(environment& env)override {
3008 if(env.mode != fif_mode::error) {
3009 env.mode = entry_mode;
3010 }
3011 return true;
3012 }
3013};
3015 auto m = std::make_unique<mode_switch_scope>(env.compiler_stack.back().get(), env, new_mode);
3016 env.compiler_stack.emplace_back(std::move(m));
3017}
3019 if(env.compiler_stack.empty() || env.compiler_stack.back()->get_type() != control_structure::mode_switch) {
3020 env.report_error("attempt to switch mode back revealed an unbalanced compiler stack");
3021 env.mode = fif_mode::error;
3022 return;
3023 }
3024 env.compiler_stack.back()->finish(env);
3025 env.compiler_stack.pop_back();
3026}
3028public:
3029 std::unique_ptr<state_stack> interpreter_state;
3030
3031 ankerl::unordered_dense::map<std::string, std::unique_ptr<var_data>> global_vars;
3032 ankerl::unordered_dense::map<std::string, std::unique_ptr<let_data>> global_lets;
3033
3034 virtual var_data* get_var(std::string const& name) override {
3035 if(auto it = global_vars.find(name); it != global_vars.end()) {
3036 return it->second.get();
3037 }
3038 return nullptr;
3039 }
3040 virtual var_data* create_var(std::string const& name, int32_t type) override {
3041 if(auto it = global_lets.find(name); it != global_lets.end()) {
3042 return nullptr;
3043 }
3044 if(auto it = global_vars.find(name); it != global_vars.end()) {
3045 return nullptr;
3046 }
3047 auto added = global_vars.insert_or_assign(name, std::make_unique<var_data>());
3048 added.first->second->type = type;
3049 added.first->second->data = 0;
3050 added.first->second->alloc = nullptr;
3051 return added.first->second.get();
3052 }
3053 virtual let_data* get_let(std::string const& name) override {
3054 if(auto it = global_lets.find(name); it != global_lets.end()) {
3055 return it->second.get();
3056 }
3057 return nullptr;
3058 }
3059 virtual let_data* create_let(std::string const& name, int32_t type, int64_t data, LLVMValueRef expression) override {
3060 if(auto it = global_lets.find(name); it != global_lets.end()) {
3061 return nullptr;
3062 }
3063 if(auto it = global_vars.find(name); it != global_vars.end()) {
3064 return nullptr;
3065 }
3066 auto added = global_lets.insert_or_assign(name, std::make_unique<let_data>());
3067 added.first->second->type = type;
3068 added.first->second->data = data;
3069 added.first->second->expression = expression;
3070 if(auto it = global_lets.find(name); it != global_lets.end()) {
3071 return it->second.get();
3072 }
3073 return nullptr;
3074 }
3075
3077 }
3078 virtual control_structure get_type() override {
3080 }
3081 virtual state_stack* working_state()override {
3082 return interpreter_state.get();
3083 }
3084 virtual void set_working_state(std::unique_ptr<state_stack> p) override {
3085 interpreter_state = std::move(p);
3086 }
3087 virtual bool finish(environment& env)override {
3088 return true;
3089 }
3090};
3092public:
3093 ankerl::unordered_dense::map<uint64_t, typecheck_3_record> tr;
3094
3096 }
3097
3098 virtual control_structure get_type() override {
3100 }
3101 virtual ankerl::unordered_dense::map<uint64_t, typecheck_3_record>* typecheck_record()override {
3102 return &tr;
3103 }
3104 virtual bool finish(environment& env)override {
3105 return true;
3106 }
3107};
3108
3109
3110inline std::vector<int32_t> expand_stack_description(state_stack& initial_stack_state, std::span<const int32_t> desc, int32_t stack_consumed, int32_t rstack_consumed) {
3111 int32_t match_position = 0;
3112 // stack matching
3113
3114 std::vector<int32_t> result;
3115
3116 int32_t consumed_stack_cells = 0;
3117 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
3118 auto match_size = next_encoded_stack_type(desc.subspan(match_position));
3119 result.insert(result.end(), desc.data() + match_position, desc.data() + match_position + match_size);
3120 match_position += match_size;
3121 ++consumed_stack_cells;
3122 }
3123 if(consumed_stack_cells < stack_consumed) {
3124 for(int32_t i = consumed_stack_cells; i < stack_consumed; ++i) {
3125 result.push_back(initial_stack_state.main_type_back(i));
3126 }
3127 }
3128
3129 if(consumed_stack_cells < stack_consumed || (match_position < int32_t(desc.size()) && desc[match_position] == -1)) {
3130 result.push_back(-1);
3131 }
3132 ++match_position; // skip -1
3133
3134 if(consumed_stack_cells < stack_consumed) { // add additional touched inputs to the end
3135 for(int32_t i = stack_consumed - 1; i >= consumed_stack_cells; --i) {
3136 result.push_back(initial_stack_state.main_type_back(i));
3137 }
3138 }
3139
3140 int32_t first_output_stack = match_position;
3141 //int32_t output_stack_types = 0;
3142 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
3143 auto match_size = next_encoded_stack_type(desc.subspan(match_position));
3144 result.insert(result.end(), desc.data() + match_position, desc.data() + match_position + match_size);
3145 match_position += match_size;
3146 //++output_stack_types;
3147 }
3148
3149 if(rstack_consumed > 0 || (match_position < int32_t(desc.size()) && desc[match_position] == -1)) {
3150 result.push_back(-1);
3151 }
3152 ++match_position; // skip -1
3153
3154 // return stack matching
3155 int32_t consumed_rstack_cells = 0;
3156 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
3157 auto match_size = next_encoded_stack_type(desc.subspan(match_position));
3158 result.insert(result.end(), desc.data() + match_position, desc.data() + match_position + match_size);
3159 match_position += match_size;
3160 ++consumed_rstack_cells;
3161 }
3162 if(consumed_rstack_cells < rstack_consumed) {
3163 for(int32_t i = consumed_rstack_cells; i < rstack_consumed; ++i) {
3164 result.push_back(initial_stack_state.return_type_back(i));
3165 }
3166 }
3167
3168 if(consumed_rstack_cells < rstack_consumed || (match_position < int32_t(desc.size()) && desc[match_position] == -1)) {
3169 result.push_back(-1);
3170 }
3171 ++match_position; // skip -1
3172
3173 if(consumed_rstack_cells < rstack_consumed) { // add additional touched inputs to the end
3174 for(int32_t i = rstack_consumed - 1; i >= consumed_rstack_cells; --i) {
3175 result.push_back(initial_stack_state.return_type_back(i));
3176 }
3177 }
3178
3179 // add new types
3180 int32_t ret_added = 0;
3181 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
3182 auto match_size = next_encoded_stack_type(desc.subspan(match_position));
3183 result.insert(result.end(), desc.data() + match_position, desc.data() + match_position + match_size);
3184 match_position += match_size;
3185 }
3186
3187 return result;
3188}
3189
3190inline bool compare_stack_description(std::span<const int32_t> a, std::span<const int32_t> b) {
3191 if(a.size() != b.size())
3192 return false;
3193 for(auto i = a.size(); i-- > 0; ) {
3194 if(a[i] != b[i])
3195 return false;
3196 }
3197 return true;
3198}
3199
3201 if(a.main_size() != b.main_size() || a.return_size() != b.return_size()) {
3202 return false;
3203 }
3204 for(size_t i = a.main_size(); i-- > 0; ) {
3205 if(a.main_type(i) != b.main_type(i))
3206 return false;
3207 }
3208 for(size_t i = a.return_size(); i-- > 0; ) {
3209 if(a.return_type(i) != b.return_type(i))
3210 return false;
3211 }
3212 return true;
3213}
3214
3215inline int32_t* conditional_jump(state_stack& s, int32_t* p, environment* env) {
3216 auto value = s.main_data_back(0);
3217 s.pop_main();
3218 if(value == 0)
3219 return p + *(p + 2);
3220 else
3221 return p + 3;
3222}
3223inline int32_t* reverse_conditional_jump(state_stack& s, int32_t* p, environment* env) {
3224 auto value = s.main_data_back(0);
3225 s.pop_main();
3226 if(value != 0)
3227 return p + *(p + 2);
3228 else
3229 return p + 3;
3230}
3231inline int32_t* unconditional_jump(state_stack& s, int32_t* p, environment* env) {
3232 return p + *(p + 2);
3233}
3234
3236public:
3237 std::unique_ptr<state_stack> initial_state;
3238 std::unique_ptr<state_stack> iworking_state;
3239 std::unique_ptr<state_stack> first_branch_state;
3250
3252 if(entry_state.main_size() == 0 || entry_state.main_type_back(0) != fif_bool) {
3253 env.report_error("attempted to start an if without a boolean value on the stack");
3255 }
3257 if(entry_state.main_data_back(0) != 0) {
3259 } else {
3262 entry_state.pop_main();
3263 }
3264 }
3266#ifdef USE_LLVM
3267 branch_condition = entry_state.main_ex_back(0);
3268 if(auto pb = env.compiler_stack.back()->llvm_block(); pb) {
3269 parent_block = *pb;
3270 *pb = LLVMCreateBasicBlockInContext(env.llvm_context, "if-first-branch");
3271 LLVMAppendExistingBasicBlock(env.compiler_stack.back()->llvm_function(), *pb);
3272 LLVMPositionBuilderAtEnd(env.llvm_builder, *pb);
3273 }
3274#endif
3275 }
3277 auto bcode = parent->bytecode_compilation_progress();
3278
3280 uint64_t imm_bytes = 0;
3281 memcpy(&imm_bytes, &imm, 8);
3282 bcode->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
3283 bcode->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
3284 bytecode_first_branch_point = bcode->size();
3285 bcode->push_back(0);
3286
3287 fif_call imm2 = enter_scope;
3288 uint64_t imm2_bytes = 0;
3289 memcpy(&imm2_bytes, &imm2, 8);
3290 bcode->push_back(int32_t(imm2_bytes & 0xFFFFFFFF));
3291 bcode->push_back(int32_t((imm2_bytes >> 32) & 0xFFFFFFFF));
3292 }
3295 entry_state.pop_main();
3296
3297 initial_state = entry_state.copy();
3298 initial_state->min_main_depth = entry_state.min_main_depth;
3299 initial_state->min_return_depth = entry_state.min_return_depth;
3300
3301 iworking_state = entry_state.copy();
3302 }
3304 if(first_branch_state) {
3305 env.report_error("attempted to compile multiple else conditions");
3307 return;
3308 }
3309
3314 } else { // not interpreted mode
3316 iworking_state = initial_state->copy();
3318
3320#ifdef USE_LLVM
3321 if(auto pb = env.compiler_stack.back()->llvm_block(); pb) {
3322 true_block = *pb;
3323 *pb = LLVMCreateBasicBlockInContext(env.llvm_context, "if-else-branch");
3324 false_block = *pb;
3326 LLVMPositionBuilderAtEnd(env.llvm_builder, *pb);
3327 }
3328#endif
3329 }
3331 auto bcode = parent->bytecode_compilation_progress();
3332 {
3333 fif_call imm2 = leave_scope;
3334 uint64_t imm2_bytes = 0;
3335 memcpy(&imm2_bytes, &imm2, 8);
3336 bcode->push_back(int32_t(imm2_bytes & 0xFFFFFFFF));
3337 bcode->push_back(int32_t((imm2_bytes >> 32) & 0xFFFFFFFF));
3338 }
3340 uint64_t imm_bytes = 0;
3341 memcpy(&imm_bytes, &imm, 8);
3342 bcode->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
3343 bcode->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
3344 bytecode_second_branch_point = bcode->size();
3345 bcode->push_back(0);
3346 (*bcode)[bytecode_first_branch_point] = int32_t(bcode->size() - (bytecode_first_branch_point - 2));
3347 {
3348 fif_call imm2 = enter_scope;
3349 uint64_t imm2_bytes = 0;
3350 memcpy(&imm2_bytes, &imm2, 8);
3351 bcode->push_back(int32_t(imm2_bytes & 0xFFFFFFFF));
3352 bcode->push_back(int32_t((imm2_bytes >> 32) & 0xFFFFFFFF));
3353 }
3354 }
3358 }
3359 }
3360 }
3361 virtual control_structure get_type()override {
3363 }
3364 virtual state_stack* working_state() override {
3365 return iworking_state.get();
3366 }
3367 virtual void set_working_state(std::unique_ptr<state_stack> p)override {
3368 iworking_state = std::move(p);
3369 }
3370 virtual bool finish(environment&)override {
3373 }
3377 return true;
3378 }
3379
3380 bool final_types_match = true;
3381 if(first_branch_state) {
3383 final_types_match = stack_types_match(*first_branch_state, *iworking_state);
3384 }
3385 } else {
3387 final_types_match = stack_types_match(*initial_state , *iworking_state);
3388 }
3389
3390 if(!final_types_match) {
3393 return true;
3394 } else {
3395 env.report_error("inconsistent stack types over a conditional branch");
3397 return true;
3398 }
3399 }
3400
3403 return true; // failed to typecheck on both branches
3406 return true;
3407 }
3408 }
3409
3411
3413 auto bcode = parent->bytecode_compilation_progress();
3414
3415 {
3416 fif_call imm2 = leave_scope;
3417 uint64_t imm2_bytes = 0;
3418 memcpy(&imm2_bytes, &imm2, 8);
3419 bcode->push_back(int32_t(imm2_bytes & 0xFFFFFFFF));
3420 bcode->push_back(int32_t((imm2_bytes >> 32) & 0xFFFFFFFF));
3421 }
3422
3424 (*bcode)[bytecode_first_branch_point] = int32_t(bcode->size() - (bytecode_first_branch_point - 2));
3425 else
3426 (*bcode)[bytecode_second_branch_point] = int32_t(bcode->size() - (bytecode_second_branch_point - 2));
3427 }
3428
3430#ifdef USE_LLVM
3431 auto pb = env.compiler_stack.back()->llvm_block();
3432 auto current_block = *pb;
3433
3434 if(first_branch_state) {
3435
3438 auto in_fn = env.compiler_stack.back()->llvm_function();
3439
3440 auto post_if = LLVMCreateBasicBlockInContext(env.llvm_context, "then-branch");
3441 *pb = post_if;
3442
3443 LLVMAppendExistingBasicBlock(in_fn, post_if);
3444
3445 LLVMPositionBuilderAtEnd(env.llvm_builder, current_block);
3446 LLVMBuildBr(env.llvm_builder, post_if);
3448 LLVMBuildBr(env.llvm_builder, post_if);
3449
3450 /*
3451 * build phi nodes
3452 */
3453
3454 LLVMPositionBuilderAtEnd(env.llvm_builder, post_if);
3455
3456 for(auto i = iworking_state->main_size(); i-- > 0; ) {
3457 if(iworking_state->main_ex(i) != first_branch_state->main_ex(i)) {
3458 auto phi_ref = LLVMBuildPhi(env.llvm_builder, env.dict.type_array[iworking_state->main_type(i)].llvm_type, "if-phi");
3459 LLVMValueRef inc_vals[2] = { iworking_state->main_ex(i), first_branch_state->main_ex(i) };
3460 LLVMBasicBlockRef inc_blocks[2] = { current_block, true_block };
3461 LLVMAddIncoming(phi_ref, inc_vals, inc_blocks, 2);
3462 iworking_state->set_main_ex(i, phi_ref);
3463 } else {
3464 // leave working state as is
3465 }
3466 }
3467 for(auto i = iworking_state->return_size(); i-- > 0; ) {
3468 if(iworking_state->return_ex(i) != first_branch_state->return_ex(i)) {
3469 auto phi_ref = LLVMBuildPhi(env.llvm_builder, env.dict.type_array[iworking_state->return_type(i)].llvm_type, "if-phi");
3470 LLVMValueRef inc_vals[2] = { iworking_state->return_ex(i), first_branch_state->return_ex(i) };
3471 LLVMBasicBlockRef inc_blocks[2] = { current_block, true_block };
3472 LLVMAddIncoming(phi_ref, inc_vals, inc_blocks, 2);
3473 iworking_state->set_return_ex(i, phi_ref);
3474 } else {
3475 // leave working state as is
3476 }
3477 }
3478 } else {
3479 auto in_fn = env.compiler_stack.back()->llvm_function();
3480 auto post_if = LLVMCreateBasicBlockInContext(env.llvm_context, "then-branch");
3481 *pb = post_if;
3482
3483 LLVMAppendExistingBasicBlock(in_fn, post_if);
3484
3486 LLVMBuildCondBr(env.llvm_builder, branch_condition, current_block, post_if);
3487
3488 LLVMPositionBuilderAtEnd(env.llvm_builder, current_block);
3489 LLVMBuildBr(env.llvm_builder, post_if);
3490
3491 /*
3492 * build phi nodes
3493 */
3494
3495 LLVMPositionBuilderAtEnd(env.llvm_builder, post_if);
3496
3497 for(auto i = iworking_state->main_size(); i-- > 0; ) {
3498 if(iworking_state->main_ex(i) != initial_state->main_ex(i)) {
3499 auto phi_ref = LLVMBuildPhi(env.llvm_builder, env.dict.type_array[iworking_state->main_type(i)].llvm_type, "if-phi");
3500 LLVMValueRef inc_vals[2] = { iworking_state->main_ex(i), initial_state->main_ex(i) };
3501 LLVMBasicBlockRef inc_blocks[2] = { current_block, parent_block };
3502 LLVMAddIncoming(phi_ref, inc_vals, inc_blocks, 2);
3503 iworking_state->set_main_ex(i, phi_ref);
3504 } else {
3505 // leave working state as is
3506 }
3507 }
3508 for(auto i = iworking_state->return_size(); i-- > 0; ) {
3509 if(iworking_state->return_ex(i) != initial_state->return_ex(i)) {
3510 auto phi_ref = LLVMBuildPhi(env.llvm_builder, env.dict.type_array[iworking_state->return_type(i)].llvm_type, "if-phi");
3511 LLVMValueRef inc_vals[2] = { iworking_state->return_ex(i), initial_state->return_ex(i) };
3512 LLVMBasicBlockRef inc_blocks[2] = { current_block, parent_block };
3513 LLVMAddIncoming(phi_ref, inc_vals, inc_blocks, 2);
3514 iworking_state->set_return_ex(i, phi_ref);
3515 } else {
3516 // leave working state as is
3517 }
3518 }
3519 }
3520#endif
3521 }
3522
3523 // branch reconciliation
3525 // case: second branch failed to typecheck, but first branch passed
3527 iworking_state->min_main_depth = std::min(iworking_state->min_main_depth, initial_state->min_main_depth);
3528 iworking_state->min_return_depth = std::min(iworking_state->min_return_depth, initial_state->min_return_depth);
3529
3531 // case: first branch failed to typecheck, but second branch passed
3532 iworking_state->min_main_depth = std::min(iworking_state->min_main_depth, initial_state->min_main_depth);
3533 iworking_state->min_return_depth = std::min(iworking_state->min_return_depth, initial_state->min_return_depth);
3534
3536 // case both branches typechecked
3537 iworking_state->min_main_depth = std::min(iworking_state->min_main_depth, first_branch_state->min_main_depth);
3538 iworking_state->min_return_depth = std::min(iworking_state->min_return_depth, first_branch_state->min_return_depth);
3539 iworking_state->min_main_depth = std::min(iworking_state->min_main_depth, initial_state->min_main_depth);
3540 iworking_state->min_return_depth = std::min(iworking_state->min_return_depth, initial_state->min_return_depth);
3542 // case both branches failed to typechecked
3543 // don't set working state
3544 return true;
3545
3547 // case: single branch failed to typecheck
3548 iworking_state = std::move(initial_state);
3549
3551 // case: single branch typechecked
3552 iworking_state->min_main_depth = std::min(iworking_state->min_main_depth, initial_state->min_main_depth);
3553 iworking_state->min_return_depth = std::min(iworking_state->min_return_depth, initial_state->min_return_depth);
3554
3555 } else if(initial_typechecking_failed) {
3556 // case: typechecking failed going into the conditional
3557 // dont set working state
3559 return true;
3560
3561 }
3562
3565 return true;
3566 }
3567};
3568
3570public:
3571 std::unique_ptr<state_stack> initial_state;
3572 std::unique_ptr<state_stack> iworking_state;
3573 std::unique_ptr<state_stack> loop_entry_copy;
3574
3575 std::string_view entry_source;
3578 bool phi_pass = false;
3580 bool saw_conditional = false;
3586 std::vector<LLVMValueRef> phinodes;
3587
3589 initial_state = entry_state.copy();
3590 iworking_state = entry_state.copy();
3591 initial_state->min_main_depth = entry_state.min_main_depth;
3592 initial_state->min_return_depth = entry_state.min_return_depth;
3594
3595 if(!env.source_stack.empty()) {
3596 entry_source = env.source_stack.back();
3597 }
3599 auto bcode = parent->bytecode_compilation_progress();
3600 loop_entry_point = bcode->size();
3601
3602 {
3603 fif_call imm2 = enter_scope;
3604 uint64_t imm2_bytes = 0;
3605 memcpy(&imm2_bytes, &imm2, 8);
3606 bcode->push_back(int32_t(imm2_bytes & 0xFFFFFFFF));
3607 bcode->push_back(int32_t((imm2_bytes >> 32) & 0xFFFFFFFF));
3608 }
3609 }
3611 phi_pass = true;
3613 if(auto pb = env.compiler_stack.back()->llvm_block(); pb) {
3614 pre_block = *pb;
3615 }
3616 }
3617 }
3618
3619 virtual control_structure get_type()override {
3621 }
3622 virtual state_stack* working_state() override {
3623 return iworking_state.get();
3624 }
3625 virtual void set_working_state(std::unique_ptr<state_stack> p) override {
3626 iworking_state = std::move(p);
3627 }
3629 if(saw_conditional) {
3630 env.report_error("multiple conditions in while loop");
3632 return;
3633 }
3634 saw_conditional = true;
3635
3637 if(iworking_state->main_type_back(0) != fif_bool) {
3638 if(!typechecking_mode(env.mode)) {
3639 env.report_error("while loop conditional expression did not produce a boolean");
3641 return;
3642 } else {
3644 return;
3645 }
3646 }
3647
3649
3651 if(iworking_state->main_data_back(0) == 0) {
3652 intepreter_skip_body = true;
3654 }
3655 iworking_state->pop_main();
3656 } else if(env.mode == fif_mode::compiling_bytecode) {
3657 auto bcode = parent->bytecode_compilation_progress();
3658
3659 {
3660 fif_call imm2 = leave_scope;
3661 uint64_t imm2_bytes = 0;
3662 memcpy(&imm2_bytes, &imm2, 8);
3663 bcode->push_back(int32_t(imm2_bytes & 0xFFFFFFFF));
3664 bcode->push_back(int32_t((imm2_bytes >> 32) & 0xFFFFFFFF));
3665 }
3666
3668 uint64_t imm_bytes = 0;
3669 memcpy(&imm_bytes, &imm, 8);
3670 bcode->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
3671 bcode->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
3672 end_of_loop_branch = bcode->size();
3673 bcode->push_back(0);
3674 iworking_state->pop_main();
3675
3676 {
3677 fif_call imm2 = enter_scope;
3678 uint64_t imm2_bytes = 0;
3679 memcpy(&imm2_bytes, &imm2, 8);
3680 bcode->push_back(int32_t(imm2_bytes & 0xFFFFFFFF));
3681 bcode->push_back(int32_t((imm2_bytes >> 32) & 0xFFFFFFFF));
3682 }
3683 } else if(env.mode == fif_mode::compiling_llvm) {
3684#ifdef USE_LLVM
3685 if(auto pb = env.compiler_stack.back()->llvm_block(); pb) {
3686 conditional_expr = iworking_state->main_ex_back(0);
3687 iworking_state->pop_main();
3688
3689 *pb = LLVMCreateBasicBlockInContext(env.llvm_context, "loop_body");
3690 body_block = *pb;
3692 LLVMPositionBuilderAtEnd(env.llvm_builder, *pb);
3693 }
3694#endif
3695 } else if(typechecking_mode(env.mode)) {
3696 iworking_state->pop_main();
3699 }
3700 }
3701 }
3702 }
3703 virtual bool finish(environment&) override {
3706
3708
3710 return true;
3711 }
3712
3714
3716 if(!saw_conditional && iworking_state->main_type_back(0) == fif_bool) {
3717 if(iworking_state->main_data_back(0) == 0) {
3718 iworking_state->pop_main();
3720 return true;
3721 }
3722 iworking_state->pop_main();
3723 }
3724 saw_conditional = false;
3725 if(!env.source_stack.empty())
3726 env.source_stack.back() = entry_source;
3727 return false;
3728 }
3729
3731 if(!saw_conditional) {
3732 if(iworking_state->main_type_back(0) == fif_bool) {
3733 iworking_state->pop_main();
3734 } else {
3735 env.report_error("while loop terminated with an appropriate conditional");
3737 return true;
3738 }
3739
3740 auto bcode = parent->bytecode_compilation_progress();
3741
3742 {
3743 fif_call imm2 = leave_scope;
3744 uint64_t imm2_bytes = 0;
3745 memcpy(&imm2_bytes, &imm2, 8);
3746 bcode->push_back(int32_t(imm2_bytes & 0xFFFFFFFF));
3747 bcode->push_back(int32_t((imm2_bytes >> 32) & 0xFFFFFFFF));
3748 }
3749
3751 uint64_t imm_bytes = 0;
3752 memcpy(&imm_bytes, &imm, 8);
3753 bcode->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
3754 bcode->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
3755 end_of_loop_branch = bcode->size();
3756 bcode->push_back(int32_t(int64_t(loop_entry_point) - int64_t(bcode->size() - 2)));
3757 }
3758
3759 bool final_types_match = stack_types_match(*initial_state, *iworking_state);
3760 if(!final_types_match) {
3761 env.report_error("while loop had a net stack effect");
3763 return true;
3764 }
3765
3766 if(saw_conditional) {
3767 auto bcode = parent->bytecode_compilation_progress();
3768
3769 {
3770 fif_call imm2 = leave_scope;
3771 uint64_t imm2_bytes = 0;
3772 memcpy(&imm2_bytes, &imm2, 8);
3773 bcode->push_back(int32_t(imm2_bytes & 0xFFFFFFFF));
3774 bcode->push_back(int32_t((imm2_bytes >> 32) & 0xFFFFFFFF));
3775 }
3776
3778 uint64_t imm_bytes = 0;
3779 memcpy(&imm_bytes, &imm, 8);
3780 bcode->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
3781 bcode->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
3782 bcode->push_back(int32_t(int64_t(loop_entry_point) - int64_t(bcode->size() - 2)));
3783 (*bcode)[end_of_loop_branch] = int32_t(bcode->size() - (end_of_loop_branch - 2));;
3784 }
3785
3786 iworking_state->min_main_depth = std::min(iworking_state->min_main_depth, initial_state->min_main_depth);
3787 iworking_state->min_return_depth = std::min(iworking_state->min_return_depth, initial_state->min_return_depth);
3789
3790 return true;
3791 } else if(env.mode == fif_mode::compiling_llvm) {
3792#ifdef USE_LLVM
3793 if(!saw_conditional) {
3794 if(auto pb = env.compiler_stack.back()->llvm_block(); pb) {
3795 conditional_expr = iworking_state->main_ex_back(0);
3796 iworking_state->pop_main();
3797
3798 *pb = LLVMCreateBasicBlockInContext(env.llvm_context, "loop_body");
3799 body_block = *pb;
3801 LLVMPositionBuilderAtEnd(env.llvm_builder, *pb);
3802 }
3803 }
3804
3805 bool final_types_match = stack_types_match(*initial_state, *iworking_state);
3806 if(!final_types_match) {
3807 env.report_error("while loop had a net stack effect");
3809 return true;
3810 }
3811
3812 if(auto pb = env.compiler_stack.back()->llvm_block(); pb) {
3813 auto in_block = *pb;
3814 LLVMBuildBr(env.llvm_builder, entry_block);
3815
3816 *pb = LLVMCreateBasicBlockInContext(env.llvm_context, "post_loop");
3818
3820 LLVMBuildCondBr(env.llvm_builder, conditional_expr, body_block, *pb);
3821
3822 LLVMPositionBuilderAtEnd(env.llvm_builder, *pb);
3823
3824 /*
3825 set phi inputs in entry block
3826 */
3827 uint32_t node_index = 0;
3828 for(auto i = iworking_state->main_size(); i-- > iworking_state->min_main_depth; ) {
3829 if(phinodes[node_index] == iworking_state->main_ex(i)) { // phi node unchanged
3830 LLVMValueRef inc_vals[1] = { initial_state->main_ex(i) };
3831 LLVMBasicBlockRef inc_blocks[1] = { pre_block };
3832 LLVMAddIncoming(phinodes[node_index], inc_vals, inc_blocks, 1);
3833 } else {
3834 LLVMValueRef inc_vals[2] = { iworking_state->main_ex(i), initial_state->main_ex(i) };
3835 LLVMBasicBlockRef inc_blocks[2] = { in_block, pre_block };
3836 LLVMAddIncoming(phinodes[node_index], inc_vals, inc_blocks, 2);
3837 }
3838 ++node_index;
3839 }
3840 for(auto i = iworking_state->return_size(); i-- > iworking_state->min_return_depth; ) {
3841 if(phinodes[node_index] == iworking_state->return_ex(i)) { // phi node unchanged
3842 LLVMValueRef inc_vals[1] = { initial_state->return_ex(i) };
3843 LLVMBasicBlockRef inc_blocks[1] = { pre_block };
3844 LLVMAddIncoming(phinodes[node_index], inc_vals, inc_blocks, 1);
3845 } else {
3846 LLVMValueRef inc_vals[2] = { iworking_state->return_ex(i), initial_state->return_ex(i) };
3847 LLVMBasicBlockRef inc_blocks[2] = { in_block, pre_block };
3848 LLVMAddIncoming(phinodes[node_index], inc_vals, inc_blocks, 2);
3849 }
3850 ++node_index;
3851 }
3852 }
3853
3854 loop_entry_copy->min_main_depth = std::min(iworking_state->min_main_depth, initial_state->min_main_depth);
3855 loop_entry_copy->min_return_depth = std::min(iworking_state->min_return_depth, initial_state->min_return_depth);
3857
3858 return true;
3859#endif
3860 } else if(env.mode == fif_mode::typechecking_lvl_2 && phi_pass == true) {
3861#ifdef USE_LLVM
3862 phi_pass = false;
3863 if(!saw_conditional) {
3864 iworking_state->pop_main();
3865 }
3866
3867
3868 if(auto pb = env.compiler_stack.back()->llvm_block(); pb) {
3869 *pb = LLVMCreateBasicBlockInContext(env.llvm_context, "while_entry");
3870 entry_block = *pb;
3872
3873 LLVMBuildBr(env.llvm_builder, entry_block);
3874 LLVMPositionBuilderAtEnd(env.llvm_builder, *pb);
3875
3876 /*
3877 build entry phi_nodes
3878 */
3879 for(auto i = iworking_state->main_size(); i-- > iworking_state->min_main_depth; ) {
3880 phinodes.push_back(LLVMBuildPhi(env.llvm_builder, env.dict.type_array[iworking_state->main_type(i)].llvm_type, ""));
3881 iworking_state->set_main_ex(i, phinodes.back());
3882 }
3883 for(auto i = iworking_state->return_size(); i-- > iworking_state->min_return_depth; ) {
3884 phinodes.push_back(LLVMBuildPhi(env.llvm_builder, env.dict.type_array[iworking_state->return_type(i)].llvm_type, ""));
3885 iworking_state->set_return_ex(i, phinodes.back());
3886 }
3887 }
3888
3890 saw_conditional = false;
3892 if(!env.source_stack.empty())
3893 env.source_stack.back() = entry_source;
3894#endif
3895 return false;
3896 } else if(typechecking_mode(env.mode)) {
3897 if(!saw_conditional) {
3898 if(iworking_state->main_type_back(0) != fif_bool) {
3902
3903 return true;
3904 }
3905 iworking_state->pop_main();
3906 }
3907 bool final_types_match = stack_types_match(*initial_state, *iworking_state);
3908 if(!final_types_match) {
3912
3913 return true;
3914 }
3916 iworking_state->min_main_depth = std::min(iworking_state->min_main_depth, initial_state->min_main_depth);
3917 iworking_state->min_return_depth = std::min(iworking_state->min_return_depth, initial_state->min_return_depth);
3921 }
3922
3923 return true;
3924 }
3925 return true;
3926 }
3927};
3928
3930public:
3931 std::unique_ptr<state_stack> initial_state;
3932 std::unique_ptr<state_stack> iworking_state;
3933
3934 std::string_view entry_source;
3937 bool phi_pass = false;
3939
3942 std::vector<LLVMValueRef> phinodes;
3943
3945 initial_state = entry_state.copy();
3946 iworking_state = entry_state.copy();
3947 initial_state->min_main_depth = entry_state.min_main_depth;
3948 initial_state->min_return_depth = entry_state.min_return_depth;
3950
3951 if(!env.source_stack.empty()) {
3952 entry_source = env.source_stack.back();
3953 }
3955 auto bcode = parent->bytecode_compilation_progress();
3956 loop_entry_point = bcode->size();
3957
3958 {
3959 fif_call imm2 = enter_scope;
3960 uint64_t imm2_bytes = 0;
3961 memcpy(&imm2_bytes, &imm2, 8);
3962 bcode->push_back(int32_t(imm2_bytes & 0xFFFFFFFF));
3963 bcode->push_back(int32_t((imm2_bytes >> 32) & 0xFFFFFFFF));
3964 }
3965 }
3967 phi_pass = true;
3969 if(auto pb = env.compiler_stack.back()->llvm_block(); pb) {
3970 pre_block = *pb;
3971 }
3972 }
3973 }
3974
3975 virtual control_structure get_type() override {
3977 }
3978 virtual state_stack* working_state() override {
3979 return iworking_state.get();
3980 }
3981 virtual void set_working_state(std::unique_ptr<state_stack> p) override {
3982 iworking_state = std::move(p);
3983 }
3985 // don't actually need to do anything here ...
3986 }
3987 virtual bool finish(environment&)override {
3989
3991 if(iworking_state->main_type_back(0) == fif_bool) {
3992 if(iworking_state->main_data_back(0) != 0) {
3993 iworking_state->pop_main();
3994
3996 return true;
3997 }
3998 iworking_state->pop_main();
3999 }
4000 if(!env.source_stack.empty())
4001 env.source_stack.back() = entry_source;
4002 return false;
4003 }
4004
4006
4007 if(iworking_state->main_type_back(0) == fif_bool) {
4008 iworking_state->pop_main();
4009 } else {
4010 env.report_error("do loop not terminated with an appropriate conditional");
4012 return true;
4013 }
4014
4015 auto bcode = parent->bytecode_compilation_progress();
4016 {
4017 fif_call imm2 = leave_scope;
4018 uint64_t imm2_bytes = 0;
4019 memcpy(&imm2_bytes, &imm2, 8);
4020 bcode->push_back(int32_t(imm2_bytes & 0xFFFFFFFF));
4021 bcode->push_back(int32_t((imm2_bytes >> 32) & 0xFFFFFFFF));
4022 }
4023
4025 uint64_t imm_bytes = 0;
4026 memcpy(&imm_bytes, &imm, 8);
4027 bcode->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
4028 bcode->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
4029 end_of_loop_branch = bcode->size();
4030 bcode->push_back(int32_t(int64_t(loop_entry_point) - int64_t(bcode->size() - 2)));
4031
4032 bool final_types_match = stack_types_match(*initial_state, *iworking_state);
4033 if(!final_types_match) {
4034 env.report_error("do loop had a net stack effect");
4036 return true;
4037 }
4038
4039 iworking_state->min_main_depth = std::min(iworking_state->min_main_depth, initial_state->min_main_depth);
4040 iworking_state->min_return_depth = std::min(iworking_state->min_return_depth, initial_state->min_return_depth);
4042
4043 return true;
4044 } else if(env.mode == fif_mode::compiling_llvm) {
4045#ifdef USE_LLVM
4046 auto conditional_expr = iworking_state->main_ex_back(0);
4047 iworking_state->pop_main();
4048
4049
4050 bool final_types_match = stack_types_match(*initial_state, *iworking_state);
4051 if(!final_types_match) {
4052 env.report_error("do loop had a net stack effect");
4054 return true;
4055 }
4056
4057 if(auto pb = env.compiler_stack.back()->llvm_block(); pb) {
4058 auto in_block = *pb;
4059 *pb = LLVMCreateBasicBlockInContext(env.llvm_context, "post_loop");
4061
4062 LLVMPositionBuilderAtEnd(env.llvm_builder, in_block);
4063 LLVMBuildCondBr(env.llvm_builder, conditional_expr, *pb, body_block);
4064
4065 LLVMPositionBuilderAtEnd(env.llvm_builder, *pb);
4066
4067 /*
4068 set phi inputs in entry block
4069 */
4070 uint32_t node_index = 0;
4071 for(auto i = iworking_state->main_size(); i-- > iworking_state->min_main_depth; ) {
4072 if(phinodes[node_index] == iworking_state->main_ex(i)) { // phi node unchanged
4073 LLVMValueRef inc_vals[1] = { initial_state->main_ex(i) };
4074 LLVMBasicBlockRef inc_blocks[1] = { pre_block };
4075 LLVMAddIncoming(phinodes[node_index], inc_vals, inc_blocks, 1);
4076 } else {
4077 LLVMValueRef inc_vals[2] = { iworking_state->main_ex(i), initial_state->main_ex(i) };
4078 LLVMBasicBlockRef inc_blocks[2] = { in_block, pre_block };
4079 LLVMAddIncoming(phinodes[node_index], inc_vals, inc_blocks, 2);
4080 }
4081 ++node_index;
4082 }
4083 for(auto i = iworking_state->return_size(); i-- > iworking_state->min_return_depth; ) {
4084 if(phinodes[node_index] == iworking_state->return_ex(i)) { // phi node unchanged
4085 LLVMValueRef inc_vals[1] = { initial_state->return_ex(i) };
4086 LLVMBasicBlockRef inc_blocks[1] = { pre_block };
4087 LLVMAddIncoming(phinodes[node_index], inc_vals, inc_blocks, 1);
4088 } else {
4089 LLVMValueRef inc_vals[2] = { iworking_state->return_ex(i), initial_state->return_ex(i) };
4090 LLVMBasicBlockRef inc_blocks[2] = { in_block, pre_block };
4091 LLVMAddIncoming(phinodes[node_index], inc_vals, inc_blocks, 2);
4092 }
4093 ++node_index;
4094 }
4095 }
4096
4097 iworking_state->min_main_depth = std::min(iworking_state->min_main_depth, initial_state->min_main_depth);
4098 iworking_state->min_return_depth = std::min(iworking_state->min_return_depth, initial_state->min_return_depth);
4100#endif
4101 return true;
4102 } else if(env.mode == fif_mode::typechecking_lvl_2 && phi_pass == true) {
4103#ifdef USE_LLVM
4104 phi_pass = false;
4105
4106 if(iworking_state->main_type_back(0) != fif_bool) {
4108 env.report_error("do loop did not finish with a boolean value");
4109 return true;
4110 }
4111 iworking_state->pop_main();
4112
4113 if(auto pb = env.compiler_stack.back()->llvm_block(); pb) {
4114 *pb = LLVMCreateBasicBlockInContext(env.llvm_context, "do_body");
4115 body_block = *pb;
4117
4118 LLVMBuildBr(env.llvm_builder, body_block);
4119 LLVMPositionBuilderAtEnd(env.llvm_builder, *pb);
4120
4121 /*
4122 build entry phi_nodes
4123 */
4124 for(auto i = iworking_state->main_size(); i-- > iworking_state->min_main_depth; ) {
4125 phinodes.push_back(LLVMBuildPhi(env.llvm_builder, env.dict.type_array[iworking_state->main_type(i)].llvm_type, ""));
4126 iworking_state->set_main_ex(i, phinodes.back());
4127 }
4128 for(auto i = iworking_state->return_size(); i-- > iworking_state->min_return_depth; ) {
4129 phinodes.push_back(LLVMBuildPhi(env.llvm_builder, env.dict.type_array[iworking_state->return_type(i)].llvm_type, ""));
4130 iworking_state->set_return_ex(i, phinodes.back());
4131 }
4132 }
4133
4135 if(!env.source_stack.empty())
4136 env.source_stack.back() = entry_source;
4137#endif
4138 return false;
4139 } else if(typechecking_mode(env.mode)) {
4140 if(iworking_state->main_type_back(0) != fif_bool) {
4144
4145 return true;
4146 }
4147 iworking_state->pop_main();
4148
4149 bool final_types_match = stack_types_match(*initial_state, *iworking_state);
4150 if(!final_types_match) {
4154
4156
4157 return true;
4158 }
4159
4161 iworking_state->min_main_depth = std::min(iworking_state->min_main_depth, initial_state->min_main_depth);
4162 iworking_state->min_return_depth = std::min(iworking_state->min_return_depth, initial_state->min_return_depth);
4166 }
4167
4168 return true;
4169 }
4170
4171 return true;
4172 }
4173};
4174
4175inline constexpr size_t inlining_cells_limit = 512;
4176
4177inline uint32_t codepoint_from_utf8(char const* start, char const* end) {
4178 uint8_t byte1 = uint8_t(start + 0 < end ? start[0] : 0);
4179 uint8_t byte2 = uint8_t(start + 1 < end ? start[1] : 0);
4180 uint8_t byte3 = uint8_t(start + 2 < end ? start[2] : 0);
4181 uint8_t byte4 = uint8_t(start + 3 < end ? start[3] : 0);
4182 if((byte1 & 0x80) == 0) {
4183 return uint32_t(byte1);
4184 } else if((byte1 & 0xE0) == 0xC0) {
4185 return uint32_t(byte2 & 0x3F) | (uint32_t(byte1 & 0x1F) << 6);
4186 } else if((byte1 & 0xF0) == 0xE0) {
4187 return uint32_t(byte3 & 0x3F) | (uint32_t(byte2 & 0x3F) << 6) | (uint32_t(byte1 & 0x0F) << 12);
4188 } else if((byte1 & 0xF8) == 0xF0) {
4189 return uint32_t(byte4 & 0x3F) | (uint32_t(byte3 & 0x3F) << 6) | (uint32_t(byte2 & 0x3F) << 12) | (uint32_t(byte1 & 0x07) << 18);
4190 }
4191 return 0;
4192}
4193inline size_t size_from_utf8(char const* start) {
4194 uint8_t b = uint8_t(start[0]);
4195 return ((b & 0x80) == 0) ? 1 : ((b & 0xE0) == 0xC0) ? 2
4196 : ((b & 0xF0) == 0xE0) ? 3 : ((b & 0xF8) == 0xF0) ? 4
4197 : 1;
4198}
4199inline bool codepoint_is_space(uint32_t c) noexcept {
4200 return (c == 0x3000 || c == 0x205F || c == 0x202F || c == 0x2029 || c == 0x2028 || c == 0x00A0
4201 || c == 0x0085 || c <= 0x0020 || (0x2000 <= c && c <= 0x200A));
4202}
4203inline bool codepoint_is_line_break(uint32_t c) noexcept {
4204 return c == 0x2029 || c == 0x2028 || c == uint32_t('\n') || c == uint32_t('\r');
4205}
4206
4208 int32_t eq_match = 0;
4209 bool starts_string = false;
4210};
4211
4212inline string_start match_string_start(std::string_view source) {
4213 if(source.length() < 2)
4214 return string_start{ 0, false };
4215 if(source[0] != '<')
4216 return string_start{ 0, false };
4217 int32_t eq_count = 0;
4218 uint32_t pos = 1;
4219 while(pos < source.length()) {
4220 if(source[pos] == '<') {
4221 return string_start{ eq_count, true };
4222 } else if(source[pos] == '=') {
4223 ++eq_count;
4224 } else {
4225 break;
4226 }
4227 ++pos;
4228 }
4229 return string_start{ 0, false };
4230}
4231inline bool match_string_end(std::string_view source, int32_t eq_count_in) {
4232 if(source.length() < 2)
4233 return false ;
4234 if(source[0] != '>')
4235 return false;
4236 int32_t eq_count = 0;
4237 uint32_t pos = 1;
4238 while(pos < source.length()) {
4239 if(source[pos] == '>') {
4240 return eq_count == eq_count_in;
4241 } else if(source[pos] == '=') {
4242 ++eq_count;
4243 } else {
4244 break;
4245 }
4246 ++pos;
4247 }
4248 return false;
4249}
4250
4251// string format: <<xxxxx>> or <=<xxxxx>=> or <==<xxxxx>==> etc
4252
4253inline parse_result read_token(std::string_view& source, environment& env) {
4254 size_t first_non_space = 0;
4255 while(first_non_space < source.length()) {
4256 auto codepoint = codepoint_from_utf8(source.data() + first_non_space, source.data() + source.length());
4257 if(codepoint_is_space(codepoint) || codepoint_is_line_break(codepoint))
4258 first_non_space += size_from_utf8(source.data() + first_non_space);
4259 else
4260 break;
4261 }
4262
4263 if(auto sm = match_string_start(source.substr(first_non_space)); sm.starts_string) {
4264 auto str_start = first_non_space + sm.eq_match + 2;
4265 auto str_pos = str_start;
4266 while(str_pos < source.length()) {
4267 if(match_string_end(source.substr(str_pos), sm.eq_match)) {
4268 auto result = source.substr(str_start, str_pos - str_start);
4269 source = source.substr(str_pos + sm.eq_match + 2);
4270 return parse_result{ result, true };
4271 }
4272 str_pos += size_from_utf8(source.data() + str_pos);
4273 }
4274
4275 // invalid text, reached the end of source within a string without closing it
4276 env.report_error("unclosed string constant");
4277 env.mode = fif_mode::error;
4278 source = std::string_view{ };
4279 return parse_result{ std::string_view{ }, false };
4280 }
4281
4282 auto word_end = first_non_space;
4283 while(word_end < source.length()) {
4284 auto codepoint = codepoint_from_utf8(source.data() + word_end, source.data() + source.length());
4285 if(codepoint_is_space(codepoint) || codepoint_is_line_break(codepoint))
4286 break;
4287 else
4288 word_end += size_from_utf8(source.data() + word_end);
4289 }
4290
4291 auto result = source.substr(first_non_space, word_end - first_non_space);
4292 source = source.substr(word_end);
4293
4294 return parse_result{ result, false };
4295
4296}
4297
4298inline void execute_fif_word(parse_result word, environment& env, bool ignore_specialization);
4299
4300
4301inline void run_to_scope_end(environment& env) { // execute/compile source code until current function is completed
4303 auto scope_depth = env.compiler_stack.size();
4304
4305 if(!env.compiler_stack.empty()) {
4306 do {
4307 if(!env.source_stack.empty())
4308 word = read_token(env.source_stack.back(), env);
4309 else
4310 word.content = std::string_view{ };
4311
4312 if(word.content.length() > 0 && env.mode != fif_mode::error) {
4313 execute_fif_word(word, env, false);
4314 }
4315 } while(word.content.length() > 0 && !env.compiler_stack.empty() && env.mode != fif_mode::error);
4316 }
4317}
4318
4319inline void run_to_function_end(environment& env) { // execute/compile source code until current function is completed
4320 run_to_scope_end(env);
4321 if(!env.compiler_stack.empty() && env.compiler_stack.back()->finish(env)) {
4322 env.compiler_stack.pop_back();
4323 }
4324}
4325
4326inline word_match_result get_basic_type_match(int32_t word_index, state_stack& current_type_state, environment& env, std::vector<int32_t>& specialize_t_subs, bool ignore_specializations) {
4327 while(word_index != -1) {
4328 specialize_t_subs.clear();
4329 bool specialization_matches = [&]() {
4330 if(env.dict.word_array[word_index].stack_types_count == 0)
4331 return true;
4332 return match_stack_description(std::span<int32_t const>{env.dict.all_stack_types.data() + env.dict.word_array[word_index].stack_types_start, size_t(env.dict.word_array[word_index].stack_types_count)}, current_type_state, env, specialize_t_subs).matched;
4333 }();
4334 if(specialization_matches && (ignore_specializations == false || env.dict.word_array[word_index].treat_as_base || env.dict.word_array[word_index].specialization_of == -1)) {
4335 word_match_result match = match_word(env.dict.word_array[word_index], current_type_state, env.dict.all_instances, env.dict.all_stack_types, env);
4336 int32_t w = word_index;
4337 match.substitution_version = word_index;
4338
4339 if(!match.matched) {
4340 if(typechecking_failed(env.mode)) {
4341 // ignore match failure and pass on through
4342 return word_match_result{ false, 0, 0, 0, 0 };
4344 if(env.dict.word_array[w].being_typechecked) { // already being typechecked -- mark as un checkable recursive branch
4345 env.mode = fail_typechecking(env.mode);
4346 } else if(env.dict.word_array[w].source.length() > 0) { // try to typecheck word as level 1
4347 env.dict.word_array[w].being_typechecked = true;
4348
4350
4351 env.source_stack.push_back(std::string_view(env.dict.word_array[w].source));
4352 auto fnscope = std::make_unique<function_scope>(env.compiler_stack.back().get(), env, current_type_state, w, -1);
4353 fnscope->type_subs = specialize_t_subs;
4354 env.compiler_stack.emplace_back(std::move(fnscope));
4355
4357 env.source_stack.pop_back();
4358
4359 env.dict.word_array[w].being_typechecked = false;
4360 match = match_word(env.dict.word_array[w], current_type_state, env.dict.all_instances, env.dict.all_stack_types, env);
4361 match.substitution_version = word_index;
4362
4364
4365 if(match.matched) {
4366 std::get<interpreted_word_instance>(env.dict.all_instances[match.word_index]).typechecking_level = 1;
4367 return match;
4368 } else {
4369 env.mode = fail_typechecking(env.mode);
4370 return word_match_result{ false, 0, 0, 0, 0 };
4371 }
4372 }
4373 } else if(env.dict.word_array[w].source.length() > 0) { // either compiling or interpreting or level 3 typecheck-- switch to typechecking to get a type definition
4375 env.dict.word_array[w].being_typechecked = true;
4376
4377 env.source_stack.push_back(std::string_view(env.dict.word_array[w].source));
4378 auto fnscope = std::make_unique<function_scope>(env.compiler_stack.back().get(), env, current_type_state, w, -1);
4379 fnscope->type_subs = specialize_t_subs;
4380 env.compiler_stack.emplace_back(std::move(fnscope));
4381
4383 env.source_stack.pop_back();
4384
4385 env.dict.word_array[w].being_typechecked = false;
4386
4388
4389 match = match_word(env.dict.word_array[w], current_type_state, env.dict.all_instances, env.dict.all_stack_types, env);
4390 match.substitution_version = word_index;
4391
4392 if(!match.matched) {
4393 env.report_error("typechecking failure for " + word_name_from_id(w, env));
4394 env.mode = fif_mode::error;
4395 return word_match_result{ false, 0, 0, 0, 0 };
4396 }
4397 return match;
4398 }
4399 }
4400
4401 return match;
4402 } else {
4403 word_index = env.dict.word_array[word_index].specialization_of;
4404 }
4405 }
4406
4407 return word_match_result{ false, 0, 0, 0, 0 };
4408}
4409
4410inline bool fully_typecheck_word(int32_t w, int32_t word_index, interpreted_word_instance& wi, state_stack& current_type_state, environment& env, std::vector<int32_t>& tsubs) {
4411 if(wi.typechecking_level == 1) {
4412 // perform level 2 typechecking
4413
4415
4416 env.source_stack.push_back(std::string_view(env.dict.word_array[w].source));
4417 auto fnscope = std::make_unique<function_scope>(env.compiler_stack.back().get(), env, current_type_state, w, word_index);
4418 fnscope->type_subs = tsubs;
4419 env.compiler_stack.emplace_back(std::move(fnscope));
4420
4422 env.source_stack.pop_back();
4423
4424 bool failed = typechecking_failed(env.mode);
4425
4427
4428 if(failed) {
4429 env.report_error("level 2 typecheck failed");
4430 env.mode = fif_mode::error;
4431 return false;
4432 }
4433
4434 wi.typechecking_level = 2;
4435 }
4436
4437 if(wi.typechecking_level == 2) {
4438 // perform level 3 typechecking
4439
4440 env.compiler_stack.emplace_back(std::make_unique< typecheck3_record_holder>(env.compiler_stack.back().get(), env));
4441 auto record_holder = static_cast<typecheck3_record_holder*>(env.compiler_stack.back().get());
4442
4444 env.source_stack.push_back(std::string_view(env.dict.word_array[w].source));
4445 auto fnscope = std::make_unique<function_scope>(env.compiler_stack.back().get(), env, current_type_state, w, word_index);
4446 fnscope->type_subs = tsubs;
4447 env.compiler_stack.emplace_back(std::move(fnscope));
4448
4450 env.source_stack.pop_back();
4451
4452 bool failed = typechecking_failed(env.mode);
4453
4455
4456 if(failed) {
4457 env.report_error("level 3 typecheck failed");
4458 env.mode = fif_mode::error;
4459 return false;
4460 }
4461
4462 wi.typechecking_level = 3;
4463
4464 if(auto erb = record_holder->tr.find((uint64_t(w) << 32) | uint64_t(word_index)); erb != record_holder->tr.end()) {
4466 r.stack_height_added_at = int32_t(current_type_state.main_size());
4467 r.rstack_height_added_at = int32_t(current_type_state.return_size());
4468
4469 auto c = get_stack_consumption(w, word_index, env);
4470 r.stack_consumed = std::max(c.stack, erb->second.stack_consumed);
4471 r.rstack_consumed = std::max(c.rstack, erb->second.rstack_consumed);
4472
4473 record_holder->tr.insert_or_assign((uint64_t(w) << 32) | uint64_t(word_index), r);
4474 } else {
4476 r.stack_height_added_at = int32_t(current_type_state.main_size());
4477 r.rstack_height_added_at = int32_t(current_type_state.return_size());
4478
4479 auto c = get_stack_consumption(w, word_index, env);
4480 r.stack_consumed = c.stack;
4481 r.rstack_consumed = c.rstack;
4482
4483 record_holder->tr.insert_or_assign((uint64_t(w) << 32) | uint64_t(word_index), r);
4484 }
4485
4486 /*
4487 process results of typechecking
4488 */
4489 auto min_stack_depth = int32_t(current_type_state.main_size());
4490 auto min_rstack_depth = int32_t(current_type_state.return_size());
4491 for(auto& s : record_holder->tr) {
4492 min_stack_depth = std::min(min_stack_depth, s.second.stack_height_added_at - s.second.stack_consumed);
4493 min_rstack_depth = std::min(min_rstack_depth, s.second.rstack_height_added_at - s.second.rstack_consumed);
4494 }
4495
4496 auto existing_description = std::span<int32_t const>(env.dict.all_stack_types.data() + wi.stack_types_start, wi.stack_types_count);
4497 auto revised_description = expand_stack_description(current_type_state, existing_description, int32_t(current_type_state.main_size()) - min_stack_depth, int32_t(current_type_state.return_size()) - min_rstack_depth);
4498
4499 if(!compare_stack_description(existing_description, std::span<int32_t const>(revised_description.data(), revised_description.size()))) {
4500 wi.stack_types_start = int32_t(env.dict.all_stack_types.size());
4501 wi.stack_types_count = int32_t(revised_description.size());
4502 env.dict.all_stack_types.insert(env.dict.all_stack_types.end(), revised_description.begin(), revised_description.end());
4503 }
4504
4505 env.compiler_stack.pop_back(); // for typecheck3_record_holder
4506 }
4507
4508 return true;
4509}
4510
4511inline bool compile_word(int32_t w, int32_t word_index, state_stack& state, fif_mode compile_mode, environment& env, std::vector<int32_t>& tsubs) {
4512 if(!std::holds_alternative<interpreted_word_instance>(env.dict.all_instances[word_index]))
4513 return true;
4514
4515 interpreted_word_instance& wi = std::get<interpreted_word_instance>(env.dict.all_instances[word_index]);
4516 if(!fully_typecheck_word(w, word_index, wi, state, env, tsubs)) {
4517 return false;
4518 }
4519
4520 switch_compiler_stack_mode(env, compile_mode);
4521
4522 if(env.mode != fif_mode::compiling_llvm && wi.compiled_bytecode.size() == 0) {
4523 // typed but uncompiled word
4524 if(!std::get<interpreted_word_instance>(env.dict.all_instances[word_index]).being_compiled) {
4525 env.source_stack.push_back(std::string_view(env.dict.word_array[w].source));
4526 auto fnscope = std::make_unique<function_scope>(env.compiler_stack.back().get(), env, state, w, word_index);
4527 fnscope->type_subs = tsubs;
4528 env.compiler_stack.emplace_back(std::move(fnscope));
4530 env.source_stack.pop_back();
4531 }
4532 }
4533
4534 // case: reached an uncompiled llvm definition
4536#ifdef USE_LLVM
4537 // typed but uncompiled word
4538 if(!std::get<interpreted_word_instance>(env.dict.all_instances[word_index]).being_compiled) {
4539 LLVMBasicBlockRef stored_block = nullptr;
4540 if(auto pb = env.compiler_stack.back()->llvm_block(); pb)
4541 stored_block = *pb;
4542
4543
4544 env.source_stack.push_back(std::string_view(env.dict.word_array[w].source));
4545 auto fnscope = std::make_unique<function_scope>(env.compiler_stack.back().get(), env, state, w, word_index);
4546 fnscope->type_subs = tsubs;
4547 env.compiler_stack.emplace_back(std::move(fnscope));
4549 env.source_stack.pop_back();
4550
4551 if(auto pb = env.compiler_stack.back()->llvm_block(); pb) {
4552 *pb = stored_block;
4553 LLVMPositionBuilderAtEnd(env.llvm_builder, stored_block);
4554 }
4555
4556 }
4557#endif
4558 }
4559
4561 return true;
4562}
4563
4564inline let_data* get_global_let(environment& env, std::string const& name) {
4565 for(auto& p : env.compiler_stack) {
4566 if(p->get_type() == control_structure::globals)
4567 return static_cast<compiler_globals_layer*>(p.get())->get_global_let(name);
4568 }
4569 return nullptr;
4570}
4571inline var_data* get_global_var(environment& env, std::string const& name) {
4572 for(auto& p : env.compiler_stack) {
4573 if(p->get_type() == control_structure::globals)
4574 return static_cast<compiler_globals_layer*>(p.get())->get_global_var(name);
4575 }
4576 return nullptr;
4577}
4578
4579inline int32_t* immediate_local(state_stack& s, int32_t* p, environment* e) {
4580 char* name = 0;
4581 memcpy(&name, p + 2, 8);
4582
4583 var_data* l = e->compiler_stack.back()->get_var(std::string(name));
4584 if(!l) {
4585 e->report_error("unable to find local var");
4586 return nullptr;
4587 }
4588 int32_t type = 0;
4589 memcpy(&type, p + 4, 4);
4590 s.push_back_main(type, (int64_t)l, nullptr);
4591 return p + 5;
4592}
4593
4594inline int32_t* immediate_let(state_stack& s, int32_t* p, environment* e) {
4595 char* name = 0;
4596 memcpy(&name, p + 2, 8);
4597 let_data* l = e->compiler_stack.back()->get_let(std::string(name));
4598 if(!l) {
4599 e->report_error("unable to find local let");
4600 return nullptr;
4601 }
4602 int32_t type = 0;
4603 memcpy(&type, p + 4, 4);
4604 s.push_back_main(type, l->data, nullptr);
4605 return p + 5;
4606}
4607
4608inline int32_t* immediate_global(state_stack& s, int32_t* p, environment* e) {
4609 char* name = 0;
4610 memcpy(&name, p + 2, 8);
4611 var_data* v = get_global_var(*e, std::string(name));
4612 if(!v) {
4613 e->report_error("unable to find local let");
4614 return nullptr;
4615 }
4616 int32_t type = 0;
4617 memcpy(&type, p + 4, 4);
4618 s.push_back_main(type, (int64_t)v, nullptr);
4619 return p + 5;
4620}
4621
4622inline void execute_fif_word(parse_result word, environment& env, bool ignore_specializations) {
4623 auto ws = env.compiler_stack.back()->working_state();
4624 if(!ws) {
4625 env.report_error("tried to execute in a scope with no working state");
4626 env.mode = fif_mode::error;
4627 return;
4628 }
4629
4630 // TODO: string constant case
4631 // TODO: restore constructor word
4632 //if(word.content.length() > 0 && word.content[0] == '@') {
4633 // do_construct_type(*ws, resolve_type(word.content.substr(1), env), &env);
4634 //} else
4635 auto content_string = std::string{ word.content };
4636 if(is_integer(word.content.data(), word.content.data() + word.content.length())) {
4637 do_immediate_i32(*ws, parse_int(word.content), &env);
4638 } else if(is_fp(word.content.data(), word.content.data() + word.content.length())) {
4639 do_immediate_f32(*ws, parse_float(word.content), &env);
4640 } else if(word.content == "true" || word.content == "false") {
4641 do_immediate_bool(*ws, word.content == "true", &env);
4642 } else if(auto it = env.dict.words.find(std::string(word.content)); it != env.dict.words.end()) {
4643 auto w = it->second;
4644 // execute / compile word
4645
4646 // IMMEDIATE words with source
4647 if(env.dict.word_array[w].immediate) {
4648 if(env.dict.word_array[w].source.length() > 0) {
4649 env.source_stack.push_back(std::string_view{ env.dict.word_array[w].source });
4651
4652 run_to_scope_end(env);
4653
4655 env.source_stack.pop_back(); // remove source replacement
4656
4657 return;
4658 }
4659 }
4660
4661 std::vector<int32_t> called_tsub_types;
4662 auto match = get_basic_type_match(w, *ws, env, called_tsub_types, ignore_specializations);
4663 w = match.substitution_version;
4664
4665 if(!match.matched) {
4666 if(typechecking_failed(env.mode)) {
4667 return;
4668 } else { // critical failure
4669 env.report_error("could not match word to stack types");
4670 env.mode = fif_mode::error;
4671 return;
4672 }
4673 }
4674
4675 word_types* wi = &(env.dict.all_instances[match.word_index]);
4676
4677 // IMMEDIATE words (source not available)
4678 if(env.dict.word_array[w].immediate) {
4679 if(std::holds_alternative<interpreted_word_instance>(*wi)) {
4681 execute_fif_word(std::get<interpreted_word_instance>(*wi), *ws, env);
4683 } else if(std::holds_alternative<compiled_word_instance>(*wi)) {
4684 execute_fif_word(std::get<compiled_word_instance>(*wi), *ws, env);
4685 }
4686 return;
4687 }
4688
4689 //
4690 // level 1 typechecking -- should be able to trace at least one path through each word using only known words
4691 //
4692 // level 2 typechecking -- should be able to trace through every branch to produce an accurate stack picture for all known words present in the definition
4693 //
4694
4697
4698 if(std::holds_alternative<interpreted_word_instance>(*wi)) {
4699 if(!typechecking_failed(env.mode)) {
4700 apply_stack_description(std::span<int32_t const>(env.dict.all_stack_types.data() + std::get<interpreted_word_instance>(*wi).stack_types_start, size_t(std::get<interpreted_word_instance>(*wi).stack_types_count)), *ws, env);
4701 }
4702 } else if(std::holds_alternative<compiled_word_instance>(*wi)) {
4703 // no special logic, compiled words assumed to always typecheck
4704 if(!typechecking_failed(env.mode)) {
4705 apply_stack_description(std::span<int32_t const>(env.dict.all_stack_types.data() + std::get<compiled_word_instance>(*wi).stack_types_start, size_t(std::get<compiled_word_instance>(*wi).stack_types_count)), *ws, env);
4706 }
4707 }
4708 return;
4709 }
4710
4711 //
4712 // level 3 typechecking -- recursively determine the minimum stack position of all dependencies
4713 //
4714
4716 if(std::holds_alternative<interpreted_word_instance>(*wi)) {
4717 if(!typechecking_failed(env.mode)) {
4718 // add typecheck info
4719 if(std::get<interpreted_word_instance>(*wi).typechecking_level < 3) {
4720 // this word also hasn't been compiled yet
4721
4722 auto rword = env.compiler_stack.back()->word_id();
4723 auto rinst = env.compiler_stack.back()->instance_id();
4724 auto& dep = *(env.compiler_stack.back()->typecheck_record());
4725 auto existing_record = dep.find((uint64_t(w) << 32) | uint64_t(match.word_index));
4726 if(existing_record != dep.end()
4727 && existing_record->second.stack_height_added_at <= int32_t(ws->main_size())
4728 && existing_record->second.rstack_height_added_at <= int32_t(ws->return_size())) {
4729
4730 // already added all dependencies of this word at this stack height or less
4731 } else { // word is occurring deeper in the stack or not yet seen
4732 // recurse and typecheck through it
4733 // first, make sure that it is typechecked to at least level 2
4734
4735 if(env.dict.word_array[w].source.length() == 0) {
4736 env.report_error(std::string("Word ") + std::to_string(w) + " is undefined.");
4737 env.mode = fif_mode::error;
4738 return;
4739 }
4740
4741 if(std::get<interpreted_word_instance>(*wi).typechecking_level < 2) {
4743
4744 env.source_stack.push_back(std::string_view(env.dict.word_array[w].source));
4745 auto fnscope = std::make_unique<function_scope>(env.compiler_stack.back().get(), env, *ws, w, match.word_index);
4746 fnscope->type_subs = called_tsub_types;
4747 env.compiler_stack.emplace_back(std::move(fnscope));
4748
4750 env.source_stack.pop_back();
4751
4752 bool failed = typechecking_failed(env.mode);
4754
4755 if(failed) {
4756 env.report_error("level 2 typecheck failed");
4757 env.mode = fif_mode::error;
4758 return;
4759 }
4760
4761 wi = &(env.dict.all_instances[match.word_index]);
4762 std::get<interpreted_word_instance>(*wi).typechecking_level = 2;
4763 }
4764
4766 if(auto erb = dep.find((uint64_t(w) << 32) | uint64_t(match.word_index)); erb != dep.end()) {
4768 r.stack_height_added_at = int32_t(ws->main_size());
4769 r.rstack_height_added_at = int32_t(ws->return_size());
4770
4771 auto c = get_stack_consumption(w, match.word_index, env);
4772 r.stack_consumed = std::max(c.stack, erb->second.stack_consumed);
4773 r.rstack_consumed = std::max(c.rstack, erb->second.rstack_consumed);
4774
4775 dep.insert_or_assign((uint64_t(w) << 32) | uint64_t(match.word_index), r);
4776 } else {
4778 r.stack_height_added_at = int32_t(ws->main_size());
4779 r.rstack_height_added_at = int32_t(ws->return_size());
4780
4781 auto c = get_stack_consumption(w, match.word_index, env);
4782 r.stack_consumed = c.stack;
4783 r.rstack_consumed = c.rstack;
4784
4785 dep.insert_or_assign((uint64_t(w) << 32) | uint64_t(match.word_index), r);
4786 }
4787 }
4788 }
4789
4790 apply_stack_description(std::span<int32_t const>(env.dict.all_stack_types.data() + std::get<interpreted_word_instance>(*wi).stack_types_start, size_t(std::get<interpreted_word_instance>(*wi).stack_types_count)), *ws, env);
4791 }
4792 } else if(std::holds_alternative<compiled_word_instance>(*wi)) {
4793 if(!typechecking_failed(env.mode)) {
4794 // no special logic, compiled words assumed to always typecheck
4795 apply_stack_description(std::span<int32_t const>(env.dict.all_stack_types.data() + std::get<compiled_word_instance>(*wi).stack_types_start, size_t(std::get<compiled_word_instance>(*wi).stack_types_count)), *ws, env);
4796 }
4797 }
4798
4799 return;
4800 }
4801
4803 if(!compile_word(w, match.word_index, *ws, env.mode != fif_mode::compiling_llvm ? fif_mode::compiling_bytecode : fif_mode::compiling_llvm, env, called_tsub_types)) {
4804 env.report_error("failed to compile word");
4805 env.mode = fif_mode::error;
4806 return;
4807 }
4808 wi = &(env.dict.all_instances[match.word_index]);
4809
4810 if(std::holds_alternative<interpreted_word_instance>(*wi)) {
4811 if(env.mode == fif_mode::interpreting) {
4812 env.compiler_stack.push_back(std::make_unique<runtime_function_scope>(env.compiler_stack.back().get(), env));
4813 execute_fif_word(std::get<interpreted_word_instance>(*wi), *ws, env);
4814 env.compiler_stack.back()->finish(env);
4815 env.compiler_stack.pop_back();
4816 } else if(env.mode == fif_mode::compiling_llvm) {
4817#ifdef USE_LLVM
4818 std::span<int32_t const> desc{ env.dict.all_stack_types.data() + std::get<interpreted_word_instance>(*wi).stack_types_start, size_t(std::get<interpreted_word_instance>(*wi).stack_types_count) };
4819 llvm_make_function_call(env, std::get<interpreted_word_instance>(*wi).llvm_function, desc);
4820#endif
4821 } else if(env.mode == fif_mode::compiling_bytecode) {
4822 auto cbytes = env.compiler_stack.back()->bytecode_compilation_progress();
4823 if(cbytes) {
4824 if(std::get<interpreted_word_instance>(*wi).being_compiled) {
4826 uint64_t imm_bytes = 0;
4827 memcpy(&imm_bytes, &imm, 8);
4828 cbytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
4829 cbytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
4830 cbytes->push_back(match.word_index);
4831 } else {
4832 {
4833 fif_call imm = call_function;
4834 uint64_t imm_bytes = 0;
4835 memcpy(&imm_bytes, &imm, 8);
4836 cbytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
4837 cbytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
4838 }
4839 {
4840 int32_t* bcode = std::get<interpreted_word_instance>(*wi).compiled_bytecode.data();
4841 uint64_t imm_bytes = 0;
4842 memcpy(&imm_bytes, &bcode, 8);
4843 cbytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
4844 cbytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
4845 }
4846 }
4847 apply_stack_description(std::span<int32_t const>(env.dict.all_stack_types.data() + std::get<interpreted_word_instance>(*wi).stack_types_start, size_t(std::get<interpreted_word_instance>(*wi).stack_types_count)), *ws, env);
4848 }
4849 }
4850 } else if(std::holds_alternative<compiled_word_instance>(*wi)) {
4852 auto cbytes = env.compiler_stack.back()->bytecode_compilation_progress();
4853 if(cbytes) {
4854 fif_call imm = std::get<compiled_word_instance>(*wi).implementation;
4855 uint64_t imm_bytes = 0;
4856 memcpy(&imm_bytes, &imm, 8);
4857 cbytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
4858 cbytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
4859
4860 apply_stack_description(std::span<int32_t const>(env.dict.all_stack_types.data() + std::get<compiled_word_instance>(*wi).stack_types_start, size_t(std::get<compiled_word_instance>(*wi).stack_types_count)), *ws, env);
4861 }
4862 } else {
4863 std::get<compiled_word_instance>(*wi).implementation(*ws, nullptr, &env);
4864 }
4865 }
4866 }
4867 } else if(auto let = env.compiler_stack.back()->get_let(content_string); word.is_string == false && let) {
4868 if(typechecking_mode(env.mode)) {
4869 ws->push_back_main(let->type, let->data, let->expression);
4870 } else if(env.mode == fif_mode::compiling_llvm) {
4871 ws->push_back_main(let->type, let->data, let->expression);
4872 } else if(env.mode == fif_mode::interpreting) {
4873 ws->push_back_main(let->type, let->data, let->expression);
4874 } else if(env.mode == fif_mode::compiling_bytecode) {
4875 // implement let
4876 auto cbytes = env.compiler_stack.back()->bytecode_compilation_progress();
4877 if(cbytes) {
4878 fif_call imm = immediate_let;
4879 uint64_t imm_bytes = 0;
4880 memcpy(&imm_bytes, &imm, 8);
4881 cbytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
4882 cbytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
4883
4884 auto string_constant = env.get_string_constant(word.content);
4885 char const* cptr = string_constant.data();
4886
4887 uint64_t let_addr = 0;
4888 memcpy(&let_addr, &cptr, 8);
4889 cbytes->push_back(int32_t(let_addr & 0xFFFFFFFF));
4890 cbytes->push_back(int32_t((let_addr >> 32) & 0xFFFFFFFF));
4891
4892 cbytes->push_back(let->type);
4893 }
4894 ws->push_back_main(let->type, 0, 0);
4895 }
4896 } else if(auto var = env.compiler_stack.back()->get_var(content_string); word.is_string == false && var) {
4897 int32_t ptr_type[] = { fif_ptr, std::numeric_limits<int32_t>::max(), var->type, -1 };
4898 std::vector<int32_t> subs;
4899 auto mem_type = resolve_span_type(std::span<int32_t const>(ptr_type, ptr_type + 4), subs, env);
4900
4901 if(typechecking_mode(env.mode)) {
4902 ws->push_back_main(mem_type.type, 0, 0);
4903 } else if(env.mode == fif_mode::compiling_llvm) {
4904 ws->push_back_main(mem_type.type, 0, var->alloc);
4905 } else if(env.mode == fif_mode::interpreting) {
4906 ws->push_back_main(mem_type.type, (int64_t)(var), 0);
4907 } else if(env.mode == fif_mode::compiling_bytecode) {
4908 // implement let
4909 auto cbytes = env.compiler_stack.back()->bytecode_compilation_progress();
4910 if(cbytes) {
4912 uint64_t imm_bytes = 0;
4913 memcpy(&imm_bytes, &imm, 8);
4914 cbytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
4915 cbytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
4916
4917 auto string_constant = env.get_string_constant(word.content);
4918 char const* cptr = string_constant.data();
4919 uint64_t let_addr = 0;
4920 memcpy(&let_addr, &cptr, 8);
4921 cbytes->push_back(int32_t(let_addr & 0xFFFFFFFF));
4922 cbytes->push_back(int32_t((let_addr >> 32) & 0xFFFFFFFF));
4923
4924 cbytes->push_back(mem_type.type);
4925 }
4926 ws->push_back_main(mem_type.type, 0, 0);
4927 }
4928 } else if(auto letb = get_global_let(env, content_string); word.is_string == false && letb) {
4929
4930 } else if(auto varb = get_global_var(env, content_string); word.is_string == false && varb) {
4931 int32_t ptr_type[] = { fif_ptr, std::numeric_limits<int32_t>::max(), varb->type, -1 };
4932 std::vector<int32_t> subs;
4933 auto mem_type = resolve_span_type(std::span<int32_t const>(ptr_type, ptr_type + 4), subs, env);
4934
4935 if(typechecking_mode(env.mode)) {
4936 ws->push_back_main(mem_type.type, 0, 0);
4937 } else if(env.mode == fif_mode::compiling_llvm) {
4938 ws->push_back_main(mem_type.type, 0, varb->alloc);
4939 } else if(env.mode == fif_mode::interpreting) {
4940 ws->push_back_main(mem_type.type, (int64_t)(varb), 0);
4941 } else if(env.mode == fif_mode::compiling_bytecode) {
4942 // implement let
4943 auto cbytes = env.compiler_stack.back()->bytecode_compilation_progress();
4944 if(cbytes) {
4946 uint64_t imm_bytes = 0;
4947 memcpy(&imm_bytes, &imm, 8);
4948 cbytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
4949 cbytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
4950
4951 auto string_constant = env.get_string_constant(word.content);
4952 char const* cptr = string_constant.data();
4953 uint64_t let_addr = 0;
4954 memcpy(&let_addr, &cptr, 8);
4955 cbytes->push_back(int32_t(let_addr & 0xFFFFFFFF));
4956 cbytes->push_back(int32_t((let_addr >> 32) & 0xFFFFFFFF));
4957
4958 cbytes->push_back(mem_type.type);
4959 }
4960 ws->push_back_main(mem_type.type, 0, 0);
4961 }
4962 } else if(auto rtype = resolve_type(word.content, env, env.compiler_stack.back()->type_substitutions()); rtype != -1) {
4963 do_immediate_type(*ws, rtype, &env);
4964 } else {
4965 env.report_error(std::string("attempted to execute an unknown word: ") + std::string(word.content));
4966 env.mode = fif_mode::error;
4967 }
4968}
4969
4970#ifdef USE_LLVM
4971inline void add_exportable_functions_to_globals(environment& env) {
4972 if(!env.exported_functions.empty()) {
4973 auto array_type = LLVMArrayType(LLVMPointerTypeInContext(env.llvm_context, 0), 1);
4974 auto used_array = LLVMAddGlobal(env.llvm_module, array_type, "llvm.used");
4975 LLVMSetLinkage(used_array, LLVMLinkage::LLVMAppendingLinkage);
4976 LLVMSetInitializer(used_array, LLVMConstArray(LLVMPointerTypeInContext(env.llvm_context, 0), env.exported_functions.data(), uint32_t(env.exported_functions.size())));
4977 LLVMSetSection(used_array, "llvm.metadata");
4978 }
4979}
4980
4981inline LLVMValueRef make_exportable_function(std::string const& export_name, std::string const& word, std::vector<int32_t> param_stack, std::vector<int32_t> return_stack, environment& env) {
4982
4983 env.compiler_stack.emplace_back(std::make_unique<outer_interpreter>(env));
4984 env.source_stack.push_back(std::string_view{ });
4985 outer_interpreter* o = static_cast<outer_interpreter*>(env.compiler_stack.back().get());
4987 static_cast<mode_switch_scope*>(env.compiler_stack.back().get())->interpreted_link = o;
4988
4989 int32_t w = -1;
4990 if(auto it = env.dict.words.find(word); it != env.dict.words.end()) {
4991 w = it->second;
4992 } else {
4993 env.report_error("failed to export function (dictionary lookup failed)");
4994 return nullptr;
4995 }
4996
4997 llvm_stack ts;
4998 ts.resize(param_stack.size(), return_stack.size());
4999 for(auto i = param_stack.size(); i-- > 0; ) {
5000 ts.set_main_type(i, param_stack[i]);
5001 }
5002 for(auto i = return_stack.size(); i-- > 0; ) {
5003 ts.set_return_type(i, return_stack[i]);
5004 }
5005 ts.min_main_depth = param_stack.size();
5006 ts.min_return_depth = param_stack.size();
5007
5008 std::vector<int32_t> typevars;
5009 auto match = get_basic_type_match(w, ts, env, typevars, false);
5010 w = match.substitution_version;
5011 if(!match.matched) {
5012 env.report_error("failed to export function (typematch failed)");
5013 return nullptr;
5014 }
5015
5016 if(!compile_word(w, match.word_index, ts, fif_mode::compiling_llvm, env, typevars)) {
5017 env.report_error("failed to export function (compilation failed)");
5018 return nullptr;
5019 }
5020
5021 if(!std::holds_alternative<interpreted_word_instance>(env.dict.all_instances[match.word_index])) {
5022 env.report_error("failed to export function (can't export built-in)");
5023 return nullptr;
5024 }
5025
5026 auto& wi = std::get<interpreted_word_instance>(env.dict.all_instances[match.word_index]);
5027
5028 auto desc = std::span<int32_t const>(env.dict.all_stack_types.data() + wi.stack_types_start, wi.stack_types_count);
5029 auto fn_type = llvm_function_type_from_desc(env, desc);
5030 auto compiled_fn = LLVMAddFunction(env.llvm_module, export_name.c_str(), fn_type);
5031
5032 LLVMSetFunctionCallConv(compiled_fn, NATIVE_CC);
5033 //LLVMSetLinkage(compiled_fn, LLVMLinkage::LLVMLinkOnceAnyLinkage);
5034 //LLVMSetVisibility(compiled_fn, LLVMVisibility::LLVMDefaultVisibility);
5035
5036 auto entry_block = LLVMAppendBasicBlockInContext(env.llvm_context, compiled_fn, "fn_entry_point");
5037 LLVMPositionBuilderAtEnd(env.llvm_builder, entry_block);
5038
5039
5040 // add body
5041 std::vector<LLVMValueRef> params;
5042
5043 int32_t match_position = 0;
5044 // stack matching
5045
5046 int32_t consumed_stack_cells = 0;
5047 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
5048 params.push_back(LLVMGetParam(compiled_fn, uint32_t(consumed_stack_cells)));
5049 ++match_position;
5050 ++consumed_stack_cells;
5051 }
5052
5053 ++match_position; // skip -1
5054
5055 // output stack
5056 int32_t first_output_stack = match_position;
5057 //int32_t output_stack_types = 0;
5058 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
5059 //returns_group.push_back(env.dict.type_array[desc[match_position]].llvm_type.llvm_type);
5060 ++match_position;
5061 //++output_stack_types;
5062 }
5063 ++match_position; // skip -1
5064
5065 // return stack matching
5066 int32_t consumed_rstack_cells = 0;
5067 while(match_position < int32_t(desc.size()) && desc[match_position] != -1) {
5068 params.push_back(LLVMGetParam(compiled_fn, uint32_t(consumed_stack_cells + consumed_rstack_cells)));
5069 ++match_position;
5070 ++consumed_rstack_cells;
5071 }
5072
5073 auto retvalue = LLVMBuildCall2(env.llvm_builder, llvm_function_type_from_desc(env, desc), wi.llvm_function, params.data(), uint32_t(params.size()), "");
5074 LLVMSetInstructionCallConv(retvalue, LLVMCallConv::LLVMFastCallConv);
5075 auto rsummary = llvm_function_return_type_from_desc(env, desc);
5076
5077 // make return
5078 if(rsummary.composite_type == nullptr) {
5079 LLVMBuildRetVoid(env.llvm_builder);
5080 } else {
5081 LLVMBuildRet(env.llvm_builder, retvalue);
5082 }
5083 if(LLVMVerifyFunction(compiled_fn, LLVMVerifierFailureAction::LLVMPrintMessageAction))
5084 std::abort();
5085
5086 env.exported_functions.push_back(compiled_fn);
5087
5089 env.compiler_stack.pop_back();
5090 env.source_stack.pop_back();
5091
5092 return compiled_fn;
5093}
5094#endif
5095
5096inline void run_fif_interpreter(environment& env, std::string_view on_text) {
5097 env.source_stack.push_back(std::string_view(on_text));
5098 env.compiler_stack.emplace_back(std::make_unique<outer_interpreter>(env));
5099 outer_interpreter* o = static_cast<outer_interpreter*>(env.compiler_stack.back().get());
5100
5102 mode_switch_scope* m = static_cast<mode_switch_scope*>(env.compiler_stack.back().get());
5103 m->interpreted_link = o;
5104
5105 run_to_scope_end(env);
5106 env.source_stack.pop_back();
5108 env.compiler_stack.pop_back();
5109}
5110
5111inline void run_fif_interpreter(environment& env, std::string_view on_text, interpreter_stack& s) {
5112 env.source_stack.push_back(std::string_view(on_text));
5113 env.compiler_stack.emplace_back(std::make_unique<outer_interpreter>(env));
5114 outer_interpreter* o = static_cast<outer_interpreter*>(env.compiler_stack.back().get());
5115 static_cast<interpreter_stack*>(o->interpreter_state.get())->move_into(std::move(s));
5116
5118 mode_switch_scope* m = static_cast<mode_switch_scope*>(env.compiler_stack.back().get());
5119 m->interpreted_link = o;
5120
5121 run_to_scope_end(env);
5122 env.source_stack.pop_back();
5124
5125 s.move_into(std::move(*(o->interpreter_state)));
5126 env.compiler_stack.pop_back();
5127}
5128
5129#ifdef USE_LLVM
5130inline LLVMErrorRef module_transform(void* Ctx, LLVMModuleRef Mod) {
5138 LLVMErrorRef E = LLVMRunPasses(Mod, "default<O3>", nullptr, pass_opts);
5139 //LLVMErrorRef E = LLVMRunPasses(Mod, "instcombine", nullptr, pass_opts);
5141 if(E) {
5142 auto msg = LLVMGetErrorMessage(E);
5143 //std::cout << msg << std::endl;
5145 std::abort();
5146 }
5147 return E;
5148}
5149
5150inline LLVMErrorRef perform_transform(void* Ctx, LLVMOrcThreadSafeModuleRef* the_module, LLVMOrcMaterializationResponsibilityRef MR) {
5151 return LLVMOrcThreadSafeModuleWithModuleDo(*the_module, module_transform, Ctx);
5152}
5153#endif
5154inline void add_import(std::string_view name, void* ptr, fif_call interpreter_implementation, std::vector<int32_t> const& params, std::vector<int32_t> const& returns, environment& env) {
5155 env.imported_functions.push_back(import_item{ std::string(name), ptr });
5156
5157 std::vector<int32_t> itype_list;
5158 for(auto j = params.size(); j-->0;) {
5159 itype_list.push_back(params[j]);
5160 }
5161 auto pcount = itype_list.size();
5162 if(!returns.empty()) {
5163 itype_list.push_back(-1);
5164 for(auto r : returns) {
5165 itype_list.push_back(r);
5166 }
5167 }
5168
5169 int32_t start_types = int32_t(env.dict.all_stack_types.size());
5170 env.dict.all_stack_types.insert(env.dict.all_stack_types.end(), itype_list.begin(), itype_list.end());
5171 int32_t count_types = int32_t(itype_list.size());
5172
5173 auto nstr = std::string(name);
5174 int32_t old_word = -1;
5175 if(auto it = env.dict.words.find(nstr); it != env.dict.words.end()) {
5176 old_word = it->second;
5177 }
5178
5179 env.dict.words.insert_or_assign(nstr, int32_t(env.dict.word_array.size()));
5180 env.dict.word_array.emplace_back();
5181 env.dict.word_array.back().specialization_of = old_word;
5182 env.dict.word_array.back().stack_types_start = start_types;
5183 env.dict.word_array.back().stack_types_count = int32_t(pcount);
5184
5185 auto instance_num = int32_t(env.dict.all_instances.size());
5186 env.dict.word_array.back().instances.push_back(instance_num);
5187
5189 {
5190 fif_call imm = interpreter_implementation;
5191 uint64_t imm_bytes = 0;
5192 memcpy(&imm_bytes, &imm, 8);
5193 wi.compiled_bytecode.push_back(int32_t(imm_bytes & 0xFFFFFFFF));
5194 wi.compiled_bytecode.push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
5195 }
5196 {
5198 uint64_t imm_bytes = 0;
5199 memcpy(&imm_bytes, &imm, 8);
5200 wi.compiled_bytecode.push_back(int32_t(imm_bytes & 0xFFFFFFFF));
5201 wi.compiled_bytecode.push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
5202 }
5203 wi.llvm_compilation_finished = true;
5204 wi.stack_types_start = start_types;
5205 wi.stack_types_count = count_types;
5206 wi.typechecking_level = 3;
5207 wi.is_imported_function = true;
5208
5209#ifdef USE_LLVM
5210 auto fn_desc = std::span<int32_t const>(itype_list.begin(), itype_list.end());
5211 auto fn_type = llvm_function_type_from_desc(env, fn_desc);
5212 wi.llvm_function = LLVMAddFunction(env.llvm_module, nstr.c_str(), fn_type);
5214 LLVMSetLinkage(wi.llvm_function, LLVMLinkage::LLVMExternalLinkage);
5215#endif
5216
5217 env.dict.all_instances.emplace_back(std::move(wi));
5218}
5219
5220#ifdef USE_LLVM
5221inline void perform_jit(environment& e) {
5222 //add_exportable_functions_to_globals(e);
5223
5224 char* out_message = nullptr;
5225 auto result = LLVMVerifyModule(e.llvm_module, LLVMVerifierFailureAction::LLVMPrintMessageAction, &out_message);
5226 if(result) {
5227 e.report_error(out_message);
5228 return;
5229 }
5230 if(out_message)
5231 LLVMDisposeMessage(out_message);
5232
5233 LLVMDisposeBuilder(e.llvm_builder);
5234 e.llvm_builder = nullptr;
5235
5236 // ORC JIT
5237 auto jit_builder = LLVMOrcCreateLLJITBuilder();
5238 assert(jit_builder);
5239
5240 auto target_machine = LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(e.llvm_target_machine);
5241 e.llvm_target_machine = nullptr;
5242 LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(jit_builder, target_machine);
5243
5244 auto errora = LLVMOrcCreateLLJIT(&e.llvm_jit, jit_builder);
5245 if(errora) {
5246 auto msg = LLVMGetErrorMessage(errora);
5247 e.report_error(msg);
5249 return;
5250 }
5251
5252 if(!e.llvm_jit) {
5253 e.report_error("failed to create jit");
5254 return;
5255 }
5256
5257
5259 LLVMOrcIRTransformLayerSetTransform(TL, *perform_transform, nullptr);
5260
5261 LLVMOrcThreadSafeModuleRef orc_mod = LLVMOrcCreateNewThreadSafeModule(e.llvm_module, e.llvm_ts_context);
5262 e.llvm_module = nullptr;
5263
5264 LLVMOrcExecutionSessionRef execution_session = LLVMOrcLLJITGetExecutionSession(e.llvm_jit);
5265 LLVMOrcJITDylibRef main_dyn_lib = LLVMOrcLLJITGetMainJITDylib(e.llvm_jit);
5266 if(!main_dyn_lib) {
5267 e.report_error("failed to get main dylib");
5268 std::abort();
5269 }
5270
5271 // add imports
5272 std::vector< LLVMOrcCSymbolMapPair> import_symbols;
5273 for(auto& i : e.imported_functions) {
5274 auto name = LLVMOrcLLJITMangleAndIntern(e.llvm_jit, i.name.c_str());
5276 sym.Address = (LLVMOrcExecutorAddress)i.ptr;
5277 sym.Flags.GenericFlags = LLVMJITSymbolGenericFlags::LLVMJITSymbolGenericFlagsCallable;
5278 sym.Flags.TargetFlags = 0;
5279 import_symbols.push_back(LLVMOrcCSymbolMapPair{ name, sym });
5280 }
5281
5282 if(import_symbols.size() > 0) {
5283 auto import_mr = LLVMOrcAbsoluteSymbols(import_symbols.data(), import_symbols.size());
5284 auto import_result = LLVMOrcJITDylibDefine(main_dyn_lib, import_mr);
5285 if(import_result) {
5286 auto msg = LLVMGetErrorMessage(import_result);
5287 e.report_error(msg);
5289 return;
5290 }
5291 }
5292
5293 auto error = LLVMOrcLLJITAddLLVMIRModule(e.llvm_jit, main_dyn_lib, orc_mod);
5294 if(error) {
5295 auto msg = LLVMGetErrorMessage(error);
5296 e.report_error(msg);
5298 return;
5299 }
5300}
5301#endif
5302
5303inline int32_t* colon_definition(fif::state_stack&, int32_t* p, fif::environment* e) {
5305 return p + 2;
5307 e->report_error("attempted to compile a definition inside a definition");
5309 return p + 2;
5310 }
5311
5312 if(e->source_stack.empty()) {
5313 e->report_error("attempted to compile a definition without a source");
5315 return p + 2;
5316 }
5317
5318 auto name_token = fif::read_token(e->source_stack.back(), *e);
5319
5320 auto string_start = e->source_stack.back().data();
5321 while(e->source_stack.back().length() > 0) {
5322 auto t = fif::read_token(e->source_stack.back(), *e);
5323 if(t.is_string == false && t.content == ";") { // end of definition
5324 auto string_end = t.content.data();
5325
5326 auto nstr = std::string(name_token.content);
5327 if(e->dict.words.find(nstr) != e->dict.words.end()) {
5328 e->report_error("illegal word redefinition");
5329 e->mode = fif_mode::error;
5330 return p + 2;
5331 }
5332
5333 e->dict.words.insert_or_assign(nstr, int32_t(e->dict.word_array.size()));
5334 e->dict.word_array.emplace_back();
5335 e->dict.word_array.back().source = std::string(string_start, string_end);
5336
5337 return p + 2;
5338 }
5339 }
5340
5341 e->report_error("reached the end of a definition source without a ; terminator");
5343 return p + 2;
5344}
5345
5346inline int32_t* colon_specialization(fif::state_stack&, int32_t* p, fif::environment* e) {
5348 return p + 2;
5350 e->report_error("attempted to compile a definition inside a definition");
5352 return p + 2;
5353 }
5354
5355 if(e->source_stack.empty()) {
5356 e->report_error("attempted to compile a definition without a source");
5358 return p + 2;
5359 }
5360
5361 auto name_token = fif::read_token(e->source_stack.back(), *e);
5362
5363 std::vector<std::string_view> stack_types;
5364 while(true) {
5365 auto next_token = fif::read_token(e->source_stack.back(), *e);
5366 if(next_token.content.length() == 0 || next_token.content == "s:") {
5367 break;
5368 }
5369 stack_types.push_back(next_token.content);
5370 }
5371
5372 std::vector<int32_t> acc_types;
5373 while(!stack_types.empty()) {
5374 auto result = internal_generate_type(stack_types.back(), *e);
5375 if(result.type_array.empty()) {
5376 e->mode = fif_mode::error;
5377 e->report_error("unable to resolve type from text");
5378 return nullptr;
5379 }
5380 acc_types.insert(acc_types.end(), result.type_array.begin(), result.type_array.end());
5381 stack_types.pop_back();
5382 }
5383 int32_t start_types = int32_t(e->dict.all_stack_types.size());
5384 e->dict.all_stack_types.insert(e->dict.all_stack_types.end(), acc_types.begin(), acc_types.end());
5385 int32_t count_types = int32_t(acc_types.size());
5386
5387 auto string_start = e->source_stack.back().data();
5388 while(e->source_stack.back().length() > 0) {
5389 auto t = fif::read_token(e->source_stack.back(), *e);
5390 if(t.is_string == false && t.content == ";") { // end of definition
5391 auto string_end = t.content.data();
5392
5393 auto nstr = std::string(name_token.content);
5394 int32_t old_word = -1;
5395 if(auto it = e->dict.words.find(nstr); it != e->dict.words.end()) {
5396 old_word = it->second;
5397 }
5398
5399 e->dict.words.insert_or_assign(nstr, int32_t(e->dict.word_array.size()));
5400 e->dict.word_array.emplace_back();
5401 e->dict.word_array.back().source = std::string(string_start, string_end);
5402 e->dict.word_array.back().specialization_of = old_word;
5403 e->dict.word_array.back().stack_types_start = start_types;
5404 e->dict.word_array.back().stack_types_count = count_types;
5405
5406 return p + 2;
5407 }
5408 }
5409
5410 e->report_error("reached the end of a definition source without a ; terminator");
5412 return p + 2;
5413}
5414
5415inline int32_t* iadd(fif::state_stack& s, int32_t* p, fif::environment* e) {
5417#ifdef USE_LLVM
5419 auto add_result = LLVMBuildAdd(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5420 s.pop_main();
5421 s.set_main_ex_back(0, add_result);
5422#endif
5423 } else if(e->mode == fif::fif_mode::interpreting) {
5425 auto a = s.main_data_back(0);
5426 auto b = s.main_data_back(1);
5427 s.pop_main();
5428 s.set_main_data_back(0, b + a);
5431 s.pop_main();
5432 }
5433 return p + 2;
5434}
5435inline int32_t* f32_add(fif::state_stack& s, int32_t* p, fif::environment* e) {
5437#ifdef USE_LLVM
5438 auto add_result = LLVMBuildFAdd(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5439 s.pop_main();
5440 s.pop_main();
5441 s.push_back_main(fif_f32, 0, add_result);
5442#endif
5443 } else if(e->mode == fif::fif_mode::interpreting) {
5444 auto a = s.main_data_back(0);
5445 auto b = s.main_data_back(1);
5446 s.pop_main();
5447 s.pop_main();
5448 float fa = 0;
5449 float fb = 0;
5450 memcpy(&fa, &a, 4);
5451 memcpy(&fb, &b, 4);
5452 fa = fa + fb;
5453 memcpy(&a, &fa, 4);
5454 s.push_back_main(fif::fif_f32, a, nullptr);
5456 s.pop_main();
5457 s.pop_main();
5458 s.push_back_main(fif::fif_f32, 0, nullptr);
5459 }
5460 return p + 2;
5461}
5462inline int32_t* f64_add(fif::state_stack& s, int32_t* p, fif::environment* e) {
5464#ifdef USE_LLVM
5465 auto add_result = LLVMBuildFAdd(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5466 s.pop_main();
5467 s.pop_main();
5468 s.push_back_main(fif_f64, 0, add_result);
5469#endif
5470 } else if(e->mode == fif::fif_mode::interpreting) {
5471 auto a = s.main_data_back(0);
5472 auto b = s.main_data_back(1);
5473 s.pop_main();
5474 s.pop_main();
5475 double fa = 0;
5476 double fb = 0;
5477 memcpy(&fa, &a, 8);
5478 memcpy(&fb, &b, 8);
5479 fa = fa + fb;
5480 memcpy(&a, &fa, 8);
5481 s.push_back_main(fif::fif_f64, a, nullptr);
5483 s.pop_main();
5484 s.pop_main();
5485 s.push_back_main(fif::fif_f64, 0, nullptr);
5486 }
5487 return p + 2;
5488}
5489inline int32_t* isub(fif::state_stack& s, int32_t* p, fif::environment* e) {
5491#ifdef USE_LLVM
5493 auto add_result = LLVMBuildSub(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5494 s.pop_main();
5495 s.set_main_ex_back(0, add_result);
5496#endif
5497 } else if(e->mode == fif::fif_mode::interpreting) {
5499 auto a = s.main_data_back(0);
5500 auto b = s.main_data_back(1);
5501 s.pop_main();
5502 s.set_main_data_back(0, b - a);
5505 s.pop_main();
5506 }
5507 return p + 2;
5508}
5509inline int32_t* f32_sub(fif::state_stack& s, int32_t* p, fif::environment* e) {
5511#ifdef USE_LLVM
5512 auto add_result = LLVMBuildFSub(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5513 s.pop_main();
5514 s.pop_main();
5515 s.push_back_main(fif_f32, 0, add_result);
5516#endif
5517 } else if(e->mode == fif::fif_mode::interpreting) {
5518 auto a = s.main_data_back(0);
5519 auto b = s.main_data_back(1);
5520 s.pop_main();
5521 s.pop_main();
5522 float fa = 0;
5523 float fb = 0;
5524 memcpy(&fa, &a, 4);
5525 memcpy(&fb, &b, 4);
5526 fa = fa - fb;
5527 memcpy(&a, &fa, 4);
5528 s.push_back_main(fif::fif_f32, a, nullptr);
5530 s.pop_main();
5531 s.pop_main();
5532 s.push_back_main(fif::fif_f32, 0, nullptr);
5533 }
5534 return p + 2;
5535}
5536inline int32_t* f64_sub(fif::state_stack& s, int32_t* p, fif::environment* e) {
5538#ifdef USE_LLVM
5539 auto add_result = LLVMBuildFSub(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5540 s.pop_main();
5541 s.pop_main();
5542 s.push_back_main(fif_f64, 0, add_result);
5543#endif
5544 } else if(e->mode == fif::fif_mode::interpreting) {
5545 auto a = s.main_data_back(0);
5546 auto b = s.main_data_back(1);
5547 s.pop_main();
5548 s.pop_main();
5549 double fa = 0;
5550 double fb = 0;
5551 memcpy(&fa, &a, 8);
5552 memcpy(&fb, &b, 8);
5553 fa = fa - fb;
5554 memcpy(&a, &fa, 8);
5555 s.push_back_main(fif::fif_f64, a, nullptr);
5557 s.pop_main();
5558 s.pop_main();
5559 s.push_back_main(fif::fif_f64, 0, nullptr);
5560 }
5561 return p + 2;
5562}
5563inline int32_t* imul(fif::state_stack& s, int32_t* p, fif::environment* e) {
5565#ifdef USE_LLVM
5567 auto add_result = LLVMBuildMul(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5568 s.pop_main();
5569 s.set_main_ex_back(0, add_result);
5570#endif
5571 } else if(e->mode == fif::fif_mode::interpreting) {
5573 auto a = s.main_data_back(0);
5574 auto b = s.main_data_back(1);
5575 s.pop_main();
5576 s.set_main_data_back(0, b * a);
5579 s.pop_main();
5580 }
5581 return p + 2;
5582}
5583inline int32_t* f32_mul(fif::state_stack& s, int32_t* p, fif::environment* e) {
5585#ifdef USE_LLVM
5586 auto add_result = LLVMBuildFMul(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5587 s.pop_main();
5588 s.pop_main();
5589 s.push_back_main(fif_f32, 0, add_result);
5590#endif
5591 } else if(e->mode == fif::fif_mode::interpreting) {
5592 auto a = s.main_data_back(0);
5593 auto b = s.main_data_back(1);
5594 s.pop_main();
5595 s.pop_main();
5596 float fa = 0;
5597 float fb = 0;
5598 memcpy(&fa, &a, 4);
5599 memcpy(&fb, &b, 4);
5600 fa = fb * fa;
5601 memcpy(&a, &fa, 4);
5602 s.push_back_main(fif::fif_f32, a, nullptr);
5604 s.pop_main();
5605 s.pop_main();
5606 s.push_back_main(fif::fif_f32, 0, nullptr);
5607 }
5608 return p + 2;
5609}
5610inline int32_t* f64_mul(fif::state_stack& s, int32_t* p, fif::environment* e) {
5612#ifdef USE_LLVM
5613 auto add_result = LLVMBuildFMul(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5614 s.pop_main();
5615 s.pop_main();
5616 s.push_back_main(fif_f64, 0, add_result);
5617#endif
5618 } else if(e->mode == fif::fif_mode::interpreting) {
5619 auto a = s.main_data_back(0);
5620 auto b = s.main_data_back(1);
5621 s.pop_main();
5622 s.pop_main();
5623 double fa = 0;
5624 double fb = 0;
5625 memcpy(&fa, &a, 8);
5626 memcpy(&fb, &b, 8);
5627 fa = fb * fa;
5628 memcpy(&a, &fa, 8);
5629 s.push_back_main(fif::fif_f64, a, nullptr);
5631 s.pop_main();
5632 s.pop_main();
5633 s.push_back_main(fif::fif_f64, 0, nullptr);
5634 }
5635 return p + 2;
5636}
5637inline int32_t* sidiv(fif::state_stack& s, int32_t* p, fif::environment* e) {
5639#ifdef USE_LLVM
5641 auto add_result = LLVMBuildSDiv(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5642 s.pop_main();
5643 s.set_main_ex_back(0, add_result);
5644#endif
5645 } else if(e->mode == fif::fif_mode::interpreting) {
5647 auto a = s.main_data_back(0);
5648 auto b = s.main_data_back(1);
5649 s.pop_main();
5650 s.set_main_data_back(0, b / a);
5653 s.pop_main();
5654 }
5655 return p + 2;
5656}
5657inline int32_t* uidiv(fif::state_stack& s, int32_t* p, fif::environment* e) {
5659#ifdef USE_LLVM
5661 auto add_result = LLVMBuildUDiv(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5662 s.pop_main();
5663 s.set_main_ex_back(0, add_result);
5664#endif
5665 } else if(e->mode == fif::fif_mode::interpreting) {
5667 auto a = uint64_t(s.main_data_back(0));
5668 auto b = uint64_t(s.main_data_back(1));
5669 s.pop_main();
5670 s.set_main_data_back(0, b / a);
5673 s.pop_main();
5674 }
5675 return p + 2;
5676}
5677inline int32_t* f32_div(fif::state_stack& s, int32_t* p, fif::environment* e) {
5679#ifdef USE_LLVM
5680 auto add_result = LLVMBuildFDiv(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5681 s.pop_main();
5682 s.pop_main();
5683 s.push_back_main(fif_f32, 0, add_result);
5684#endif
5685 } else if(e->mode == fif::fif_mode::interpreting) {
5686 auto a = s.main_data_back(0);
5687 auto b = s.main_data_back(1);
5688 s.pop_main();
5689 s.pop_main();
5690 float fa = 0;
5691 float fb = 0;
5692 memcpy(&fa, &a, 4);
5693 memcpy(&fb, &b, 4);
5694 fa = fb / fa;
5695 memcpy(&a, &fa, 4);
5696 s.push_back_main(fif::fif_f32, a, nullptr);
5698 s.pop_main();
5699 s.pop_main();
5700 s.push_back_main(fif::fif_f32, 0, nullptr);
5701 }
5702 return p + 2;
5703}
5704inline int32_t* f64_div(fif::state_stack& s, int32_t* p, fif::environment* e) {
5706#ifdef USE_LLVM
5707 auto add_result = LLVMBuildFDiv(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5708 s.pop_main();
5709 s.pop_main();
5710 s.push_back_main(fif_f64, 0, add_result);
5711#endif
5712 } else if(e->mode == fif::fif_mode::interpreting) {
5713 auto a = s.main_data_back(0);
5714 auto b = s.main_data_back(1);
5715 s.pop_main();
5716 s.pop_main();
5717 double fa = 0;
5718 double fb = 0;
5719 memcpy(&fa, &a, 8);
5720 memcpy(&fb, &b, 8);
5721 fa = fb / fa;
5722 memcpy(&a, &fa, 8);
5723 s.push_back_main(fif::fif_f64, a, nullptr);
5725 s.pop_main();
5726 s.pop_main();
5727 s.push_back_main(fif::fif_f64, 0, nullptr);
5728 }
5729 return p + 2;
5730}
5731inline int32_t* simod(fif::state_stack& s, int32_t* p, fif::environment* e) {
5733#ifdef USE_LLVM
5735 auto add_result = LLVMBuildSRem(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5736 s.pop_main();
5737 s.set_main_ex_back(0, add_result);
5738#endif
5739 } else if(e->mode == fif::fif_mode::interpreting) {
5741 auto a = s.main_data_back(0);
5742 auto b = s.main_data_back(1);
5743 s.pop_main();
5744 s.set_main_data_back(0, b % a);
5747 s.pop_main();
5748 }
5749 return p + 2;
5750}
5751inline int32_t* uimod(fif::state_stack& s, int32_t* p, fif::environment* e) {
5753#ifdef USE_LLVM
5755 auto add_result = LLVMBuildURem(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5756 s.pop_main();
5757 s.set_main_ex_back(0, add_result);
5758#endif
5759 } else if(e->mode == fif::fif_mode::interpreting) {
5761 auto a = uint64_t(s.main_data_back(0));
5762 auto b = uint64_t(s.main_data_back(1));
5763 s.pop_main();
5764 s.set_main_data_back(0, b % a);
5767 s.pop_main();
5768 }
5769 return p + 2;
5770}
5771inline int32_t* f32_mod(fif::state_stack& s, int32_t* p, fif::environment* e) {
5773#ifdef USE_LLVM
5774 auto add_result = LLVMBuildFRem(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5775 s.pop_main();
5776 s.pop_main();
5777 s.push_back_main(fif_f32, 0, add_result);
5778#endif
5779 } else if(e->mode == fif::fif_mode::interpreting) {
5780 auto a = s.main_data_back(0);
5781 auto b = s.main_data_back(1);
5782 s.pop_main();
5783 s.pop_main();
5784 float fa = 0;
5785 float fb = 0;
5786 memcpy(&fa, &a, 4);
5787 memcpy(&fb, &b, 4);
5788 fa = fmodf(fb, fa);
5789 memcpy(&a, &fa, 4);
5790 s.push_back_main(fif::fif_f32, a, nullptr);
5792 s.pop_main();
5793 s.pop_main();
5794 s.push_back_main(fif::fif_f32, 0, nullptr);
5795 }
5796 return p + 2;
5797}
5798inline int32_t* f64_mod(fif::state_stack& s, int32_t* p, fif::environment* e) {
5800#ifdef USE_LLVM
5801 auto add_result = LLVMBuildFDiv(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
5802 s.pop_main();
5803 s.pop_main();
5804 s.push_back_main(fif_f64, 0, add_result);
5805#endif
5806 } else if(e->mode == fif::fif_mode::interpreting) {
5807 auto a = s.main_data_back(0);
5808 auto b = s.main_data_back(1);
5809 s.pop_main();
5810 s.pop_main();
5811 double fa = 0;
5812 double fb = 0;
5813 memcpy(&fa, &a, 8);
5814 memcpy(&fb, &b, 8);
5815 fa = fmod(fb, fa);
5816 memcpy(&a, &fa, 8);
5817 s.push_back_main(fif::fif_f64, a, nullptr);
5819 s.pop_main();
5820 s.pop_main();
5821 s.push_back_main(fif::fif_f64, 0, nullptr);
5822 }
5823 return p + 2;
5824}
5825inline int32_t* dup(fif::state_stack& s, int32_t* p, fif::environment* e) {
5828 auto type = s.main_type_back(0);
5829 auto expr = s.main_ex_back(0);
5830 s.push_back_main(type, 0, expr);
5831 } else if(e->mode == fif::fif_mode::interpreting) {
5833 auto type = s.main_type_back(0);
5834 auto dat = s.main_data_back(0);
5835 s.push_back_main(type, dat, nullptr);
5838 auto type = s.main_type_back(0);
5839 s.push_back_main(type, 0, nullptr);
5840 }
5841 return p + 2;
5842}
5843inline int32_t* init(fif::state_stack& s, int32_t* p, fif::environment* e) {
5846 } else if(e->mode == fif::fif_mode::interpreting) {
5850 }
5851 return p + 2;
5852}
5853inline int32_t* copy(fif::state_stack& s, int32_t* p, fif::environment* e) {
5856 auto type = s.main_type_back(0);
5857 auto expr = s.main_ex_back(0);
5858 s.push_back_main(type, 0, expr);
5859 } else if(e->mode == fif::fif_mode::interpreting) {
5861 auto type = s.main_type_back(0);
5862 auto dat = s.main_data_back(0);
5863 s.push_back_main(type, dat, nullptr);
5866 auto type = s.main_type_back(0);
5867 s.push_back_main(type, 0, nullptr);
5868 }
5869 return p + 2;
5870}
5871inline int32_t* drop(fif::state_stack& s, int32_t* p, fif::environment* e) {
5873 auto type = s.main_type_back(0);
5874 s.pop_main();
5875 } else if(e->mode == fif::fif_mode::interpreting) {
5876 auto type = s.main_type_back(0);
5877 s.pop_main();
5879 s.pop_main();
5880 }
5881 return p + 2;
5882}
5883inline int32_t* fif_swap(fif::state_stack& s, int32_t* p, fif::environment* e) {
5885 auto type_a = s.main_type_back(0);
5886 auto type_b = s.main_type_back(1);
5887 auto expr_a = s.main_ex_back(0);
5888 auto expr_b = s.main_ex_back(1);
5889 s.pop_main();
5890 s.pop_main();
5891 s.push_back_main(type_a, 0, expr_a);
5892 s.push_back_main(type_b, 0, expr_b);
5893 } else if(e->mode == fif::fif_mode::interpreting) {
5894 auto type_a = s.main_type_back(0);
5895 auto type_b = s.main_type_back(1);
5896 auto dat_a = s.main_data_back(0);
5897 auto dat_b = s.main_data_back(1);
5898 s.pop_main();
5899 s.pop_main();
5900 s.push_back_main(type_a, dat_a, nullptr);
5901 s.push_back_main(type_b, dat_b, nullptr);
5903 auto type_a = s.main_type_back(0);
5904 auto type_b = s.main_type_back(1);
5905 s.pop_main();
5906 s.pop_main();
5907 s.push_back_main(type_a, 0, nullptr);
5908 s.push_back_main(type_b, 0, nullptr);
5909 }
5910 return p + 2;
5911}
5912
5913
5914inline int32_t* fif_if(fif::state_stack& s, int32_t* p, fif::environment* e) {
5915 e->compiler_stack.emplace_back(std::make_unique<fif::conditional_scope>(e->compiler_stack.back().get(), *e, s));
5916 return p + 2;
5917}
5918inline int32_t* fif_else(fif::state_stack& s, int32_t* p, fif::environment* e) {
5919 if(e->compiler_stack.empty() || e->compiler_stack.back()->get_type() != fif::control_structure::str_if) {
5920 e->report_error("invalid use of else");
5922 } else {
5923 fif::conditional_scope* c = static_cast<fif::conditional_scope*>(e->compiler_stack.back().get());
5924 c->commit_first_branch(*e);
5925 }
5926 return p + 2;
5927}
5928inline int32_t* fif_then(fif::state_stack& s, int32_t* p, fif::environment* e) {
5929 if(e->compiler_stack.empty() || e->compiler_stack.back()->get_type() != fif::control_structure::str_if) {
5930 e->report_error("invalid use of then/end-if");
5932 } else {
5933 if(e->compiler_stack.back()->finish(*e))
5934 e->compiler_stack.pop_back();
5935 }
5936 return p + 2;
5937}
5938
5939inline int32_t* fif_while(fif::state_stack& s, int32_t* p, fif::environment* e) {
5940 e->compiler_stack.emplace_back(std::make_unique<fif::while_loop_scope>(e->compiler_stack.back().get(), *e, s));
5941 return p + 2;
5942}
5943inline int32_t* fif_loop(fif::state_stack& s, int32_t* p, fif::environment* e) {
5944 if(e->compiler_stack.empty() || e->compiler_stack.back()->get_type() != fif::control_structure::str_while_loop) {
5945 e->report_error("invalid use of loop");
5947 } else {
5948 fif::while_loop_scope* c = static_cast<fif::while_loop_scope*>(e->compiler_stack.back().get());
5949 c->end_condition(*e);
5950 }
5951 return p + 2;
5952}
5953inline int32_t* fif_end_while(fif::state_stack& s, int32_t* p, fif::environment* e) {
5954 if(e->compiler_stack.empty() || e->compiler_stack.back()->get_type() != fif::control_structure::str_while_loop) {
5955 e->report_error("invalid use of end-while");
5957 } else {
5958 if(e->compiler_stack.back()->finish(*e))
5959 e->compiler_stack.pop_back();
5960 }
5961 return p + 2;
5962}
5963inline int32_t* fif_do(fif::state_stack& s, int32_t* p, fif::environment* e) {
5964 e->compiler_stack.emplace_back(std::make_unique<fif::do_loop_scope>(e->compiler_stack.back().get(), *e, s));
5965 return p + 2;
5966}
5967inline int32_t* fif_until(fif::state_stack& s, int32_t* p, fif::environment* e) {
5968 if(e->compiler_stack.empty() || e->compiler_stack.back()->get_type() != fif::control_structure::str_do_loop) {
5969 e->report_error("invalid use of until");
5971 } else {
5972 fif::do_loop_scope* c = static_cast<fif::do_loop_scope*>(e->compiler_stack.back().get());
5973 c->at_until(*e);
5974 }
5975 return p + 2;
5976}
5977inline int32_t* fif_end_do(fif::state_stack& s, int32_t* p, fif::environment* e) {
5978 if(e->compiler_stack.empty() || e->compiler_stack.back()->get_type() != fif::control_structure::str_do_loop) {
5979 e->report_error("invalid use of end-do");
5981 } else {
5982 if(e->compiler_stack.back()->finish(*e))
5983 e->compiler_stack.pop_back();
5984 }
5985 return p + 2;
5986}
5987inline int32_t* from_r(fif::state_stack& s, int32_t* p, fif::environment* e) {
5989 auto type_a = s.return_type_back(0);
5990 auto expr_a = s.return_ex_back(0);
5991 s.push_back_main(type_a, 0, expr_a);
5992 s.pop_return();
5993 } else if(e->mode == fif::fif_mode::interpreting) {
5994 auto type_a = s.return_type_back(0);
5995 auto dat_a = s.return_data_back(0);
5996 s.push_back_main(type_a, dat_a, nullptr);
5997 s.pop_return();
5999 auto type_a = s.return_type_back(0);
6000 s.push_back_main(type_a, 0, nullptr);
6001 s.pop_return();
6002 }
6003 return p + 2;
6004}
6005inline int32_t* r_at(fif::state_stack& s, int32_t* p, fif::environment* e) {
6007 auto type_a = s.return_type_back(0);
6008 auto expr_a = s.return_ex_back(0);
6009 s.push_back_main(type_a, 0, expr_a);
6010 s.pop_return();
6011
6012 execute_fif_word(fif::parse_result{ "dup", false }, *e, false);
6013 auto type_b = s.main_type_back(0);
6014 auto expr_b = s.main_ex_back(0);
6015 s.pop_main();
6016
6017 s.push_back_return(type_b, 0, expr_b);
6018
6019 } else if(e->mode == fif::fif_mode::interpreting) {
6020 auto type_a = s.return_type_back(0);
6021 auto dat_a = s.return_data_back(0);
6022 s.push_back_main(type_a, dat_a, nullptr);
6023 s.pop_return();
6024
6025 execute_fif_word(fif::parse_result{ "dup", false }, *e, false);
6026 auto type_b = s.main_type_back(0);
6027 auto dat_b = s.main_data_back(0);
6028 s.pop_main();
6029
6030 s.push_back_return(type_b, dat_b, nullptr);
6031
6033 auto type_a = s.return_type_back(0);
6034 s.push_back_main(type_a, 0, nullptr);
6035 }
6036 return p + 2;
6037}
6038inline int32_t* to_r(fif::state_stack& s, int32_t* p, fif::environment* e) {
6040 auto type_a = s.main_type_back(0);
6041 auto expr_a = s.main_ex_back(0);
6042 s.push_back_return(type_a, 0, expr_a);
6043 s.pop_main();
6044 } else if(e->mode == fif::fif_mode::interpreting) {
6045 auto type_a = s.main_type_back(0);
6046 auto dat_a = s.main_data_back(0);
6047 s.push_back_return(type_a, dat_a, nullptr);
6048 s.pop_main();
6050 auto type_a = s.main_type_back(0);
6051 s.push_back_return(type_a, 0, nullptr);
6052 s.pop_main();
6053 }
6054 return p + 2;
6055}
6056
6057
6058inline void add_precompiled(fif::environment& env, std::string name, fif::fif_call fn, std::vector<int32_t> types, bool immediate = false) {
6059 if(auto it = env.dict.words.find(name); it != env.dict.words.end()) {
6060 env.dict.word_array[it->second].instances.push_back(int32_t(env.dict.all_instances.size()));
6061 env.dict.word_array[it->second].immediate |= immediate;
6062 } else {
6063 env.dict.words.insert_or_assign(name, int32_t(env.dict.word_array.size()));
6064 env.dict.word_array.emplace_back();
6065 env.dict.word_array.back().instances.push_back(int32_t(env.dict.all_instances.size()));
6066 env.dict.word_array.back().immediate = immediate;
6067 }
6069 auto& w = std::get< fif::compiled_word_instance>(env.dict.all_instances.back());
6070 w.implementation = fn;
6071 w.stack_types_count = int32_t(types.size());
6072 w.stack_types_start = int32_t(env.dict.all_stack_types.size());
6073 env.dict.all_stack_types.insert(env.dict.all_stack_types.end(), types.begin(), types.end());
6074}
6075
6076inline int32_t* ilt(fif::state_stack& s, int32_t* p, fif::environment* e) {
6078#ifdef USE_LLVM
6079 auto result = LLVMBuildICmp(e->llvm_builder, LLVMIntPredicate::LLVMIntSLT, s.main_ex_back(1), s.main_ex_back(0), "");
6080 s.pop_main();
6081 s.pop_main();
6082 s.push_back_main(fif_bool, 0, result);
6083#endif
6084 } else if(e->mode == fif::fif_mode::interpreting) {
6085 auto a = s.main_data_back(0);
6086 auto b = s.main_data_back(1);
6087 s.pop_main();
6088 s.pop_main();
6089 s.push_back_main(fif::fif_bool, b < a, nullptr);
6091 s.pop_main();
6092 s.pop_main();
6093 s.push_back_main(fif::fif_bool, 0, nullptr);
6094 }
6095 return p + 2;
6096}
6097inline int32_t* f32lt(fif::state_stack& s, int32_t* p, fif::environment* e) {
6099#ifdef USE_LLVM
6100 auto result = LLVMBuildFCmp(e->llvm_builder, LLVMRealPredicate::LLVMRealOLT, s.main_ex_back(1), s.main_ex_back(0), "");
6101 s.pop_main();
6102 s.pop_main();
6103 s.push_back_main(fif_bool, 0, result);
6104#endif
6105 } else if(e->mode == fif::fif_mode::interpreting) {
6106 auto ia = s.main_data_back(0);
6107 auto ib = s.main_data_back(1);
6108 float fa = 0;
6109 float fb = 0;
6110 memcpy(&fa, &ia, 4);
6111 memcpy(&fb, &ib, 4);
6112 s.pop_main();
6113 s.pop_main();
6114 s.push_back_main(fif::fif_bool, fb < fa, nullptr);
6116 s.pop_main();
6117 s.pop_main();
6118 s.push_back_main(fif::fif_bool, 0, nullptr);
6119 }
6120 return p + 2;
6121}
6122inline int32_t* f64lt(fif::state_stack& s, int32_t* p, fif::environment* e) {
6124#ifdef USE_LLVM
6125 auto result = LLVMBuildFCmp(e->llvm_builder, LLVMRealPredicate::LLVMRealOLT, s.main_ex_back(1), s.main_ex_back(0), "");
6126 s.pop_main();
6127 s.pop_main();
6128 s.push_back_main(fif_bool, 0, result);
6129#endif
6130 } else if(e->mode == fif::fif_mode::interpreting) {
6131 auto ia = s.main_data_back(0);
6132 auto ib = s.main_data_back(1);
6133 double fa = 0;
6134 double fb = 0;
6135 memcpy(&fa, &ia, 8);
6136 memcpy(&fb, &ib, 8);
6137 s.pop_main();
6138 s.pop_main();
6139 s.push_back_main(fif::fif_bool, fb < fa, nullptr);
6141 s.pop_main();
6142 s.pop_main();
6143 s.push_back_main(fif::fif_bool, 0, nullptr);
6144 }
6145 return p + 2;
6146}
6147inline int32_t* uilt(fif::state_stack& s, int32_t* p, fif::environment* e) {
6149#ifdef USE_LLVM
6150 auto result = LLVMBuildICmp(e->llvm_builder, LLVMIntPredicate::LLVMIntULT, s.main_ex_back(1), s.main_ex_back(0), "");
6151 s.pop_main();
6152 s.pop_main();
6153 s.push_back_main(fif_bool, 0, result);
6154#endif
6155 } else if(e->mode == fif::fif_mode::interpreting) {
6156 auto a = uint64_t(s.main_data_back(0));
6157 auto b = uint64_t(s.main_data_back(1));
6158 s.pop_main();
6159 s.pop_main();
6160 s.push_back_main(fif::fif_bool, b < a, nullptr);
6162 s.pop_main();
6163 s.pop_main();
6164 s.push_back_main(fif::fif_bool, 0, nullptr);
6165 }
6166 return p + 2;
6167}
6168inline int32_t* igt(fif::state_stack& s, int32_t* p, fif::environment* e) {
6170#ifdef USE_LLVM
6171 auto result = LLVMBuildICmp(e->llvm_builder, LLVMIntPredicate::LLVMIntSGT, s.main_ex_back(1), s.main_ex_back(0), "");
6172 s.pop_main();
6173 s.pop_main();
6174 s.push_back_main(fif_bool, 0, result);
6175#endif
6176 } else if(e->mode == fif::fif_mode::interpreting) {
6177 auto a = s.main_data_back(0);
6178 auto b = s.main_data_back(1);
6179 s.pop_main();
6180 s.pop_main();
6181 s.push_back_main(fif::fif_bool, b > a, nullptr);
6183 s.pop_main();
6184 s.pop_main();
6185 s.push_back_main(fif::fif_bool, 0, nullptr);
6186 }
6187 return p + 2;
6188}
6189inline int32_t* uigt(fif::state_stack& s, int32_t* p, fif::environment* e) {
6191#ifdef USE_LLVM
6192 auto result = LLVMBuildICmp(e->llvm_builder, LLVMIntPredicate::LLVMIntUGT, s.main_ex_back(1), s.main_ex_back(0), "");
6193 s.pop_main();
6194 s.pop_main();
6195 s.push_back_main(fif_bool, 0, result);
6196#endif
6197 } else if(e->mode == fif::fif_mode::interpreting) {
6198 auto a = uint64_t(s.main_data_back(0));
6199 auto b = uint64_t(s.main_data_back(1));
6200 s.pop_main();
6201 s.pop_main();
6202 s.push_back_main(fif::fif_bool, b > a, nullptr);
6204 s.pop_main();
6205 s.pop_main();
6206 s.push_back_main(fif::fif_bool, 0, nullptr);
6207 }
6208 return p + 2;
6209}
6210inline int32_t* f32gt(fif::state_stack& s, int32_t* p, fif::environment* e) {
6212#ifdef USE_LLVM
6213 auto result = LLVMBuildFCmp(e->llvm_builder, LLVMRealPredicate::LLVMRealOGT, s.main_ex_back(1), s.main_ex_back(0), "");
6214 s.pop_main();
6215 s.pop_main();
6216 s.push_back_main(fif_bool, 0, result);
6217#endif
6218 } else if(e->mode == fif::fif_mode::interpreting) {
6219 auto ia = s.main_data_back(0);
6220 auto ib = s.main_data_back(1);
6221 float fa = 0;
6222 float fb = 0;
6223 memcpy(&fa, &ia, 4);
6224 memcpy(&fb, &ib, 4);
6225 s.pop_main();
6226 s.pop_main();
6227 s.push_back_main(fif::fif_bool, fb > fa, nullptr);
6229 s.pop_main();
6230 s.pop_main();
6231 s.push_back_main(fif::fif_bool, 0, nullptr);
6232 }
6233 return p + 2;
6234}
6235inline int32_t* f64gt(fif::state_stack& s, int32_t* p, fif::environment* e) {
6237#ifdef USE_LLVM
6238 auto result = LLVMBuildFCmp(e->llvm_builder, LLVMRealPredicate::LLVMRealOGT, s.main_ex_back(1), s.main_ex_back(0), "");
6239 s.pop_main();
6240 s.pop_main();
6241 s.push_back_main(fif_bool, 0, result);
6242#endif
6243 } else if(e->mode == fif::fif_mode::interpreting) {
6244 auto ia = s.main_data_back(0);
6245 auto ib = s.main_data_back(1);
6246 double fa = 0;
6247 double fb = 0;
6248 memcpy(&fa, &ia, 8);
6249 memcpy(&fb, &ib, 8);
6250 s.pop_main();
6251 s.pop_main();
6252 s.push_back_main(fif::fif_bool, fb > fa, nullptr);
6254 s.pop_main();
6255 s.pop_main();
6256 s.push_back_main(fif::fif_bool, 0, nullptr);
6257 }
6258 return p + 2;
6259}
6260inline int32_t* ile(fif::state_stack& s, int32_t* p, fif::environment* e) {
6262#ifdef USE_LLVM
6263 auto result = LLVMBuildICmp(e->llvm_builder, LLVMIntPredicate::LLVMIntSLE, s.main_ex_back(1), s.main_ex_back(0), "");
6264 s.pop_main();
6265 s.pop_main();
6266 s.push_back_main(fif_bool, 0, result);
6267#endif
6268 } else if(e->mode == fif::fif_mode::interpreting) {
6269 auto a = s.main_data_back(0);
6270 auto b = s.main_data_back(1);
6271 s.pop_main();
6272 s.pop_main();
6273 s.push_back_main(fif::fif_bool, b <= a, nullptr);
6275 s.pop_main();
6276 s.pop_main();
6277 s.push_back_main(fif::fif_bool, 0, nullptr);
6278 }
6279 return p + 2;
6280}
6281inline int32_t* uile(fif::state_stack& s, int32_t* p, fif::environment* e) {
6283#ifdef USE_LLVM
6284 auto result = LLVMBuildICmp(e->llvm_builder, LLVMIntPredicate::LLVMIntULE, s.main_ex_back(1), s.main_ex_back(0), "");
6285 s.pop_main();
6286 s.pop_main();
6287 s.push_back_main(fif_bool, 0, result);
6288#endif
6289 } else if(e->mode == fif::fif_mode::interpreting) {
6290 auto a = uint64_t(s.main_data_back(0));
6291 auto b = uint64_t(s.main_data_back(1));
6292 s.pop_main();
6293 s.pop_main();
6294 s.push_back_main(fif::fif_bool, b <= a, nullptr);
6296 s.pop_main();
6297 s.pop_main();
6298 s.push_back_main(fif::fif_bool, 0, nullptr);
6299 }
6300 return p + 2;
6301}
6302inline int32_t* f32le(fif::state_stack& s, int32_t* p, fif::environment* e) {
6304#ifdef USE_LLVM
6305 auto result = LLVMBuildFCmp(e->llvm_builder, LLVMRealPredicate::LLVMRealOLE, s.main_ex_back(1), s.main_ex_back(0), "");
6306 s.pop_main();
6307 s.pop_main();
6308 s.push_back_main(fif_bool, 0, result);
6309#endif
6310 } else if(e->mode == fif::fif_mode::interpreting) {
6311 auto ia = s.main_data_back(0);
6312 auto ib = s.main_data_back(1);
6313 float fa = 0;
6314 float fb = 0;
6315 memcpy(&fa, &ia, 4);
6316 memcpy(&fb, &ib, 4);
6317 s.pop_main();
6318 s.pop_main();
6319 s.push_back_main(fif::fif_bool, fb <= fa, nullptr);
6321 s.pop_main();
6322 s.pop_main();
6323 s.push_back_main(fif::fif_bool, 0, nullptr);
6324 }
6325 return p + 2;
6326}
6327inline int32_t* f64le(fif::state_stack& s, int32_t* p, fif::environment* e) {
6329#ifdef USE_LLVM
6330 auto result = LLVMBuildFCmp(e->llvm_builder, LLVMRealPredicate::LLVMRealOLE, s.main_ex_back(1), s.main_ex_back(0), "");
6331 s.pop_main();
6332 s.pop_main();
6333 s.push_back_main(fif_bool, 0, result);
6334#endif
6335 } else if(e->mode == fif::fif_mode::interpreting) {
6336 auto ia = s.main_data_back(0);
6337 auto ib = s.main_data_back(1);
6338 double fa = 0;
6339 double fb = 0;
6340 memcpy(&fa, &ia, 8);
6341 memcpy(&fb, &ib, 8);
6342 s.pop_main();
6343 s.pop_main();
6344 s.push_back_main(fif::fif_bool, fb <= fa, nullptr);
6346 s.pop_main();
6347 s.pop_main();
6348 s.push_back_main(fif::fif_bool, 0, nullptr);
6349 }
6350 return p + 2;
6351}
6352inline int32_t* ige(fif::state_stack& s, int32_t* p, fif::environment* e) {
6354#ifdef USE_LLVM
6355 auto result = LLVMBuildICmp(e->llvm_builder, LLVMIntPredicate::LLVMIntSGE, s.main_ex_back(1), s.main_ex_back(0), "");
6356 s.pop_main();
6357 s.pop_main();
6358 s.push_back_main(fif_bool, 0, result);
6359#endif
6360 } else if(e->mode == fif::fif_mode::interpreting) {
6361 auto a = s.main_data_back(0);
6362 auto b = s.main_data_back(1);
6363 s.pop_main();
6364 s.pop_main();
6365 s.push_back_main(fif::fif_bool, b >= a, nullptr);
6367 s.pop_main();
6368 s.pop_main();
6369 s.push_back_main(fif::fif_bool, 0, nullptr);
6370 }
6371 return p + 2;
6372}
6373inline int32_t* uige(fif::state_stack& s, int32_t* p, fif::environment* e) {
6375#ifdef USE_LLVM
6376 auto result = LLVMBuildICmp(e->llvm_builder, LLVMIntPredicate::LLVMIntUGE, s.main_ex_back(1), s.main_ex_back(0), "");
6377 s.pop_main();
6378 s.pop_main();
6379 s.push_back_main(fif_bool, 0, result);
6380#endif
6381 } else if(e->mode == fif::fif_mode::interpreting) {
6382 auto a = uint64_t(s.main_data_back(0));
6383 auto b = uint64_t(s.main_data_back(1));
6384 s.pop_main();
6385 s.pop_main();
6386 s.push_back_main(fif::fif_bool, b >= a, nullptr);
6388 s.pop_main();
6389 s.pop_main();
6390 s.push_back_main(fif::fif_bool, 0, nullptr);
6391 }
6392 return p + 2;
6393}
6394inline int32_t* f32ge(fif::state_stack& s, int32_t* p, fif::environment* e) {
6396#ifdef USE_LLVM
6397 auto result = LLVMBuildFCmp(e->llvm_builder, LLVMRealPredicate::LLVMRealOGE, s.main_ex_back(1), s.main_ex_back(0), "");
6398 s.pop_main();
6399 s.pop_main();
6400 s.push_back_main(fif_bool, 0, result);
6401#endif
6402 } else if(e->mode == fif::fif_mode::interpreting) {
6403 auto ia = s.main_data_back(0);
6404 auto ib = s.main_data_back(1);
6405 float fa = 0;
6406 float fb = 0;
6407 memcpy(&fa, &ia, 4);
6408 memcpy(&fb, &ib, 4);
6409 s.pop_main();
6410 s.pop_main();
6411 s.push_back_main(fif::fif_bool, fb >= fa, nullptr);
6413 s.pop_main();
6414 s.pop_main();
6415 s.push_back_main(fif::fif_bool, 0, nullptr);
6416 }
6417 return p + 2;
6418}
6419inline int32_t* f64ge(fif::state_stack& s, int32_t* p, fif::environment* e) {
6421#ifdef USE_LLVM
6422 auto result = LLVMBuildFCmp(e->llvm_builder, LLVMRealPredicate::LLVMRealOGE, s.main_ex_back(1), s.main_ex_back(0), "");
6423 s.pop_main();
6424 s.pop_main();
6425 s.push_back_main(fif_bool, 0, result);
6426#endif
6427 } else if(e->mode == fif::fif_mode::interpreting) {
6428 auto ia = s.main_data_back(0);
6429 auto ib = s.main_data_back(1);
6430 double fa = 0;
6431 double fb = 0;
6432 memcpy(&fa, &ia, 8);
6433 memcpy(&fb, &ib, 8);
6434 s.pop_main();
6435 s.pop_main();
6436 s.push_back_main(fif::fif_bool, fb >= fa, nullptr);
6438 s.pop_main();
6439 s.pop_main();
6440 s.push_back_main(fif::fif_bool, 0, nullptr);
6441 }
6442 return p + 2;
6443}
6444inline int32_t* ieq(fif::state_stack& s, int32_t* p, fif::environment* e) {
6446#ifdef USE_LLVM
6447 auto result = LLVMBuildICmp(e->llvm_builder, LLVMIntPredicate::LLVMIntEQ, s.main_ex_back(1), s.main_ex_back(0), "");
6448 s.pop_main();
6449 s.pop_main();
6450 s.push_back_main(fif_bool, 0, result);
6451#endif
6452 } else if(e->mode == fif::fif_mode::interpreting) {
6453 auto a = s.main_data_back(0);
6454 auto b = s.main_data_back(1);
6455 s.pop_main();
6456 s.pop_main();
6457 s.push_back_main(fif::fif_bool, b == a, nullptr);
6459 s.pop_main();
6460 s.pop_main();
6461 s.push_back_main(fif::fif_bool, 0, nullptr);
6462 }
6463 return p + 2;
6464}
6465inline int32_t* f32eq(fif::state_stack& s, int32_t* p, fif::environment* e) {
6467#ifdef USE_LLVM
6468 auto result = LLVMBuildFCmp(e->llvm_builder, LLVMRealPredicate::LLVMRealOEQ, s.main_ex_back(1), s.main_ex_back(0), "");
6469 s.pop_main();
6470 s.pop_main();
6471 s.push_back_main(fif_bool, 0, result);
6472#endif
6473 } else if(e->mode == fif::fif_mode::interpreting) {
6474 auto ia = s.main_data_back(0);
6475 auto ib = s.main_data_back(1);
6476 float fa = 0;
6477 float fb = 0;
6478 memcpy(&fa, &ia, 4);
6479 memcpy(&fb, &ib, 4);
6480 s.pop_main();
6481 s.pop_main();
6482 s.push_back_main(fif::fif_bool, fb == fa, nullptr);
6484 s.pop_main();
6485 s.pop_main();
6486 s.push_back_main(fif::fif_bool, 0, nullptr);
6487 }
6488 return p + 2;
6489}
6490inline int32_t* f64eq(fif::state_stack& s, int32_t* p, fif::environment* e) {
6492#ifdef USE_LLVM
6493 auto result = LLVMBuildFCmp(e->llvm_builder, LLVMRealPredicate::LLVMRealOEQ, s.main_ex_back(1), s.main_ex_back(0), "");
6494 s.pop_main();
6495 s.pop_main();
6496 s.push_back_main(fif_bool, 0, result);
6497#endif
6498 } else if(e->mode == fif::fif_mode::interpreting) {
6499 auto ia = s.main_data_back(0);
6500 auto ib = s.main_data_back(1);
6501 double fa = 0;
6502 double fb = 0;
6503 memcpy(&fa, &ia, 8);
6504 memcpy(&fb, &ib, 8);
6505 s.pop_main();
6506 s.pop_main();
6507 s.push_back_main(fif::fif_bool, fb == fa, nullptr);
6509 s.pop_main();
6510 s.pop_main();
6511 s.push_back_main(fif::fif_bool, 0, nullptr);
6512 }
6513 return p + 2;
6514}
6515inline int32_t* ine(fif::state_stack& s, int32_t* p, fif::environment* e) {
6517#ifdef USE_LLVM
6518 auto result = LLVMBuildICmp(e->llvm_builder, LLVMIntPredicate::LLVMIntNE, s.main_ex_back(1), s.main_ex_back(0), "");
6519 s.pop_main();
6520 s.pop_main();
6521 s.push_back_main(fif_bool, 0, result);
6522#endif
6523 } else if(e->mode == fif::fif_mode::interpreting) {
6524 auto a = s.main_data_back(0);
6525 auto b = s.main_data_back(1);
6526 s.pop_main();
6527 s.pop_main();
6528 s.push_back_main(fif::fif_bool, b != a, nullptr);
6530 s.pop_main();
6531 s.pop_main();
6532 s.push_back_main(fif::fif_bool, 0, nullptr);
6533 }
6534 return p + 2;
6535}
6536inline int32_t* f32ne(fif::state_stack& s, int32_t* p, fif::environment* e) {
6538#ifdef USE_LLVM
6539 auto result = LLVMBuildFCmp(e->llvm_builder, LLVMRealPredicate::LLVMRealONE, s.main_ex_back(1), s.main_ex_back(0), "");
6540 s.pop_main();
6541 s.pop_main();
6542 s.push_back_main(fif_bool, 0, result);
6543#endif
6544 } else if(e->mode == fif::fif_mode::interpreting) {
6545 auto ia = s.main_data_back(0);
6546 auto ib = s.main_data_back(1);
6547 float fa = 0;
6548 float fb = 0;
6549 memcpy(&fa, &ia, 4);
6550 memcpy(&fb, &ib, 4);
6551 s.pop_main();
6552 s.pop_main();
6553 s.push_back_main(fif::fif_bool, fb != fa, nullptr);
6555 s.pop_main();
6556 s.pop_main();
6557 s.push_back_main(fif::fif_bool, 0, nullptr);
6558 }
6559 return p + 2;
6560}
6561inline int32_t* f64ne(fif::state_stack& s, int32_t* p, fif::environment* e) {
6563#ifdef USE_LLVM
6564 auto result = LLVMBuildFCmp(e->llvm_builder, LLVMRealPredicate::LLVMRealONE, s.main_ex_back(1), s.main_ex_back(0), "");
6565 s.pop_main();
6566 s.pop_main();
6567 s.push_back_main(fif_bool, 0, result);
6568#endif
6569 } else if(e->mode == fif::fif_mode::interpreting) {
6570 auto ia = s.main_data_back(0);
6571 auto ib = s.main_data_back(1);
6572 double fa = 0;
6573 double fb = 0;
6574 memcpy(&fa, &ia, 8);
6575 memcpy(&fb, &ib, 8);
6576 s.pop_main();
6577 s.pop_main();
6578 s.push_back_main(fif::fif_bool, fb != fa, nullptr);
6580 s.pop_main();
6581 s.pop_main();
6582 s.push_back_main(fif::fif_bool, 0, nullptr);
6583 }
6584 return p + 2;
6585}
6586
6587inline int32_t* f_select(fif::state_stack& s, int32_t* p, fif::environment* e) {
6589#ifdef USE_LLVM
6591 auto result = LLVMBuildSelect(e->llvm_builder, s.main_ex_back(0), s.main_ex_back(1), s.main_ex_back(2), "");
6592
6593 if(e->dict.type_array[s.main_type_back(1)].flags != 0) {
6594 auto drop_result = LLVMBuildSelect(e->llvm_builder, s.main_ex_back(0), s.main_ex_back(2), s.main_ex_back(1), "");
6595 s.push_back_main(s.main_type_back(1), 0, drop_result);
6596 execute_fif_word(fif::parse_result{ "drop", false }, *e, false);
6597 }
6598
6599 s.pop_main();
6600 s.pop_main();
6601 s.set_main_ex_back(0, result);
6602#endif
6603 } else if(e->mode == fif::fif_mode::interpreting) {
6605 auto ib = s.main_data_back(2);
6606 auto ia = s.main_data_back(1);
6607 auto ex = s.main_data_back(0);
6608
6609 if(e->dict.type_array[s.main_type_back(1)].flags != 0) {
6610 s.push_back_main(s.main_type_back(1), ex != 0 ? ib : ia, nullptr);
6611 execute_fif_word(fif::parse_result{ "drop", false }, *e, false);
6612 }
6613
6614 s.pop_main();
6615 s.pop_main();
6616 s.set_main_data_back(0, ex != 0 ? ia : ib);
6619 s.pop_main();
6620 s.pop_main();
6621 }
6622 return p + 2;
6623}
6624
6625inline int32_t* make_immediate(fif::state_stack& s, int32_t* p, fif::environment* e) {
6627 e->report_error("cannot turn a word immediate in compiled code");
6628 e->mode = fif_mode::error;
6629 return nullptr;
6630 } else if(e->mode == fif::fif_mode::interpreting) {
6631 if(e->dict.word_array.back().specialization_of == -1) {
6632 e->dict.word_array.back().immediate = true;
6633 } else {
6634 e->report_error("cannot mark a specialized word as immediate");
6635 e->mode = fif_mode::error;
6636 return nullptr;
6637 }
6639
6640 }
6641 return p + 2;
6642}
6643
6644inline int32_t* open_bracket(fif::state_stack& s, int32_t* p, fif::environment* e) {
6645 switch_compiler_stack_mode(*e, fif_mode::interpreting);
6646 return p + 2;
6647}
6648inline int32_t* close_bracket(fif::state_stack& s, int32_t* p, fif::environment* e) {
6650 return p + 2;
6651}
6652
6653inline int32_t* impl_heap_allot(fif::state_stack& s, int32_t* p, fif::environment* e) { // must drop contents ?
6655#ifdef USE_LLVM
6656 auto val = s.main_ex_back(0);
6657 auto new_mem = LLVMBuildMalloc(e->llvm_builder, e->dict.type_array[s.main_type_back(0)].llvm_type, "");
6658 LLVMBuildStore(e->llvm_builder, val, new_mem);
6659 int32_t ptr_type[] = { fif_ptr, std::numeric_limits<int32_t>::max(), s.main_type_back(0), -1 };
6660 std::vector<int32_t> subs;
6661 auto mem_type = resolve_span_type(std::span<int32_t const>(ptr_type, ptr_type + 4), subs, *e);
6662 s.pop_main();
6663 s.push_back_main(mem_type.type, 0, new_mem);
6664#endif
6665 } else if(e->mode == fif::fif_mode::interpreting) {
6666 auto ptr = malloc(8);
6667 int64_t dat = s.main_data_back(0);
6668 memcpy(ptr, &dat, 8);
6669
6670 int32_t ptr_type[] = { fif_ptr, std::numeric_limits<int32_t>::max(), s.main_type_back(0), -1 };
6671 std::vector<int32_t> subs;
6672 auto mem_type = resolve_span_type(std::span<int32_t const>(ptr_type, ptr_type + 4), subs, *e);
6673 s.pop_main();
6674 s.push_back_main(mem_type.type, (int64_t)ptr, nullptr);
6676 int32_t ptr_type[] = { fif_ptr, std::numeric_limits<int32_t>::max(), s.main_type_back(0), -1 };
6677 std::vector<int32_t> subs;
6678 auto mem_type = resolve_span_type(std::span<int32_t const>(ptr_type, ptr_type + 4), subs, *e);
6679 s.pop_main();
6680 s.push_back_main(mem_type.type, 0, nullptr);
6681 }
6682 return p + 2;
6683}
6684
6685inline int32_t* impl_heap_free(fif::state_stack& s, int32_t* p, fif::environment* e) { // must drop contents ?
6687 return p + 2;
6688
6689 auto ptr_type = s.main_type_back(0);
6690 auto decomp = e->dict.type_array[ptr_type].decomposed_types_start;
6691 auto pointer_contents = e->dict.all_stack_types[decomp + 1];
6692
6694#ifdef USE_LLVM
6695 auto iresult = LLVMBuildLoad2(e->llvm_builder, e->dict.type_array[pointer_contents].llvm_type, s.main_ex_back(0), "");
6696 LLVMBuildFree(e->llvm_builder, s.main_ex_back(0));
6697 s.pop_main();
6698 s.push_back_main(pointer_contents, 0, iresult);
6699#endif
6700 } else if(e->mode == fif::fif_mode::interpreting) {
6701
6702 auto a = s.main_data_back(0);
6703 int64_t* ptr = (int64_t*)a;
6704 auto val = *ptr;
6705 free(ptr);
6706 s.pop_main();
6707 s.push_back_main(pointer_contents, val, 0);
6709 s.pop_main();
6710 s.push_back_main(pointer_contents, 0, 0);
6711 }
6712 return p + 2;
6713}
6714
6715inline int32_t* impl_load(fif::state_stack& s, int32_t* p, fif::environment* e) {
6717 return p + 2;
6718
6719 auto ptr_type = s.main_type_back(0);
6720 auto decomp = e->dict.type_array[ptr_type].decomposed_types_start;
6721 auto pointer_contents = e->dict.all_stack_types[decomp + 1];
6722
6724#ifdef USE_LLVM
6725 auto result = LLVMBuildLoad2(e->llvm_builder, e->dict.type_array[pointer_contents].llvm_type, s.main_ex_back(0), "");
6726 s.pop_main();
6727 s.push_back_main(pointer_contents, 0, result);
6728
6729 if(e->dict.type_array[pointer_contents].flags != 0) {
6730 execute_fif_word(fif::parse_result{ "dup", false }, *e, false);
6731
6732 // remove the extra value and save the duplicated expression on top of the stack
6733 auto expr_b = s.main_ex_back(0);
6734 s.set_main_ex_back(1, expr_b);
6735 s.pop_main();
6736 }
6737#endif
6738 } else if(e->mode == fif::fif_mode::interpreting) {
6739 auto v = s.main_data_back(0);
6740 s.pop_main();
6741 int64_t* ptr_val = (int64_t*)v;
6742 auto effective_type = pointer_contents;
6743
6744 if(pointer_contents != -1 && e->dict.type_array[pointer_contents].refcounted_type()) {
6745 if(e->dict.type_array[pointer_contents].decomposed_types_count >= 2) {
6746 auto child_index = e->dict.type_array[pointer_contents].decomposed_types_start + 1;
6747 auto child_type = e->dict.all_stack_types[child_index];
6748
6749 if(e->dict.type_array[pointer_contents].single_member_struct()) {
6750 effective_type = child_type;
6751 }
6752 }
6753 }
6754
6755 if(effective_type == fif_i32 || effective_type == fif_f32)
6756 s.push_back_main(pointer_contents, *(int32_t*)(ptr_val), nullptr);
6757 else if(effective_type == fif_u32)
6758 s.push_back_main(pointer_contents, *(uint32_t*)(ptr_val), nullptr);
6759 else if(effective_type == fif_i16)
6760 s.push_back_main(pointer_contents, *(int16_t*)(ptr_val), nullptr);
6761 else if(effective_type == fif_u16)
6762 s.push_back_main(pointer_contents, *(uint16_t*)(ptr_val), nullptr);
6763 else if(effective_type == fif_i8)
6764 s.push_back_main(pointer_contents, *(int8_t*)(ptr_val), nullptr);
6765 else if(effective_type == fif_u8 || effective_type == fif_bool)
6766 s.push_back_main(pointer_contents, *(uint8_t*)(ptr_val), nullptr);
6767 else
6768 s.push_back_main(pointer_contents, *ptr_val, nullptr);
6769
6770 if(e->dict.type_array[pointer_contents].flags != 0) {
6771 execute_fif_word(fif::parse_result{ "dup", false }, *e, false);
6772 // remove the extra value and save the duplicated expression on top of the stack
6773 auto data_b = s.main_data_back(0);
6774 s.set_main_data_back(1, data_b);
6775 s.pop_main();
6776 }
6777 } else if(fif::typechecking_mode(e->mode)) {
6778 s.pop_main();
6779 s.push_back_main(pointer_contents, 0, nullptr);
6780 }
6781 return p + 2;
6782}
6783
6784inline int32_t* impl_load_deallocated(fif::state_stack& s, int32_t* p, fif::environment* e) {
6786 return p + 2;
6787
6788 auto ptr_type = s.main_type_back(0);
6789 auto decomp = e->dict.type_array[ptr_type].decomposed_types_start;
6790 auto pointer_contents = e->dict.all_stack_types[decomp + 1];
6791
6793#ifdef USE_LLVM
6794 auto result = LLVMBuildLoad2(e->llvm_builder, e->dict.type_array[pointer_contents].llvm_type, s.main_ex_back(0), "");
6795 s.pop_main();
6796 s.push_back_main(pointer_contents, 0, result);
6797#endif
6798 } else if(e->mode == fif::fif_mode::interpreting) {
6799 auto v = s.main_data_back(0);
6800 s.pop_main();
6801 int64_t* ptr_val = (int64_t*)v;
6802 auto effective_type = pointer_contents;
6803
6804 if(pointer_contents != -1 && e->dict.type_array[pointer_contents].refcounted_type()) {
6805 if(e->dict.type_array[pointer_contents].decomposed_types_count >= 2) {
6806 auto child_index = e->dict.type_array[pointer_contents].decomposed_types_start + 1;
6807 auto child_type = e->dict.all_stack_types[child_index];
6808
6809 if(e->dict.type_array[pointer_contents].single_member_struct()) {
6810 effective_type = child_type;
6811 }
6812 }
6813 }
6814
6815 if(effective_type == fif_i32 || effective_type == fif_f32)
6816 s.push_back_main(pointer_contents, *(int32_t*)(ptr_val), nullptr);
6817 else if(effective_type == fif_u32)
6818 s.push_back_main(pointer_contents, *(uint32_t*)(ptr_val), nullptr);
6819 else if(effective_type == fif_i16)
6820 s.push_back_main(pointer_contents, *(int16_t*)(ptr_val), nullptr);
6821 else if(effective_type == fif_u16)
6822 s.push_back_main(pointer_contents, *(uint16_t*)(ptr_val), nullptr);
6823 else if(effective_type == fif_i8)
6824 s.push_back_main(pointer_contents, *(int8_t*)(ptr_val), nullptr);
6825 else if(effective_type == fif_u8 || effective_type == fif_bool)
6826 s.push_back_main(pointer_contents, *(uint8_t*)(ptr_val), nullptr);
6827 else
6828 s.push_back_main(pointer_contents, *ptr_val, nullptr);
6829
6830 } else if(fif::typechecking_mode(e->mode)) {
6831 s.pop_main();
6832 s.push_back_main(pointer_contents, 0, nullptr);
6833 }
6834 return p + 2;
6835}
6836
6837inline int32_t* impl_store(fif::state_stack& s, int32_t* p, fif::environment* e) {
6839 return p + 2;
6840
6841 auto ptr_type = s.main_type_back(0);
6842 auto decomp = e->dict.type_array[ptr_type].decomposed_types_start;
6843 auto pointer_contents = e->dict.all_stack_types[decomp + 1];
6844
6846#ifdef USE_LLVM
6847 if(e->dict.type_array[pointer_contents].flags != 0) {
6848 auto iresult = LLVMBuildLoad2(e->llvm_builder, e->dict.type_array[pointer_contents].llvm_type, s.main_ex_back(0), "");
6849 s.push_back_main(pointer_contents, 0, iresult);
6850 execute_fif_word(fif::parse_result{ "drop", false }, *e, false);
6851 }
6852
6853 auto result = LLVMBuildStore(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0));
6854 s.pop_main();
6855 s.pop_main();
6856#endif
6857 } else if(e->mode == fif::fif_mode::interpreting) {
6858
6859 auto v = s.main_data_back(0);
6860 int64_t* ptr_val = (int64_t*)v;
6861
6862 if(e->dict.type_array[pointer_contents].flags != 0) {
6863 s.push_back_main(pointer_contents, *ptr_val, nullptr);
6864 execute_fif_word(fif::parse_result{ "drop", false }, *e, false);
6865 }
6866
6867 auto to_write = s.main_data_back(1);
6868
6869 auto effective_type = pointer_contents;
6870 if(pointer_contents != -1 && e->dict.type_array[pointer_contents].refcounted_type()) {
6871 if(e->dict.type_array[pointer_contents].decomposed_types_count >= 2) {
6872 auto child_index = e->dict.type_array[pointer_contents].decomposed_types_start + 1;
6873 auto child_type = e->dict.all_stack_types[child_index];
6874
6875 if(e->dict.type_array[pointer_contents].single_member_struct()) {
6876 effective_type = child_type;
6877 }
6878 }
6879 }
6880
6881 if(effective_type == fif_i32 || effective_type == fif_f32 || effective_type == fif_u32)
6882 memcpy(ptr_val, &to_write, 4);
6883 else if(effective_type == fif_u16 || effective_type == fif_i16)
6884 memcpy(ptr_val, &to_write, 2);
6885 else if(effective_type == fif_u8 || effective_type == fif_bool || effective_type == fif_i8)
6886 memcpy(ptr_val, &to_write, 1);
6887 else
6888 memcpy(ptr_val, &to_write, 8);
6889
6890 s.pop_main();
6891 s.pop_main();
6892 } else if(fif::typechecking_mode(e->mode)) {
6893 s.pop_main();
6894 s.pop_main();
6895 }
6896 return p + 2;
6897}
6898
6899inline int32_t* impl_uninit_store(fif::state_stack& s, int32_t* p, fif::environment* e) {
6901 return p + 2;
6902
6903 auto ptr_type = s.main_type_back(0);
6904 auto decomp = e->dict.type_array[ptr_type].decomposed_types_start;
6905 auto pointer_contents = e->dict.all_stack_types[decomp + 1];
6906
6908#ifdef USE_LLVM
6909 auto result = LLVMBuildStore(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0));
6910 s.pop_main();
6911 s.pop_main();
6912#endif
6913 } else if(e->mode == fif::fif_mode::interpreting) {
6914
6915 auto v = s.main_data_back(0);
6916 int64_t* ptr_val = (int64_t*)v;
6917
6918 auto to_write = s.main_data_back(1);
6919
6920 auto effective_type = pointer_contents;
6921 if(pointer_contents != -1 && e->dict.type_array[pointer_contents].refcounted_type()) {
6922 if(e->dict.type_array[pointer_contents].decomposed_types_count >= 2) {
6923 auto child_index = e->dict.type_array[pointer_contents].decomposed_types_start + 1;
6924 auto child_type = e->dict.all_stack_types[child_index];
6925
6926 if(e->dict.type_array[pointer_contents].single_member_struct()) {
6927 effective_type = child_type;
6928 }
6929 }
6930 }
6931
6932 if(effective_type == fif_i32 || effective_type == fif_f32 || effective_type == fif_u32)
6933 memcpy(ptr_val, &to_write, 4);
6934 else if(effective_type == fif_u16 || effective_type == fif_i16)
6935 memcpy(ptr_val, &to_write, 2);
6936 else if(effective_type == fif_u8 || effective_type == fif_bool || effective_type == fif_i8)
6937 memcpy(ptr_val, &to_write, 1);
6938 else
6939 memcpy(ptr_val, &to_write, 8);
6940
6941 s.pop_main();
6942 s.pop_main();
6943 } else if(fif::typechecking_mode(e->mode)) {
6944 s.pop_main();
6945 s.pop_main();
6946 }
6947 return p + 2;
6948}
6949
6950inline int32_t* do_pointer_cast(fif::state_stack& s, int32_t* p, fif::environment* e) {
6951 s.set_main_type_back(0, *(p + 2));
6952 return p + 3;
6953}
6954
6955
6956inline int32_t* pointer_cast(fif::state_stack& s, int32_t* p, fif::environment* e) {
6957 if(e->source_stack.empty()) {
6958 e->report_error("pointer cast was unable to read the word describing the pointer type");
6959 e->mode = fif_mode::error;
6960 return nullptr;
6961 }
6962 auto ptype = read_token(e->source_stack.back(), *e);
6963 bool bad_type = ptype.is_string;
6964 auto resolved_type = resolve_type(ptype.content, *e, e->compiler_stack.back()->type_substitutions());
6965 if(resolved_type == -1) {
6966 bad_type = true;
6967 } else if(resolved_type != fif_opaque_ptr) {
6968 if(e->dict.type_array[resolved_type].decomposed_types_count == 0) {
6969 bad_type = true;
6970 } else if(e->dict.all_stack_types[e->dict.type_array[resolved_type].decomposed_types_start] != fif_ptr) {
6971 bad_type = true;
6972 }
6973 }
6974
6975 if(bad_type) {
6976 e->report_error("pointer attempted to be cast to a non pointer type");
6977 e->mode = fif_mode::error;
6978 return nullptr;
6979 }
6980
6981 if(!typechecking_failed(e->mode)) {
6983 s.set_main_type_back(0, resolved_type);
6984 }
6985
6987 auto compile_bytes = e->compiler_stack.back()->bytecode_compilation_progress();
6988 if(compile_bytes) {
6990 uint64_t imm_bytes = 0;
6991 memcpy(&imm_bytes, &imm, 8);
6992 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
6993 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
6994 compile_bytes->push_back(resolved_type);
6995 }
6996 }
6997 return p + 2;
6998}
6999
7000inline int32_t* impl_sizeof(fif::state_stack& s, int32_t* p, fif::environment* e) {
7001 if(e->source_stack.empty()) {
7002 e->report_error("sizeof was unable to read the word describing the type");
7003 e->mode = fif_mode::error;
7004 return nullptr;
7005 }
7006 auto ptype = read_token(e->source_stack.back(), *e);
7007 bool bad_type = ptype.is_string;
7008 auto resolved_type = resolve_type(ptype.content, *e, e->compiler_stack.back()->type_substitutions());
7009 if(resolved_type == -1) {
7010 e->report_error("sizeof given an invalid type");
7011 e->mode = fif_mode::error;
7012 return nullptr;
7013 }
7014
7016#ifdef USE_LLVM
7017 s.push_back_main(fif_i32, 0, LLVMConstTrunc(LLVMSizeOf(e->dict.type_array[resolved_type].llvm_type), LLVMInt32TypeInContext(e->llvm_context)));
7018#endif
7019 } else if(e->mode == fif::fif_mode::compiling_bytecode) {
7020 auto compile_bytes = e->compiler_stack.back()->bytecode_compilation_progress();
7021 if(compile_bytes) {
7022 fif_call imm = immediate_i32;
7023 uint64_t imm_bytes = 0;
7024 memcpy(&imm_bytes, &imm, 8);
7025 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
7026 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
7027 compile_bytes->push_back(interepreter_size(resolved_type, *e));
7028 }
7029 s.push_back_main(fif_i32, 8, 0);
7030 } else if(e->mode == fif::fif_mode::interpreting) {
7031 s.push_back_main(fif_i32, 8, 0);
7033 s.push_back_main(fif_i32, 0, 0);
7034 }
7035 return p + 2;
7036}
7037
7038inline int32_t* impl_index(fif::state_stack& s, int32_t* p, fif::environment* e) {
7040#ifdef USE_LLVM
7041 auto num_bytes = s.main_ex_back(1);
7042 auto iresult = LLVMBuildInBoundsGEP2(e->llvm_builder, LLVMInt8TypeInContext(e->llvm_context), s.main_ex_back(0), &num_bytes, 1, "");
7043 s.pop_main();
7044 s.pop_main();
7045 s.push_back_main(fif_opaque_ptr, 0, iresult);
7046#endif
7047 } else if(e->mode == fif::fif_mode::interpreting) {
7048 auto bytes = s.main_data_back(1);
7049 auto pval = s.main_data_back(0);
7050 uint8_t* ptr = (uint8_t*)pval;
7051 pval += bytes;
7052 s.pop_main();
7053 s.pop_main();
7054 s.push_back_main(fif_opaque_ptr, (int64_t)pval, 0);
7056 s.pop_main();
7057 s.pop_main();
7059 }
7060
7061 return p + 2;
7062}
7063
7064inline int32_t* allocate_buffer(fif::state_stack& s, int32_t* p, fif::environment* e) {
7066#ifdef USE_LLVM
7067 auto iresult = LLVMBuildArrayMalloc(e->llvm_builder, LLVMInt8TypeInContext(e->llvm_context), s.main_ex_back(0), "");
7068 LLVMBuildMemSet(e->llvm_builder, iresult, LLVMConstInt(LLVMInt8TypeInContext(e->llvm_context), 0, false), s.main_ex_back(0), 1);
7069 s.pop_main();
7070 s.push_back_main(fif_opaque_ptr, 0, iresult);
7071#endif
7072 } else if(e->mode == fif::fif_mode::interpreting) {
7073
7074 auto bytes = s.main_data_back(0);
7075 auto val = malloc(size_t(bytes));
7076 memset(val, 0, size_t(bytes));
7077 s.pop_main();
7078 s.push_back_main(fif_opaque_ptr, (int64_t)val, 0);
7080 s.pop_main();
7082 }
7083 return p + 2;
7084}
7085
7086inline int32_t* copy_buffer(fif::state_stack& s, int32_t* p, fif::environment* e) {
7088#ifdef USE_LLVM
7089 auto bytes = s.main_ex_back(0);
7090 auto dest_ptr = s.main_ex_back(1);
7091 auto source_ptr = s.main_ex_back(2);
7092 s.pop_main();
7093 s.pop_main();
7094 s.pop_main();
7095 auto res = LLVMBuildMemCpy(e->llvm_builder, dest_ptr, 1, source_ptr, 1, bytes);
7096 s.push_back_main(fif_opaque_ptr, 0, dest_ptr);
7097#endif
7098 } else if(e->mode == fif::fif_mode::interpreting) {
7099 auto bytes = s.main_data_back(0);
7100 auto dest_ptr = s.main_data_back(1);
7101 auto source_ptr = s.main_data_back(2);
7102 s.pop_main();
7103 s.pop_main();
7104 s.pop_main();
7105 memcpy((void*)dest_ptr, (void*)source_ptr, size_t(bytes));
7106 s.push_back_main(fif_opaque_ptr, dest_ptr, 0);
7108 s.pop_main();
7109 s.pop_main();
7110 s.pop_main();
7112 }
7113 return p + 2;
7114}
7115
7116inline int32_t* free_buffer(fif::state_stack& s, int32_t* p, fif::environment* e) {
7118 return p + 2;
7119
7121#ifdef USE_LLVM
7122 LLVMBuildFree(e->llvm_builder, s.main_ex_back(0));
7123 s.pop_main();
7124#endif
7125 } else if(e->mode == fif::fif_mode::interpreting) {
7126 auto a = s.main_data_back(0);
7127 void* ptr = (void*)a;
7128 free(ptr);
7129 s.pop_main();
7131 s.pop_main();
7132 }
7133 return p + 2;
7134}
7135
7136inline int32_t* do_let_creation(fif::state_stack& s, int32_t* p, fif::environment* e) {
7137 char* string_ptr = nullptr;
7138 memcpy(&string_ptr, p + 2, 8);
7139
7140 auto l = e->compiler_stack.back()->create_let(std::string{ string_ptr }, s.main_type_back(0), s.main_data_back(0), nullptr);
7141 if(!l) {
7142 e->report_error("could not create a let with that name");
7143 e->mode = fif_mode::error;
7144 return nullptr;
7145 }
7146 s.pop_main();
7147 return p + 4;
7148}
7149
7150inline int32_t* create_let(fif::state_stack& s, int32_t* p, fif::environment* e) {
7151 if(e->source_stack.empty()) {
7152 e->report_error("let was unable to read the declaration name");
7153 e->mode = fif_mode::error;
7154 return nullptr;
7155 }
7156 auto name = read_token(e->source_stack.back(), *e);
7157
7158 if(e->mode == fif_mode::interpreting || (typechecking_mode(e->mode) && !typechecking_failed(e->mode))) {
7159 auto l = e->compiler_stack.back()->create_let(std::string{ name.content }, s.main_type_back(0), s.main_data_back(0), nullptr);
7160 if(!l) {
7161 e->report_error("could not create a let with that name");
7162 e->mode = fif_mode::error;
7163 return nullptr;
7164 }
7165 } else if(e->mode == fif_mode::compiling_llvm) {
7166 auto l = e->compiler_stack.back()->create_let(std::string{ name.content }, s.main_type_back(0), 0, s.main_ex_back(0));
7167 if(!l) {
7168 e->report_error("could not create a let with that name");
7169 e->mode = fif_mode::error;
7170 return nullptr;
7171 }
7172 } else if(e->mode == fif_mode::compiling_bytecode) {
7173 auto l = e->compiler_stack.back()->create_let(std::string{ name.content }, s.main_type_back(0), 0, 0);
7174 if(!l) {
7175 e->report_error("could not create a let with that name");
7176 e->mode = fif_mode::error;
7177 return nullptr;
7178 }
7179 auto compile_bytes = e->compiler_stack.back()->bytecode_compilation_progress();
7180 if(compile_bytes) {
7182 uint64_t imm_bytes = 0;
7183 memcpy(&imm_bytes, &imm, 8);
7184 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
7185 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
7186
7187 auto string_constant = e->get_string_constant(name.content);
7188 char const* cptr = string_constant.data();
7189 uint64_t let_addr = 0;
7190 memcpy(&let_addr, &cptr, 8);
7191 compile_bytes->push_back(int32_t(let_addr & 0xFFFFFFFF));
7192 compile_bytes->push_back(int32_t((let_addr >> 32) & 0xFFFFFFFF));
7193 }
7194 }
7195
7196 if(!typechecking_failed(e->mode)) {
7197 s.pop_main();
7198 }
7199 return p + 2;
7200}
7201
7202inline int32_t* do_var_creation(fif::state_stack& s, int32_t* p, fif::environment* e) {
7203 char* string_ptr = nullptr;
7204 memcpy(&string_ptr, p + 2, 8);
7205
7206 auto l = e->compiler_stack.back()->create_var(std::string{ string_ptr }, s.main_type_back(0));
7207 if(!l) {
7208 e->report_error("could not create a var with that name");
7209 e->mode = fif_mode::error;
7210 return nullptr;
7211 }
7212 l->data = s.main_data_back(0);
7213 s.pop_main();
7214 return p + 4;
7215}
7216
7217inline int32_t* create_var(fif::state_stack& s, int32_t* p, fif::environment* e) {
7218 if(e->source_stack.empty()) {
7219 e->report_error("war was unable to read the declaration name");
7220 e->mode = fif_mode::error;
7221 return nullptr;
7222 }
7223 auto name = read_token(e->source_stack.back(), *e);
7224
7225 if(e->mode == fif_mode::interpreting || (typechecking_mode(e->mode) && !typechecking_failed(e->mode))) {
7226 auto l = e->compiler_stack.back()->create_var(std::string{ name.content }, s.main_type_back(0));
7227 if(!l) {
7228 e->report_error("could not create a var with that name");
7229 e->mode = fif_mode::error;
7230 return nullptr;
7231 }
7232 l->data = s.main_data_back(0);
7233 } else if(e->mode == fif_mode::compiling_llvm) {
7234#ifdef USE_LLVM
7235 auto l = e->compiler_stack.back()->create_var(std::string{ name.content }, s.main_type_back(0));
7236 if(!l) {
7237 e->report_error("could not create a var with that name");
7238 e->mode = fif_mode::error;
7239 return nullptr;
7240 }
7241 LLVMBuildStore(e->llvm_builder, s.main_ex_back(0), l->alloc);
7242#endif
7243 } else if(e->mode == fif_mode::compiling_bytecode) {
7244 auto l = e->compiler_stack.back()->create_var(std::string{ name.content }, s.main_type_back(0));
7245 if(!l) {
7246 e->report_error("could not create a var with that name");
7247 e->mode = fif_mode::error;
7248 return nullptr;
7249 }
7250 auto compile_bytes = e->compiler_stack.back()->bytecode_compilation_progress();
7251 if(compile_bytes) {
7253 uint64_t imm_bytes = 0;
7254 memcpy(&imm_bytes, &imm, 8);
7255 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
7256 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
7257
7258 auto string_constant = e->get_string_constant(name.content);
7259 char const* cptr = string_constant.data();
7260 uint64_t let_addr = 0;
7261 memcpy(&let_addr, &cptr, 8);
7262 compile_bytes->push_back(int32_t(let_addr & 0xFFFFFFFF));
7263 compile_bytes->push_back(int32_t((let_addr >> 32) & 0xFFFFFFFF));
7264 }
7265 }
7266
7267 if(!typechecking_failed(e->mode)) {
7268 s.pop_main();
7269 }
7270 return p + 2;
7271}
7272
7273inline int32_t* create_global_impl(fif::state_stack& s, int32_t* p, fif::environment* e) {
7274 if(e->source_stack.empty()) {
7275 e->report_error("global was unable to read the declaration name");
7276 e->mode = fif_mode::error;
7277 return nullptr;
7278 }
7279 auto name = read_token(e->source_stack.back(), *e);
7280 auto type = s.main_data_back(0);
7281
7282 if(typechecking_mode(e->mode)) {
7283 if(!typechecking_failed(e->mode))
7284 s.pop_main();
7285 return p + 2;
7286 }
7287
7288 s.pop_main();
7289 for(auto& ptr : e->compiler_stack) {
7290 if(ptr->get_type() == control_structure::globals) {
7291 auto existing = static_cast<compiler_globals_layer*>(ptr.get())->get_global_var(std::string{ name.content });
7292
7293 if(existing) {
7294 e->report_error("duplicate global definition");
7295 e->mode = fif_mode::error;
7296 return nullptr;
7297 }
7298
7299 static_cast<compiler_globals_layer*>(ptr.get())->create_global_var(std::string{ name.content }, int32_t(type));
7300 return p + 2;
7301 }
7302 }
7303
7304 e->report_error("could not find the globals layer");
7305 e->mode = fif_mode::error;
7306 return nullptr;
7307}
7308
7309inline int32_t* do_fextract(fif::state_stack& s, int32_t* p, fif::environment* e) {
7310 int32_t index_value = *(p + 2);
7311 auto stype = s.main_type_back(0);
7312 assert(1 + index_value < e->dict.type_array[stype].decomposed_types_count);
7313 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + index_value;
7314 auto child_type = e->dict.all_stack_types[child_index];
7315
7316 if(e->dict.type_array[stype].single_member_struct()) {
7318 s.set_main_type_back(0, child_type);
7319 } else {
7320 auto ptr = s.main_data_back(0);
7321 auto children = (int64_t*)(ptr);
7322 auto child_data = children[index_value];
7323
7324 if(e->dict.type_array[child_type].flags != 0) {
7325 s.push_back_main(child_type, child_data, nullptr);
7326 execute_fif_word(fif::parse_result{ "dup", false }, *e, false);
7327 child_data = s.main_data_back(0);
7328 s.pop_main();
7329 s.pop_main();
7330 }
7331
7332 if(e->dict.type_array[stype].flags != 0) {
7333 execute_fif_word(fif::parse_result{ "drop", false }, *e, false);
7334 } else {
7335 s.pop_main();
7336 }
7337
7338 s.push_back_main(child_type, child_data, nullptr);
7339 }
7340
7341 return p + 3;
7342}
7343
7344inline int32_t* forth_extract(fif::state_stack& s, int32_t* p, fif::environment* e) {
7345 auto index_str = read_token(e->source_stack.back(), *e);
7346 auto index_value = parse_int(index_str.content);
7347 auto stype = s.main_type_back(0);
7348
7349 if(stype == -1 || e->dict.type_array[stype].refcounted_type() == false) {
7350 e->report_error("attempted to use a structure operation on a non-structure type");
7351 e->mode = fif_mode::error;
7352 return nullptr;
7353 }
7354
7355 assert(1 + index_value < e->dict.type_array[stype].decomposed_types_count);
7356 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + index_value;
7357 auto child_type = e->dict.all_stack_types[child_index];
7358
7360#ifdef USE_LLVM
7361 if(e->dict.type_array[stype].single_member_struct()) {
7363 s.set_main_type_back(0, child_type);
7364 } else {
7365 auto struct_expr = s.main_ex_back(0);
7366 auto result = LLVMBuildExtractValue(e->llvm_builder, struct_expr, index_value, "");
7367
7368 if(e->dict.type_array[child_type].flags != 0) {
7369 s.push_back_main(child_type, 0, result);
7370 execute_fif_word(fif::parse_result{ "dup", false }, *e, false);
7371 result = s.main_ex_back(0);
7372 s.pop_main();
7373 s.pop_main();
7374 }
7375 if(e->dict.type_array[stype].flags != 0) {
7376 execute_fif_word(fif::parse_result{ "drop", false }, *e, false);
7377 } else {
7378 s.pop_main();
7379 }
7380 s.push_back_main(child_type, 0, result);
7381 }
7382#endif
7383 } else if(e->mode == fif::fif_mode::interpreting) {
7384 if(e->dict.type_array[stype].single_member_struct()) {
7386 s.set_main_type_back(0, child_type);
7387 } else {
7388 auto ptr = s.main_data_back(0);
7389 auto children = (int64_t*)(ptr);
7390 auto child_data = children[index_value];
7391
7392
7393 if(e->dict.type_array[child_type].flags != 0) {
7394 s.push_back_main(child_type, child_data, nullptr);
7395 execute_fif_word(fif::parse_result{ "dup", false }, *e, false);
7396 child_data = s.main_data_back(0);
7397 s.pop_main();
7398 s.pop_main();
7399 }
7400
7401 if(e->dict.type_array[stype].flags != 0) {
7402 execute_fif_word(fif::parse_result{ "drop", false }, *e, false);
7403 } else {
7404 s.pop_main();
7405 }
7406
7407 s.push_back_main(child_type, child_data, nullptr);
7408 }
7410 s.pop_main();
7411 s.push_back_main(child_type, 0, nullptr);
7412 } else if(e->mode == fif_mode::compiling_bytecode) {
7413 auto compile_bytes = e->compiler_stack.back()->bytecode_compilation_progress();
7414 if(compile_bytes) {
7415 fif_call imm = do_fextract;
7416 uint64_t imm_bytes = 0;
7417 memcpy(&imm_bytes, &imm, 8);
7418 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
7419 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
7420 compile_bytes->push_back(index_value);
7421 }
7422 s.pop_main();
7423 s.push_back_main(child_type, 0, nullptr);
7424 }
7425 return p + 2;
7426}
7427inline int32_t* do_fextractc(fif::state_stack& s, int32_t* p, fif::environment* e) {
7428 int32_t index_value = *(p + 2);
7429 auto stype = s.main_type_back(0);
7430 assert(1 + index_value < e->dict.type_array[stype].decomposed_types_count);
7431 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + index_value;
7432 auto child_type = e->dict.all_stack_types[child_index];
7433
7434 if(e->dict.type_array[stype].single_member_struct()) {
7436 s.set_main_type_back(0, child_type);
7437 execute_fif_word(fif::parse_result{ "dup", false }, *e, false);
7438 s.set_main_type_back(1, stype);
7439 } else {
7440 auto ptr = s.main_data_back(0);
7441 auto children = (int64_t*)(ptr);
7442 auto child_data = children[index_value];
7443
7444 if(e->dict.type_array[child_type].flags != 0) {
7445 s.push_back_main(child_type, child_data, nullptr);
7446 execute_fif_word(fif::parse_result{ "dup", false }, *e, false);
7447 child_data = s.main_data_back(0);
7448 s.pop_main();
7449 s.pop_main();
7450 }
7451
7453 s.push_back_main(child_type, child_data, nullptr);
7454 }
7455 return p + 3;
7456}
7457
7458inline int32_t* forth_extract_copy(fif::state_stack& s, int32_t* p, fif::environment* e) {
7459 auto index_str = read_token(e->source_stack.back(), *e);
7460 auto index_value = parse_int(index_str.content);
7461 auto stype = s.main_type_back(0);
7462
7463 if(stype == -1 || e->dict.type_array[stype].refcounted_type() == false) {
7464 e->report_error("attempted to use a structure operation on a non-structure type");
7465 e->mode = fif_mode::error;
7466 return nullptr;
7467 }
7468
7469 assert(1 + index_value < e->dict.type_array[stype].decomposed_types_count);
7470 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + index_value;
7471 auto child_type = e->dict.all_stack_types[child_index];
7472
7474#ifdef USE_LLVM
7475 if(e->dict.type_array[stype].single_member_struct()) {
7477 s.set_main_type_back(0, child_type);
7478 execute_fif_word(fif::parse_result{ "dup", false }, *e, false);
7479 s.set_main_type_back(1, stype);
7480 } else {
7481 auto struct_expr = s.main_ex_back(0);
7482 auto result = LLVMBuildExtractValue(e->llvm_builder, struct_expr, index_value, "");
7484
7485 if(e->dict.type_array[child_type].flags != 0) {
7486 s.push_back_main(child_type, 0, result);
7487 execute_fif_word(fif::parse_result{ "dup", false }, *e, false);
7488 result = s.main_ex_back(0);
7489 s.pop_main();
7490 s.pop_main();
7491 }
7492 s.push_back_main(child_type, 0, result);
7493 }
7494#endif
7495 } else if(e->mode == fif::fif_mode::interpreting) {
7496 if(e->dict.type_array[stype].single_member_struct()) {
7498 s.set_main_type_back(0, child_type);
7499 execute_fif_word(fif::parse_result{ "dup", false }, *e, false);
7500 s.set_main_type_back(1, stype);
7501 } else {
7502 auto ptr = s.main_data_back(0);
7503 auto children = (int64_t*)(ptr);
7504 auto child_data = children[index_value];
7506
7507 if(e->dict.type_array[child_type].flags != 0) {
7508 s.push_back_main(child_type, child_data, nullptr);
7509 execute_fif_word(fif::parse_result{ "dup", false }, *e, false);
7510 child_data = s.main_data_back(0);
7511 s.pop_main();
7512 s.pop_main();
7513 }
7514
7515 s.push_back_main(child_type, child_data, nullptr);
7516 }
7519 s.push_back_main(child_type, 0, nullptr);
7520 } else if(e->mode == fif_mode::compiling_bytecode) {
7521 auto compile_bytes = e->compiler_stack.back()->bytecode_compilation_progress();
7522 if(compile_bytes) {
7523 fif_call imm = do_fextractc;
7524 uint64_t imm_bytes = 0;
7525 memcpy(&imm_bytes, &imm, 8);
7526 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
7527 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
7528 compile_bytes->push_back(index_value);
7529 }
7531 s.push_back_main(child_type, 0, nullptr);
7532 }
7533 return p + 2;
7534}
7535inline int32_t* do_finsert(fif::state_stack& s, int32_t* p, fif::environment* e) {
7536 int32_t index_value = *(p + 2);
7537 auto stype = s.main_type_back(0);
7538 assert(1 + index_value < e->dict.type_array[stype].decomposed_types_count);
7539 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + index_value;
7540 auto child_type = e->dict.all_stack_types[child_index];
7541
7542 if(e->dict.type_array[stype].single_member_struct()) {
7544 s.set_main_type_back(0, child_type);
7545 execute_fif_word(fif::parse_result{ "drop", false }, *e, false);
7546 s.set_main_type_back(0, stype);
7547 } else {
7548 auto ptr = s.main_data_back(0);
7549 auto children = (int64_t*)(ptr);
7550
7551 if(e->dict.type_array[child_type].flags != 0) {
7552 s.push_back_main(child_type, children[index_value], 0);
7553 execute_fif_word(fif::parse_result{ "drop", false }, *e, false);
7554 }
7555 s.pop_main();
7556 children[index_value] = s.main_data_back(0);
7557 s.pop_main();
7558
7559 s.push_back_main(stype, ptr, 0);
7560 }
7561 return p + 3;
7562}
7563
7564inline int32_t* forth_insert(fif::state_stack& s, int32_t* p, fif::environment* e) {
7565 auto index_str = read_token(e->source_stack.back(), *e);
7566 auto index_value = parse_int(index_str.content);
7567 auto stype = s.main_type_back(0);
7568
7569 if(stype == -1 || e->dict.type_array[stype].refcounted_type() == false) {
7570 e->report_error("attempted to use a structure operation on a non-structure type");
7571 e->mode = fif_mode::error;
7572 return nullptr;
7573 }
7574
7575 assert(1 + index_value < e->dict.type_array[stype].decomposed_types_count);
7576 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + index_value;
7577 auto child_type = e->dict.all_stack_types[child_index];
7578
7580#ifdef USE_LLVM
7581 if(e->dict.type_array[stype].single_member_struct()) {
7583 s.set_main_type_back(0, child_type);
7584 execute_fif_word(fif::parse_result{ "drop", false }, *e, false);
7585 s.set_main_type_back(0, stype);
7586 } else {
7587 auto struct_expr = s.main_ex_back(0);
7588
7589 if(e->dict.type_array[child_type].flags != 0) {
7590 auto oldv = LLVMBuildExtractValue(e->llvm_builder, struct_expr, index_value, "");
7591 s.push_back_main(child_type, 0, oldv);
7592 execute_fif_word(fif::parse_result{ "drop", false }, *e, false);
7593 }
7594
7595 s.pop_main();
7596 struct_expr = LLVMBuildInsertValue(e->llvm_builder, struct_expr, s.main_ex_back(0), index_value, "");
7597 s.pop_main();
7598 s.push_back_main(stype, 0, struct_expr);
7599 }
7600#endif
7601 } else if(e->mode == fif::fif_mode::interpreting) {
7602 if(e->dict.type_array[stype].single_member_struct()) {
7604 s.set_main_type_back(0, child_type);
7605 execute_fif_word(fif::parse_result{ "drop", false }, *e, false);
7606 s.set_main_type_back(0, stype);
7607 } else {
7608 auto ptr = s.main_data_back(0);
7609 auto children = (int64_t*)(ptr);
7610
7611 if(e->dict.type_array[child_type].flags != 0) {
7612 s.push_back_main(child_type, children[index_value], 0);
7613 execute_fif_word(fif::parse_result{ "drop", false }, *e, false);
7614 }
7615 s.pop_main();
7616 children[index_value] = s.main_data_back(0);
7617 s.pop_main();
7618
7619 s.push_back_main(stype, ptr, 0);
7620 }
7622 s.pop_main();
7623 s.pop_main();
7624 s.push_back_main(stype, 0, nullptr);
7625 } else if(e->mode == fif_mode::compiling_bytecode) {
7626 auto compile_bytes = e->compiler_stack.back()->bytecode_compilation_progress();
7627 if(compile_bytes) {
7628 fif_call imm = do_finsert;
7629 uint64_t imm_bytes = 0;
7630 memcpy(&imm_bytes, &imm, 8);
7631 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
7632 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
7633 compile_bytes->push_back(index_value);
7634 }
7635 s.pop_main();
7636 s.pop_main();
7637 s.push_back_main(stype, 0, nullptr);
7638 }
7639 return p + 2;
7640}
7641
7642inline int32_t* do_fgep(fif::state_stack& s, int32_t* p, fif::environment* e) {
7643 int32_t index_value = *(p + 2);
7644 auto ptr_type = s.main_type_back(0);
7645
7646 if(ptr_type == -1) {
7647 e->report_error("attempted to use a pointer operation on a non-pointer type");
7648 e->mode = fif_mode::error;
7649 return nullptr;
7650 }
7651 auto decomp = e->dict.type_array[ptr_type].decomposed_types_start;
7652 if(e->dict.type_array[ptr_type].decomposed_types_count == 0 || e->dict.all_stack_types[e->dict.type_array[ptr_type].decomposed_types_start] != fif_ptr) {
7653 e->report_error("attempted to use a struct-pointer operation on a non-struct-pointer type");
7654 e->mode = fif_mode::error;
7655 return nullptr;
7656 }
7657 auto stype = e->dict.all_stack_types[decomp + 1];
7658
7659 assert(1 + index_value < e->dict.type_array[stype].decomposed_types_count);
7660 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + index_value;
7661 auto child_type = e->dict.all_stack_types[child_index];
7662
7663 if(e->dict.type_array[stype].single_member_struct()) {
7664 int32_t type_storage[] = { fif_ptr, std::numeric_limits<int32_t>::max(), child_type, -1 };
7665 std::vector<int32_t> subs;
7666 auto child_ptr_type = resolve_span_type(std::span<int32_t const>(type_storage, type_storage + 4), subs, *e);
7667
7669 s.set_main_type_back(0, child_ptr_type.type);
7670 } else {
7671 auto ptr = s.main_data_back(0);
7672 auto children = (int64_t*)(ptr);
7673 auto child_ptr = children + index_value;
7674
7675 int32_t type_storage[] = { fif_ptr, std::numeric_limits<int32_t>::max(), child_type, -1 };
7676 std::vector<int32_t> subs;
7677 auto child_ptr_type = resolve_span_type(std::span<int32_t const>(type_storage, type_storage + 4), subs, *e);
7678
7679 s.pop_main();
7680 s.push_back_main(child_ptr_type.type, (int64_t)child_ptr, 0);
7681 }
7682 return p + 3;
7683}
7684
7685inline int32_t* forth_gep(fif::state_stack& s, int32_t* p, fif::environment* e) {
7686 auto index_str = read_token(e->source_stack.back(), *e);
7687 auto index_value = parse_int(index_str.content);
7688 auto ptr_type = s.main_type_back(0);
7689
7690 if(ptr_type == -1) {
7691 e->report_error("attempted to use a pointer operation on a non-pointer type");
7692 e->mode = fif_mode::error;
7693 return nullptr;
7694 }
7695
7696 auto decomp = e->dict.type_array[ptr_type].decomposed_types_start;
7697
7698 if(e->dict.type_array[ptr_type].decomposed_types_count == 0 || e->dict.all_stack_types[e->dict.type_array[ptr_type].decomposed_types_start] != fif_ptr) {
7699 e->report_error("attempted to use a struct-pointer operation on a non-struct-pointer type");
7700 e->mode = fif_mode::error;
7701 return nullptr;
7702 }
7703
7704 auto stype = e->dict.all_stack_types[decomp + 1];
7705
7706 if(stype == -1 || e->dict.type_array[stype].refcounted_type() == false) {
7707 e->report_error("attempted to use a structure operation on a non-structure type");
7708 e->mode = fif_mode::error;
7709 return nullptr;
7710 }
7711
7712 assert(1 + index_value < e->dict.type_array[stype].decomposed_types_count);
7713 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + index_value;
7714 auto child_type = e->dict.all_stack_types[child_index];
7715
7716 int32_t type_storage[] = { fif_ptr, std::numeric_limits<int32_t>::max(), child_type, -1 };
7717 std::vector<int32_t> subs;
7718 auto child_ptr_type = resolve_span_type(std::span<int32_t const>(type_storage, type_storage + 4), subs, *e);
7719
7721#ifdef USE_LLVM
7722 if(e->dict.type_array[stype].single_member_struct()) {
7724 s.set_main_type_back(0, child_ptr_type.type);
7725 } else {
7726 auto struct_expr = s.main_ex_back(0);
7727 auto ptr_expr = LLVMBuildStructGEP2(e->llvm_builder, e->dict.type_array[stype].llvm_type, struct_expr, uint32_t(index_value), "");
7728 s.pop_main();
7729 s.push_back_main(child_ptr_type.type, 0, ptr_expr);
7730 }
7731#endif
7732 } else if(e->mode == fif::fif_mode::interpreting) {
7733 if(e->dict.type_array[stype].single_member_struct()) {
7735 s.set_main_type_back(0, child_ptr_type.type);
7736 } else {
7737 auto ptr = s.main_data_back(0);
7738 auto children = (int64_t*)(ptr);
7739 auto child_ptr = children + index_value;
7740
7741 s.pop_main();
7742 s.push_back_main(child_ptr_type.type, (int64_t)child_ptr, 0);
7743 }
7745 s.pop_main();
7746 s.push_back_main(child_ptr_type.type, 0, nullptr);
7747 } else if(e->mode == fif_mode::compiling_bytecode) {
7748 auto compile_bytes = e->compiler_stack.back()->bytecode_compilation_progress();
7749 if(compile_bytes) {
7750 fif_call imm = do_fgep;
7751 uint64_t imm_bytes = 0;
7752 memcpy(&imm_bytes, &imm, 8);
7753 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
7754 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
7755 compile_bytes->push_back(index_value);
7756 }
7757 s.pop_main();
7758 s.push_back_main(child_ptr_type.type, 0, nullptr);
7759 }
7760 return p + 2;
7761}
7762
7763inline int32_t* do_fsmz(fif::state_stack& s, int32_t* p, fif::environment* e) {
7764 char* command = nullptr;
7765 memcpy(&command, p + 2, 8);
7766
7767 auto stype = s.main_type_back(0);
7768
7769 if(e->dict.type_array[stype].single_member_struct()) {
7770 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1;
7771 auto child_type = e->dict.all_stack_types[child_index];
7772
7774 s.set_main_type_back(0, child_type);
7775 execute_fif_word(parse_result{ std::string_view{ command }, false }, *e, false);
7776 } else {
7777 auto children_count = struct_child_count(stype, *e);
7778 auto ptr = s.main_data_back(0);
7779 auto children = (int64_t*)(ptr);
7780
7781 for(int32_t i = 0; i < children_count; ++i) {
7782 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + i;
7783 auto child_type = e->dict.all_stack_types[child_index];
7784 s.push_back_main(child_type, children[i], nullptr);
7785 execute_fif_word(parse_result{ std::string_view{ command }, false }, *e, false);
7786 }
7787
7788 free(children);
7789 s.pop_main();
7790 }
7791 return p + 4;
7792}
7793
7794inline int32_t* forth_struct_map_zero(fif::state_stack& s, int32_t* p, fif::environment* e) {
7795 auto mapped_function = read_token(e->source_stack.back(), *e);
7796 auto stype = s.main_type_back(0);
7797 auto children_count = struct_child_count(stype, *e);
7798
7799
7801#ifdef USE_LLVM
7802 if(e->dict.type_array[stype].single_member_struct()) {
7803 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1;
7804 auto child_type = e->dict.all_stack_types[child_index];
7805
7807 s.set_main_type_back(0, child_type);
7808 execute_fif_word(mapped_function, *e, false);
7809 } else {
7810 auto struct_expr = s.main_ex_back(0);
7811
7812 for(int32_t i = 0; i < children_count; ++i) {
7813 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + i;
7814 auto child_type = e->dict.all_stack_types[child_index];
7815 s.push_back_main(child_type, 0, LLVMBuildExtractValue(e->llvm_builder, struct_expr, uint32_t(i), ""));
7816 execute_fif_word(mapped_function, *e, false);
7817 }
7818
7819 s.pop_main();
7820 }
7821#endif
7822 } else if(e->mode == fif::fif_mode::interpreting) {
7823 if(e->dict.type_array[stype].single_member_struct()) {
7824 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1;
7825 auto child_type = e->dict.all_stack_types[child_index];
7826
7828 s.set_main_type_back(0, child_type);
7829 execute_fif_word(mapped_function, *e, false);
7830 } else {
7831 auto ptr = s.main_data_back(0);
7832 auto children = (int64_t*)(ptr);
7833
7834 for(int32_t i = 0; i < children_count; ++i) {
7835 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + i;
7836 auto child_type = e->dict.all_stack_types[child_index];
7837 s.push_back_main(child_type, children[i], nullptr);
7838 execute_fif_word(mapped_function, *e, false);
7839 }
7840 free(children);
7841 s.pop_main();
7842 }
7844 s.pop_main();
7845 } else if(e->mode == fif_mode::compiling_bytecode) {
7846 auto compile_bytes = e->compiler_stack.back()->bytecode_compilation_progress();
7847 if(compile_bytes) {
7848 {
7849 fif_call imm = do_fsmz;
7850 uint64_t imm_bytes = 0;
7851 memcpy(&imm_bytes, &imm, 8);
7852 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
7853 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
7854 }
7855 {
7856 auto str_const = e->get_string_constant(mapped_function.content).data();
7857 uint64_t imm_bytes = 0;
7858 memcpy(&imm_bytes, &str_const, 8);
7859 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
7860 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
7861 }
7862 }
7863 s.pop_main();
7864 }
7865 return p + 2;
7866}
7867
7868inline int32_t* do_fsmo(fif::state_stack& s, int32_t* p, fif::environment* e) {
7869 char* command = nullptr;
7870 memcpy(&command, p + 2, 8);
7871
7872 auto stype = s.main_type_back(0);
7873
7874 if(e->dict.type_array[stype].single_member_struct()) {
7875 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + 0;
7876 auto child_type = e->dict.all_stack_types[child_index];
7877 s.set_main_type_back(0, child_type);
7878 execute_fif_word(parse_result{ std::string_view{ command }, false }, *e, false);
7879 s.set_main_type_back(0, stype);
7880 } else {
7881 auto children_count = struct_child_count(stype, *e);
7882 auto ptr = s.main_data_back(0);
7883 auto children = (int64_t*)(ptr);
7884
7885 for(int32_t i = 0; i < children_count; ++i) {
7886 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + i;
7887 auto child_type = e->dict.all_stack_types[child_index];
7888 s.push_back_main(child_type, children[i], nullptr);
7889 execute_fif_word(parse_result{ std::string_view{ command }, false }, *e, false);
7890 children[i] = s.main_data_back(0);
7891 s.pop_main();
7892 }
7893 }
7894
7896 return p + 4;
7897}
7898inline int32_t* forth_struct_map_one(fif::state_stack& s, int32_t* p, fif::environment* e) {
7899 auto mapped_function = read_token(e->source_stack.back(), *e);
7900 auto stype = s.main_type_back(0);
7901 auto children_count = struct_child_count(stype, *e);
7902
7903
7905#ifdef USE_LLVM
7906 if(e->dict.type_array[stype].single_member_struct()) {
7907 assert(children_count == 1);
7908 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + 0;
7909 auto child_type = e->dict.all_stack_types[child_index];
7910 s.set_main_type_back(0, child_type);
7911 execute_fif_word(mapped_function, *e, false);
7912 s.set_main_type_back(0, stype);
7913 } else {
7914 auto struct_expr = s.main_ex_back(0);
7915
7916 for(int32_t i = 0; i < children_count; ++i) {
7917 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + i;
7918 auto child_type = e->dict.all_stack_types[child_index];
7919 s.push_back_main(child_type, 0, LLVMBuildExtractValue(e->llvm_builder, struct_expr, uint32_t(i), ""));
7920 execute_fif_word(mapped_function, *e, false);
7921 struct_expr = LLVMBuildInsertValue(e->llvm_builder, struct_expr, s.main_ex_back(0), uint32_t(i), "");
7922 s.pop_main();
7923 }
7924 s.set_main_ex_back(0, struct_expr);
7925 }
7927#endif
7928 } else if(e->mode == fif::fif_mode::interpreting) {
7929 if(e->dict.type_array[stype].single_member_struct()) {
7930 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + 0;
7931 auto child_type = e->dict.all_stack_types[child_index];
7932 s.set_main_type_back(0, child_type);
7933 execute_fif_word(mapped_function, *e, false);
7934 s.set_main_type_back(0, stype);
7935 } else {
7936 auto ptr = s.main_data_back(0);
7937 auto children = (int64_t*)(ptr);
7938
7939 for(int32_t i = 0; i < children_count; ++i) {
7940 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + i;
7941 auto child_type = e->dict.all_stack_types[child_index];
7942 s.push_back_main(child_type, children[i], nullptr);
7943 execute_fif_word(mapped_function, *e, false);
7944
7945 children[i] = s.main_data_back(0);
7946
7947 s.pop_main();
7948 }
7949 }
7953 } else if(e->mode == fif_mode::compiling_bytecode) {
7954 auto compile_bytes = e->compiler_stack.back()->bytecode_compilation_progress();
7955 if(compile_bytes) {
7956 {
7957 fif_call imm = do_fsmo;
7958 uint64_t imm_bytes = 0;
7959 memcpy(&imm_bytes, &imm, 8);
7960 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
7961 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
7962 }
7963 {
7964 auto str_const = e->get_string_constant(mapped_function.content).data();
7965 uint64_t imm_bytes = 0;
7966 memcpy(&imm_bytes, &str_const, 8);
7967 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
7968 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
7969 }
7970 }
7972 }
7973 return p + 2;
7974}
7975inline int32_t* do_fsmt(fif::state_stack& s, int32_t* p, fif::environment* e) {
7976 char* command = nullptr;
7977 memcpy(&command, p + 2, 8);
7978
7979 auto stype = s.main_type_back(0);
7980
7981 if(e->dict.type_array[stype].single_member_struct()) {
7983 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + 0;
7984 auto child_type = e->dict.all_stack_types[child_index];
7985 s.set_main_type_back(0, child_type);
7986 execute_fif_word(parse_result{ std::string_view{ command }, false }, *e, false);
7987 s.set_main_type_back(0, stype);
7988 s.set_main_type_back(1, stype);
7989 } else {
7990 auto children_count = struct_child_count(stype, *e);
7991 auto ptr = s.main_data_back(0);
7992 auto new_ptr = e->dict.type_array[stype].interpreter_zero(stype, e);
7993
7994 auto children = (int64_t*)(ptr);
7995 auto new_children = (int64_t*)(new_ptr);
7996
7997 for(int32_t i = 0; i < children_count; ++i) {
7998 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + i;
7999 auto child_type = e->dict.all_stack_types[child_index];
8000 s.push_back_main(child_type, children[i], nullptr);
8001 execute_fif_word(parse_result{ std::string_view{ command }, false }, *e, false);
8002
8003 new_children[i] = s.main_data_back(0);
8004
8005 s.pop_main();
8006 s.pop_main();
8007 }
8008
8010 s.push_back_main(stype, new_ptr, nullptr);
8011 }
8012 return p + 4;
8013}
8014inline int32_t* forth_struct_map_two(fif::state_stack& s, int32_t* p, fif::environment* e) {
8015 auto mapped_function = read_token(e->source_stack.back(), *e);
8016 auto stype = s.main_type_back(0);
8017 auto children_count = struct_child_count(stype, *e);
8018
8019
8021#ifdef USE_LLVM
8022 if(e->dict.type_array[stype].single_member_struct()) {
8024 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + 0;
8025 auto child_type = e->dict.all_stack_types[child_index];
8026 s.set_main_type_back(0, child_type);
8027 execute_fif_word(mapped_function, *e, false);
8028 s.set_main_type_back(0, stype);
8029 s.set_main_type_back(1, stype);
8030 } else {
8031 auto struct_expr = s.main_ex_back(0);
8032 auto new_struct_expr = e->dict.type_array[stype].zero_constant(e->llvm_context, stype, e);
8033
8034 for(int32_t i = 0; i < children_count; ++i) {
8035 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + i;
8036 auto child_type = e->dict.all_stack_types[child_index];
8037 s.push_back_main(child_type, 0, LLVMBuildExtractValue(e->llvm_builder, struct_expr, uint32_t(i), ""));
8038 execute_fif_word(mapped_function, *e, false);
8039 new_struct_expr = LLVMBuildInsertValue(e->llvm_builder, new_struct_expr, s.main_ex_back(0), uint32_t(i), "");
8040 s.pop_main();
8041 s.pop_main();
8042 }
8044 s.push_back_main(stype, 0, new_struct_expr);
8045 }
8046#endif
8047 } else if(e->mode == fif::fif_mode::interpreting) {
8048 if(e->dict.type_array[stype].single_member_struct()) {
8050 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + 0;
8051 auto child_type = e->dict.all_stack_types[child_index];
8052 s.set_main_type_back(0, child_type);
8053 execute_fif_word(mapped_function, *e, false);
8054 s.set_main_type_back(0, stype);
8055 s.set_main_type_back(1, stype);
8056 } else {
8057 auto ptr = s.main_data_back(0);
8058 auto new_ptr = e->dict.type_array[stype].interpreter_zero(stype, e);
8059
8060 auto children = (int64_t*)(ptr);
8061 auto new_children = (int64_t*)(new_ptr);
8062
8063 for(int32_t i = 0; i < children_count; ++i) {
8064 auto child_index = e->dict.type_array[stype].decomposed_types_start + 1 + i;
8065 auto child_type = e->dict.all_stack_types[child_index];
8066 s.push_back_main(child_type, children[i], nullptr);
8067 execute_fif_word(mapped_function, *e, false);
8068
8069
8070 new_children[i] = s.main_data_back(0);
8071
8072
8073 s.pop_main();
8074 s.pop_main();
8075 }
8076
8078 s.push_back_main(stype, new_ptr, nullptr);
8079 }
8082 s.push_back_main(stype, 0, nullptr);
8083 } else if(e->mode == fif_mode::compiling_bytecode) {
8084 auto compile_bytes = e->compiler_stack.back()->bytecode_compilation_progress();
8085 if(compile_bytes) {
8086 {
8087 fif_call imm = do_fsmt;
8088 uint64_t imm_bytes = 0;
8089 memcpy(&imm_bytes, &imm, 8);
8090 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
8091 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
8092 }
8093 {
8094 auto str_const = e->get_string_constant(mapped_function.content).data();
8095 uint64_t imm_bytes = 0;
8096 memcpy(&imm_bytes, &str_const, 8);
8097 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
8098 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
8099 }
8100 }
8102 s.push_back_main(stype, 0, nullptr);
8103 }
8104 return p + 2;
8105}
8106
8107inline int32_t* type_construction(state_stack& s, int32_t* p, environment* e) {
8108 auto type = *(p + 2);
8109 auto is_refcounted = e->dict.type_array[type].refcounted_type();
8110 s.push_back_main( type, (is_refcounted && e->dict.type_array[type].interpreter_zero) ? e->dict.type_array[type].interpreter_zero(type, e) : 0, nullptr);
8111 return p + 3;
8112}
8113inline int32_t* do_make(state_stack& s, int32_t* p, environment* env) {
8114 if(env->source_stack.empty()) {
8115 env->report_error("make was unable to read the word describing the type");
8116 env->mode = fif_mode::error;
8117 return nullptr;
8118 }
8119 auto type = read_token(env->source_stack.back(), *env);
8120
8121 if(typechecking_failed(env->mode))
8122 return p + 2;
8123
8124 auto resolved_type = resolve_type(type.content, *env, env->compiler_stack.back()->type_substitutions());
8125
8126 if(resolved_type == -1) {
8127 env->report_error("make was unable to resolve the type");
8128 env->mode = fif_mode::error;
8129 return nullptr;
8130 }
8131
8132 if(typechecking_mode(env->mode)) {
8133 s.push_back_main(resolved_type, 0, nullptr);
8134 return p + 2;
8135 }
8136
8137 auto compile_bytes = env->compiler_stack.back()->bytecode_compilation_progress();
8138 if(compile_bytes && env->mode == fif_mode::compiling_bytecode) {
8140 uint64_t imm_bytes = 0;
8141 memcpy(&imm_bytes, &imm, 8);
8142 compile_bytes->push_back(int32_t(imm_bytes & 0xFFFFFFFF));
8143 compile_bytes->push_back(int32_t((imm_bytes >> 32) & 0xFFFFFFFF));
8144 compile_bytes->push_back(resolved_type);
8145 }
8146 LLVMValueRef val = nullptr;
8147 if(env->mode == fif_mode::compiling_llvm) {
8148#ifdef USE_LLVM
8149 if(env->dict.type_array[resolved_type].zero_constant) {
8150 val = env->dict.type_array[resolved_type].zero_constant(env->llvm_context, resolved_type, env);
8151 } else {
8152 env->report_error("attempted to compile a type without an llvm representation");
8153 env->mode = fif_mode::error;
8154 return nullptr;
8155 }
8156#endif
8157 }
8158 int64_t data = 0;
8159 if(env->mode == fif_mode::interpreting) {
8160 if(env->dict.type_array[resolved_type].refcounted_type() && env->dict.type_array[resolved_type].interpreter_zero)
8161 data = env->dict.type_array[resolved_type].interpreter_zero(resolved_type, env);
8162 }
8163 s.push_back_main(resolved_type, data, val);
8164 execute_fif_word(fif::parse_result{ "init", false }, *env, false);
8165
8166 return p + 2;
8167}
8168
8169inline int32_t* struct_definition(fif::state_stack&, int32_t* p, fif::environment* e) {
8171 return p + 2;
8173 e->report_error("attempted to define a struct inside a definition");
8175 return nullptr;
8176 }
8177
8178 if(e->source_stack.empty()) {
8179 e->report_error("attempted to define a struct without a source");
8181 return nullptr;
8182 }
8183
8184 auto name_token = fif::read_token(e->source_stack.back(), *e);
8185
8186 if(e->dict.types.find(std::string(name_token.content)) != e->dict.types.end()) {
8187 e->report_error("attempted to redefine an existing type");
8189 return nullptr;
8190 }
8191
8192 std::vector<int32_t> stack_types;
8193 std::vector<std::string_view> names;
8194 int32_t max_variable = -1;
8195 bool read_extra_count = false;
8196
8197 while(true) {
8198 auto next_token = fif::read_token(e->source_stack.back(), *e);
8199 if(next_token.content.length() == 0 || next_token.content == ";") {
8200 break;
8201 }
8202 if(next_token.content == "$") {
8203 read_extra_count = true;
8204 break;
8205 }
8206
8207 auto result = internal_generate_type(next_token.content, *e);
8208 if(result.type_array.empty()) {
8209 e->mode = fif_mode::error;
8210 e->report_error("unable to resolve type from text");
8211 return nullptr;
8212 }
8213 stack_types.insert(stack_types.end(), result.type_array.begin(), result.type_array.end());
8214 max_variable = std::max(max_variable, result.max_variable);
8215
8216 auto nnext_token = fif::read_token(e->source_stack.back(), *e);
8217 if(nnext_token.content.length() == 0 || nnext_token.content == ";") {
8218 e->report_error("struct contained a type without a matching name");
8220 return nullptr;
8221 }
8222 names.push_back(nnext_token.content);
8223 }
8224
8225 int32_t extra_count = 0;
8226 if(read_extra_count) {
8227 auto next_token = fif::read_token(e->source_stack.back(), *e);
8228 auto next_next_token = fif::read_token(e->source_stack.back(), *e);
8229 if(next_next_token.content != ";") {
8230 e->report_error("struct definition ended incorrectly");
8232 return nullptr;
8233 }
8234 extra_count = parse_int(next_token.content);
8235 }
8236
8237 make_struct_type(name_token.content, std::span<int32_t const>{stack_types.begin(), stack_types.end()}, names, *e, max_variable + 1, extra_count);
8238
8239 return p + 2;
8240}
8241inline int32_t* export_definition(fif::state_stack&, int32_t* p, fif::environment* e) {
8243 return p + 2;
8245 e->report_error("attempted to define an export inside a definition");
8247 return nullptr;
8248 }
8249
8250 if(e->source_stack.empty()) {
8251 e->report_error("attempted to define an export without a source");
8253 return nullptr;
8254 }
8255
8256 auto name_token = fif::read_token(e->source_stack.back(), *e);
8257
8258 std::vector<int32_t> stack_types;
8259 std::vector<std::string_view> names;
8260 int32_t max_variable = -1;
8261 bool read_extra_count = false;
8262
8263 while(true) {
8264 auto next_token = fif::read_token(e->source_stack.back(), *e);
8265 if(next_token.content.length() == 0 || next_token.content == ";") {
8266 break;
8267 }
8268 names.push_back(next_token.content);
8269 }
8270
8271 auto fn_to_export = names.back();
8272 names.pop_back();
8273
8274 for(auto tyn : names) {
8275 auto result = resolve_type(tyn, *e, nullptr);
8276 if(result == -1) {
8277 e->mode = fif_mode::error;
8278 e->report_error("unable to resolve type from text");
8279 return nullptr;
8280 }
8281 stack_types.push_back(result);
8282 }
8283#ifdef USE_LLVM
8284 make_exportable_function(std::string(name_token.content), std::string(fn_to_export), stack_types, { }, *e);
8285#endif
8286 return p + 2;
8287}
8288inline int32_t* do_use_base(state_stack& s, int32_t* p, environment* env) {
8289 if(env->source_stack.empty()) {
8290 env->report_error("make was unable to read name of word");
8291 env->mode = fif_mode::error;
8292 return nullptr;
8293 }
8294 auto type = read_token(env->source_stack.back(), *env);
8295
8296 if(typechecking_failed(env->mode))
8297 return p + 2;
8298
8299 execute_fif_word(type, *env, true);
8300
8301 return p + 2;
8302}
8303
8304inline int32_t* long_comment(fif::state_stack&, int32_t* p, fif::environment* e) {
8305 if(e->source_stack.empty()) {
8306 return p + 2;
8307 }
8308
8309 int32_t depth = 1;
8310 while(depth > 0) {
8311 auto token = fif::read_token(e->source_stack.back(), *e);
8312 if(token.content == "))" && token.is_string == false)
8313 --depth;
8314 if(token.content == "((" && token.is_string == false)
8315 ++depth;
8316 if(token.content == "" && token.is_string == false)
8317 break;
8318 }
8319
8320 return p + 2;
8321}
8322inline int32_t* line_comment(fif::state_stack&, int32_t* p, fif::environment* e) {
8323 if(e->source_stack.empty()) {
8324 return p + 2;
8325 }
8326
8327 std::string_view& source = e->source_stack.back();
8328 while(source.length() > 0 && source[0] != '\n' && source[0] != '\r')
8329 source = source.substr(1);
8330
8331 return p + 2;
8332}
8333
8334inline int32_t* zext_i64(fif::state_stack& s, int32_t* p, fif::environment* e) {
8336#ifdef USE_LLVM
8337 auto result = LLVMBuildZExt(e->llvm_builder, s.main_ex_back(0), LLVMInt64TypeInContext(e->llvm_context), "");
8338 s.pop_main();
8339 s.push_back_main(fif_i64, 0, result);
8340#endif
8341 } else if(e->mode == fif::fif_mode::interpreting) {
8345 s.pop_main();
8346 s.push_back_main(fif::fif_i64, 0, nullptr);
8347 }
8348 return p + 2;
8349}
8350inline int32_t* zext_i32(fif::state_stack& s, int32_t* p, fif::environment* e) {
8352#ifdef USE_LLVM
8353 auto result = LLVMBuildZExt(e->llvm_builder, s.main_ex_back(0), LLVMInt32TypeInContext(e->llvm_context), "");
8354 s.pop_main();
8355 s.push_back_main(fif_i32, 0, result);
8356#endif
8357 } else if(e->mode == fif::fif_mode::interpreting) {
8359 s.set_main_data_back(0, s.main_data_back(0) & 0x0FFFFFFFF);
8362 s.pop_main();
8363 s.push_back_main(fif::fif_i32, 0, nullptr);
8364 }
8365 return p + 2;
8366}
8367inline int32_t* zext_i16(fif::state_stack& s, int32_t* p, fif::environment* e) {
8369#ifdef USE_LLVM
8370 auto result = LLVMBuildZExt(e->llvm_builder, s.main_ex_back(0), LLVMInt16TypeInContext(e->llvm_context), "");
8371 s.pop_main();
8372 s.push_back_main(fif_i16, 0, result);
8373#endif
8374 } else if(e->mode == fif::fif_mode::interpreting) {
8376 s.set_main_data_back(0, s.main_data_back(0) & 0x0FFFF);
8379 s.pop_main();
8380 s.push_back_main(fif::fif_i16, 0, nullptr);
8381 }
8382 return p + 2;
8383}
8384inline int32_t* zext_i8(fif::state_stack& s, int32_t* p, fif::environment* e) {
8386#ifdef USE_LLVM
8387 auto result = LLVMBuildZExt(e->llvm_builder, s.main_ex_back(0), LLVMInt8TypeInContext(e->llvm_context), "");
8388 s.pop_main();
8389 s.push_back_main(fif_i8, 0, result);
8390#endif
8391 } else if(e->mode == fif::fif_mode::interpreting) {
8393 s.set_main_data_back(0, s.main_data_back(0) & 0x0FF);
8396 s.pop_main();
8397 s.push_back_main(fif::fif_i8, 0, nullptr);
8398 }
8399 return p + 2;
8400}
8401inline int32_t* zext_ui64(fif::state_stack& s, int32_t* p, fif::environment* e) {
8403#ifdef USE_LLVM
8404 auto result = LLVMBuildZExt(e->llvm_builder, s.main_ex_back(0), LLVMInt64TypeInContext(e->llvm_context), "");
8405 s.pop_main();
8406 s.push_back_main(fif_u64, 0, result);
8407#endif
8408 } else if(e->mode == fif::fif_mode::interpreting) {
8412 s.pop_main();
8413 s.push_back_main(fif::fif_u64, 0, nullptr);
8414 }
8415 return p + 2;
8416}
8417inline int32_t* zext_ui32(fif::state_stack& s, int32_t* p, fif::environment* e) {
8419#ifdef USE_LLVM
8420 auto result = LLVMBuildZExt(e->llvm_builder, s.main_ex_back(0), LLVMInt32TypeInContext(e->llvm_context), "");
8421 s.pop_main();
8422 s.push_back_main(fif_u32, 0, result);
8423#endif
8424 } else if(e->mode == fif::fif_mode::interpreting) {
8426 s.set_main_data_back(0, s.main_data_back(0) & 0x0FFFFFFFF);
8429 s.pop_main();
8430 s.push_back_main(fif::fif_u32, 0, nullptr);
8431 }
8432 return p + 2;
8433}
8434inline int32_t* zext_ui16(fif::state_stack& s, int32_t* p, fif::environment* e) {
8436#ifdef USE_LLVM
8437 auto result = LLVMBuildZExt(e->llvm_builder, s.main_ex_back(0), LLVMInt16TypeInContext(e->llvm_context), "");
8438 s.pop_main();
8439 s.push_back_main(fif_u16, 0, result);
8440#endif
8441 } else if(e->mode == fif::fif_mode::interpreting) {
8443 s.set_main_data_back(0, s.main_data_back(0) & 0x0FFFF);
8446 s.pop_main();
8447 s.push_back_main(fif::fif_u16, 0, nullptr);
8448 }
8449 return p + 2;
8450}
8451inline int32_t* zext_ui8(fif::state_stack& s, int32_t* p, fif::environment* e) {
8453#ifdef USE_LLVM
8454 auto result = LLVMBuildZExt(e->llvm_builder, s.main_ex_back(0), LLVMInt8TypeInContext(e->llvm_context), "");
8455 s.pop_main();
8456 s.push_back_main(fif_u8, 0, result);
8457#endif
8458 } else if(e->mode == fif::fif_mode::interpreting) {
8460 s.set_main_data_back(0, s.main_data_back(0) & 0x0FF);
8463 s.pop_main();
8464 s.push_back_main(fif::fif_u8, 0, nullptr);
8465 }
8466 return p + 2;
8467}
8468inline int32_t* sext_i64(fif::state_stack& s, int32_t* p, fif::environment* e) {
8470#ifdef USE_LLVM
8471 auto result = LLVMBuildSExt(e->llvm_builder, s.main_ex_back(0), LLVMInt64TypeInContext(e->llvm_context), "");
8472 s.pop_main();
8473 s.push_back_main(fif_i64, 0, result);
8474#endif
8475 } else if(e->mode == fif::fif_mode::interpreting) {
8477 if(s.main_type_back(0) == fif_i8 || s.main_type_back(0) == fif_u8) {
8478 auto v = int8_t(s.main_data_back(0));
8479 s.set_main_data_back(0, v);
8480 } else if(s.main_type_back(0) == fif_i16 || s.main_type_back(0) == fif_u16) {
8481 auto v = int16_t(s.main_data_back(0));
8482 s.set_main_data_back(0, v);
8483 } else if(s.main_type_back(0) == fif_i32 || s.main_type_back(0) == fif_u32) {
8484 auto v = int32_t(s.main_data_back(0));
8485 s.set_main_data_back(0, v);
8486 } if(s.main_type_back(0) == fif_bool) {
8487 auto v = s.main_data_back(0);
8488 s.set_main_data_back(0, v != 0 ? -1 : 0);
8489 }
8492 s.pop_main();
8493 s.push_back_main(fif::fif_i64, 0, nullptr);
8494 }
8495 return p + 2;
8496}
8497inline int32_t* sext_i32(fif::state_stack& s, int32_t* p, fif::environment* e) {
8499#ifdef USE_LLVM
8500 auto result = LLVMBuildSExt(e->llvm_builder, s.main_ex_back(0), LLVMInt32TypeInContext(e->llvm_context), "");
8501 s.pop_main();
8502 s.push_back_main(fif_i32, 0, result);
8503#endif
8504 } else if(e->mode == fif::fif_mode::interpreting) {
8506 if(s.main_type_back(0) == fif_i8 || s.main_type_back(0) == fif_u8) {
8507 auto v = int8_t(s.main_data_back(0));
8508 s.set_main_data_back(0, v);
8509 } else if(s.main_type_back(0) == fif_i16 || s.main_type_back(0) == fif_u16) {
8510 auto v = int16_t(s.main_data_back(0));
8511 s.set_main_data_back(0, v);
8512 } else if(s.main_type_back(0) == fif_i32 || s.main_type_back(0) == fif_u32) {
8513 auto v = int32_t(s.main_data_back(0));
8514 s.set_main_data_back(0, v);
8515 } if(s.main_type_back(0) == fif_bool) {
8516 auto v = s.main_data_back(0);
8517 s.set_main_data_back(0, v != 0 ? -1 : 0);
8518 }
8521 s.pop_main();
8522 s.push_back_main(fif::fif_i32, 0, nullptr);
8523 }
8524 return p + 2;
8525}
8526inline int32_t* sext_i16(fif::state_stack& s, int32_t* p, fif::environment* e) {
8528#ifdef USE_LLVM
8529 auto result = LLVMBuildSExt(e->llvm_builder, s.main_ex_back(0), LLVMInt16TypeInContext(e->llvm_context), "");
8530 s.pop_main();
8531 s.push_back_main(fif_i16, 0, result);
8532#endif
8533 } else if(e->mode == fif::fif_mode::interpreting) {
8535 if(s.main_type_back(0) == fif_i8 || s.main_type_back(0) == fif_u8) {
8536 auto v = int8_t(s.main_data_back(0));
8537 s.set_main_data_back(0, v);
8538 } else if(s.main_type_back(0) == fif_i16 || s.main_type_back(0) == fif_u16) {
8539 auto v = int16_t(s.main_data_back(0));
8540 s.set_main_data_back(0, v);
8541 } else if(s.main_type_back(0) == fif_i32 || s.main_type_back(0) == fif_u32) {
8542 auto v = int32_t(s.main_data_back(0));
8543 s.set_main_data_back(0, v);
8544 } if(s.main_type_back(0) == fif_bool) {
8545 auto v = s.main_data_back(0);
8546 s.set_main_data_back(0, v != 0 ? -1 : 0);
8547 }
8550 s.pop_main();
8551 s.push_back_main(fif::fif_i16, 0, nullptr);
8552 }
8553 return p + 2;
8554}
8555inline int32_t* sext_i8(fif::state_stack& s, int32_t* p, fif::environment* e) {
8557#ifdef USE_LLVM
8558 auto result = LLVMBuildSExt(e->llvm_builder, s.main_ex_back(0), LLVMInt8TypeInContext(e->llvm_context), "");
8559 s.pop_main();
8560 s.push_back_main(fif_i8, 0, result);
8561#endif
8562 } else if(e->mode == fif::fif_mode::interpreting) {
8564 if(s.main_type_back(0) == fif_i8 || s.main_type_back(0) == fif_u8) {
8565 auto v = int8_t(s.main_data_back(0));
8566 s.set_main_data_back(0, v);
8567 } else if(s.main_type_back(0) == fif_i16 || s.main_type_back(0) == fif_u16) {
8568 auto v = int16_t(s.main_data_back(0));
8569 s.set_main_data_back(0, v);
8570 } else if(s.main_type_back(0) == fif_i32 || s.main_type_back(0) == fif_u32) {
8571 auto v = int32_t(s.main_data_back(0));
8572 s.set_main_data_back(0, v);
8573 } if(s.main_type_back(0) == fif_bool) {
8574 auto v = s.main_data_back(0);
8575 s.set_main_data_back(0, v != 0 ? -1 : 0);
8576 }
8579 s.pop_main();
8580 s.push_back_main(fif::fif_i8, 0, nullptr);
8581 }
8582 return p + 2;
8583}
8584inline int32_t* sext_ui64(fif::state_stack& s, int32_t* p, fif::environment* e) {
8586#ifdef USE_LLVM
8587 auto result = LLVMBuildSExt(e->llvm_builder, s.main_ex_back(0), LLVMInt64TypeInContext(e->llvm_context), "");
8588 s.pop_main();
8589 s.push_back_main(fif_u64, 0, result);
8590#endif
8591 } else if(e->mode == fif::fif_mode::interpreting) {
8593 if(s.main_type_back(0) == fif_i8 || s.main_type_back(0) == fif_u8) {
8594 auto v = int8_t(s.main_data_back(0));
8595 s.set_main_data_back(0, v);
8596 } else if(s.main_type_back(0) == fif_i16 || s.main_type_back(0) == fif_u16) {
8597 auto v = int16_t(s.main_data_back(0));
8598 s.set_main_data_back(0, v);
8599 } else if(s.main_type_back(0) == fif_i32 || s.main_type_back(0) == fif_u32) {
8600 auto v = int32_t(s.main_data_back(0));
8601 s.set_main_data_back(0, v);
8602 } if(s.main_type_back(0) == fif_bool) {
8603 auto v = s.main_data_back(0);
8604 s.set_main_data_back(0, v != 0 ? -1 : 0);
8605 }
8608 s.pop_main();
8609 s.push_back_main(fif::fif_u64, 0, nullptr);
8610 }
8611 return p + 2;
8612}
8613inline int32_t* sext_ui32(fif::state_stack& s, int32_t* p, fif::environment* e) {
8615#ifdef USE_LLVM
8616 auto result = LLVMBuildSExt(e->llvm_builder, s.main_ex_back(0), LLVMInt32TypeInContext(e->llvm_context), "");
8617 s.pop_main();
8618 s.push_back_main(fif_u32, 0, result);
8619#endif
8620 } else if(e->mode == fif::fif_mode::interpreting) {
8622 if(s.main_type_back(0) == fif_i8 || s.main_type_back(0) == fif_u8) {
8623 auto v = int8_t(s.main_data_back(0));
8624 s.set_main_data_back(0, v);
8625 } else if(s.main_type_back(0) == fif_i16 || s.main_type_back(0) == fif_u16) {
8626 auto v = int16_t(s.main_data_back(0));
8627 s.set_main_data_back(0, v);
8628 } else if(s.main_type_back(0) == fif_i32 || s.main_type_back(0) == fif_u32) {
8629 auto v = int32_t(s.main_data_back(0));
8630 s.set_main_data_back(0, v);
8631 } if(s.main_type_back(0) == fif_bool) {
8632 auto v = s.main_data_back(0);
8633 s.set_main_data_back(0, v != 0 ? -1 : 0);
8634 }
8637 s.pop_main();
8638 s.push_back_main(fif::fif_u32, 0, nullptr);
8639 }
8640 return p + 2;
8641}
8642inline int32_t* sext_ui16(fif::state_stack& s, int32_t* p, fif::environment* e) {
8644#ifdef USE_LLVM
8645 auto result = LLVMBuildSExt(e->llvm_builder, s.main_ex_back(0), LLVMInt16TypeInContext(e->llvm_context), "");
8646 s.pop_main();
8647 s.push_back_main(fif_u16, 0, result);
8648#endif
8649 } else if(e->mode == fif::fif_mode::interpreting) {
8651 if(s.main_type_back(0) == fif_i8 || s.main_type_back(0) == fif_u8) {
8652 auto v = int8_t(s.main_data_back(0));
8653 s.set_main_data_back(0, v);
8654 } else if(s.main_type_back(0) == fif_i16 || s.main_type_back(0) == fif_u16) {
8655 auto v = int16_t(s.main_data_back(0));
8656 s.set_main_data_back(0, v);
8657 } else if(s.main_type_back(0) == fif_i32 || s.main_type_back(0) == fif_u32) {
8658 auto v = int32_t(s.main_data_back(0));
8659 s.set_main_data_back(0, v);
8660 } if(s.main_type_back(0) == fif_bool) {
8661 auto v = s.main_data_back(0);
8662 s.set_main_data_back(0, v != 0 ? -1 : 0);
8663 }
8666 s.pop_main();
8667 s.push_back_main(fif::fif_u16, 0, nullptr);
8668 }
8669 return p + 2;
8670}
8671inline int32_t* sext_ui8(fif::state_stack& s, int32_t* p, fif::environment* e) {
8673#ifdef USE_LLVM
8674 auto result = LLVMBuildSExt(e->llvm_builder, s.main_ex_back(0), LLVMInt8TypeInContext(e->llvm_context), "");
8675 s.pop_main();
8676 s.push_back_main(fif_u8, 0, result);
8677#endif
8678 } else if(e->mode == fif::fif_mode::interpreting) {
8680 if(s.main_type_back(0) == fif_i8 || s.main_type_back(0) == fif_u8) {
8681 auto v = int8_t(s.main_data_back(0));
8682 s.set_main_data_back(0, v);
8683 } else if(s.main_type_back(0) == fif_i16 || s.main_type_back(0) == fif_u16) {
8684 auto v = int16_t(s.main_data_back(0));
8685 s.set_main_data_back(0, v);
8686 } else if(s.main_type_back(0) == fif_i32 || s.main_type_back(0) == fif_u32) {
8687 auto v = int32_t(s.main_data_back(0));
8688 s.set_main_data_back(0, v);
8689 } if(s.main_type_back(0) == fif_bool) {
8690 auto v = s.main_data_back(0);
8691 s.set_main_data_back(0, v != 0 ? -1 : 0);
8692 }
8695 s.pop_main();
8696 s.push_back_main(fif::fif_u8, 0, nullptr);
8697 }
8698 return p + 2;
8699}
8700inline int32_t* trunc_ui8(fif::state_stack& s, int32_t* p, fif::environment* e) {
8702#ifdef USE_LLVM
8703 auto result = LLVMBuildTrunc(e->llvm_builder, s.main_ex_back(0), LLVMInt8TypeInContext(e->llvm_context), "");
8704 s.pop_main();
8705 s.push_back_main(fif_u8, 0, result);
8706#endif
8707 } else if(e->mode == fif::fif_mode::interpreting) {
8709 s.set_main_data_back(0, s.main_data_back(0) & 0x0FF);
8712 s.pop_main();
8713 s.push_back_main(fif::fif_u8, 0, nullptr);
8714 }
8715 return p + 2;
8716}
8717inline int32_t* trunc_i8(fif::state_stack& s, int32_t* p, fif::environment* e) {
8719#ifdef USE_LLVM
8720 auto result = LLVMBuildTrunc(e->llvm_builder, s.main_ex_back(0), LLVMInt8TypeInContext(e->llvm_context), "");
8721 s.pop_main();
8722 s.push_back_main(fif_i8, 0, result);
8723#endif
8724 } else if(e->mode == fif::fif_mode::interpreting) {
8726 s.set_main_data_back(0, int8_t(s.main_data_back(0) & 0x0FF));
8729 s.pop_main();
8730 s.push_back_main(fif::fif_i8, 0, nullptr);
8731 }
8732 return p + 2;
8733}
8734inline int32_t* trunc_i1(fif::state_stack& s, int32_t* p, fif::environment* e) {
8736#ifdef USE_LLVM
8737 auto result = LLVMBuildTrunc(e->llvm_builder, s.main_ex_back(0), LLVMInt1TypeInContext(e->llvm_context), "");
8738 s.pop_main();
8739 s.push_back_main(fif_bool, 0, result);
8740#endif
8741 } else if(e->mode == fif::fif_mode::interpreting) {
8743 s.set_main_data_back(0, s.main_data_back(0) & 0x01);
8746 s.pop_main();
8747 s.push_back_main(fif::fif_bool, 0, nullptr);
8748 }
8749 return p + 2;
8750}
8751inline int32_t* trunc_ui16(fif::state_stack& s, int32_t* p, fif::environment* e) {
8753#ifdef USE_LLVM
8754 auto result = LLVMBuildTrunc(e->llvm_builder, s.main_ex_back(0), LLVMInt16TypeInContext(e->llvm_context), "");
8755 s.pop_main();
8756 s.push_back_main(fif_u16, 0, result);
8757#endif
8758 } else if(e->mode == fif::fif_mode::interpreting) {
8760 s.set_main_data_back(0, s.main_data_back(0) & 0x0FFFF);
8763 s.pop_main();
8764 s.push_back_main(fif::fif_u16, 0, nullptr);
8765 }
8766 return p + 2;
8767}
8768inline int32_t* trunc_i16(fif::state_stack& s, int32_t* p, fif::environment* e) {
8770#ifdef USE_LLVM
8771 auto result = LLVMBuildTrunc(e->llvm_builder, s.main_ex_back(0), LLVMInt16TypeInContext(e->llvm_context), "");
8772 s.pop_main();
8773 s.push_back_main(fif_i16, 0, result);
8774#endif
8775 } else if(e->mode == fif::fif_mode::interpreting) {
8777 s.set_main_data_back(0, int16_t(s.main_data_back(0) & 0x0FFFF));
8780 s.pop_main();
8781 s.push_back_main(fif::fif_i16, 0, nullptr);
8782 }
8783 return p + 2;
8784}
8785inline int32_t* trunc_ui32(fif::state_stack& s, int32_t* p, fif::environment* e) {
8787#ifdef USE_LLVM
8788 auto result = LLVMBuildTrunc(e->llvm_builder, s.main_ex_back(0), LLVMInt32TypeInContext(e->llvm_context), "");
8789 s.pop_main();
8790 s.push_back_main(fif_u32, 0, result);
8791#endif
8792 } else if(e->mode == fif::fif_mode::interpreting) {
8794 s.set_main_data_back(0, s.main_data_back(0) & 0x0FFFFFFFF);
8797 s.pop_main();
8798 s.push_back_main(fif::fif_u32, 0, nullptr);
8799 }
8800 return p + 2;
8801}
8802inline int32_t* trunc_i32(fif::state_stack& s, int32_t* p, fif::environment* e) {
8804#ifdef USE_LLVM
8805 auto result = LLVMBuildTrunc(e->llvm_builder, s.main_ex_back(0), LLVMInt32TypeInContext(e->llvm_context), "");
8806 s.pop_main();
8807 s.push_back_main(fif_i32, 0, result);
8808#endif
8809 } else if(e->mode == fif::fif_mode::interpreting) {
8811 s.set_main_data_back(0, int32_t(s.main_data_back(0) & 0x0FFFFFFFF));
8814 s.pop_main();
8815 s.push_back_main(fif::fif_i32, 0, nullptr);
8816 }
8817 return p + 2;
8818}
8819inline int32_t* nop1(fif::state_stack& s, int32_t* p, fif::environment* e) {
8822 } else if(e->mode == fif::fif_mode::interpreting) {
8826 }
8827 return p + 2;
8828}
8829inline int32_t* ftrunc(fif::state_stack& s, int32_t* p, fif::environment* e) {
8831#ifdef USE_LLVM
8832 auto result = LLVMBuildFPTrunc(e->llvm_builder, s.main_ex_back(0), LLVMFloatTypeInContext(e->llvm_context), "");
8833 s.pop_main();
8834 s.push_back_main(fif_f32, 0, result);
8835#endif
8836 } else if(e->mode == fif::fif_mode::interpreting) {
8837 auto v = s.main_data_back(0);
8838 double fin = 0;
8839 memcpy(&fin, &v, 8);
8840 float fout = float(fin);
8841 int64_t iout = 0;
8842 memcpy(&iout, &fout, 4);
8843 s.pop_main();
8844 s.push_back_main(fif_f32, iout, nullptr);
8846 s.pop_main();
8847 s.push_back_main(fif::fif_f32, 0, nullptr);
8848 }
8849 return p + 2;
8850}
8851inline int32_t* fext(fif::state_stack& s, int32_t* p, fif::environment* e) {
8853#ifdef USE_LLVM
8854 auto result = LLVMBuildFPExt(e->llvm_builder, s.main_ex_back(0), LLVMFloatTypeInContext(e->llvm_context), "");
8855 s.pop_main();
8856 s.push_back_main(fif_f64, 0, result);
8857#endif
8858 } else if(e->mode == fif::fif_mode::interpreting) {
8859 auto v = s.main_data_back(0);
8860 float fin = 0;
8861 memcpy(&fin, &v, 4);
8862 double fout = double(fin);
8863 int64_t iout = 0;
8864 memcpy(&iout, &fout, 8);
8865 s.pop_main();
8866 s.push_back_main(fif_f64, iout, nullptr);
8868 s.pop_main();
8869 s.push_back_main(fif::fif_f64, 0, nullptr);
8870 }
8871 return p + 2;
8872}
8873inline int32_t* f32i8(fif::state_stack& s, int32_t* p, fif::environment* e) {
8875#ifdef USE_LLVM
8876 auto result = LLVMBuildFPToSI(e->llvm_builder, s.main_ex_back(0), LLVMInt8TypeInContext(e->llvm_context), "");
8877 s.pop_main();
8878 s.push_back_main(fif_i8, 0, result);
8879#endif
8880 } else if(e->mode == fif::fif_mode::interpreting) {
8881 auto v = s.main_data_back(0);
8882 float fin = 0;
8883 memcpy(&fin, &v, 4);
8884 int64_t iout = int8_t(fin);
8885 s.pop_main();
8886 s.push_back_main(fif_i8, iout, nullptr);
8888 s.pop_main();
8889 s.push_back_main(fif::fif_i8, 0, nullptr);
8890 }
8891 return p + 2;
8892}
8893inline int32_t* sif32(fif::state_stack& s, int32_t* p, fif::environment* e) {
8895#ifdef USE_LLVM
8896 auto result = LLVMBuildSIToFP(e->llvm_builder, s.main_ex_back(0), LLVMFloatTypeInContext(e->llvm_context), "");
8897 s.pop_main();
8898 s.push_back_main(fif_f32, 0, result);
8899#endif
8900 } else if(e->mode == fif::fif_mode::interpreting) {
8901 auto v = s.main_data_back(0);
8902 float fout = float(v);
8903 int64_t iout = 0;
8904 memcpy(&iout, &fout, 4);
8905 s.pop_main();
8906 s.push_back_main(fif_f32, iout, nullptr);
8908 s.pop_main();
8909 s.push_back_main(fif::fif_f32, 0, nullptr);
8910 }
8911 return p + 2;
8912}
8913inline int32_t* uif32(fif::state_stack& s, int32_t* p, fif::environment* e) {
8915#ifdef USE_LLVM
8916 auto result = LLVMBuildUIToFP(e->llvm_builder, s.main_ex_back(0), LLVMFloatTypeInContext(e->llvm_context), "");
8917 s.pop_main();
8918 s.push_back_main(fif_f32, 0, result);
8919#endif
8920 } else if(e->mode == fif::fif_mode::interpreting) {
8921 auto v = uint64_t(s.main_data_back(0));
8922 float fout = float(v);
8923 int64_t iout = 0;
8924 memcpy(&iout, &fout, 4);
8925 s.pop_main();
8926 s.push_back_main(fif_f32, iout, nullptr);
8928 s.pop_main();
8929 s.push_back_main(fif::fif_f32, 0, nullptr);
8930 }
8931 return p + 2;
8932}
8933inline int32_t* sif64(fif::state_stack& s, int32_t* p, fif::environment* e) {
8935#ifdef USE_LLVM
8936 auto result = LLVMBuildSIToFP(e->llvm_builder, s.main_ex_back(0), LLVMDoubleTypeInContext(e->llvm_context), "");
8937 s.pop_main();
8938 s.push_back_main(fif_f64, 0, result);
8939#endif
8940 } else if(e->mode == fif::fif_mode::interpreting) {
8941 auto v = s.main_data_back(0);
8942 double fout = double(v);
8943 int64_t iout = 0;
8944 memcpy(&iout, &fout, 8);
8945 s.pop_main();
8946 s.push_back_main(fif_f64, iout, nullptr);
8948 s.pop_main();
8949 s.push_back_main(fif::fif_f64, 0, nullptr);
8950 }
8951 return p + 2;
8952}
8953inline int32_t* uif64(fif::state_stack& s, int32_t* p, fif::environment* e) {
8955#ifdef USE_LLVM
8956 auto result = LLVMBuildUIToFP(e->llvm_builder, s.main_ex_back(0), LLVMDoubleTypeInContext(e->llvm_context), "");
8957 s.pop_main();
8958 s.push_back_main(fif_f64, 0, result);
8959#endif
8960 } else if(e->mode == fif::fif_mode::interpreting) {
8961 auto v = uint64_t(s.main_data_back(0));
8962 double fout = double(v);
8963 int64_t iout = 0;
8964 memcpy(&iout, &fout, 8);
8965 s.pop_main();
8966 s.push_back_main(fif_f64, iout, nullptr);
8968 s.pop_main();
8969 s.push_back_main(fif::fif_f64, 0, nullptr);
8970 }
8971 return p + 2;
8972}
8973inline int32_t* f32i16(fif::state_stack& s, int32_t* p, fif::environment* e) {
8975#ifdef USE_LLVM
8976 auto result = LLVMBuildFPToSI(e->llvm_builder, s.main_ex_back(0), LLVMInt16TypeInContext(e->llvm_context), "");
8977 s.pop_main();
8978 s.push_back_main(fif_i16, 0, result);
8979#endif
8980 } else if(e->mode == fif::fif_mode::interpreting) {
8981 auto v = s.main_data_back(0);
8982 float fin = 0;
8983 memcpy(&fin, &v, 4);
8984 int64_t iout = int16_t(fin);
8985 s.pop_main();
8986 s.push_back_main(fif_i16, iout, nullptr);
8988 s.pop_main();
8989 s.push_back_main(fif::fif_i16, 0, nullptr);
8990 }
8991 return p + 2;
8992}
8993inline int32_t* f32i32(fif::state_stack& s, int32_t* p, fif::environment* e) {
8995#ifdef USE_LLVM
8996 auto result = LLVMBuildFPToSI(e->llvm_builder, s.main_ex_back(0), LLVMInt32TypeInContext(e->llvm_context), "");
8997 s.pop_main();
8998 s.push_back_main(fif_i32, 0, result);
8999#endif
9000 } else if(e->mode == fif::fif_mode::interpreting) {
9001 auto v = s.main_data_back(0);
9002 float fin = 0;
9003 memcpy(&fin, &v, 4);
9004 int64_t iout = int32_t(fin);
9005 s.pop_main();
9006 s.push_back_main(fif_i32, iout, nullptr);
9008 s.pop_main();
9009 s.push_back_main(fif::fif_i32, 0, nullptr);
9010 }
9011 return p + 2;
9012}
9013inline int32_t* f32i64(fif::state_stack& s, int32_t* p, fif::environment* e) {
9015#ifdef USE_LLVM
9016 auto result = LLVMBuildFPToSI(e->llvm_builder, s.main_ex_back(0), LLVMInt64TypeInContext(e->llvm_context), "");
9017 s.pop_main();
9018 s.push_back_main(fif_i64, 0, result);
9019#endif
9020 } else if(e->mode == fif::fif_mode::interpreting) {
9021 auto v = s.main_data_back(0);
9022 float fin = 0;
9023 memcpy(&fin, &v, 4);
9024 int64_t iout = int64_t(fin);
9025 s.pop_main();
9026 s.push_back_main(fif_i64, iout, nullptr);
9028 s.pop_main();
9029 s.push_back_main(fif::fif_i64, 0, nullptr);
9030 }
9031 return p + 2;
9032}
9033inline int32_t* f32ui8(fif::state_stack& s, int32_t* p, fif::environment* e) {
9035#ifdef USE_LLVM
9036 auto result = LLVMBuildFPToUI(e->llvm_builder, s.main_ex_back(0), LLVMInt8TypeInContext(e->llvm_context), "");
9037 s.pop_main();
9038 s.push_back_main(fif_u8, 0, result);
9039#endif
9040 } else if(e->mode == fif::fif_mode::interpreting) {
9041 auto v = s.main_data_back(0);
9042 float fin = 0;
9043 memcpy(&fin, &v, 4);
9044 int64_t iout = int64_t(uint8_t(fin));
9045 s.pop_main();
9046 s.push_back_main(fif_u8, iout, nullptr);
9048 s.pop_main();
9049 s.push_back_main(fif::fif_u8, 0, nullptr);
9050 }
9051 return p + 2;
9052}
9053inline int32_t* f32ui16(fif::state_stack& s, int32_t* p, fif::environment* e) {
9055#ifdef USE_LLVM
9056 auto result = LLVMBuildFPToUI(e->llvm_builder, s.main_ex_back(0), LLVMInt16TypeInContext(e->llvm_context), "");
9057 s.pop_main();
9058 s.push_back_main(fif_u16, 0, result);
9059#endif
9060 } else if(e->mode == fif::fif_mode::interpreting) {
9061 auto v = s.main_data_back(0);
9062 float fin = 0;
9063 memcpy(&fin, &v, 4);
9064 int64_t iout = int64_t(uint16_t(fin));
9065 s.pop_main();
9066 s.push_back_main(fif_u16, iout, nullptr);
9068 s.pop_main();
9069 s.push_back_main(fif::fif_u16, 0, nullptr);
9070 }
9071 return p + 2;
9072}
9073inline int32_t* f32ui32(fif::state_stack& s, int32_t* p, fif::environment* e) {
9075#ifdef USE_LLVM
9076 auto result = LLVMBuildFPToUI(e->llvm_builder, s.main_ex_back(0), LLVMInt32TypeInContext(e->llvm_context), "");
9077 s.pop_main();
9078 s.push_back_main(fif_u32, 0, result);
9079#endif
9080 } else if(e->mode == fif::fif_mode::interpreting) {
9081 auto v = s.main_data_back(0);
9082 float fin = 0;
9083 memcpy(&fin, &v, 4);
9084 int64_t iout = int64_t(uint32_t(fin));
9085 s.pop_main();
9086 s.push_back_main(fif_u32, iout, nullptr);
9088 s.pop_main();
9089 s.push_back_main(fif::fif_u32, 0, nullptr);
9090 }
9091 return p + 2;
9092}
9093inline int32_t* f32ui64(fif::state_stack& s, int32_t* p, fif::environment* e) {
9095#ifdef USE_LLVM
9096 auto result = LLVMBuildFPToUI(e->llvm_builder, s.main_ex_back(0), LLVMInt64TypeInContext(e->llvm_context), "");
9097 s.pop_main();
9098 s.push_back_main(fif_u64, 0, result);
9099#endif
9100 } else if(e->mode == fif::fif_mode::interpreting) {
9101 auto v = s.main_data_back(0);
9102 float fin = 0;
9103 memcpy(&fin, &v, 4);
9104 int64_t iout = int64_t(uint64_t(fin));
9105 s.pop_main();
9106 s.push_back_main(fif_u64, iout, nullptr);
9108 s.pop_main();
9109 s.push_back_main(fif::fif_u64, 0, nullptr);
9110 }
9111 return p + 2;
9112}
9113
9114inline int32_t* f64i8(fif::state_stack& s, int32_t* p, fif::environment* e) {
9116#ifdef USE_LLVM
9117 auto result = LLVMBuildFPToSI(e->llvm_builder, s.main_ex_back(0), LLVMInt8TypeInContext(e->llvm_context), "");
9118 s.pop_main();
9119 s.push_back_main(fif_i8, 0, result);
9120#endif
9121 } else if(e->mode == fif::fif_mode::interpreting) {
9122 auto v = s.main_data_back(0);
9123 double fin = 0;
9124 memcpy(&fin, &v, 8);
9125 int64_t iout = int8_t(fin);
9126 s.pop_main();
9127 s.push_back_main(fif_i8, iout, nullptr);
9129 s.pop_main();
9130 s.push_back_main(fif::fif_i8, 0, nullptr);
9131 }
9132 return p + 2;
9133}
9134inline int32_t* f64i16(fif::state_stack& s, int32_t* p, fif::environment* e) {
9136#ifdef USE_LLVM
9137 auto result = LLVMBuildFPToSI(e->llvm_builder, s.main_ex_back(0), LLVMInt16TypeInContext(e->llvm_context), "");
9138 s.pop_main();
9139 s.push_back_main(fif_i16, 0, result);
9140#endif
9141 } else if(e->mode == fif::fif_mode::interpreting) {
9142 auto v = s.main_data_back(0);
9143 double fin = 0;
9144 memcpy(&fin, &v, 8);
9145 int64_t iout = int16_t(fin);
9146 s.pop_main();
9147 s.push_back_main(fif_i16, iout, nullptr);
9149 s.pop_main();
9150 s.push_back_main(fif::fif_i16, 0, nullptr);
9151 }
9152 return p + 2;
9153}
9154inline int32_t* f64i32(fif::state_stack& s, int32_t* p, fif::environment* e) {
9156#ifdef USE_LLVM
9157 auto result = LLVMBuildFPToSI(e->llvm_builder, s.main_ex_back(0), LLVMInt32TypeInContext(e->llvm_context), "");
9158 s.pop_main();
9159 s.push_back_main(fif_i32, 0, result);
9160#endif
9161 } else if(e->mode == fif::fif_mode::interpreting) {
9162 auto v = s.main_data_back(0);
9163 double fin = 0;
9164 memcpy(&fin, &v, 8);
9165 int64_t iout = int32_t(fin);
9166 s.pop_main();
9167 s.push_back_main(fif_i32, iout, nullptr);
9169 s.pop_main();
9170 s.push_back_main(fif::fif_i32, 0, nullptr);
9171 }
9172 return p + 2;
9173}
9174inline int32_t* f64i64(fif::state_stack& s, int32_t* p, fif::environment* e) {
9176#ifdef USE_LLVM
9177 auto result = LLVMBuildFPToSI(e->llvm_builder, s.main_ex_back(0), LLVMInt64TypeInContext(e->llvm_context), "");
9178 s.pop_main();
9179 s.push_back_main(fif_i64, 0, result);
9180#endif
9181 } else if(e->mode == fif::fif_mode::interpreting) {
9182 auto v = s.main_data_back(0);
9183 double fin = 0;
9184 memcpy(&fin, &v, 8);
9185 int64_t iout = int64_t(fin);
9186 s.pop_main();
9187 s.push_back_main(fif_i64, iout, nullptr);
9189 s.pop_main();
9190 s.push_back_main(fif::fif_i64, 0, nullptr);
9191 }
9192 return p + 2;
9193}
9194inline int32_t* f64ui8(fif::state_stack& s, int32_t* p, fif::environment* e) {
9196#ifdef USE_LLVM
9197 auto result = LLVMBuildFPToUI(e->llvm_builder, s.main_ex_back(0), LLVMInt8TypeInContext(e->llvm_context), "");
9198 s.pop_main();
9199 s.push_back_main(fif_u8, 0, result);
9200#endif
9201 } else if(e->mode == fif::fif_mode::interpreting) {
9202 auto v = s.main_data_back(0);
9203 double fin = 0;
9204 memcpy(&fin, &v, 8);
9205 int64_t iout = int64_t(uint8_t(fin));
9206 s.pop_main();
9207 s.push_back_main(fif_u8, iout, nullptr);
9209 s.pop_main();
9210 s.push_back_main(fif::fif_u8, 0, nullptr);
9211 }
9212 return p + 2;
9213}
9214inline int32_t* f64ui16(fif::state_stack& s, int32_t* p, fif::environment* e) {
9216#ifdef USE_LLVM
9217 auto result = LLVMBuildFPToUI(e->llvm_builder, s.main_ex_back(0), LLVMInt16TypeInContext(e->llvm_context), "");
9218 s.pop_main();
9219 s.push_back_main(fif_u16, 0, result);
9220#endif
9221 } else if(e->mode == fif::fif_mode::interpreting) {
9222 auto v = s.main_data_back(0);
9223 double fin = 0;
9224 memcpy(&fin, &v, 8);
9225 int64_t iout = int64_t(uint16_t(fin));
9226 s.pop_main();
9227 s.push_back_main(fif_u16, iout, nullptr);
9229 s.pop_main();
9230 s.push_back_main(fif::fif_u16, 0, nullptr);
9231 }
9232 return p + 2;
9233}
9234inline int32_t* f64ui32(fif::state_stack& s, int32_t* p, fif::environment* e) {
9236#ifdef USE_LLVM
9237 auto result = LLVMBuildFPToUI(e->llvm_builder, s.main_ex_back(0), LLVMInt32TypeInContext(e->llvm_context), "");
9238 s.pop_main();
9239 s.push_back_main(fif_u32, 0, result);
9240#endif
9241 } else if(e->mode == fif::fif_mode::interpreting) {
9242 auto v = s.main_data_back(0);
9243 double fin = 0;
9244 memcpy(&fin, &v, 8);
9245 int64_t iout = int64_t(uint32_t(fin));
9246 s.pop_main();
9247 s.push_back_main(fif_u32, iout, nullptr);
9249 s.pop_main();
9250 s.push_back_main(fif::fif_u32, 0, nullptr);
9251 }
9252 return p + 2;
9253}
9254inline int32_t* f64ui64(fif::state_stack& s, int32_t* p, fif::environment* e) {
9256#ifdef USE_LLVM
9257 auto result = LLVMBuildFPToUI(e->llvm_builder, s.main_ex_back(0), LLVMInt64TypeInContext(e->llvm_context), "");
9258 s.pop_main();
9259 s.push_back_main(fif_u64, 0, result);
9260#endif
9261 } else if(e->mode == fif::fif_mode::interpreting) {
9262 auto v = s.main_data_back(0);
9263 double fin = 0;
9264 memcpy(&fin, &v, 8);
9265 int64_t iout = int64_t(uint64_t(fin));
9266 s.pop_main();
9267 s.push_back_main(fif_u64, iout, nullptr);
9269 s.pop_main();
9270 s.push_back_main(fif::fif_u64, 0, nullptr);
9271 }
9272 return p + 2;
9273}
9274inline int32_t* bit_and(fif::state_stack& s, int32_t* p, fif::environment* e) {
9276#ifdef USE_LLVM
9278 auto result = LLVMBuildAnd(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
9279 s.pop_main();
9280 s.set_main_ex_back(0, result);
9281#endif
9282 } else if(e->mode == fif::fif_mode::interpreting) {
9284 auto a = s.main_data_back(0);
9285 auto b = s.main_data_back(1);
9286 s.pop_main();
9287 s.set_main_data_back(0, a & b);
9290 s.pop_main();
9291 }
9292 return p + 2;
9293}
9294inline int32_t* bit_or(fif::state_stack& s, int32_t* p, fif::environment* e) {
9296#ifdef USE_LLVM
9298 auto result = LLVMBuildOr(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
9299 s.pop_main();
9300 s.set_main_ex_back(0, result);
9301#endif
9302 } else if(e->mode == fif::fif_mode::interpreting) {
9304 auto a = s.main_data_back(0);
9305 auto b = s.main_data_back(1);
9306 s.pop_main();
9307 s.set_main_data_back(0, a | b);
9310 s.pop_main();
9311 }
9312 return p + 2;
9313}
9314inline int32_t* bit_xor(fif::state_stack& s, int32_t* p, fif::environment* e) {
9316#ifdef USE_LLVM
9318 auto result = LLVMBuildXor(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
9319 s.pop_main();
9320 s.set_main_ex_back(0, result);
9321#endif
9322 } else if(e->mode == fif::fif_mode::interpreting) {
9324 auto a = s.main_data_back(0);
9325 auto b = s.main_data_back(1);
9326 s.pop_main();
9327 s.set_main_data_back(0, a ^ b);
9330 s.pop_main();
9331 }
9332 return p + 2;
9333}
9334inline int32_t* bit_not(fif::state_stack& s, int32_t* p, fif::environment* e) {
9336#ifdef USE_LLVM
9338 auto result = LLVMBuildNot(e->llvm_builder, s.main_ex_back(0), "");
9339 s.set_main_ex_back(0, result);
9340#endif
9341 } else if(e->mode == fif::fif_mode::interpreting) {
9343 auto a = s.main_data_back(0);
9344 if(s.main_type_back(0) == fif_bool)
9345 s.set_main_data_back(0, a == 0);
9346 else
9347 s.set_main_data_back(0, ~a);
9350 }
9351 return p + 2;
9352}
9353inline int32_t* bit_shl(fif::state_stack& s, int32_t* p, fif::environment* e) {
9355#ifdef USE_LLVM
9357 auto result = LLVMBuildShl(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
9358 s.pop_main();
9359 s.set_main_ex_back(0, result);
9360#endif
9361 } else if(e->mode == fif::fif_mode::interpreting) {
9363 auto a = s.main_data_back(0);
9364 auto b = s.main_data_back(1);
9365 s.pop_main();
9366 s.set_main_data_back(0, b << a);
9369 s.pop_main();
9370 }
9371 return p + 2;
9372}
9373inline int32_t* bit_ashr(fif::state_stack& s, int32_t* p, fif::environment* e) {
9375#ifdef USE_LLVM
9377 auto result = LLVMBuildAShr(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
9378 s.pop_main();
9379 s.set_main_ex_back(0, result);
9380#endif
9381 } else if(e->mode == fif::fif_mode::interpreting) {
9383 auto a = s.main_data_back(0);
9384 auto b = s.main_data_back(1);
9385 s.pop_main();
9386 s.set_main_data_back(0, b >> a);
9389 s.pop_main();
9390 }
9391 return p + 2;
9392}
9393inline int32_t* bit_lshr(fif::state_stack& s, int32_t* p, fif::environment* e) {
9395#ifdef USE_LLVM
9397 auto result = LLVMBuildLShr(e->llvm_builder, s.main_ex_back(1), s.main_ex_back(0), "");
9398 s.pop_main();
9399 s.set_main_ex_back(0, result);
9400#endif
9401 } else if(e->mode == fif::fif_mode::interpreting) {
9403 auto a = s.main_data_back(0);
9404 auto b = s.main_data_back(1);
9405 s.pop_main();
9406 s.set_main_data_back(0, uint64_t(b) >> a);
9409 s.pop_main();
9410 }
9411 return p + 2;
9412}
9413
9414inline int32_t* ident32(fif::state_stack& s, int32_t* p, fif::environment* e) {
9416 } else if(e->mode == fif::fif_mode::interpreting) {
9418 s.set_main_data_back(0, s.main_data_back(0) & 0x0FFFFFFFF);
9421 }
9422 return p + 2;
9423}
9424inline int32_t* ident16(fif::state_stack& s, int32_t* p, fif::environment* e) {
9426 } else if(e->mode == fif::fif_mode::interpreting) {
9428 s.set_main_data_back(0, s.main_data_back(0) & 0x0FFFF);
9431 }
9432 return p + 2;
9433}
9434inline int32_t* ident8(fif::state_stack& s, int32_t* p, fif::environment* e) {
9436 } else if(e->mode == fif::fif_mode::interpreting) {
9438 s.set_main_data_back(0, s.main_data_back(0) & 0x0FF);
9441 }
9442 return p + 2;
9443}
9444inline int32_t* idents32(fif::state_stack& s, int32_t* p, fif::environment* e) {
9446 } else if(e->mode == fif::fif_mode::interpreting) {
9448 s.set_main_data_back(0, int32_t(s.main_data_back(0) & 0x0FFFFFFFF));
9451 }
9452 return p + 2;
9453}
9454inline int32_t* idents16(fif::state_stack& s, int32_t* p, fif::environment* e) {
9456 } else if(e->mode == fif::fif_mode::interpreting) {
9458 s.set_main_data_back(0, int16_t(s.main_data_back(0) & 0x0FFFF));
9461 }
9462 return p + 2;
9463}
9464inline int32_t* idents8(fif::state_stack& s, int32_t* p, fif::environment* e) {
9466 } else if(e->mode == fif::fif_mode::interpreting) {
9468 s.set_main_data_back(0, int8_t(s.main_data_back(0) & 0x0FF));
9471 }
9472 return p + 2;
9473}
9474inline int32_t* ident1(fif::state_stack& s, int32_t* p, fif::environment* e) {
9476 } else if(e->mode == fif::fif_mode::interpreting) {
9478 s.set_main_data_back(0, s.main_data_back(0) & 0x01);
9481 }
9482 return p + 2;
9483}
9484
9486 add_precompiled(fif_env, ":", colon_definition, { });
9487 add_precompiled(fif_env, ":s", colon_specialization, { });
9488 add_precompiled(fif_env, "((", long_comment, { }, true);
9489 add_precompiled(fif_env, "--", line_comment, { }, true);
9490
9491 add_precompiled(fif_env, "+", iadd, { fif::fif_i32, fif::fif_i32, -1, fif::fif_i32 });
9492 add_precompiled(fif_env, "+", iadd, { fif::fif_u32, fif::fif_u32, -1, fif::fif_u32 });
9493 add_precompiled(fif_env, "+", iadd, { fif::fif_u64, fif::fif_u64, -1, fif::fif_u64 });
9494 add_precompiled(fif_env, "+", iadd, { fif::fif_i64, fif::fif_i64, -1, fif::fif_i64 });
9495 add_precompiled(fif_env, "+", iadd, { fif::fif_i16, fif::fif_i16, -1, fif::fif_i16 });
9496 add_precompiled(fif_env, "+", iadd, { fif::fif_u16, fif::fif_u16, -1, fif::fif_u16 });
9497 add_precompiled(fif_env, "+", iadd, { fif::fif_i8, fif::fif_i8, -1, fif::fif_i8 });
9498 add_precompiled(fif_env, "+", iadd, { fif::fif_u8, fif::fif_u8, -1, fif::fif_u8 });
9501
9502 add_precompiled(fif_env, "-", isub, { fif::fif_i32, fif::fif_i32, -1, fif::fif_i32 });
9503 add_precompiled(fif_env, "-", isub, { fif::fif_u32, fif::fif_u32, -1, fif::fif_u32 });
9504 add_precompiled(fif_env, "-", isub, { fif::fif_u64, fif::fif_u64, -1, fif::fif_u64 });
9505 add_precompiled(fif_env, "-", isub, { fif::fif_i64, fif::fif_i64, -1, fif::fif_i64 });
9506 add_precompiled(fif_env, "-", isub, { fif::fif_i16, fif::fif_i16, -1, fif::fif_i16 });
9507 add_precompiled(fif_env, "-", isub, { fif::fif_u16, fif::fif_u16, -1, fif::fif_u16 });
9508 add_precompiled(fif_env, "-", isub, { fif::fif_i8, fif::fif_i8, -1, fif::fif_i8 });
9509 add_precompiled(fif_env, "-", isub, { fif::fif_u8, fif::fif_u8, -1, fif::fif_u8 });
9512
9519 add_precompiled(fif_env, "/", sidiv, { fif::fif_i8, fif::fif_i8, -1, fif::fif_i8 });
9520 add_precompiled(fif_env, "/", uidiv, { fif::fif_u8, fif::fif_u8, -1, fif::fif_u8 });
9523
9524 add_precompiled(fif_env, "mod", simod, { fif::fif_i32, fif::fif_i32, -1, fif::fif_i32 });
9525 add_precompiled(fif_env, "mod", uimod, { fif::fif_u32, fif::fif_u32, -1, fif::fif_u32 });
9526 add_precompiled(fif_env, "mod", uimod, { fif::fif_u64, fif::fif_u64, -1, fif::fif_u64 });
9527 add_precompiled(fif_env, "mod", simod, { fif::fif_i64, fif::fif_i64, -1, fif::fif_i64 });
9528 add_precompiled(fif_env, "mod", simod, { fif::fif_i16, fif::fif_i16, -1, fif::fif_i16 });
9529 add_precompiled(fif_env, "mod", uimod, { fif::fif_u16, fif::fif_u16, -1, fif::fif_u16 });
9530 add_precompiled(fif_env, "mod", simod, { fif::fif_i8, fif::fif_i8, -1, fif::fif_i8 });
9531 add_precompiled(fif_env, "mod", uimod, { fif::fif_u8, fif::fif_u8, -1, fif::fif_u8 });
9532 add_precompiled(fif_env, "mod", f32_mod, { fif::fif_f32, fif::fif_f32, -1, fif::fif_f32 });
9533 add_precompiled(fif_env, "mod", f64_mod, { fif::fif_f64, fif::fif_f64, -1, fif::fif_f64 });
9534
9535 add_precompiled(fif_env, "*", imul, { fif::fif_i32, fif::fif_i32, -1, fif::fif_i32 });
9536 add_precompiled(fif_env, "*", imul, { fif::fif_u32, fif::fif_u32, -1, fif::fif_u32 });
9537 add_precompiled(fif_env, "*", imul, { fif::fif_u64, fif::fif_u64, -1, fif::fif_u64 });
9538 add_precompiled(fif_env, "*", imul, { fif::fif_i64, fif::fif_i64, -1, fif::fif_i64 });
9539 add_precompiled(fif_env, "*", imul, { fif::fif_i16, fif::fif_i16, -1, fif::fif_i16 });
9540 add_precompiled(fif_env, "*", imul, { fif::fif_u16, fif::fif_u16, -1, fif::fif_u16 });
9541 add_precompiled(fif_env, "*", imul, { fif::fif_i8, fif::fif_i8, -1, fif::fif_i8 });
9542 add_precompiled(fif_env, "*", imul, { fif::fif_u8, fif::fif_u8, -1, fif::fif_u8 });
9545
9546 add_precompiled(fif_env, "<", ilt, { fif::fif_i32, fif::fif_i32, -1, fif::fif_bool });
9547 add_precompiled(fif_env, "<=", ile, { fif::fif_i32, fif::fif_i32, -1, fif::fif_bool });
9548 add_precompiled(fif_env, ">", igt, { fif::fif_i32, fif::fif_i32, -1, fif::fif_bool });
9549 add_precompiled(fif_env, ">=", ige, { fif::fif_i32, fif::fif_i32, -1, fif::fif_bool });
9550 add_precompiled(fif_env, "=", ieq, { fif::fif_i32, fif::fif_i32, -1, fif::fif_bool });
9551 add_precompiled(fif_env, "<>", ine, { fif::fif_i32, fif::fif_i32, -1, fif::fif_bool });
9552 add_precompiled(fif_env, "<", ilt, { fif::fif_i64, fif::fif_i64, -1, fif::fif_bool });
9553 add_precompiled(fif_env, "<=", ile, { fif::fif_i64, fif::fif_i64, -1, fif::fif_bool });
9554 add_precompiled(fif_env, ">", igt, { fif::fif_i64, fif::fif_i64, -1, fif::fif_bool });
9555 add_precompiled(fif_env, ">=", ige, { fif::fif_i64, fif::fif_i64, -1, fif::fif_bool });
9556 add_precompiled(fif_env, "=", ieq, { fif::fif_i64, fif::fif_i64, -1, fif::fif_bool });
9557 add_precompiled(fif_env, "<>", ine, { fif::fif_i64, fif::fif_i64, -1, fif::fif_bool });
9558 add_precompiled(fif_env, "<", ilt, { fif::fif_i16, fif::fif_i16, -1, fif::fif_bool });
9559 add_precompiled(fif_env, "<=", ile, { fif::fif_i16, fif::fif_i16, -1, fif::fif_bool });
9560 add_precompiled(fif_env, ">", igt, { fif::fif_i16, fif::fif_i16, -1, fif::fif_bool });
9561 add_precompiled(fif_env, ">=", ige, { fif::fif_i16, fif::fif_i16, -1, fif::fif_bool });
9562 add_precompiled(fif_env, "=", ieq, { fif::fif_i16, fif::fif_i16, -1, fif::fif_bool });
9563 add_precompiled(fif_env, "<>", ine, { fif::fif_i16, fif::fif_i16, -1, fif::fif_bool });
9564 add_precompiled(fif_env, "<", ilt, { fif::fif_i8, fif::fif_i8, -1, fif::fif_bool });
9565 add_precompiled(fif_env, "<=", ile, { fif::fif_i8, fif::fif_i8, -1, fif::fif_bool });
9566 add_precompiled(fif_env, ">", igt, { fif::fif_i8, fif::fif_i8, -1, fif::fif_bool });
9567 add_precompiled(fif_env, ">=", ige, { fif::fif_i8, fif::fif_i8, -1, fif::fif_bool });
9568 add_precompiled(fif_env, "=", ieq, { fif::fif_i8, fif::fif_i8, -1, fif::fif_bool });
9569 add_precompiled(fif_env, "<>", ine, { fif::fif_i8, fif::fif_i8, -1, fif::fif_bool });
9570
9572 add_precompiled(fif_env, "<=", uile, { fif::fif_u32, fif::fif_u32, -1, fif::fif_bool });
9574 add_precompiled(fif_env, ">=", uige, { fif::fif_u32, fif::fif_u32, -1, fif::fif_bool });
9575 add_precompiled(fif_env, "=", ieq, { fif::fif_u32, fif::fif_u32, -1, fif::fif_bool });
9576 add_precompiled(fif_env, "<>", ine, { fif::fif_u32, fif::fif_u32, -1, fif::fif_bool });
9578 add_precompiled(fif_env, "<=", uile, { fif::fif_u64, fif::fif_u64, -1, fif::fif_bool });
9580 add_precompiled(fif_env, ">=", uige, { fif::fif_u64, fif::fif_u64, -1, fif::fif_bool });
9581 add_precompiled(fif_env, "=", ieq, { fif::fif_u64, fif::fif_u64, -1, fif::fif_bool });
9582 add_precompiled(fif_env, "<>", ine, { fif::fif_u64, fif::fif_u64, -1, fif::fif_bool });
9584 add_precompiled(fif_env, "<=", uile, { fif::fif_u16, fif::fif_u16, -1, fif::fif_bool });
9586 add_precompiled(fif_env, ">=", uige, { fif::fif_u16, fif::fif_u16, -1, fif::fif_bool });
9587 add_precompiled(fif_env, "=", ieq, { fif::fif_u16, fif::fif_u16, -1, fif::fif_bool });
9588 add_precompiled(fif_env, "<>", ine, { fif::fif_u16, fif::fif_u16, -1, fif::fif_bool });
9589 add_precompiled(fif_env, "<", uilt, { fif::fif_u8, fif::fif_u8, -1, fif::fif_bool });
9590 add_precompiled(fif_env, "<=", uile, { fif::fif_u8, fif::fif_u8, -1, fif::fif_bool });
9591 add_precompiled(fif_env, ">", uigt, { fif::fif_u8, fif::fif_u8, -1, fif::fif_bool });
9592 add_precompiled(fif_env, ">=", uige, { fif::fif_u8, fif::fif_u8, -1, fif::fif_bool });
9593 add_precompiled(fif_env, "=", ieq, { fif::fif_u8, fif::fif_u8, -1, fif::fif_bool });
9594 add_precompiled(fif_env, "<>", ine, { fif::fif_u8, fif::fif_u8, -1, fif::fif_bool });
9595
9597 add_precompiled(fif_env, "<=", f32le, { fif::fif_f32, fif::fif_f32, -1, fif::fif_bool });
9599 add_precompiled(fif_env, ">=", f32ge, { fif::fif_f32, fif::fif_f32, -1, fif::fif_bool });
9601 add_precompiled(fif_env, "<>", f32ne, { fif::fif_f32, fif::fif_f32, -1, fif::fif_bool });
9603 add_precompiled(fif_env, "<=", f64le, { fif::fif_f64, fif::fif_f64, -1, fif::fif_bool });
9605 add_precompiled(fif_env, ">=", f64ge, { fif::fif_f64, fif::fif_f64, -1, fif::fif_bool });
9607 add_precompiled(fif_env, "<>", f64ne, { fif::fif_f64, fif::fif_f64, -1, fif::fif_bool });
9608
9610 add_precompiled(fif_env, "<>", ine, { fif::fif_bool, fif::fif_bool, -1, fif::fif_bool });
9611
9612 add_precompiled(fif_env, ">i64", zext_i64, { fif::fif_u64, -1, fif::fif_i64 });
9613 add_precompiled(fif_env, ">i64", zext_i64, { fif::fif_u32, -1, fif::fif_i64 });
9614 add_precompiled(fif_env, ">i64", zext_i64, { fif::fif_u16, -1, fif::fif_i64 });
9615 add_precompiled(fif_env, ">i64", zext_i64, { fif::fif_u8, -1, fif::fif_i64 });
9616 add_precompiled(fif_env, ">i64", nop1, { fif::fif_i64, -1, fif::fif_i64 });
9617 add_precompiled(fif_env, ">i64", sext_i64, { fif::fif_i32, -1, fif::fif_i64 });
9618 add_precompiled(fif_env, ">i64", sext_i64, { fif::fif_i16, -1, fif::fif_i64 });
9619 add_precompiled(fif_env, ">i64", sext_i64, { fif::fif_i8, -1, fif::fif_i64 });
9620 add_precompiled(fif_env, ">i64", zext_i64, { fif::fif_bool, -1, fif::fif_i64 });
9621 add_precompiled(fif_env, ">i64", f32i64, { fif::fif_f32, -1, fif::fif_i64 });
9622 add_precompiled(fif_env, ">i64", f64i64, { fif::fif_f64, -1, fif::fif_i64 });
9623
9624 add_precompiled(fif_env, ">u64", nop1, { fif::fif_u64, -1, fif::fif_u64 });
9625 add_precompiled(fif_env, ">u64", zext_ui64, { fif::fif_u32, -1, fif::fif_u64 });
9626 add_precompiled(fif_env, ">u64", zext_ui64, { fif::fif_u16, -1, fif::fif_u64 });
9627 add_precompiled(fif_env, ">u64", zext_ui64, { fif::fif_u8, -1, fif::fif_u64 });
9628 add_precompiled(fif_env, ">u64", sext_ui64, { fif::fif_i64, -1, fif::fif_u64 });
9629 add_precompiled(fif_env, ">u64", sext_ui64, { fif::fif_i32, -1, fif::fif_u64 });
9630 add_precompiled(fif_env, ">u64", sext_ui64, { fif::fif_i16, -1, fif::fif_u64 });
9631 add_precompiled(fif_env, ">u64", sext_ui64, { fif::fif_i8, -1, fif::fif_u64 });
9632 add_precompiled(fif_env, ">u64", zext_ui64, { fif::fif_bool, -1, fif::fif_u64 });
9633 add_precompiled(fif_env, ">u64", f32ui64, { fif::fif_f32, -1, fif::fif_u64 });
9634 add_precompiled(fif_env, ">u64", f64ui64, { fif::fif_f64, -1, fif::fif_u64 });
9635
9636 add_precompiled(fif_env, ">i32", trunc_i32, { fif::fif_u64, -1, fif::fif_i32 });
9637 add_precompiled(fif_env, ">i32", zext_i32, { fif::fif_u32, -1, fif::fif_i32 });
9638 add_precompiled(fif_env, ">i32", zext_i32, { fif::fif_u16, -1, fif::fif_i32 });
9639 add_precompiled(fif_env, ">i32", zext_i32, { fif::fif_u8, -1, fif::fif_i32 });
9640 add_precompiled(fif_env, ">i32", trunc_i32, { fif::fif_i64, -1, fif::fif_i32 });
9641 add_precompiled(fif_env, ">i32", idents32, { fif::fif_i32, -1, fif::fif_i32 });
9642 add_precompiled(fif_env, ">i32", sext_i32, { fif::fif_i16, -1, fif::fif_i32 });
9643 add_precompiled(fif_env, ">i32", sext_i32, { fif::fif_i8, -1, fif::fif_i32 });
9644 add_precompiled(fif_env, ">i32", zext_i32, { fif::fif_bool, -1, fif::fif_i32 });
9645 add_precompiled(fif_env, ">i32", f32i32, { fif::fif_f32, -1, fif::fif_i32 });
9646 add_precompiled(fif_env, ">i32", f64i32, { fif::fif_f64, -1, fif::fif_i32 });
9647
9648 add_precompiled(fif_env, ">u32", trunc_ui32, { fif::fif_u64, -1, fif::fif_u32 });
9649 add_precompiled(fif_env, ">u32", ident32, { fif::fif_u32, -1, fif::fif_u32 });
9650 add_precompiled(fif_env, ">u32", zext_ui32, { fif::fif_u16, -1, fif::fif_u32 });
9651 add_precompiled(fif_env, ">u32", zext_ui32, { fif::fif_u8, -1, fif::fif_u32 });
9652 add_precompiled(fif_env, ">u32", trunc_ui32, { fif::fif_i64, -1, fif::fif_u32 });
9653 add_precompiled(fif_env, ">u32", sext_ui32, { fif::fif_i32, -1, fif::fif_u32 });
9654 add_precompiled(fif_env, ">u32", sext_ui32, { fif::fif_i16, -1, fif::fif_u32 });
9655 add_precompiled(fif_env, ">u32", sext_ui32, { fif::fif_i8, -1, fif::fif_u32 });
9656 add_precompiled(fif_env, ">u32", zext_ui32, { fif::fif_bool, -1, fif::fif_u32 });
9657 add_precompiled(fif_env, ">u32", f32ui32, { fif::fif_f32, -1, fif::fif_u32 });
9658 add_precompiled(fif_env, ">u32", f64ui32, { fif::fif_f64, -1, fif::fif_u32 });
9659
9660 add_precompiled(fif_env, ">i16", trunc_i16, { fif::fif_u64, -1, fif::fif_i16 });
9661 add_precompiled(fif_env, ">i16", trunc_i16, { fif::fif_u32, -1, fif::fif_i16 });
9662 add_precompiled(fif_env, ">i16", zext_i16, { fif::fif_u16, -1, fif::fif_i16 });
9663 add_precompiled(fif_env, ">i16", zext_i16, { fif::fif_u8, -1, fif::fif_i16 });
9664 add_precompiled(fif_env, ">i16", trunc_i16, { fif::fif_i64, -1, fif::fif_i16 });
9665 add_precompiled(fif_env, ">i16", trunc_i16, { fif::fif_i32, -1, fif::fif_i16 });
9666 add_precompiled(fif_env, ">i16", idents16, { fif::fif_i16, -1, fif::fif_i16 });
9667 add_precompiled(fif_env, ">i16", sext_i16, { fif::fif_i8, -1, fif::fif_i16 });
9668 add_precompiled(fif_env, ">i16", zext_i16, { fif::fif_bool, -1, fif::fif_i16 });
9669 add_precompiled(fif_env, ">i16", f32i16, { fif::fif_f32, -1, fif::fif_i16 });
9670 add_precompiled(fif_env, ">i16", f64i16, { fif::fif_f64, -1, fif::fif_i16 });
9671
9672 add_precompiled(fif_env, ">u16", trunc_ui16, { fif::fif_u64, -1, fif::fif_u16 });
9673 add_precompiled(fif_env, ">u16", trunc_ui16, { fif::fif_u32, -1, fif::fif_u16 });
9674 add_precompiled(fif_env, ">u16", ident16, { fif::fif_u16, -1, fif::fif_u16 });
9675 add_precompiled(fif_env, ">u16", zext_ui16, { fif::fif_u8, -1, fif::fif_u16 });
9676 add_precompiled(fif_env, ">u16", trunc_ui16, { fif::fif_i64, -1, fif::fif_u16 });
9677 add_precompiled(fif_env, ">u16", trunc_ui16, { fif::fif_i32, -1, fif::fif_u16 });
9678 add_precompiled(fif_env, ">u16", sext_ui16, { fif::fif_i16, -1, fif::fif_u16 });
9679 add_precompiled(fif_env, ">u16", sext_ui16, { fif::fif_i8, -1, fif::fif_u16 });
9680 add_precompiled(fif_env, ">u16", zext_ui16, { fif::fif_bool, -1, fif::fif_u16 });
9681 add_precompiled(fif_env, ">u16", f32ui16, { fif::fif_f32, -1, fif::fif_u16 });
9682 add_precompiled(fif_env, ">u16", f64ui16, { fif::fif_f64, -1, fif::fif_u16 });
9683
9684 add_precompiled(fif_env, ">i8", trunc_i8, { fif::fif_u64, -1, fif::fif_i8 });
9685 add_precompiled(fif_env, ">i8", trunc_i8, { fif::fif_u32, -1, fif::fif_i8 });
9686 add_precompiled(fif_env, ">i8", trunc_i8, { fif::fif_u16, -1, fif::fif_i8 });
9687 add_precompiled(fif_env, ">i8", zext_i8, { fif::fif_u8, -1, fif::fif_i8 });
9688 add_precompiled(fif_env, ">i8", trunc_i8, { fif::fif_i64, -1, fif::fif_i8 });
9689 add_precompiled(fif_env, ">i8", trunc_i8, { fif::fif_i32, -1, fif::fif_i8 });
9690 add_precompiled(fif_env, ">i8", trunc_i8, { fif::fif_i16, -1, fif::fif_i8 });
9691 add_precompiled(fif_env, ">i8", idents8, { fif::fif_i8, -1, fif::fif_i8 });
9692 add_precompiled(fif_env, ">i8", zext_i8, { fif::fif_bool, -1, fif::fif_i8 });
9693 add_precompiled(fif_env, ">i8", f32i8, { fif::fif_f32, -1, fif::fif_i8 });
9694 add_precompiled(fif_env, ">i8", f64i8, { fif::fif_f64, -1, fif::fif_i8 });
9695
9696 add_precompiled(fif_env, ">u8", trunc_ui8, { fif::fif_u64, -1, fif::fif_u8 });
9697 add_precompiled(fif_env, ">u8", trunc_ui8, { fif::fif_u32, -1, fif::fif_u8 });
9698 add_precompiled(fif_env, ">u8", trunc_ui8, { fif::fif_u16, -1, fif::fif_u8 });
9699 add_precompiled(fif_env, ">u8", ident8, { fif::fif_u8, -1, fif::fif_u8 });
9700 add_precompiled(fif_env, ">u8", trunc_ui8, { fif::fif_i64, -1, fif::fif_u8 });
9701 add_precompiled(fif_env, ">u8", trunc_ui8, { fif::fif_i32, -1, fif::fif_u8 });
9702 add_precompiled(fif_env, ">u8", trunc_ui8, { fif::fif_i16, -1, fif::fif_u8 });
9703 add_precompiled(fif_env, ">u8", sext_ui8, { fif::fif_i8, -1, fif::fif_u8 });
9704 add_precompiled(fif_env, ">u8", zext_ui8, { fif::fif_bool, -1, fif::fif_u8 });
9705 add_precompiled(fif_env, ">u8", f32ui8, { fif::fif_f32, -1, fif::fif_u8 });
9706 add_precompiled(fif_env, ">u8", f64ui8, { fif::fif_f64, -1, fif::fif_u8 });
9707
9708 add_precompiled(fif_env, ">f32", uif32, { fif::fif_u64, -1, fif::fif_f32 });
9709 add_precompiled(fif_env, ">f32", uif32, { fif::fif_u32, -1, fif::fif_f32 });
9710 add_precompiled(fif_env, ">f32", uif32, { fif::fif_u16, -1, fif::fif_f32 });
9711 add_precompiled(fif_env, ">f32", uif32, { fif::fif_u8, -1, fif::fif_f32 });
9712 add_precompiled(fif_env, ">f32", sif32, { fif::fif_i64, -1, fif::fif_f32 });
9713 add_precompiled(fif_env, ">f32", sif32, { fif::fif_i32, -1, fif::fif_f32 });
9714 add_precompiled(fif_env, ">f32", sif32, { fif::fif_i16, -1, fif::fif_f32 });
9715 add_precompiled(fif_env, ">f32", sif32, { fif::fif_i8, -1, fif::fif_f32 });
9716 add_precompiled(fif_env, ">f32", nop1, { fif::fif_f32, -1, fif::fif_f32 });
9717 add_precompiled(fif_env, ">f32", ftrunc, { fif::fif_f64, -1, fif::fif_f32 });
9718
9719 add_precompiled(fif_env, ">f64", uif64, { fif::fif_u64, -1, fif::fif_f64 });
9720 add_precompiled(fif_env, ">f64", uif64, { fif::fif_u32, -1, fif::fif_f64 });
9721 add_precompiled(fif_env, ">f64", uif64, { fif::fif_u16, -1, fif::fif_f64 });
9722 add_precompiled(fif_env, ">f64", uif64, { fif::fif_u8, -1, fif::fif_f64 });
9723 add_precompiled(fif_env, ">f64", sif64, { fif::fif_i64, -1, fif::fif_f64 });
9724 add_precompiled(fif_env, ">f64", sif64, { fif::fif_i32, -1, fif::fif_f64 });
9725 add_precompiled(fif_env, ">f64", sif64, { fif::fif_i16, -1, fif::fif_f64 });
9726 add_precompiled(fif_env, ">f64", sif64, { fif::fif_i8, -1, fif::fif_f64 });
9727 add_precompiled(fif_env, ">f64", fext, { fif::fif_f32, -1, fif::fif_f64 });
9728 add_precompiled(fif_env, ">f64", nop1, { fif::fif_f64, -1, fif::fif_f64 });
9729
9730 add_precompiled(fif_env, ">bool", trunc_i1, { fif::fif_u64, -1, fif::fif_bool });
9731 add_precompiled(fif_env, ">bool", trunc_i1, { fif::fif_u32, -1, fif::fif_bool });
9732 add_precompiled(fif_env, ">bool", trunc_i1, { fif::fif_u16, -1, fif::fif_bool });
9733 add_precompiled(fif_env, ">bool", trunc_i1, { fif::fif_u8, -1, fif::fif_bool });
9734 add_precompiled(fif_env, ">bool", trunc_i1, { fif::fif_i64, -1, fif::fif_bool });
9735 add_precompiled(fif_env, ">bool", trunc_i1, { fif::fif_i32, -1, fif::fif_bool });
9736 add_precompiled(fif_env, ">bool", trunc_i1, { fif::fif_i16, -1, fif::fif_bool });
9737 add_precompiled(fif_env, ">bool", trunc_i1, { fif::fif_i8, -1, fif::fif_bool });
9738 add_precompiled(fif_env, ">bool", ident1, { fif::fif_bool, -1, fif::fif_bool });
9739
9740 add_precompiled(fif_env, "and", bit_and, { fif::fif_u64, fif_u64, -1, fif::fif_u64 });
9741 add_precompiled(fif_env, "and", bit_and, { fif::fif_u32, fif_u32, -1, fif::fif_u32 });
9742 add_precompiled(fif_env, "and", bit_and, { fif::fif_u16, fif_u16, -1, fif::fif_u16 });
9743 add_precompiled(fif_env, "and", bit_and, { fif::fif_u8, fif_u8, -1, fif::fif_u8 });
9744 add_precompiled(fif_env, "and", bit_and, { fif::fif_i64, fif_i64, -1, fif::fif_i64 });
9745 add_precompiled(fif_env, "and", bit_and, { fif::fif_i32, fif_i32, -1, fif::fif_i32 });
9746 add_precompiled(fif_env, "and", bit_and, { fif::fif_i16, fif_i16, -1, fif::fif_i16 });
9747 add_precompiled(fif_env, "and", bit_and, { fif::fif_i8, fif_i8, -1, fif::fif_i8 });
9748 add_precompiled(fif_env, "and", bit_and, { fif::fif_bool, fif_bool, -1, fif::fif_bool });
9749
9750 add_precompiled(fif_env, "or", bit_or, { fif::fif_u64, fif_u64, -1, fif::fif_u64 });
9751 add_precompiled(fif_env, "or", bit_or, { fif::fif_u32, fif_u32, -1, fif::fif_u32 });
9752 add_precompiled(fif_env, "or", bit_or, { fif::fif_u16, fif_u16, -1, fif::fif_u16 });
9753 add_precompiled(fif_env, "or", bit_or, { fif::fif_u8, fif_u8, -1, fif::fif_u8 });
9754 add_precompiled(fif_env, "or", bit_or, { fif::fif_i64, fif_i64, -1, fif::fif_i64 });
9755 add_precompiled(fif_env, "or", bit_or, { fif::fif_i32, fif_i32, -1, fif::fif_i32 });
9756 add_precompiled(fif_env, "or", bit_or, { fif::fif_i16, fif_i16, -1, fif::fif_i16 });
9757 add_precompiled(fif_env, "or", bit_or, { fif::fif_i8, fif_i8, -1, fif::fif_i8 });
9758 add_precompiled(fif_env, "or", bit_or, { fif::fif_bool, fif_bool, -1, fif::fif_bool });
9759
9760 add_precompiled(fif_env, "xor", bit_xor, { fif::fif_u64, fif_u64, -1, fif::fif_u64 });
9761 add_precompiled(fif_env, "xor", bit_xor, { fif::fif_u32, fif_u32, -1, fif::fif_u32 });
9762 add_precompiled(fif_env, "xor", bit_xor, { fif::fif_u16, fif_u16, -1, fif::fif_u16 });
9763 add_precompiled(fif_env, "xor", bit_xor, { fif::fif_u8, fif_u8, -1, fif::fif_u8 });
9764 add_precompiled(fif_env, "xor", bit_xor, { fif::fif_i64, fif_i64, -1, fif::fif_i64 });
9765 add_precompiled(fif_env, "xor", bit_xor, { fif::fif_i32, fif_i32, -1, fif::fif_i32 });
9766 add_precompiled(fif_env, "xor", bit_xor, { fif::fif_i16, fif_i16, -1, fif::fif_i16 });
9767 add_precompiled(fif_env, "xor", bit_xor, { fif::fif_i8, fif_i8, -1, fif::fif_i8 });
9768 add_precompiled(fif_env, "xor", bit_xor, { fif::fif_bool, fif_bool, -1, fif::fif_bool });
9769
9770 add_precompiled(fif_env, "not", bit_not, { fif::fif_u64, -1, fif::fif_u64 });
9771 add_precompiled(fif_env, "not", bit_not, { fif::fif_u32, -1, fif::fif_u32 });
9772 add_precompiled(fif_env, "not", bit_not, { fif::fif_u16, -1, fif::fif_u16 });
9773 add_precompiled(fif_env, "not", bit_not, { fif::fif_u8, -1, fif::fif_u8 });
9774 add_precompiled(fif_env, "not", bit_not, { fif::fif_i64, -1, fif::fif_i64 });
9775 add_precompiled(fif_env, "not", bit_not, { fif::fif_i32, -1, fif::fif_i32 });
9776 add_precompiled(fif_env, "not", bit_not, { fif::fif_i16, -1, fif::fif_i16 });
9777 add_precompiled(fif_env, "not", bit_not, { fif::fif_i8, -1, fif::fif_i8 });
9778 add_precompiled(fif_env, "not", bit_not, { fif::fif_bool, -1, fif::fif_bool });
9779
9780 add_precompiled(fif_env, "shl", bit_shl, { fif::fif_u64, fif_i32, -1, fif::fif_u64 });
9781 add_precompiled(fif_env, "shl", bit_shl, { fif::fif_i64, fif_i32, -1, fif::fif_i64 });
9782 add_precompiled(fif_env, "shl", bit_shl, { fif::fif_u32, fif_i32, -1, fif::fif_u32 });
9783 add_precompiled(fif_env, "shl", bit_shl, { fif::fif_i32, fif_i32, -1, fif::fif_i32 });
9784 add_precompiled(fif_env, "shl", bit_shl, { fif::fif_u16, fif_i32, -1, fif::fif_u16 });
9785 add_precompiled(fif_env, "shl", bit_shl, { fif::fif_i16, fif_i32, -1, fif::fif_i16 });
9786 add_precompiled(fif_env, "shl", bit_shl, { fif::fif_u8, fif_i32, -1, fif::fif_u8 });
9787 add_precompiled(fif_env, "shl", bit_shl, { fif::fif_i8, fif_i32, -1, fif::fif_i8 });
9788
9789 add_precompiled(fif_env, "shr", bit_lshr, { fif::fif_u64, fif_i32, -1, fif::fif_u64 });
9790 add_precompiled(fif_env, "shr", bit_ashr, { fif::fif_i64, fif_i32, -1, fif::fif_i64 });
9791 add_precompiled(fif_env, "shr", bit_lshr, { fif::fif_u32, fif_i32, -1, fif::fif_u32 });
9792 add_precompiled(fif_env, "shr", bit_ashr, { fif::fif_i32, fif_i32, -1, fif::fif_i32 });
9793 add_precompiled(fif_env, "shr", bit_lshr, { fif::fif_u16, fif_i32, -1, fif::fif_u16 });
9794 add_precompiled(fif_env, "shr", bit_ashr, { fif::fif_i16, fif_i32, -1, fif::fif_i16 });
9795 add_precompiled(fif_env, "shr", bit_lshr, { fif::fif_u8, fif_i32, -1, fif::fif_u8 });
9796 add_precompiled(fif_env, "shr", bit_ashr, { fif::fif_i8, fif_i32, -1, fif::fif_i8 });
9797
9798 add_precompiled(fif_env, "init", init, { -2, -1, -2 });
9799 add_precompiled(fif_env, "dup", dup, { -2, -1, -2, -2 });
9800 add_precompiled(fif_env, "copy", copy, { -2, -1, -2, -2 });
9801 add_precompiled(fif_env, "drop", drop, { -2 });
9802 add_precompiled(fif_env, "swap", fif_swap, { -2, -3, -1, -2, -3 });
9803 add_precompiled(fif_env, "if", fif_if, { }, true);
9804 add_precompiled(fif_env, "else", fif_else, { }, true);
9805 add_precompiled(fif_env, "then", fif_then, { }, true);
9806 add_precompiled(fif_env, "end-if", fif_then, { }, true);
9807 add_precompiled(fif_env, "while", fif_while, { }, true);
9808 add_precompiled(fif_env, "loop", fif_loop, { }, true);
9809 add_precompiled(fif_env, "end-while", fif_end_while, { }, true);
9810 add_precompiled(fif_env, "do", fif_do, { }, true);
9811 add_precompiled(fif_env, "until", fif_until, { }, true);
9812 add_precompiled(fif_env, "end-do", fif_end_do, { fif::fif_bool }, true);
9813 add_precompiled(fif_env, ">r", to_r, { -2, -1, -1, -1, -2 });
9814 add_precompiled(fif_env, "r>", from_r, { -1, -2, -1, -2 });
9815 add_precompiled(fif_env, "r@", r_at, { -1, -2, -1, -2, -1, -2 });
9816 add_precompiled(fif_env, "immediate", make_immediate, { });
9817 add_precompiled(fif_env, "[", open_bracket, { }, true);
9818 add_precompiled(fif_env, "]", close_bracket, { }, true);
9819 add_precompiled(fif_env, "ptr-cast", pointer_cast, { fif_opaque_ptr }, true);
9820 add_precompiled(fif_env, "ptr-cast", pointer_cast, { fif_ptr, std::numeric_limits<int32_t>::max(), -2, -1 }, true);
9821 add_precompiled(fif_env, "heap-alloc", impl_heap_allot, { -2, -1, fif_ptr, std::numeric_limits<int32_t>::max(), -2, -1 });
9822 add_precompiled(fif_env, "heap-free", impl_heap_free, { fif_ptr, std::numeric_limits<int32_t>::max(), -2, -1, -1, -2 });
9823 add_precompiled(fif_env, "@", impl_load, { fif_ptr, std::numeric_limits<int32_t>::max(), -2, -1, -1, -2 });
9824 add_precompiled(fif_env, "@@", impl_load_deallocated, { fif_ptr, std::numeric_limits<int32_t>::max(), -2, -1, -1, -2 });
9825 add_precompiled(fif_env, "!", impl_store, { fif_ptr, std::numeric_limits<int32_t>::max(), -2, -1, -2 });
9826 add_precompiled(fif_env, "!!", impl_uninit_store, { fif_ptr, std::numeric_limits<int32_t>::max(), -2, -1, -2 });
9827 add_precompiled(fif_env, "sizeof", impl_sizeof, { -1, fif_i32 }, true);
9828 add_precompiled(fif_env, "buf-free", free_buffer, { fif_opaque_ptr });
9829 add_precompiled(fif_env, "buf-alloc", allocate_buffer, { fif_i32, -1, fif_opaque_ptr });
9830 add_precompiled(fif_env, "buf-alloc", allocate_buffer, { fif_i64, -1, fif_opaque_ptr });
9831 add_precompiled(fif_env, "buf-alloc", allocate_buffer, { fif_i16, -1, fif_opaque_ptr });
9832 add_precompiled(fif_env, "buf-alloc", allocate_buffer, { fif_i8, -1, fif_opaque_ptr });
9837 add_precompiled(fif_env, "buf-add", impl_index, { fif_opaque_ptr, fif_i32, -1, fif_opaque_ptr });
9838 add_precompiled(fif_env, "buf-add", impl_index, { fif_opaque_ptr, fif_i64, -1, fif_opaque_ptr });
9839 add_precompiled(fif_env, "buf-add", impl_index, { fif_opaque_ptr, fif_i16, -1, fif_opaque_ptr });
9840 add_precompiled(fif_env, "buf-add", impl_index, { fif_opaque_ptr, fif_i8, -1, fif_opaque_ptr });
9841 add_precompiled(fif_env, "let", create_let, { -2 }, true);
9842 add_precompiled(fif_env, "var", create_var, { -2 }, true);
9843 add_precompiled(fif_env, "global", create_global_impl, { fif_type });
9844 add_precompiled(fif_env, "forth.insert", forth_insert, { }, true);
9845 add_precompiled(fif_env, "forth.extract", forth_extract, { }, true);
9846 add_precompiled(fif_env, "forth.extract-copy", forth_extract_copy, { }, true);
9847 add_precompiled(fif_env, "forth.gep", forth_gep, { }, true);
9848 add_precompiled(fif_env, "struct-map2", forth_struct_map_two, { }, true);
9849 add_precompiled(fif_env, "struct-map1", forth_struct_map_one, { }, true);
9850 add_precompiled(fif_env, "struct-map0", forth_struct_map_zero, { }, true);
9851 add_precompiled(fif_env, "make", do_make, { }, true);
9852 add_precompiled(fif_env, ":struct", struct_definition, { });
9853 add_precompiled(fif_env, ":export", export_definition, { });
9854 add_precompiled(fif_env, "use-base", do_use_base, { }, true);
9855 add_precompiled(fif_env, "select", f_select, { fif_bool, -2, -2, -1, -2 });
9856
9857 auto preinterpreted =
9858 ": over >r dup r> swap ; "
9859 ": nip >r drop r> ; "
9860 ": tuck swap over ; "
9861 ": 2dup >r dup r> dup >r swap r> ; "
9862 ": buf-resize " // ptr old new -> ptr
9863 " buf-alloc swap >r >r dup r> r> buf-copy swap buf-free "
9864 " ; "
9865 ":struct dy-array-block ptr(nil) memory i32 size i32 capacity i32 refcount ; "
9866 ":struct dy-array ptr(dy-array-block) ptr $ 1 ; "
9867 ":s init dy-array($0) s: " // array -> array
9868 " sizeof dy-array-block buf-alloc ptr-cast ptr(dy-array-block) swap .ptr! "
9869 " ; "
9870 ":s dup dy-array($0) s: " // array -> array, array
9871 " use-base dup .ptr@ " // original copy ptr-to-block
9872 " .refcount dup @ 1 + swap ! " // increase ref count
9873 " ; "
9874 ":s drop dy-array($0) s: .ptr@ " // array ->
9875 " .refcount dup @ -1 + " // decrement refcount
9876 " dup 0 >= if "
9877 " swap ! " // store refcount back into pointer
9878 " else "
9879 " drop drop " // drop pointer to refcount and -1
9880 " .ptr@ dup .size let sz .memory let mem " // grab values
9881 " while "
9882 " sz @ 0 > "
9883 " loop "
9884 " sz @ -1 + sz ! " // reduce sz
9885 " sz @ sizeof $0 * mem @ buf-add ptr-cast ptr($0) @@ " // copy last value, dupless
9886 " drop " // run its destructor
9887 " end-while "
9888 " mem @ buf-free " // free managed buffer
9889 " .ptr@ ptr-cast ptr(nil) buf-free " // destroy control block
9890 " end-if "
9891 " use-base drop "
9892 " ; "
9893 ":s push dy-array($0) $0 s: " // array , value -> array
9894 " let val " // store value to be saved in val
9895 " .ptr@ "
9896 " dup dup .size let sz .capacity let cap .memory let mem" // destructure
9897 " sz @ sizeof $0 * cap @ >= if " // size >= capacity ?
9898 " mem @ " // put old buffer on stack
9899 " cap @ sizeof $0 * " // old size
9900 " cap @ 1 + 2 * sizeof $0 * " // new size
9901 " dup cap ! " // copy new size to capacity
9902 " buf-resize "
9903 " mem ! "
9904 " end-if "
9905 " sz @ sizeof $0 * mem @ buf-add ptr-cast ptr($0) val swap !! " // move value into last position
9906 " sz @ 1 + sz ! " // +1 to stored size
9907 " ; "
9908 ":s pop dy-array($0) s: " // array -> array , value
9909 " .ptr@ " // ptr to control block on stack
9910 " dup .size let sz .memory let mem" // destructure
9911 " sz @ 0 > if "
9912 " sz @ -1 + sz ! " // reduce sz
9913 " sz @ sizeof $0 * mem @ buf-add ptr-cast ptr($0) @@ " // copy last value, dupless
9914 " else "
9915 " make $0 " // nothing left, make new value
9916 " end-if "
9917 " ; "
9918 ":s empty? dy-array($0) s: " // array -> array, value
9919 " .ptr@ .size @ <= 0 "
9920 " ; "
9921 ":s index-into dy-array($0) i32 s:" // array, int -> array, ptr(0)
9922 " let index .ptr@ .memory @ sizeof $0 index * swap buf-add ptr-cast ptr($0) "
9923 " ; "
9924 ":s size dy-array($0) s:" // array -> array, int
9925 " .ptr@ .size @ "
9926 " ; "
9927 ;
9928
9929 fif::interpreter_stack values{ };
9930 fif::run_fif_interpreter(fif_env, preinterpreted, values);
9931
9932}
9933
9934}
var_data * get_global_var(std::string const &name)
Definition: fif.hpp:817
let_data * get_global_let(std::string const &name)
Definition: fif.hpp:839
compiler_globals_layer(opaque_compiler_data *p, environment &env)
Definition: fif.hpp:810
ankerl::unordered_dense::map< std::string, std::unique_ptr< let_data > > global_lets
Definition: fif.hpp:808
var_data * create_global_var(std::string const &name, int32_t type)
Definition: fif.hpp:823
virtual control_structure get_type() override
Definition: fif.hpp:813
ankerl::unordered_dense::map< std::string, std::unique_ptr< var_data > > global_vars
Definition: fif.hpp:807
environment & env
Definition: fif.hpp:809
let_data * create_global_let(std::string const &name, int32_t type, int64_t data, LLVMValueRef expression)
Definition: fif.hpp:845
std::unique_ptr< opaque_compiler_data > data
Definition: fif.hpp:699
LLVMBasicBlockRef true_block
Definition: fif.hpp:3242
conditional_scope(opaque_compiler_data *p, environment &e, state_stack &entry_state)
Definition: fif.hpp:3251
size_t bytecode_second_branch_point
Definition: fif.hpp:3249
std::unique_ptr< state_stack > first_branch_state
Definition: fif.hpp:3239
size_t bytecode_first_branch_point
Definition: fif.hpp:3248
bool typechecking_failed_on_first_branch
Definition: fif.hpp:3246
LLVMBasicBlockRef parent_block
Definition: fif.hpp:3241
std::unique_ptr< state_stack > iworking_state
Definition: fif.hpp:3238
virtual control_structure get_type() override
Definition: fif.hpp:3361
LLVMBasicBlockRef false_block
Definition: fif.hpp:3243
virtual state_stack * working_state() override
Definition: fif.hpp:3364
bool interpreter_skipped_second_branch
Definition: fif.hpp:3245
void commit_first_branch(environment &)
Definition: fif.hpp:3303
virtual void set_working_state(std::unique_ptr< state_stack > p) override
Definition: fif.hpp:3367
LLVMValueRef branch_condition
Definition: fif.hpp:3240
virtual bool finish(environment &) override
Definition: fif.hpp:3370
std::unique_ptr< state_stack > initial_state
Definition: fif.hpp:3237
bool interpreter_skipped_first_branch
Definition: fif.hpp:3244
bool initial_typechecking_failed
Definition: fif.hpp:3247
std::vector< word > word_array
Definition: fif.hpp:506
std::vector< int32_t > all_compiled
Definition: fif.hpp:509
ankerl::unordered_dense::map< std::string, int32_t > words
Definition: fif.hpp:504
std::vector< word_types > all_instances
Definition: fif.hpp:508
ankerl::unordered_dense::map< std::string, int32_t > types
Definition: fif.hpp:505
std::vector< type > type_array
Definition: fif.hpp:507
std::vector< int32_t > all_stack_types
Definition: fif.hpp:510
virtual control_structure get_type() override
Definition: fif.hpp:3975
bool initial_typechecking_failed
Definition: fif.hpp:3938
virtual state_stack * working_state() override
Definition: fif.hpp:3978
std::vector< LLVMValueRef > phinodes
Definition: fif.hpp:3942
virtual void set_working_state(std::unique_ptr< state_stack > p) override
Definition: fif.hpp:3981
std::unique_ptr< state_stack > initial_state
Definition: fif.hpp:3931
size_t end_of_loop_branch
Definition: fif.hpp:3936
std::unique_ptr< state_stack > iworking_state
Definition: fif.hpp:3932
size_t loop_entry_point
Definition: fif.hpp:3935
do_loop_scope(opaque_compiler_data *p, environment &e, state_stack &entry_state)
Definition: fif.hpp:3944
void at_until(environment &)
Definition: fif.hpp:3984
LLVMBasicBlockRef pre_block
Definition: fif.hpp:3940
virtual bool finish(environment &) override
Definition: fif.hpp:3987
std::string_view entry_source
Definition: fif.hpp:3934
LLVMBasicBlockRef body_block
Definition: fif.hpp:3941
std::vector< std::unique_ptr< opaque_compiler_data > > compiler_stack
Definition: fif.hpp:764
std::vector< LLVMValueRef > exported_functions
Definition: fif.hpp:747
std::function< void(std::string_view)> report_error
Definition: fif.hpp:768
std::vector< std::string_view > source_stack
Definition: fif.hpp:765
std::string_view get_string_constant(std::string_view data)
Definition: fif.hpp:792
fif_mode mode
Definition: fif.hpp:767
dictionary dict
Definition: fif.hpp:762
ankerl::unordered_dense::set< std::unique_ptr< char[]>, indirect_string_hash, indirect_string_eq > string_constants
Definition: fif.hpp:746
std::vector< import_item > imported_functions
Definition: fif.hpp:748
virtual std::vector< int32_t > * type_substitutions() override
Definition: fif.hpp:2743
virtual bool finish(environment &) override
Definition: fif.hpp:2773
int32_t for_instance
Definition: fif.hpp:2691
std::vector< int32_t > compiled_bytes
Definition: fif.hpp:2686
std::unique_ptr< state_stack > iworking_state
Definition: fif.hpp:2685
virtual LLVMBasicBlockRef * llvm_block() override
Definition: fif.hpp:2752
function_scope(opaque_compiler_data *p, environment &e, state_stack &entry_state, int32_t for_word, int32_t for_instance)
Definition: fif.hpp:2694
int32_t for_word
Definition: fif.hpp:2690
virtual state_stack * working_state() override
Definition: fif.hpp:2767
virtual std::vector< int32_t > * bytecode_compilation_progress() override
Definition: fif.hpp:2761
LLVMBasicBlockRef current_block
Definition: fif.hpp:2689
virtual int32_t instance_id() override
Definition: fif.hpp:2758
virtual int32_t word_id() override
Definition: fif.hpp:2755
virtual void set_working_state(std::unique_ptr< state_stack > p) override
Definition: fif.hpp:2770
virtual ankerl::unordered_dense::map< uint64_t, typecheck_3_record > * typecheck_record() override
Definition: fif.hpp:2764
virtual LLVMValueRef llvm_function() override
Definition: fif.hpp:2749
virtual control_structure get_type() override
Definition: fif.hpp:2746
std::vector< int32_t > type_subs
Definition: fif.hpp:2687
std::unique_ptr< state_stack > initial_state
Definition: fif.hpp:2684
LLVMValueRef llvm_fn
Definition: fif.hpp:2688
virtual int64_t main_data_back(size_t index) const override
Definition: fif.hpp:933
virtual void set_return_ex(size_t index, LLVMValueRef value) override
Definition: fif.hpp:956
virtual void set_return_ex_back(size_t index, LLVMValueRef value) override
Definition: fif.hpp:970
virtual void pop_main() override
Definition: fif.hpp:894
virtual void set_main_data(size_t index, int64_t value) override
Definition: fif.hpp:945
std::vector< int64_t > return_datas
Definition: fif.hpp:890
virtual void resize(size_t main_sz, size_t return_sz) override
Definition: fif.hpp:912
virtual void set_return_data(size_t index, int64_t value) override
Definition: fif.hpp:949
virtual void pop_return() override
Definition: fif.hpp:903
virtual LLVMValueRef main_ex(size_t index) const override
Definition: fif.hpp:927
virtual void copy_into(state_stack const &other) override
Definition: fif.hpp:992
std::vector< int64_t > main_datas
Definition: fif.hpp:889
virtual void push_back_main(int32_t type, int64_t data, LLVMValueRef expr) override
Definition: fif.hpp:1003
virtual LLVMValueRef main_ex_back(size_t index) const override
Definition: fif.hpp:939
virtual void set_main_ex_back(size_t index, LLVMValueRef value) override
Definition: fif.hpp:967
virtual void set_main_data_back(size_t index, int64_t value) override
Definition: fif.hpp:959
virtual LLVMValueRef return_ex_back(size_t index) const override
Definition: fif.hpp:942
virtual stack_type get_type() const override
Definition: fif.hpp:973
virtual void push_back_return(int32_t type, int64_t data, LLVMValueRef expr) override
Definition: fif.hpp:1007
virtual int64_t return_data_back(size_t index) const override
Definition: fif.hpp:936
virtual LLVMValueRef return_ex(size_t index) const override
Definition: fif.hpp:930
virtual void set_return_data_back(size_t index, int64_t value) override
Definition: fif.hpp:963
virtual void move_into(state_stack &&other) override
Definition: fif.hpp:976
virtual std::unique_ptr< state_stack > copy() const override
Definition: fif.hpp:1011
virtual void set_main_ex(size_t index, LLVMValueRef value) override
Definition: fif.hpp:953
virtual int64_t return_data(size_t index) const override
Definition: fif.hpp:924
virtual int64_t main_data(size_t index) const override
Definition: fif.hpp:921
virtual int64_t return_data_back(size_t index) const override
Definition: fif.hpp:220
virtual void resize(size_t main_sz, size_t return_sz) override
Definition: fif.hpp:197
virtual void set_main_ex_back(size_t index, LLVMValueRef value) override
Definition: fif.hpp:249
std::vector< LLVMValueRef > main_exs
Definition: fif.hpp:180
virtual std::unique_ptr< state_stack > copy() const override
Definition: fif.hpp:292
virtual void pop_return() override
Definition: fif.hpp:190
virtual void push_back_return(int32_t type, int64_t data, LLVMValueRef expr) override
Definition: fif.hpp:288
virtual LLVMValueRef return_ex_back(size_t index) const override
Definition: fif.hpp:226
virtual stack_type get_type() const override
Definition: fif.hpp:257
virtual void set_return_ex_back(size_t index, LLVMValueRef value) override
Definition: fif.hpp:253
virtual void move_into(state_stack &&other) override
Definition: fif.hpp:260
virtual LLVMValueRef main_ex_back(size_t index) const override
Definition: fif.hpp:223
virtual LLVMValueRef return_ex(size_t index) const override
Definition: fif.hpp:214
virtual void copy_into(state_stack const &other) override
Definition: fif.hpp:272
std::vector< LLVMValueRef > return_exs
Definition: fif.hpp:181
virtual int64_t main_data(size_t index) const override
Definition: fif.hpp:205
virtual void set_return_ex(size_t index, LLVMValueRef value) override
Definition: fif.hpp:239
virtual void push_back_main(int32_t type, int64_t data, LLVMValueRef expr) override
Definition: fif.hpp:284
virtual void set_return_data(size_t index, int64_t value) override
Definition: fif.hpp:232
virtual void set_main_ex(size_t index, LLVMValueRef value) override
Definition: fif.hpp:235
virtual int64_t main_data_back(size_t index) const override
Definition: fif.hpp:217
virtual int64_t return_data(size_t index) const override
Definition: fif.hpp:208
virtual void set_main_data_back(size_t index, int64_t value) override
Definition: fif.hpp:243
virtual LLVMValueRef main_ex(size_t index) const override
Definition: fif.hpp:211
virtual void pop_main() override
Definition: fif.hpp:183
virtual void set_main_data(size_t index, int64_t value) override
Definition: fif.hpp:229
virtual void set_return_data_back(size_t index, int64_t value) override
Definition: fif.hpp:246
virtual var_data * create_var(std::string const &name, int32_t type) override
Definition: fif.hpp:2619
ankerl::unordered_dense::map< std::string, std::unique_ptr< var_data > > vars
Definition: fif.hpp:2605
virtual let_data * get_let(std::string const &name) override
Definition: fif.hpp:2635
virtual let_data * create_let(std::string const &name, int32_t type, int64_t data, LLVMValueRef expression) override
Definition: fif.hpp:2641
ankerl::unordered_dense::map< std::string, std::unique_ptr< let_data > > lets
Definition: fif.hpp:2606
environment & env
Definition: fif.hpp:2607
virtual var_data * get_var(std::string const &name) override
Definition: fif.hpp:2613
const bool llvm_mode
Definition: fif.hpp:2608
locals_holder(opaque_compiler_data *p, environment &env)
Definition: fif.hpp:2610
void release_locals()
Definition: fif.hpp:2658
fif_mode running_mode
Definition: fif.hpp:2957
virtual bool finish(environment &env) override
Definition: fif.hpp:3007
virtual var_data * get_var(std::string const &name) override
Definition: fif.hpp:2991
virtual ankerl::unordered_dense::map< uint64_t, typecheck_3_record > * typecheck_record() override
Definition: fif.hpp:2985
opaque_compiler_data * interpreted_link
Definition: fif.hpp:2955
virtual state_stack * working_state() override
Definition: fif.hpp:2988
virtual void set_working_state(std::unique_ptr< state_stack > p) override
Definition: fif.hpp:3003
mode_switch_scope(opaque_compiler_data *p, environment &env, fif_mode running_mode)
Definition: fif.hpp:2959
virtual var_data * create_var(std::string const &name, int32_t type) override
Definition: fif.hpp:2994
virtual control_structure get_type() override
Definition: fif.hpp:2982
virtual let_data * create_let(std::string const &name, int32_t type, int64_t data, LLVMValueRef expression) override
Definition: fif.hpp:3000
fif_mode entry_mode
Definition: fif.hpp:2956
virtual let_data * get_let(std::string const &name) override
Definition: fif.hpp:2997
opaque_compiler_data(opaque_compiler_data *parent)
Definition: fif.hpp:645
virtual LLVMBasicBlockRef * llvm_block()
Definition: fif.hpp:654
virtual state_stack * working_state()
Definition: fif.hpp:669
virtual control_structure get_type()
Definition: fif.hpp:648
virtual void set_working_state(std::unique_ptr< state_stack > p)
Definition: fif.hpp:672
virtual std::vector< int32_t > * bytecode_compilation_progress()
Definition: fif.hpp:663
virtual ankerl::unordered_dense::map< uint64_t, typecheck_3_record > * typecheck_record()
Definition: fif.hpp:666
virtual int32_t word_id()
Definition: fif.hpp:657
virtual let_data * create_let(std::string const &name, int32_t type, int64_t data, LLVMValueRef expression)
Definition: fif.hpp:688
virtual let_data * get_let(std::string const &name)
Definition: fif.hpp:682
virtual bool finish(environment &env)
Definition: fif.hpp:676
virtual int32_t instance_id()
Definition: fif.hpp:660
virtual LLVMValueRef llvm_function()
Definition: fif.hpp:651
virtual ~opaque_compiler_data()=default
virtual var_data * create_var(std::string const &name, int32_t type)
Definition: fif.hpp:685
virtual std::vector< int32_t > * type_substitutions()
Definition: fif.hpp:691
opaque_compiler_data * parent
Definition: fif.hpp:643
virtual var_data * get_var(std::string const &name)
Definition: fif.hpp:679
virtual let_data * get_let(std::string const &name) override
Definition: fif.hpp:3053
ankerl::unordered_dense::map< std::string, std::unique_ptr< let_data > > global_lets
Definition: fif.hpp:3032
virtual var_data * create_var(std::string const &name, int32_t type) override
Definition: fif.hpp:3040
virtual let_data * create_let(std::string const &name, int32_t type, int64_t data, LLVMValueRef expression) override
Definition: fif.hpp:3059
virtual bool finish(environment &env) override
Definition: fif.hpp:3087
virtual var_data * get_var(std::string const &name) override
Definition: fif.hpp:3034
std::unique_ptr< state_stack > interpreter_state
Definition: fif.hpp:3029
virtual state_stack * working_state() override
Definition: fif.hpp:3081
outer_interpreter(environment &env)
Definition: fif.hpp:3076
virtual void set_working_state(std::unique_ptr< state_stack > p) override
Definition: fif.hpp:3084
ankerl::unordered_dense::map< std::string, std::unique_ptr< var_data > > global_vars
Definition: fif.hpp:3031
virtual control_structure get_type() override
Definition: fif.hpp:3078
runtime_function_scope(opaque_compiler_data *p, environment &e)
Definition: fif.hpp:2916
virtual bool finish(environment &) override
Definition: fif.hpp:2918
virtual control_structure get_type() override
Definition: fif.hpp:2922
virtual void copy_into(state_stack const &other)=0
state_stack()=default
virtual stack_type get_type() const =0
size_t min_main_depth
Definition: fif.hpp:101
virtual void set_return_ex_back(size_t index, LLVMValueRef value)=0
void set_main_type(size_t index, int32_t type)
Definition: fif.hpp:160
size_t main_size() const
Definition: fif.hpp:142
virtual LLVMValueRef return_ex(size_t index) const =0
void set_return_type_back(size_t index, int32_t type)
Definition: fif.hpp:172
void mark_used_from_return(size_t count)
Definition: fif.hpp:107
virtual void set_return_data_back(size_t index, int64_t value)=0
virtual LLVMValueRef return_ex_back(size_t index) const =0
virtual void set_main_data(size_t index, int64_t value)=0
virtual void resize(size_t main_sz, size_t return_sz)=0
virtual void set_main_data_back(size_t index, int64_t value)=0
virtual std::unique_ptr< state_stack > copy() const =0
virtual LLVMValueRef main_ex_back(size_t index) const =0
int32_t main_type_back(size_t index) const
Definition: fif.hpp:154
std::vector< int32_t > main_types
Definition: fif.hpp:98
virtual ~state_stack()=default
virtual int64_t main_data_back(size_t index) const =0
virtual int64_t main_data(size_t index) const =0
size_t min_return_depth
Definition: fif.hpp:102
virtual int64_t return_data(size_t index) const =0
virtual void set_main_ex_back(size_t index, LLVMValueRef value)=0
virtual void push_back_return(int32_t type, int64_t data, LLVMValueRef expr)=0
virtual void pop_main()=0
void set_main_type_back(size_t index, int32_t type)
Definition: fif.hpp:168
virtual int64_t return_data_back(size_t index) const =0
int32_t return_type_back(size_t index) const
Definition: fif.hpp:157
virtual void push_back_main(int32_t type, int64_t data, LLVMValueRef expr)=0
size_t return_size() const
Definition: fif.hpp:145
virtual void set_main_ex(size_t index, LLVMValueRef value)=0
virtual void set_return_ex(size_t index, LLVMValueRef value)=0
int32_t return_type(size_t index) const
Definition: fif.hpp:151
void set_return_type(size_t index, int32_t type)
Definition: fif.hpp:164
virtual void pop_return()=0
virtual LLVMValueRef main_ex(size_t index) const =0
void mark_used_from_main(size_t count)
Definition: fif.hpp:104
virtual void move_into(state_stack &&other)=0
virtual void set_return_data(size_t index, int64_t value)=0
int32_t main_type(size_t index) const
Definition: fif.hpp:148
state_stack(state_stack &&)=default
state_stack(const state_stack &)=default
std::vector< int32_t > return_types
Definition: fif.hpp:99
virtual int64_t return_data_back(size_t index) const override
Definition: fif.hpp:335
virtual int64_t main_data_back(size_t index) const override
Definition: fif.hpp:332
virtual void set_return_data(size_t index, int64_t value) override
Definition: fif.hpp:350
virtual void move_into(state_stack &&other) override
Definition: fif.hpp:371
virtual stack_type get_type() const override
Definition: fif.hpp:344
virtual void pop_return() override
Definition: fif.hpp:308
virtual void set_return_ex_back(size_t index, LLVMValueRef value) override
Definition: fif.hpp:368
virtual std::unique_ptr< state_stack > copy() const override
Definition: fif.hpp:397
virtual void set_main_data_back(size_t index, int64_t value) override
Definition: fif.hpp:359
virtual void push_back_return(int32_t type, int64_t data, LLVMValueRef expr) override
Definition: fif.hpp:394
virtual LLVMValueRef main_ex(size_t index) const override
Definition: fif.hpp:326
virtual void pop_main() override
Definition: fif.hpp:302
virtual LLVMValueRef main_ex_back(size_t index) const override
Definition: fif.hpp:338
virtual LLVMValueRef return_ex(size_t index) const override
Definition: fif.hpp:329
virtual void set_return_data_back(size_t index, int64_t value) override
Definition: fif.hpp:362
virtual LLVMValueRef return_ex_back(size_t index) const override
Definition: fif.hpp:341
virtual void push_back_main(int32_t type, int64_t data, LLVMValueRef expr) override
Definition: fif.hpp:391
virtual void resize(size_t main_sz, size_t return_sz) override
Definition: fif.hpp:314
virtual void copy_into(state_stack const &other) override
Definition: fif.hpp:381
virtual void set_main_ex(size_t index, LLVMValueRef value) override
Definition: fif.hpp:353
virtual void set_main_data(size_t index, int64_t value) override
Definition: fif.hpp:347
virtual int64_t return_data(size_t index) const override
Definition: fif.hpp:323
virtual void set_return_ex(size_t index, LLVMValueRef value) override
Definition: fif.hpp:356
virtual int64_t main_data(size_t index) const override
Definition: fif.hpp:320
virtual void set_main_ex_back(size_t index, LLVMValueRef value) override
Definition: fif.hpp:365
virtual bool finish(environment &env) override
Definition: fif.hpp:3104
typecheck3_record_holder(opaque_compiler_data *p, environment &env)
Definition: fif.hpp:3095
virtual ankerl::unordered_dense::map< uint64_t, typecheck_3_record > * typecheck_record() override
Definition: fif.hpp:3101
virtual control_structure get_type() override
Definition: fif.hpp:3098
ankerl::unordered_dense::map< uint64_t, typecheck_3_record > tr
Definition: fif.hpp:3093
LLVMBasicBlockRef body_block
Definition: fif.hpp:3585
LLVMBasicBlockRef pre_block
Definition: fif.hpp:3583
std::unique_ptr< state_stack > loop_entry_copy
Definition: fif.hpp:3573
LLVMBasicBlockRef entry_block
Definition: fif.hpp:3584
virtual bool finish(environment &) override
Definition: fif.hpp:3703
while_loop_scope(opaque_compiler_data *p, environment &e, state_stack &entry_state)
Definition: fif.hpp:3588
size_t end_of_loop_branch
Definition: fif.hpp:3577
virtual void set_working_state(std::unique_ptr< state_stack > p) override
Definition: fif.hpp:3625
std::string_view entry_source
Definition: fif.hpp:3575
virtual control_structure get_type() override
Definition: fif.hpp:3619
size_t loop_entry_point
Definition: fif.hpp:3576
std::vector< LLVMValueRef > phinodes
Definition: fif.hpp:3586
std::unique_ptr< state_stack > iworking_state
Definition: fif.hpp:3572
LLVMValueRef conditional_expr
Definition: fif.hpp:3582
void end_condition(environment &)
Definition: fif.hpp:3628
bool initial_typechecking_failed
Definition: fif.hpp:3581
std::unique_ptr< state_stack > initial_state
Definition: fif.hpp:3571
virtual state_stack * working_state() override
Definition: fif.hpp:3622
bool intepreter_skip_body
Definition: fif.hpp:3579
#define assert(condition)
Definition: debug.h:74
#define LLVMValueRef
Definition: fif.hpp:91
LLVMBool LLVMVerifyModule(LLVMModuleRef M, LLVMVerifierFailureAction Action, char **OutMessage)
LLVMBool LLVMVerifyFunction(LLVMValueRef Fn, LLVMVerifierFailureAction Action)
@ LLVMReturnStatusAction
Definition: Analysis.h:37
void LLVMDisposeMessage(char *Message)
LLVMValueRef LLVMBuildLoad2(LLVMBuilderRef, LLVMTypeRef Ty, LLVMValueRef PointerVal, const char *Name)
LLVMValueRef LLVMBuildNot(LLVMBuilderRef, LLVMValueRef V, const char *Name)
LLVMValueRef LLVMBuildAnd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildFPExt(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name)
LLVMValueRef LLVMBuildFDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildFAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildFMul(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildZExt(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name)
LLVMValueRef LLVMBuildSExt(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name)
LLVMValueRef LLVMBuildExtractValue(LLVMBuilderRef, LLVMValueRef AggVal, unsigned Index, const char *Name)
LLVMValueRef LLVMBuildFCmp(LLVMBuilderRef, LLVMRealPredicate Op, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildFPTrunc(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name)
LLVMValueRef LLVMBuildSIToFP(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name)
LLVMValueRef LLVMBuildShl(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildFRem(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildAlloca(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name)
LLVMValueRef LLVMBuildSelect(LLVMBuilderRef, LLVMValueRef If, LLVMValueRef Then, LLVMValueRef Else, const char *Name)
LLVMValueRef LLVMBuildMul(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildMalloc(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name)
LLVMValueRef LLVMBuildAShr(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildInsertValue(LLVMBuilderRef, LLVMValueRef AggVal, LLVMValueRef EltVal, unsigned Index, const char *Name)
LLVMValueRef LLVMBuildAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef Val, LLVMValueRef Len, unsigned Align)
LLVMValueRef LLVMBuildBr(LLVMBuilderRef, LLVMBasicBlockRef Dest)
LLVMValueRef LLVMBuildSRem(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
void LLVMDisposeBuilder(LLVMBuilderRef Builder)
LLVMValueRef LLVMBuildFSub(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMBuilderRef LLVMCreateBuilderInContext(LLVMContextRef C)
LLVMValueRef LLVMBuildICmp(LLVMBuilderRef, LLVMIntPredicate Op, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildTrunc(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name)
LLVMValueRef LLVMBuildURem(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildCall2(LLVMBuilderRef, LLVMTypeRef, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, const char *Name)
LLVMValueRef LLVMBuildOr(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildFPToUI(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name)
LLVMValueRef LLVMBuildFPToSI(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name)
LLVMValueRef LLVMBuildUDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildStructGEP2(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Pointer, unsigned Idx, const char *Name)
LLVMValueRef LLVMBuildSDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildStore(LLVMBuilderRef, LLVMValueRef Val, LLVMValueRef Ptr)
LLVMValueRef LLVMBuildArrayMalloc(LLVMBuilderRef, LLVMTypeRef Ty, LLVMValueRef Val, const char *Name)
LLVMValueRef LLVMBuildInBoundsGEP2(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Pointer, LLVMValueRef *Indices, unsigned NumIndices, const char *Name)
LLVMValueRef LLVMBuildUIToFP(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name)
LLVMValueRef LLVMBuildCondBr(LLVMBuilderRef, LLVMValueRef If, LLVMBasicBlockRef Then, LLVMBasicBlockRef Else)
LLVMValueRef LLVMBuildXor(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size)
LLVMValueRef LLVMBuildSub(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildFree(LLVMBuilderRef, LLVMValueRef PointerVal)
LLVMValueRef LLVMBuildPhi(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name)
LLVMValueRef LLVMBuildLShr(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name)
LLVMValueRef LLVMBuildRetVoid(LLVMBuilderRef)
LLVMValueRef LLVMBuildRet(LLVMBuilderRef, LLVMValueRef V)
void LLVMPositionBuilderAtEnd(LLVMBuilderRef Builder, LLVMBasicBlockRef Block)
LLVMValueRef LLVMAddFunction(LLVMModuleRef M, const char *Name, LLVMTypeRef FunctionTy)
void LLVMDisposeModule(LLVMModuleRef M)
LLVMModuleRef LLVMModuleCreateWithNameInContext(const char *ModuleID, LLVMContextRef C)
void LLVMSetTarget(LLVMModuleRef M, const char *Triple)
char * LLVMPrintModuleToString(LLVMModuleRef M)
void LLVMPassBuilderOptionsSetMergeFunctions(LLVMPassBuilderOptionsRef Options, LLVMBool MergeFunctions)
LLVMPassBuilderOptionsRef LLVMCreatePassBuilderOptions(void)
void LLVMDisposePassBuilderOptions(LLVMPassBuilderOptionsRef Options)
void LLVMPassBuilderOptionsSetSLPVectorization(LLVMPassBuilderOptionsRef Options, LLVMBool SLPVectorization)
void LLVMPassBuilderOptionsSetLoopVectorization(LLVMPassBuilderOptionsRef Options, LLVMBool LoopVectorization)
void LLVMPassBuilderOptionsSetLoopUnrolling(LLVMPassBuilderOptionsRef Options, LLVMBool LoopUnrolling)
typedefLLVM_C_EXTERN_C_BEGIN struct LLVMOpaquePassBuilderOptions * LLVMPassBuilderOptionsRef
Definition: PassBuilder.h:38
void LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll(LLVMPassBuilderOptionsRef Options, LLVMBool ForgetAllSCEVInLoopUnroll)
void LLVMPassBuilderOptionsSetLoopInterleaving(LLVMPassBuilderOptionsRef Options, LLVMBool LoopInterleaving)
LLVMErrorRef LLVMRunPasses(LLVMModuleRef M, const char *Passes, LLVMTargetMachineRef TM, LLVMPassBuilderOptionsRef Options)
LLVMTypeRef LLVMDoubleTypeInContext(LLVMContextRef C)
LLVMTypeRef LLVMFloatTypeInContext(LLVMContextRef C)
LLVMTypeRef LLVMFunctionType(LLVMTypeRef ReturnType, LLVMTypeRef *ParamTypes, unsigned ParamCount, LLVMBool IsVarArg)
LLVMTypeRef LLVMInt64TypeInContext(LLVMContextRef C)
LLVMTypeRef LLVMInt16TypeInContext(LLVMContextRef C)
LLVMTypeRef LLVMInt1TypeInContext(LLVMContextRef C)
LLVMTypeRef LLVMInt32TypeInContext(LLVMContextRef C)
LLVMTypeRef LLVMInt8TypeInContext(LLVMContextRef C)
LLVMTypeRef LLVMVoidTypeInContext(LLVMContextRef C)
LLVMTypeRef LLVMPointerTypeInContext(LLVMContextRef C, unsigned AddressSpace)
LLVMTypeRef LLVMArrayType(LLVMTypeRef ElementType, unsigned ElementCount)
void LLVMStructSetBody(LLVMTypeRef StructTy, LLVMTypeRef *ElementTypes, unsigned ElementCount, LLVMBool Packed)
LLVMTypeRef LLVMStructCreateNamed(LLVMContextRef C, const char *Name)
LLVMTypeRef LLVMStructTypeInContext(LLVMContextRef C, LLVMTypeRef *ElementTypes, unsigned ElementCount, LLVMBool Packed)
@ LLVMRealOLE
Definition: Core.h:310
@ LLVMRealOGE
Definition: Core.h:308
@ LLVMRealOEQ
Definition: Core.h:306
@ LLVMRealOLT
Definition: Core.h:309
@ LLVMRealOGT
Definition: Core.h:307
@ LLVMRealONE
Definition: Core.h:311
@ LLVMIntSGT
Definition: Core.h:298
@ LLVMIntULE
Definition: Core.h:297
@ LLVMIntEQ
Definition: Core.h:292
@ LLVMIntUGE
Definition: Core.h:295
@ LLVMIntSGE
Definition: Core.h:299
@ LLVMIntULT
Definition: Core.h:296
@ LLVMIntUGT
Definition: Core.h:294
@ LLVMIntSLE
Definition: Core.h:301
@ LLVMIntSLT
Definition: Core.h:300
@ LLVMIntNE
Definition: Core.h:293
void LLVMAppendExistingBasicBlock(LLVMValueRef Fn, LLVMBasicBlockRef BB)
LLVMBasicBlockRef LLVMCreateBasicBlockInContext(LLVMContextRef C, const char *Name)
LLVMBasicBlockRef LLVMAppendBasicBlockInContext(LLVMContextRef C, LLVMValueRef Fn, const char *Name)
LLVMValueRef LLVMConstArray(LLVMTypeRef ElementTy, LLVMValueRef *ConstantVals, unsigned Length)
LLVMValueRef LLVMConstNamedStruct(LLVMTypeRef StructTy, LLVMValueRef *ConstantVals, unsigned Count)
LLVMValueRef LLVMSizeOf(LLVMTypeRef Ty)
LLVMValueRef LLVMConstTrunc(LLVMValueRef ConstantVal, LLVMTypeRef ToType)
void LLVMSetLinkage(LLVMValueRef Global, LLVMLinkage Linkage)
void LLVMSetSection(LLVMValueRef Global, const char *Section)
LLVMValueRef LLVMGetUndef(LLVMTypeRef Ty)
LLVMValueRef LLVMConstInt(LLVMTypeRef IntTy, unsigned long long N, LLVMBool SignExtend)
LLVMValueRef LLVMConstReal(LLVMTypeRef RealTy, double N)
void LLVMSetFunctionCallConv(LLVMValueRef Fn, unsigned CC)
LLVMValueRef LLVMGetParam(LLVMValueRef Fn, unsigned Index)
void LLVMSetInstructionCallConv(LLVMValueRef Instr, unsigned CC)
void LLVMAddIncoming(LLVMValueRef PhiNode, LLVMValueRef *IncomingValues, LLVMBasicBlockRef *IncomingBlocks, unsigned Count)
char * LLVMGetErrorMessage(LLVMErrorRef Err)
void LLVMDisposeErrorMessage(char *ErrMsg)
struct LLVMOpaqueError * LLVMErrorRef
Definition: Error.h:33
struct LLVMOrcOpaqueLLJIT * LLVMOrcLLJITRef
Definition: LLJIT.h:66
void LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(LLVMOrcLLJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMB)
LLVMErrorRef LLVMOrcDisposeLLJIT(LLVMOrcLLJITRef J)
LLVMErrorRef LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J, LLVMOrcJITDylibRef JD, LLVMOrcThreadSafeModuleRef TSM)
LLVMOrcSymbolStringPoolEntryRef LLVMOrcLLJITMangleAndIntern(LLVMOrcLLJITRef J, const char *UnmangledName)
LLVMOrcJITDylibRef LLVMOrcLLJITGetMainJITDylib(LLVMOrcLLJITRef J)
LLVMOrcIRTransformLayerRef LLVMOrcLLJITGetIRTransformLayer(LLVMOrcLLJITRef J)
LLVMOrcLLJITBuilderRef LLVMOrcCreateLLJITBuilder(void)
LLVMOrcExecutionSessionRef LLVMOrcLLJITGetExecutionSession(LLVMOrcLLJITRef J)
LLVMErrorRef LLVMOrcCreateLLJIT(LLVMOrcLLJITRef *Result, LLVMOrcLLJITBuilderRef Builder)
LLVMErrorRef LLVMOrcThreadSafeModuleWithModuleDo(LLVMOrcThreadSafeModuleRef TSM, LLVMOrcGenericIRModuleOperationFunction F, void *Ctx)
LLVMOrcMaterializationUnitRef LLVMOrcAbsoluteSymbols(LLVMOrcCSymbolMapPairs Syms, size_t NumPairs)
LLVMOrcThreadSafeModuleRef LLVMOrcCreateNewThreadSafeModule(LLVMModuleRef M, LLVMOrcThreadSafeContextRef TSCtx)
struct LLVMOrcOpaqueMaterializationResponsibility * LLVMOrcMaterializationResponsibilityRef
Definition: Orc.h:262
struct LLVMOrcOpaqueThreadSafeModule * LLVMOrcThreadSafeModuleRef
Definition: Orc.h:382
struct LLVMOrcOpaqueExecutionSession * LLVMOrcExecutionSessionRef
Definition: Orc.h:88
void LLVMOrcDisposeThreadSafeContext(LLVMOrcThreadSafeContextRef TSCtx)
uint64_t LLVMOrcExecutorAddress
Definition: Orc.h:51
LLVMOrcJITTargetMachineBuilderRef LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM)
LLVMErrorRef LLVMOrcJITDylibDefine(LLVMOrcJITDylibRef JD, LLVMOrcMaterializationUnitRef MU)
LLVMOrcThreadSafeContextRef LLVMOrcCreateNewThreadSafeContext(void)
struct LLVMOrcOpaqueIRTransformLayer * LLVMOrcIRTransformLayerRef
Definition: Orc.h:410
LLVMContextRef LLVMOrcThreadSafeContextGetContext(LLVMOrcThreadSafeContextRef TSCtx)
struct LLVMOrcOpaqueJITDylib * LLVMOrcJITDylibRef
Definition: Orc.h:159
struct LLVMOrcOpaqueThreadSafeContext * LLVMOrcThreadSafeContextRef
Definition: Orc.h:377
void LLVMOrcIRTransformLayerSetTransform(LLVMOrcIRTransformLayerRef IRTransformLayer, LLVMOrcIRTransformLayerTransformFunction TransformFunction, void *Ctx)
struct LLVMOpaqueValue * LLVMValueRef
Definition: Types.h:75
struct LLVMOpaqueContext * LLVMContextRef
Definition: Types.h:53
struct LLVMOpaqueBuilder * LLVMBuilderRef
Definition: Types.h:110
struct LLVMOpaqueBasicBlock * LLVMBasicBlockRef
Definition: Types.h:82
struct LLVMOpaqueType * LLVMTypeRef
Definition: Types.h:68
struct LLVMOpaqueModule * LLVMModuleRef
Definition: Types.h:61
void LLVMSetModuleDataLayout(LLVMModuleRef M, LLVMTargetDataRef DL)
char * LLVMGetHostCPUFeatures(void)
LLVMTargetRef LLVMGetFirstTarget(void)
struct LLVMTarget * LLVMTargetRef
Definition: TargetMachine.h:36
char * LLVMGetHostCPUName(void)
void LLVMDisposeTargetData(LLVMTargetDataRef TD)
struct LLVMOpaqueTargetMachine * LLVMTargetMachineRef
Definition: TargetMachine.h:35
char * LLVMGetDefaultTargetTriple(void)
LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple, const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, LLVMCodeModel CodeModel)
LLVMTargetDataRef LLVMCreateTargetDataLayout(LLVMTargetMachineRef T)
struct LLVMOpaqueTargetData * LLVMTargetDataRef
Definition: Target.h:37
void LLVMDisposeTargetMachine(LLVMTargetMachineRef T)
LLVMValueRef LLVMAddGlobal(LLVMModuleRef M, LLVMTypeRef Ty, const char *Name)
void LLVMSetInitializer(LLVMValueRef GlobalVar, LLVMValueRef ConstantVal)
Definition: fif.hpp:44
int32_t * forth_struct_map_two(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8014
constexpr int32_t fif_struct
Definition: fif.hpp:498
int32_t * f32lt(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6097
int32_t * fif_swap(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5883
int32_t * enter_scope(state_stack &s, int32_t *p, environment *env)
Definition: fif.hpp:2943
int32_t * fif_end_do(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5977
int32_t * fif_until(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5967
int32_t * uile(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6281
int64_t(*)(int32_t t, environment *) interpreter_zero_expr
Definition: fif.hpp:448
int32_t make_struct_type(std::string_view name, std::span< int32_t const > subtypes, std::vector< std::string_view > const &member_names, environment &env, int32_t template_types, int32_t extra_count)
Definition: fif.hpp:1392
int32_t * sext_i8(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8555
bool non_immediate_mode(fif_mode m)
Definition: fif.hpp:716
int32_t * do_pointer_cast(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6950
int32_t * illegal_interpretation(state_stack &s, int32_t *p, environment *e)
Definition: fif.hpp:1027
int32_t * nop1(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8819
void execute_fif_word(interpreted_word_instance &wi, state_stack &ss, environment &env)
Definition: fif.hpp:2146
int32_t * impl_heap_allot(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6653
int32_t *(*)(state_stack &, int32_t *, environment *) fif_call
Definition: fif.hpp:409
constexpr size_t inlining_cells_limit
Definition: fif.hpp:4175
type_match internal_resolve_type(std::string_view text, environment &env, std::vector< int32_t > *type_subs)
Definition: fif.hpp:1621
void run_fif_interpreter(environment &env, std::string_view on_text)
Definition: fif.hpp:5096
int32_t * colon_specialization(fif::state_stack &, int32_t *p, fif::environment *e)
Definition: fif.hpp:5346
int32_t * immediate_i32(state_stack &s, int32_t *p, environment *)
Definition: fif.hpp:2171
int32_t * fif_if(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5914
constexpr int32_t fif_ptr
Definition: fif.hpp:496
int32_t * f64_mod(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5798
int32_t * ieq(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6444
int32_t * do_fextract(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7309
constexpr int32_t fif_i32
Definition: fif.hpp:483
int32_t * f64eq(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6490
int32_t * fif_while(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5939
int32_t * function_return(state_stack &s, int32_t *p, environment *)
Definition: fif.hpp:2284
constexpr int32_t fif_u16
Definition: fif.hpp:492
bool is_fp(char const *start, char const *end)
Definition: fif.hpp:1075
float parse_float(std::string_view content)
Definition: fif.hpp:1162
int32_t * f32gt(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6210
int32_t * ftrunc(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8829
int32_t * drop(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5871
int32_t * f_select(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6587
type_match_result match_stack_description(std::span< int32_t const > desc, state_stack &ts, environment &env, std::vector< int32_t > &type_subs)
Definition: fif.hpp:1931
parse_result read_token(std::string_view &source, environment &env)
Definition: fif.hpp:4253
bool codepoint_is_space(uint32_t c) noexcept
Definition: fif.hpp:4199
int32_t * unconditional_jump(state_stack &s, int32_t *p, environment *env)
Definition: fif.hpp:3231
int32_t * f32ui16(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9053
int32_t * simod(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5731
constexpr int32_t fif_i8
Definition: fif.hpp:493
int32_t * type_construction(state_stack &s, int32_t *p, environment *e)
Definition: fif.hpp:8107
int32_t * zext_ui8(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8451
int32_t * colon_definition(fif::state_stack &, int32_t *p, fif::environment *e)
Definition: fif.hpp:5303
constexpr int32_t fif_u32
Definition: fif.hpp:489
int32_t * f64le(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6327
int32_t * iadd(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5415
int32_t * create_var(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7217
stack_consumption get_stack_consumption(int32_t word, int32_t alternative, environment &env)
Definition: fif.hpp:2057
constexpr int32_t fif_bool
Definition: fif.hpp:485
void add_precompiled(fif::environment &env, std::string name, fif::fif_call fn, std::vector< int32_t > types, bool immediate=false)
Definition: fif.hpp:6058
int32_t * ident8(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9434
bool stack_types_match(state_stack &a, state_stack &b)
Definition: fif.hpp:3200
int32_t * forth_gep(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7685
int32_t * f32_mul(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5583
int32_t * ile(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6260
int32_t * uimod(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5751
int32_t * forth_extract_copy(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7458
int64_t(*)() interpreted_new
Definition: fif.hpp:449
int32_t * r_at(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6005
int32_t * do_fsmt(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7975
int32_t * sext_i16(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8526
int32_t * do_var_creation(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7202
int32_t * imul(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5563
int32_t * copy_buffer(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7086
int32_t * zext_ui16(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8434
int32_t * bit_lshr(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9393
int32_t * sext_ui64(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8584
int32_t * f64ui16(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9214
void do_immediate_bool(state_stack &s, bool value, environment *e)
Definition: fif.hpp:2237
uint32_t codepoint_from_utf8(char const *start, char const *end)
Definition: fif.hpp:4177
int32_t * f64ne(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6561
int32_t * call_function_indirect(state_stack &s, int32_t *p, environment *env)
Definition: fif.hpp:2935
int32_t * sif64(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8933
int32_t * do_fsmo(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7868
int32_t * impl_load_deallocated(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6784
int32_t * f64i8(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9114
int32_t * create_let(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7150
int32_t * sext_ui16(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8642
int32_t * impl_index(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7038
int32_t * zext_i32(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8350
int32_t * fif_end_while(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5953
int32_t * sext_ui32(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8613
bool typechecking_mode(fif_mode m)
Definition: fif.hpp:719
int32_t struct_child_count(int32_t type, environment &env)
Definition: fif.hpp:1195
int32_t * f32ui64(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9093
int32_t * f64i16(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9134
int32_t * fif_then(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5928
int32_t * f64i64(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9174
int32_t * bit_xor(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9314
int32_t * f64_div(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5704
int32_t * forth_extract(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7344
int32_t * impl_uninit_store(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6899
int32_t * conditional_jump(state_stack &s, int32_t *p, environment *env)
Definition: fif.hpp:3215
std::variant< interpreted_word_instance, compiled_word_instance > word_types
Definition: fif.hpp:428
int32_t * zext_i8(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8384
int32_t * impl_load(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6715
bool is_positive_integer(char const *start, char const *end)
Definition: fif.hpp:1044
void add_import(std::string_view name, void *ptr, fif_call interpreter_implementation, std::vector< int32_t > const &params, std::vector< int32_t > const &returns, environment &env)
Definition: fif.hpp:5154
int32_t * uif64(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8953
int32_t * trunc_i1(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8734
fif_mode fail_typechecking(fif_mode m)
Definition: fif.hpp:731
int32_t * uif32(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8913
word_match_result match_word(word const &w, state_stack &ts, std::vector< word_types > const &all_instances, std::vector< int32_t > const &all_stack_types, environment &env)
Definition: fif.hpp:2110
variable_match_result fill_in_variable_types(int32_t source_type, std::span< int32_t const > match_span, std::vector< int32_t > &type_subs, environment &env)
Definition: fif.hpp:1876
int32_t * copy(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5853
var_data * get_global_var(environment &env, std::string const &name)
Definition: fif.hpp:4571
bool compile_word(int32_t w, int32_t word_index, state_stack &state, fif_mode compile_mode, environment &env, std::vector< int32_t > &tsubs)
Definition: fif.hpp:4511
int32_t * dup(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5825
int32_t * create_global_impl(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7273
int32_t * f32ui8(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9033
int32_t * forth_struct_map_zero(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7794
int32_t * zext_ui64(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8401
int32_t * uilt(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6147
int32_t * f32i16(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8973
int32_t * zext_i64(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8334
int32_t interepreter_size(int32_t type, environment &env)
Definition: fif.hpp:1188
void switch_compiler_stack_mode(environment &env, fif_mode new_mode)
Definition: fif.hpp:3014
int32_t * fif_else(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5918
int32_t * f32ge(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6394
uint32_t next_encoded_stack_type(std::span< int32_t const > desc)
Definition: fif.hpp:1218
int32_t * do_use_base(state_stack &s, int32_t *p, environment *env)
Definition: fif.hpp:8288
void do_immediate_i32(state_stack &s, int32_t value, environment *e)
Definition: fif.hpp:2189
double pow_10(int n)
Definition: fif.hpp:1084
int32_t * immediate_f32(state_stack &s, int32_t *p, environment *)
Definition: fif.hpp:2177
int64_t interpreter_struct_zero_constant(int32_t t, environment *e)
Definition: fif.hpp:1202
int32_t * zext_ui32(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8417
constexpr int32_t fif_u8
Definition: fif.hpp:494
int32_t * close_bracket(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6648
int32_t * immediate_global(state_stack &s, int32_t *p, environment *e)
Definition: fif.hpp:4608
type_match resolve_span_type(std::span< int32_t const > tlist, std::vector< int32_t > const &type_subs, environment &env)
Definition: fif.hpp:1797
let_data * get_global_let(environment &env, std::string const &name)
Definition: fif.hpp:4564
int32_t * idents32(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9444
int32_t * impl_store(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6837
int32_t * forth_struct_map_one(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7898
int32_t * do_fextractc(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7427
int32_t * f64ge(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6419
int32_t * trunc_i32(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8802
int32_t * free_buffer(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7116
int32_t resolve_type(std::string_view text, environment &env, std::vector< int32_t > *type_subs)
Definition: fif.hpp:1707
int32_t * reverse_conditional_jump(state_stack &s, int32_t *p, environment *env)
Definition: fif.hpp:3223
int32_t * fif_loop(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5943
int32_t * ident1(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9474
int32_t * bit_shl(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9353
int32_t * sext_i32(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8497
size_t size_from_utf8(char const *start)
Definition: fif.hpp:4193
constexpr int32_t fif_nil
Definition: fif.hpp:495
int32_t * immediate_local(state_stack &s, int32_t *p, environment *e)
Definition: fif.hpp:4579
int32_t * allocate_buffer(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7064
void run_to_scope_end(environment &env)
Definition: fif.hpp:4301
control_structure
Definition: fif.hpp:617
int32_t * do_fsmz(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7763
int32_t * bit_and(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9274
constexpr int32_t fif_type
Definition: fif.hpp:486
int32_t * f32i8(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8873
int32_t * sext_i64(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8468
void do_immediate_type(state_stack &s, int32_t value, environment *e)
Definition: fif.hpp:2216
int32_t * impl_heap_free(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6685
int32_t * trunc_i8(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8717
int32_t * f32i32(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8993
int32_t * bit_not(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9334
int32_t * make_immediate(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6625
void restore_compiler_stack_mode(environment &env)
Definition: fif.hpp:3018
int32_t * sif32(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8893
std::string_view read_word(std::string_view source, uint32_t &read_position)
Definition: fif.hpp:2132
int32_t * call_function(state_stack &s, int32_t *p, environment *env)
Definition: fif.hpp:2926
int32_t * to_r(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6038
bool compare_stack_description(std::span< const int32_t > a, std::span< const int32_t > b)
Definition: fif.hpp:3190
int32_t * f32le(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6302
int32_t * sidiv(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5637
string_start match_string_start(std::string_view source)
Definition: fif.hpp:4212
int32_t * f32eq(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6465
int32_t * export_definition(fif::state_stack &, int32_t *p, fif::environment *e)
Definition: fif.hpp:8241
int32_t * f64i32(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9154
int32_t * f64_sub(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5536
bool is_integer(char const *start, char const *end)
Definition: fif.hpp:1055
int32_t * zext_i16(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8367
int32_t * idents16(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9454
int32_t * f64ui8(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9194
int32_t * f32_mod(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5771
int32_t * ident32(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9414
int32_t * pointer_cast(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6956
std::string word_name_from_id(int32_t w, environment const &e)
Definition: fif.hpp:1019
int32_t * f64_add(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5462
int32_t * immediate_type(state_stack &s, int32_t *p, environment *)
Definition: fif.hpp:2210
int32_t * f64gt(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6235
LLVMValueRef empty_type_fn(LLVMValueRef r, int32_t type, environment *)
Definition: fif.hpp:441
int32_t instantiate_templated_struct(int32_t template_base, std::vector< int32_t > const &subtypes, environment &env)
Definition: fif.hpp:1322
std::vector< int32_t > expand_stack_description(state_stack &initial_stack_state, std::span< const int32_t > desc, int32_t stack_consumed, int32_t rstack_consumed)
Definition: fif.hpp:3110
bool is_positive_fp(char const *start, char const *end)
Definition: fif.hpp:1064
stack_type
Definition: fif.hpp:46
bool fully_typecheck_word(int32_t w, int32_t word_index, interpreted_word_instance &wi, state_stack &current_type_state, environment &env, std::vector< int32_t > &tsubs)
Definition: fif.hpp:4410
int32_t * ident16(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9424
int32_t * uidiv(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5657
int32_t * isub(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5489
bool typechecking_failed(fif_mode m)
Definition: fif.hpp:723
bool codepoint_is_line_break(uint32_t c) noexcept
Definition: fif.hpp:4203
constexpr int32_t fif_f32
Definition: fif.hpp:484
int32_t * leave_scope(state_stack &s, int32_t *p, environment *env)
Definition: fif.hpp:2947
int32_t * immediate_let(state_stack &s, int32_t *p, environment *e)
Definition: fif.hpp:4594
int32_t * ige(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6352
void do_immediate_f32(state_stack &s, float value, environment *e)
Definition: fif.hpp:2258
int32_t * long_comment(fif::state_stack &, int32_t *p, fif::environment *e)
Definition: fif.hpp:8304
int32_t * fif_do(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5963
constexpr int32_t fif_opaque_ptr
Definition: fif.hpp:497
int32_t * f64ui64(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9254
int32_t * do_fgep(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7642
int32_t * do_finsert(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7535
int32_t * f32_add(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5435
constexpr int32_t fif_i16
Definition: fif.hpp:491
int32_t parse_int(std::string_view content)
Definition: fif.hpp:1154
void initialize_standard_vocab(environment &fif_env)
Definition: fif.hpp:9485
int32_t * f64ui32(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9234
fif_mode reset_typechecking(fif_mode m)
Definition: fif.hpp:726
int32_t * bit_or(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9294
int32_t * trunc_ui32(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8785
bool float_from_chars(char const *start, char const *end, float &float_out)
Definition: fif.hpp:1109
int32_t * f32ui32(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9073
int32_t * do_make(state_stack &s, int32_t *p, environment *env)
Definition: fif.hpp:8113
int32_t * open_bracket(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6644
type_span_gen_result internal_generate_type(std::string_view text, environment &env)
Definition: fif.hpp:1717
void run_to_function_end(environment &env)
Definition: fif.hpp:4319
int32_t * f32_sub(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5509
int32_t * ilt(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6076
int32_t * trunc_ui16(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8751
int32_t * do_let_creation(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7136
int32_t * forth_insert(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7564
int32_t * uige(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6373
constexpr int32_t fif_u64
Definition: fif.hpp:490
int32_t * fext(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8851
int32_t * trunc_i16(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8768
int32_t * sext_ui8(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8671
int32_t * immediate_bool(state_stack &s, int32_t *p, environment *)
Definition: fif.hpp:2183
int32_t * struct_definition(fif::state_stack &, int32_t *p, fif::environment *e)
Definition: fif.hpp:8169
constexpr int32_t fif_i64
Definition: fif.hpp:487
int32_t * f32i64(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9013
int32_t * f64_mul(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5610
int32_t * f64lt(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6122
int32_t instantiate_templated_struct_full(int32_t template_base, std::vector< int32_t > const &final_subtype_list, environment &env)
Definition: fif.hpp:1234
int32_t * impl_sizeof(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:7000
bool match_string_end(std::string_view source, int32_t eq_count_in)
Definition: fif.hpp:4231
int32_t * trunc_ui8(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:8700
void apply_stack_description(std::span< int32_t const > desc, state_stack &ts, environment &env)
Definition: fif.hpp:1986
int32_t * uigt(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6189
int32_t * line_comment(fif::state_stack &, int32_t *p, fif::environment *e)
Definition: fif.hpp:8322
int32_t * ine(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6515
fif_mode
Definition: fif.hpp:702
@ typechecking_lvl2_failed
@ typechecking_lvl1_failed
@ typechecking_lvl3_failed
int32_t * bit_ashr(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9373
word_match_result get_basic_type_match(int32_t word_index, state_stack &current_type_state, environment &env, std::vector< int32_t > &specialize_t_subs, bool ignore_specializations)
Definition: fif.hpp:4326
int32_t * from_r(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5987
int32_t * f32ne(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6536
int32_t * f32_div(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:5677
int32_t * igt(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:6168
constexpr int32_t fif_f64
Definition: fif.hpp:488
int32_t * idents8(fif::state_stack &s, int32_t *p, fif::environment *e)
Definition: fif.hpp:9464
Definition: bmfont.cpp:118
uint uint32_t
ulong uint64_t
uchar uint8_t
LLVMOrcExecutorAddress Address
Definition: Orc.h:81
LLVMJITSymbolFlags Flags
Definition: Orc.h:82
uint8_t GenericFlags
Definition: Orc.h:73
uint8_t TargetFlags
Definition: Orc.h:74
void * ptr
Definition: fif.hpp:742
std::string name
Definition: fif.hpp:741
bool operator()(std::unique_ptr< char[]> const &l, std::unique_ptr< char[]> const &r) const noexcept
Definition: fif.hpp:72
bool operator()(std::unique_ptr< char[]> const &l, std::string_view r) const noexcept
Definition: fif.hpp:75
bool operator()(std::string const &r, std::unique_ptr< char[]> const &l) const noexcept
Definition: fif.hpp:84
bool operator()(std::string_view r, std::unique_ptr< char[]> const &l) const noexcept
Definition: fif.hpp:78
bool operator()(std::unique_ptr< char[]> const &l, std::string const &r) const noexcept
Definition: fif.hpp:81
auto operator()(std::string_view sv) const noexcept -> uint64_t
Definition: fif.hpp:58
auto operator()(std::unique_ptr< char[]> const &str) const noexcept -> uint64_t
Definition: fif.hpp:61
LLVMValueRef llvm_function
Definition: fif.hpp:413
std::vector< int32_t > compiled_bytecode
Definition: fif.hpp:412
int32_t type
Definition: fif.hpp:638
int64_t data
Definition: fif.hpp:636
LLVMValueRef expression
Definition: fif.hpp:637
std::string_view content
Definition: fif.hpp:2289
bool starts_string
Definition: fif.hpp:4209
int32_t eq_match
Definition: fif.hpp:4208
int32_t stack_consumed
Definition: fif.hpp:1035
int32_t ret_stack_consumed
Definition: fif.hpp:1036
int32_t type
Definition: fif.hpp:1039
uint32_t end_match_pos
Definition: fif.hpp:1040
std::vector< int32_t > type_array
Definition: fif.hpp:1712
int32_t decomposed_types_start
Definition: fif.hpp:467
static constexpr uint32_t FLAG_REFCOUNTED
Definition: fif.hpp:452
bool refcounted_type() const
Definition: fif.hpp:472
interpreter_zero_expr interpreter_zero
Definition: fif.hpp:463
int32_t type_slots
Definition: fif.hpp:465
void * zero_constant
Definition: fif.hpp:461
uint32_t flags
Definition: fif.hpp:470
static constexpr uint32_t FLAG_TEMPLATE
Definition: fif.hpp:454
static constexpr uint32_t FLAG_SINGLE_MEMBER
Definition: fif.hpp:453
bool is_struct_template() const
Definition: fif.hpp:478
void * llvm_type
Definition: fif.hpp:460
int32_t non_member_types
Definition: fif.hpp:466
bool single_member_struct() const
Definition: fif.hpp:475
int32_t decomposed_types_count
Definition: fif.hpp:468
int32_t stack_consumed
Definition: fif.hpp:626
int32_t stack_height_added_at
Definition: fif.hpp:624
int32_t rstack_consumed
Definition: fif.hpp:627
int32_t rstack_height_added_at
Definition: fif.hpp:625
LLVMValueRef alloc
Definition: fif.hpp:632
int32_t type
Definition: fif.hpp:633
int64_t data
Definition: fif.hpp:631
int32_t substitution_version
Definition: fif.hpp:2107
int32_t stack_consumed
Definition: fif.hpp:2104
int32_t ret_stack_consumed
Definition: fif.hpp:2105
bool treat_as_base
Definition: fif.hpp:436
std::string source
Definition: fif.hpp:432
std::vector< int32_t > instances
Definition: fif.hpp:431
int32_t stack_types_start
Definition: fif.hpp:434
int32_t stack_types_count
Definition: fif.hpp:435
bool being_typechecked
Definition: fif.hpp:438
int32_t specialization_of
Definition: fif.hpp:433
bool immediate
Definition: fif.hpp:437