Phasor 3.3.0
Stack VM based Programming Language
Loading...
Searching...
No Matches
PhasorIR.cpp
Go to the documentation of this file.
1#include "PhasorIR.hpp"
2#include "../../ISA/map.hpp"
3#include <cstring>
4#include <fstream>
5#include <iomanip>
6#include <iostream>
7#include <sstream>
8#include <stdexcept>
9#include <utility>
10#include <functional>
11#include <map>
12#include <filesystem>
13#include <string>
14#include <vector>
15#include <phsint.hpp>
16
17namespace Phasor
18{
19
21{
22 switch (op)
23 {
24 // 0 operands
25 case OpCode::POP:
26 case OpCode::IADD:
29 case OpCode::IDIVIDE:
30 case OpCode::IMODULO:
31 case OpCode::FLADD:
36 case OpCode::SQRT:
37 case OpCode::POW:
38 case OpCode::LOG:
39 case OpCode::EXP:
40 case OpCode::SIN:
41 case OpCode::COS:
42 case OpCode::TAN:
43 case OpCode::NEGATE:
44 case OpCode::NOT:
45 case OpCode::IAND:
46 case OpCode::IOR:
47 case OpCode::IEQUAL:
53 case OpCode::FLEQUAL:
59 case OpCode::PRINT:
62 case OpCode::HALT:
63 case OpCode::RETURN:
64 case OpCode::TRUE_P:
65 case OpCode::FALSE_P:
67 case OpCode::LEN:
68 case OpCode::CHAR_AT:
69 case OpCode::SUBSTR:
70 return 0;
71
72 // 1 operand
74 case OpCode::JUMP:
80 case OpCode::IMPORT:
82 case OpCode::CALL:
83 case OpCode::SYSTEM:
86 case OpCode::PUSH_R:
87 case OpCode::POP_R:
88 case OpCode::PRINT_R:
98 return 1;
99
100 // 2 operands
101 case OpCode::MOV:
105 case OpCode::SQRT_R:
106 case OpCode::LOG_R:
107 case OpCode::EXP_R:
108 case OpCode::SIN_R:
109 case OpCode::COS_R:
110 case OpCode::TAN_R:
111 case OpCode::NEG_R:
112 case OpCode::NOT_R:
113 case OpCode::PUSH2_R:
114 case OpCode::POP2_R:
117 return 2;
118
119 // 3 operands
120 case OpCode::IADD_R:
121 case OpCode::ISUB_R:
122 case OpCode::IMUL_R:
123 case OpCode::IDIV_R:
124 case OpCode::IMOD_R:
125 case OpCode::FLADD_R:
126 case OpCode::FLSUB_R:
127 case OpCode::FLMUL_R:
128 case OpCode::FLDIV_R:
129 case OpCode::FLMOD_R:
130 case OpCode::POW_R:
131 case OpCode::IAND_R:
132 case OpCode::IOR_R:
133 case OpCode::IEQ_R:
134 case OpCode::INE_R:
135 case OpCode::ILT_R:
136 case OpCode::IGT_R:
137 case OpCode::ILE_R:
138 case OpCode::IGE_R:
139 case OpCode::FLAND_R:
140 case OpCode::FLOR_R:
141 case OpCode::FLEQ_R:
142 case OpCode::FLNE_R:
143 case OpCode::FLLT_R:
144 case OpCode::FLGT_R:
145 case OpCode::FLLE_R:
146 case OpCode::FLGE_R:
147 return 3;
148
149 default:
150 return 0;
151 }
152}
153
155{
156 // Stack operations with special indices
157 if (op == OpCode::PUSH_CONST && operandIndex == 0)
159 if (op == OpCode::STORE_VAR && operandIndex == 0)
161 if (op == OpCode::LOAD_VAR && operandIndex == 0)
163 if (op == OpCode::IMPORT && operandIndex == 0)
165 if (op == OpCode::CALL_NATIVE && operandIndex == 0)
167 if (op == OpCode::CALL && operandIndex == 0)
169 if (op == OpCode::SYSTEM && operandIndex == 0)
171
172 // Register operations with mixed types
173 if (op == OpCode::LOAD_CONST_R)
174 {
175 if (operandIndex == 0) return OperandType::REGISTER;
176 if (operandIndex == 1) return OperandType::CONSTANT_IDX;
177 }
178 if (op == OpCode::LOAD_VAR_R)
179 {
180 if (operandIndex == 0) return OperandType::REGISTER;
181 if (operandIndex == 1) return OperandType::VARIABLE_IDX;
182 }
183 if (op == OpCode::STORE_VAR_R)
184 {
185 if (operandIndex == 0) return OperandType::REGISTER;
186 if (operandIndex == 1) return OperandType::VARIABLE_IDX;
187 }
188
189 // JUMP instructions take an offset (INT)
190 if (op == OpCode::JUMP || op == OpCode::JUMP_IF_FALSE ||
192 return OperandType::INT;
193
194 // Register ops use REGISTER for all operands
195 if (static_cast<int>(op) >= static_cast<int>(OpCode::MOV))
197
198 return OperandType::INT;
199}
200
201std::string PhasorIR::escapeString(const std::string &str)
202{
203 std::stringstream ss;
204 for (unsigned char c : str)
205 {
206 switch (c)
207 {
208 case '\a': ss << "\\a"; break;
209 case '\b': ss << "\\b"; break;
210 case '\f': ss << "\\f"; break;
211 case '\n': ss << "\\n"; break;
212 case '\r': ss << "\\r"; break;
213 case '\t': ss << "\\t"; break;
214 case '\v': ss << "\\v"; break;
215 case '\x1b': ss << "\\e"; break;
216 case '\\': ss << "\\\\"; break;
217 case '"': ss << "\\\""; break;
218 default:
219 if (c < 0x20 || c == 0x7F)
220 {
221 ss << "\\x"
222 << "0123456789abcdef"[c >> 4]
223 << "0123456789abcdef"[c & 0xF];
224 }
225 else
226 {
227 ss << static_cast<char>(c);
228 }
229 break;
230 }
231 }
232 return ss.str();
233}
234
235std::string PhasorIR::unescapeString(const std::string &str)
236{
237 std::string result;
238 size_t len = str.length();
239
240 auto hexVal = [](char c) -> int {
241 if (c >= '0' && c <= '9') return c - '0';
242 if (c >= 'a' && c <= 'f') return c - 'a' + 10;
243 if (c >= 'A' && c <= 'F') return c - 'A' + 10;
244 return -1;
245 };
246
247 for (size_t i = 0; i < len; ++i)
248 {
249 if (str[i] != '\\' || i + 1 >= len)
250 {
251 result += str[i];
252 continue;
253 }
254
255 char esc = str[++i];
256 switch (esc)
257 {
258 case 'a': result += '\a'; break;
259 case 'b': result += '\b'; break;
260 case 'f': result += '\f'; break;
261 case 'n': result += '\n'; break;
262 case 'r': result += '\r'; break;
263 case 't': result += '\t'; break;
264 case 'v': result += '\v'; break;
265 case '\\': result += '\\'; break;
266 case '\'': result += '\''; break;
267 case '"': result += '"'; break;
268 case 'e':
269 case 'E': result += '\x1b'; break;
270
271 case '0': case '1': case '2': case '3':
272 case '4': case '5': case '6': case '7':
273 {
274 u32 val = static_cast<u32>(esc - '0');
275 for (int k = 1; k < 3 && i + 1 < len; ++k)
276 {
277 char d = str[i + 1];
278 if (d < '0' || d > '7') break;
279 val = val * 8 + static_cast<u32>(d - '0');
280 ++i;
281 }
282 result += static_cast<char>(val & 0xFF);
283 break;
284 }
285
286 case 'x':
287 {
288 if (i + 1 >= len || hexVal(str[i + 1]) < 0) { result += esc; break; }
289 int val = hexVal(str[++i]);
290 if (i + 1 < len && hexVal(str[i + 1]) >= 0)
291 val = (val << 4) | hexVal(str[++i]);
292 result += static_cast<char>(val);
293 break;
294 }
295
296 case 'u':
297 case 'U':
298 {
299 int ndigits = (esc == 'u') ? 4 : 8;
300 u32 cp = 0;
301 bool ok = true;
302 for (int k = 0; k < ndigits; ++k)
303 {
304 if (i + 1 >= len || hexVal(str[i + 1]) < 0) { ok = false; break; }
305 cp = (cp << 4) | static_cast<u32>(hexVal(str[++i]));
306 }
307 if (!ok || cp > 0x10FFFF || (cp >= 0xD800 && cp <= 0xDFFF))
308 {
309 result += esc; break;
310 }
311 if (cp <= 0x7F) { result += static_cast<char>(cp); }
312 else if (cp <= 0x7FF) { result += static_cast<char>(0xC0 | (cp >> 6));
313 result += static_cast<char>(0x80 | (cp & 0x3F)); }
314 else if (cp <= 0xFFFF) { result += static_cast<char>(0xE0 | (cp >> 12));
315 result += static_cast<char>(0x80 | ((cp >> 6) & 0x3F));
316 result += static_cast<char>(0x80 | (cp & 0x3F)); }
317 else { result += static_cast<char>(0xF0 | (cp >> 18));
318 result += static_cast<char>(0x80 | ((cp >> 12) & 0x3F));
319 result += static_cast<char>(0x80 | ((cp >> 6) & 0x3F));
320 result += static_cast<char>(0x80 | (cp & 0x3F)); }
321 break;
322 }
323
324 default:
325 result += '\\';
326 result += esc;
327 break;
328 }
329 }
330 return result;
331}
332
333// ---------------------------------------------------------------------------
334// Helper: write a single Value to a stringstream
335// ---------------------------------------------------------------------------
336static void writeIRValue(std::stringstream &ss, const Value &val,
337 const std::function<std::string(const std::string &)> &escape)
338{
339 switch (val.getType())
340 {
341 case ValueType::Null:
342 ss << "NULL\n";
343 break;
344 case ValueType::Bool:
345 ss << "BOOL " << (val.asBool() ? "true" : "false") << "\n";
346 break;
347 case ValueType::Int:
348 ss << "INT " << val.asInt() << "\n";
349 break;
350 case ValueType::Float:
351 ss << "FLOAT " << val.asFloat() << "\n";
352 break;
354 ss << "STRING \"" << escape(val.asString()) << "\"\n";
355 break;
356
358 {
359 auto structPtr = val.asStruct();
360 if (!structPtr)
361 throw std::runtime_error("PhasorIR::serialize: null struct pointer");
362 ss << "STRUCT \"" << escape(structPtr->structName) << "\" " << structPtr->fields.size() << "\n";
363 for (const auto &[fieldName, fieldVal] : structPtr->fields)
364 {
365 ss << " FIELD " << fieldName << " ";
366 writeIRValue(ss, fieldVal, escape);
367 }
368 break;
369 }
370
371 case ValueType::Array:
372 {
373 auto arrayPtr = val.asArray();
374 if (!arrayPtr)
375 throw std::runtime_error("PhasorIR::serialize: null array pointer");
376 ss << "ARRAY " << arrayPtr->size() << "\n";
377 for (const auto &elem : *arrayPtr)
378 {
379 ss << " ELEM ";
380 writeIRValue(ss, elem, escape);
381 }
382 break;
383 }
384
385 default:
386 throw std::runtime_error("PhasorIR::serialize: unknown ValueType");
387 }
388}
389
390// ---------------------------------------------------------------------------
391// Helper: read a single Value from a stringstream
392// ---------------------------------------------------------------------------
393static Value readIRValue(const std::string &type, std::stringstream &ss,
394 const std::function<std::string(const std::string &)> &unescape)
395{
396 if (type == "NULL")
397 {
398 return Value{};
399 }
400 else if (type == "BOOL")
401 {
402 std::string b;
403 ss >> b;
404 return Value{b == "true"};
405 }
406 else if (type == "INT")
407 {
408 i64 v;
409 ss >> v;
410 return Value{v};
411 }
412 else if (type == "FLOAT")
413 {
414 f64 v;
415 ss >> v;
416 return Value{v};
417 }
418 else if (type == "STRING")
419 {
420 std::string s;
421 char c;
422 while (ss.get(c) && c != '"') {}
423 std::getline(ss, s, '"');
424 return Value{unescape(s)};
425 }
426 else if (type == "STRUCT")
427 {
428 std::string typeName;
429 int fieldCount = 0;
430
431 char qc;
432 while (ss.get(qc) && qc != '"') {}
433 std::getline(ss, typeName, '"');
434 typeName = unescape(typeName);
435 ss >> fieldCount;
436
437 auto structInstance = std::make_shared<Value::StructInstance>();
438 structInstance->structName = PhsString(typeName);
439
440 for (int f = 0; f < fieldCount; ++f)
441 {
442 std::string keyword, fieldName, fieldType;
443 ss >> keyword; // "FIELD"
444 ss >> fieldName;
445 ss >> fieldType;
446 structInstance->fields[fieldName] = readIRValue(fieldType, ss, unescape);
447 }
448
449 return Value{std::move(structInstance)};
450 }
451 else if (type == "ARRAY")
452 {
453 int elementCount = 0;
454 ss >> elementCount;
455
456 auto arrayInstance = std::make_shared<Value::ArrayInstance>();
457 arrayInstance->reserve(static_cast<size_t>(elementCount));
458
459 for (int e = 0; e < elementCount; ++e)
460 {
461 std::string keyword, elemType;
462 ss >> keyword; // "ELEM"
463 ss >> elemType;
464 arrayInstance->push_back(readIRValue(elemType, ss, unescape));
465 }
466
467 return Value{std::move(arrayInstance)};
468 }
469 else
470 {
471 throw std::runtime_error("PhasorIR: unknown value type tag: " + type);
472 }
473}
474
475// ---------------------------------------------------------------------------
476// serialize
477// ---------------------------------------------------------------------------
478std::vector<u8> PhasorIR::serialize(const Bytecode &bytecode)
479{
480 std::stringstream ss;
481
482 // Header
483 ss << ".PHIR 3.0.0\n";
484
485 // Build reverse lookup maps for inline comments
486 std::map<int, std::string> indexToVarName;
487 for (const auto &[name, index] : bytecode.variables)
488 indexToVarName[index] = name;
489
490 std::map<int, std::string> addressToFuncName;
491 for (const auto &[name, address] : bytecode.functionEntries)
492 addressToFuncName[address] = name;
493
494 // Constants Section
495 ss << ".CONSTANTS " << bytecode.constants.size() << "\n";
496 for (const auto &val : bytecode.constants)
497 writeIRValue(ss, val, escapeString);
498
499 // Variables Section
500 ss << ".VARIABLES " << bytecode.variables.size() << " " << bytecode.nextVarIndex << "\n";
501 for (const auto &[name, index] : bytecode.variables)
502 ss << name << " " << index << "\n";
503
504 // Functions Section
505 ss << ".FUNCTIONS " << bytecode.functionEntries.size() << "\n";
506 for (const auto &[name, address] : bytecode.functionEntries)
507 ss << name << " " << address << "\n";
508
509 // Structs Section
510 ss << ".STRUCTS " << bytecode.structs.size() << "\n";
511 for (const auto &info : bytecode.structs)
512 {
513 ss << info.name << " " << info.firstConstIndex << " " << info.fieldCount;
514 for (const auto &fieldName : info.fieldNames)
515 ss << " " << fieldName;
516 ss << "\n";
517 }
518
519 // Instructions Section
520 ss << ".INSTRUCTIONS " << bytecode.instructions.size() << "\n";
521 for (const auto &instr : bytecode.instructions)
522 {
523 std::stringstream instrLine;
524 instrLine << opCodeToString(instr.op);
525
526 int operandCount = getOperandCount(instr.op);
527 i32 operands[3] = {instr.operand1, instr.operand2, instr.operand3};
528 std::string comment;
529
530 for (int i = 0; i < operandCount; ++i)
531 {
532 OperandType type = getOperandType(instr.op, i);
533
534 if (i > 0) instrLine << ",";
535 instrLine << " ";
536
537 switch (type)
538 {
540 instrLine << "r" << operands[i];
541 break;
543 instrLine << operands[i];
544 if (operands[i] >= 0 && std::cmp_less(operands[i], bytecode.constants.size()))
545 {
546 const Value &v = bytecode.constants[operands[i]];
547 if (v.getType() == ValueType::String)
548 {
549 std::string str = v.asString();
550 if (str.length() > 20) str = str.substr(0, 20) + "...";
551 comment = "const[" + std::to_string(operands[i]) + "]=\"" + escapeString(str) + "\"";
552 }
553 else if (v.getType() == ValueType::Int)
554 comment = "const[" + std::to_string(operands[i]) + "]=" + std::to_string(v.asInt());
555 else if (v.getType() == ValueType::Float)
556 comment = "const[" + std::to_string(operands[i]) + "]=" + std::to_string(v.asFloat());
557 }
558 break;
560 instrLine << operands[i];
561 if (indexToVarName.contains(operands[i]))
562 comment = "var=" + indexToVarName[operands[i]];
563 break;
565 instrLine << operands[i];
566 if (addressToFuncName.contains(operands[i]))
567 comment = "func=" + addressToFuncName[operands[i]];
568 break;
569 default:
570 instrLine << operands[i];
571 break;
572 }
573 }
574
575 std::string lineStr = instrLine.str();
576 if (!comment.empty())
577 {
578 const size_t commentColumn = 40;
579 if (lineStr.length() < commentColumn)
580 lineStr.append(commentColumn - lineStr.length(), ' ');
581 else
582 lineStr += " ";
583 lineStr += "; " + comment;
584 }
585 ss << lineStr << "\n";
586 }
587
588 std::string textData = ss.str();
589 std::vector<u8> buffer;
590 buffer.insert(buffer.end(), textData.begin(), textData.end());
591 return buffer;
592}
593
594// ---------------------------------------------------------------------------
595// deserialize
596// ---------------------------------------------------------------------------
597Bytecode PhasorIR::deserialize(const std::vector<u8> &data)
598{
599 if (data.size() < 8)
600 throw std::runtime_error("Invalid Phasor IR file: too small");
601
602 std::string textData(data.begin() + 8, data.end());
603 std::stringstream ss(textData);
604 std::string section;
605 Bytecode bytecode;
606
607 while (ss >> section)
608 {
609 if (section == ".PHIR")
610 {
611 std::string version;
612 ss >> version;
613 if (version < "3.0.0")
614 throw std::runtime_error("Incompatible Phasor IR version");
615 }
616 else if (section == ".CONSTANTS")
617 {
618 int count;
619 ss >> count;
620 bytecode.constants.reserve(count);
621 for (int i = 0; i < count; ++i)
622 {
623 std::string type;
624 ss >> type;
625 bytecode.constants.push_back(readIRValue(type, ss, unescapeString));
626 }
627 }
628 else if (section == ".VARIABLES")
629 {
630 int count;
631 ss >> count >> bytecode.nextVarIndex;
632 for (int i = 0; i < count; ++i)
633 {
634 std::string name;
635 int index;
636 ss >> name >> index;
637 bytecode.variables[name] = index;
638 }
639 }
640 else if (section == ".FUNCTIONS")
641 {
642 int count;
643 ss >> count;
644 for (int i = 0; i < count; ++i)
645 {
646 std::string name;
647 int address;
648 ss >> name >> address;
649 bytecode.functionEntries[name] = address;
650 }
651 }
652 else if (section == ".STRUCTS")
653 {
654 int count;
655 ss >> count;
656 for (int i = 0; i < count; ++i)
657 {
658 StructInfo info;
659 ss >> info.name >> info.firstConstIndex >> info.fieldCount;
660 info.fieldNames.clear();
661 for (int f = 0; f < info.fieldCount; ++f)
662 {
663 std::string fieldName;
664 ss >> fieldName;
665 info.fieldNames.push_back(fieldName);
666 }
667 int index = static_cast<int>(bytecode.structs.size());
668 bytecode.structs.push_back(std::move(info));
669 bytecode.structEntries[bytecode.structs.back().name] = index;
670 }
671 }
672 else if (section == ".INSTRUCTIONS")
673 {
674 int count;
675 ss >> count;
676 bytecode.instructions.reserve(count);
677 for (int i = 0; i < count; ++i)
678 {
679 std::string opStr;
680 ss >> opStr;
681
682 OpCode op = stringToOpCode(opStr);
683 int operandCount = getOperandCount(op);
684 i32 operands[3] = {0, 0, 0};
685
686 for (int j = 0; j < operandCount; ++j)
687 {
688 std::string token;
689 ss >> token;
690
691 if (token.empty() || token[0] == ';')
692 {
693 std::getline(ss, token);
694 break;
695 }
696
697 if (!token.empty() && token.back() == ',')
698 token.pop_back();
699
700 if (!token.empty() && token[0] == 'r')
701 operands[j] = std::stoi(token.substr(1));
702 else
703 operands[j] = std::stoi(token);
704 }
705
706 // Skip any remaining content on the line (comments)
707 char c;
708 while (ss.get(c) && c != '\n') {}
709
710 bytecode.instructions.emplace_back(op, operands[0], operands[1], operands[2]);
711 }
712 }
713 }
714
715 return bytecode;
716}
717
718// ---------------------------------------------------------------------------
719// saveToFile / loadFromFile
720// ---------------------------------------------------------------------------
721bool PhasorIR::saveToFile(const Bytecode &bytecode, const std::filesystem::path &filename)
722{
723 try
724 {
725 std::vector<u8> data = serialize(bytecode);
726 std::ofstream file(filename, std::ios::binary);
727 if (!file.is_open())
728 return false;
729 file.write(reinterpret_cast<const char *>(data.data()), (std::streamsize)data.size());
730 return true;
731 }
732 catch (...)
733 {
734 return false;
735 }
736}
737
738Bytecode PhasorIR::loadFromFile(const std::filesystem::path &filename)
739{
740 std::ifstream file(filename, std::ios::binary | std::ios::ate);
741 if (!file.is_open())
742 throw std::runtime_error("Cannot open file");
743
744 std::streamsize size = file.tellg();
745 file.seekg(0, std::ios::beg);
746 std::vector<u8> buffer(size);
747 if (!file.read(reinterpret_cast<char *>(buffer.data()), size))
748 throw std::runtime_error("Cannot read file");
749
750 return deserialize(buffer);
751}
752
753} // namespace Phasor
static std::string unescapeString(const std::string &str)
Helper to unescape strings from text format.
Definition PhasorIR.cpp:235
OperandType
Operand types for instructions.
Definition PhasorIR.hpp:42
@ VARIABLE_IDX
Index into variable mapping.
Definition PhasorIR.hpp:47
@ CONSTANT_IDX
Index into constant pool.
Definition PhasorIR.hpp:46
@ FUNCTION_IDX
Index into function entries.
Definition PhasorIR.hpp:48
@ REGISTER
Register operand.
Definition PhasorIR.hpp:45
static std::vector< u8 > serialize(const Bytecode &bytecode)
Serialize bytecode to Phasor IR format.
Definition PhasorIR.cpp:478
static OperandType getOperandType(OpCode op, int operandIndex)
Definition PhasorIR.cpp:154
static Bytecode loadFromFile(const std::filesystem::path &filename)
Load bytecode from .phir file.
Definition PhasorIR.cpp:738
static int getOperandCount(OpCode op)
Definition PhasorIR.cpp:20
static std::string escapeString(const std::string &str)
Helper to escape strings for text format.
Definition PhasorIR.cpp:201
static Bytecode deserialize(const std::vector< u8 > &data)
Deserialize Phasor IR format to bytecode.
Definition PhasorIR.cpp:597
static bool saveToFile(const Bytecode &bytecode, const std::filesystem::path &filename)
Save bytecode to .phir file.
Definition PhasorIR.cpp:721
A value in the Phasor VM.
Definition Value.hpp:59
PhsString asString() const noexcept
Get the value as a Small String.
Definition Value.hpp:199
std::shared_ptr< StructInstance > asStruct()
Definition Value.hpp:557
std::shared_ptr< ArrayInstance > asArray()
Get the value as an array.
Definition Value.hpp:208
ValueType getType() const noexcept
Get the type of the value.
Definition Value.hpp:118
f64 asFloat() const noexcept
Get the value as a f64.
Definition Value.hpp:177
i64 asInt() const noexcept
Get the value as an integer.
Definition Value.hpp:164
bool asBool() const noexcept
Get the value as a boolean.
Definition Value.hpp:159
static Phasor::u64 s[2]
Definition random.cpp:7
The Phasor Programming Language and Runtime.
Definition AST.hpp:13
int64_t i64
Definition phsint.hpp:16
static Value readIRValue(const std::string &type, std::stringstream &ss, const std::function< std::string(const std::string &)> &unescape)
Definition PhasorIR.cpp:393
double f64
Definition phsint.hpp:7
OpCode stringToOpCode(const std::string &str)
Definition map.cpp:142
std::string opCodeToString(OpCode op)
Definition map.cpp:132
int32_t i32
Definition phsint.hpp:15
OpCode
Definition ISA.hpp:12
@ IGREATER_THAN
Pop b, pop a, push a > b.
Definition ISA.hpp:50
@ IEQUAL
Pop b, pop a, push a == b.
Definition ISA.hpp:47
@ SYSTEM_OUT
Call system function and push stdout.
Definition ISA.hpp:79
@ LOG_R
R[rA] = log(R[rB]).
Definition ISA.hpp:125
@ FLMOD_R
R[rA] = R[rB] % R[rC].
Definition ISA.hpp:122
@ SUBSTR
Pop len, pop start, pop s, push s.substr(start, len).
Definition ISA.hpp:91
@ IAND
Pop b, pop a, push a && b.
Definition ISA.hpp:41
@ NOT
Pop a, push !a.
Definition ISA.hpp:38
@ SET_FIELD_STATIC
Pop value and struct instance, set field by static offset.
Definition ISA.hpp:99
@ NULL_VAL
Push null.
Definition ISA.hpp:86
@ MOV
Copy register to register: R[rA] = R[rB].
Definition ISA.hpp:103
@ POW
pow()
Definition ISA.hpp:29
@ PRINTERROR_R
Print register to stderr: printerror(R[rA]).
Definition ISA.hpp:155
@ IAND_R
R[rA] = R[rB] && R[rC].
Definition ISA.hpp:132
@ FLMUL_R
R[rA] = R[rB] * R[rC].
Definition ISA.hpp:120
@ IADD
Pop b, pop a, push a + b.
Definition ISA.hpp:18
@ PUSH2_R
Push 2 registers to stack: push2(R[rA], R[rB]).
Definition ISA.hpp:108
@ FLGE_R
R[rA] = R[rB] >= R[rC].
Definition ISA.hpp:147
@ SYSTEM_R
Run an operating system shell command: system(R[rA]).
Definition ISA.hpp:157
@ PUSH_CONST
Push constant from constant pool.
Definition ISA.hpp:14
@ JUMP_IF_TRUE
Jump if top of stack is true (pops value).
Definition ISA.hpp:63
@ FLGT_R
R[rA] = R[rB] > R[rC].
Definition ISA.hpp:145
@ PUSH_R
Push register to stack: push(R[rA]).
Definition ISA.hpp:107
@ POP_R
Pop stack to register: R[rA] = pop().
Definition ISA.hpp:109
@ FLEQUAL
Pop b, pop a, push a == b.
Definition ISA.hpp:53
@ GET_FIELD_STATIC
Pop struct instance, push field by static offset (structIndex, fieldOffset).
Definition ISA.hpp:98
@ FLNOT_EQUAL
Pop b, pop a, push a != b.
Definition ISA.hpp:54
@ FLADD_R
R[rA] = R[rB] + R[rC].
Definition ISA.hpp:118
@ POP2_R
Pop 2 values from stack to registers: pop2(R[rA], R[rB]).
Definition ISA.hpp:110
@ LOAD_CONST_R
Load constant to register: R[rA] = constants[immediate].
Definition ISA.hpp:104
@ SQRT
sqrt()
Definition ISA.hpp:28
@ FLADD
Pop b, pop a, push a + b.
Definition ISA.hpp:23
@ JUMP
Unconditional jump to offset.
Definition ISA.hpp:61
@ FLLT_R
R[rA] = R[rB] < R[rC].
Definition ISA.hpp:144
@ SET_FIELD
Pop struct, pop field name, pop value, set field value.
Definition ISA.hpp:95
@ NOT_R
R[rA] = !R[rB].
Definition ISA.hpp:151
@ IMULTIPLY
Pop b, pop a, push a * b.
Definition ISA.hpp:20
@ READLINE_R
Read line into register: readline(R[rA]).
Definition ISA.hpp:156
@ LOG
log()
Definition ISA.hpp:30
@ CHAR_AT
Pop index, pop s, push s[index].
Definition ISA.hpp:90
@ IMUL_R
R[rA] = R[rB] * R[rC].
Definition ISA.hpp:115
@ FLGREATER_EQUAL
Pop b, pop a, push a >= b.
Definition ISA.hpp:58
@ FLLE_R
R[rA] = R[rB] <= R[rC].
Definition ISA.hpp:146
@ IGREATER_EQUAL
Pop b, pop a, push a >= b.
Definition ISA.hpp:52
@ SIN
sin()
Definition ISA.hpp:32
@ SYSTEM_ERR
Call system function and push stderr.
Definition ISA.hpp:80
@ SQRT_R
R[rA] = sqrt(R[rB]).
Definition ISA.hpp:123
@ ISUB_R
R[rA] = R[rB] - R[rC].
Definition ISA.hpp:114
@ FLDIV_R
R[rA] = R[rB] / R[rC].
Definition ISA.hpp:121
@ COS_R
R[rA] = cos(R[rB]).
Definition ISA.hpp:128
@ CALL_NATIVE
Call a native function: operand is index of function name in constants.
Definition ISA.hpp:76
@ ISUBTRACT
Pop b, pop a, push a - b.
Definition ISA.hpp:19
@ LEN
Pop s, push len(s).
Definition ISA.hpp:89
@ TAN
tan()
Definition ISA.hpp:34
@ FLMODULO
Pop b, pop a, push a % b.
Definition ISA.hpp:27
@ FALSE_P
Push false.
Definition ISA.hpp:85
@ NEW_STRUCT_INSTANCE_STATIC
Create new struct instance using struct section metadata (structIndex).
Definition ISA.hpp:97
@ NEG_R
R[rA] = -R[rB].
Definition ISA.hpp:150
@ IDIVIDE
Pop b, pop a, push a / b.
Definition ISA.hpp:21
@ STORE_VAR
Pop top of stack, store in variable slot.
Definition ISA.hpp:67
@ ILE_R
R[rA] = R[rB] <= R[rC].
Definition ISA.hpp:138
@ FLDIVIDE
Pop b, pop a, push a / b.
Definition ISA.hpp:26
@ POW_R
R[rA] = pow(R[rB], R[rC]).
Definition ISA.hpp:124
@ EXP
exp()
Definition ISA.hpp:31
@ IMODULO
Pop b, pop a, push a % b.
Definition ISA.hpp:22
@ FLAND_R
R[rA] = R[rB] && R[rC].
Definition ISA.hpp:140
@ JUMP_IF_FALSE
Jump if top of stack is false (pops value).
Definition ISA.hpp:62
@ INOT_EQUAL
Pop b, pop a, push a != b.
Definition ISA.hpp:48
@ FLEQ_R
R[rA] = R[rB] == R[rC].
Definition ISA.hpp:142
@ LOAD_VAR
Push variable value onto stack.
Definition ISA.hpp:68
@ IOR
Pop b, pop a, push a || b.
Definition ISA.hpp:42
@ EXP_R
R[rA] = exp(R[rB]).
Definition ISA.hpp:126
@ RETURN
Return from function.
Definition ISA.hpp:81
@ STORE_VAR_R
Store register to varible: variables[immediate] = R[rA].
Definition ISA.hpp:106
@ READLINE
Read line from input and push onto stack.
Definition ISA.hpp:73
@ IGT_R
R[rA] = R[rB] > R[rC].
Definition ISA.hpp:137
@ FLSUBTRACT
Pop b, pop a, push a - b.
Definition ISA.hpp:24
@ IADD_R
R[rA] = R[rB] + R[rC].
Definition ISA.hpp:113
@ IDIV_R
R[rA] = R[rB] / R[rC].
Definition ISA.hpp:116
@ FLLESS_EQUAL
Pop b, pop a, push a <= b.
Definition ISA.hpp:57
@ SYSTEM_ERR_R
Run shell command and get output: system_out(R[rA], R[rB]).
Definition ISA.hpp:159
@ FLMULTIPLY
Pop b, pop a, push a * b.
Definition ISA.hpp:25
@ ILESS_EQUAL
Pop b, pop a, push a <= b.
Definition ISA.hpp:51
@ HALT
Stop execution.
Definition ISA.hpp:75
@ PRINT_R
Print register: print(R[rA]).
Definition ISA.hpp:154
@ PRINTERROR
Pop top of stack and print to stderr.
Definition ISA.hpp:72
@ TAN_R
R[rA] = tan(R[rB]).
Definition ISA.hpp:129
@ FLSUB_R
R[rA] = R[rB] - R[rC].
Definition ISA.hpp:119
@ JUMP_BACK
Jump backwards (for loops).
Definition ISA.hpp:64
@ FLOR_R
R[rA] = R[rB] || R[rC].
Definition ISA.hpp:141
@ CALL
Call a user function: operand is index of function name in constants.
Definition ISA.hpp:77
@ INE_R
R[rA] = R[rB] != R[rC].
Definition ISA.hpp:135
@ NEGATE
Pop a, push -a.
Definition ISA.hpp:37
@ FLNE_R
R[rA] = R[rB] != R[rC].
Definition ISA.hpp:143
@ FLGREATER_THAN
Pop b, pop a, push a > b.
Definition ISA.hpp:56
@ ILESS_THAN
Pop b, pop a, push a < b.
Definition ISA.hpp:49
@ GET_FIELD
Pop struct, pop field name, push field value.
Definition ISA.hpp:94
@ SIN_R
R[rA] = sin(R[rB]).
Definition ISA.hpp:127
@ IMPORT
Import a module: operand is index of module path in constants.
Definition ISA.hpp:74
@ LOAD_VAR_R
Load variable to register: R[rA] = variables[immediate].
Definition ISA.hpp:105
@ FLLESS_THAN
Pop b, pop a, push a < b.
Definition ISA.hpp:55
@ NEW_STRUCT
Create new struct: operand is index of struct name in constants.
Definition ISA.hpp:93
@ IOR_R
R[rA] = R[rB] || R[rC].
Definition ISA.hpp:133
@ ILT_R
R[rA] = R[rB] < R[rC].
Definition ISA.hpp:136
@ TRUE_P
Push true.
Definition ISA.hpp:84
@ COS
cos()
Definition ISA.hpp:33
@ POP
Pop top of stack.
Definition ISA.hpp:15
@ IMOD_R
R[rA] = R[rB] % R[rC].
Definition ISA.hpp:117
@ PRINT
Pop top of stack and print.
Definition ISA.hpp:71
@ SYSTEM
Call a system function: operand is index of function name in constants.
Definition ISA.hpp:78
@ IEQ_R
R[rA] = R[rB] == R[rC].
Definition ISA.hpp:134
@ IGE_R
R[rA] = R[rB] >= R[rC].
Definition ISA.hpp:139
static void writeIRValue(std::stringstream &ss, const Value &val, const std::function< std::string(const std::string &)> &escape)
Definition PhasorIR.cpp:336
uint32_t u32
Definition phsint.hpp:11
Complete bytecode structure.
Definition CodeGen.hpp:50
std::unordered_map< std::string, int > variables
Variable name -> index mapping.
Definition CodeGen.hpp:53
std::vector< Instruction > instructions
List of instructions.
Definition CodeGen.hpp:51
std::unordered_map< std::string, int > functionEntries
Function name -> instruction index mapping.
Definition CodeGen.hpp:54
int nextVarIndex
Next available variable index.
Definition CodeGen.hpp:56
std::vector< Value > constants
Constant pool.
Definition CodeGen.hpp:52
std::vector< StructInfo > structs
List of struct descriptors.
Definition CodeGen.hpp:59
std::unordered_map< std::string, int > structEntries
Struct name -> index in structs.
Definition CodeGen.hpp:60
Struct metadata stored alongside bytecode (struct section).
Definition CodeGen.hpp:41
int firstConstIndex
Index into constants for the first default value.
Definition CodeGen.hpp:43
std::vector< std::string > fieldNames
Field names in declaration order.
Definition CodeGen.hpp:45
int fieldCount
Number of fields in this struct.
Definition CodeGen.hpp:44
std::string name
Struct name.
Definition CodeGen.hpp:42