Phasor 3.1.1
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
10#if defined(_MSC_VER)
11#define COMPILE_MESSAGE(msg) __pragma(message(msg))
12#elif defined(__GNUC__) || defined(__clang__)
13#define DO_PRAGMA(x) _Pragma(#x)
14#define COMPILE_MESSAGE(msg) DO_PRAGMA(message msg)
15#else
16#define COMPILE_MESSAGE(msg)
17#endif
18#define STR2(x) #x
19#define STR(x) STR2(x)
20
21namespace Phasor
22{
23
25{
26 switch (op)
27 {
28 // 0 operands
29 case OpCode::POP:
30 case OpCode::IADD:
33 case OpCode::IDIVIDE:
34 case OpCode::IMODULO:
35 case OpCode::FLADD:
40 case OpCode::SQRT:
41 case OpCode::POW:
42 case OpCode::LOG:
43 case OpCode::EXP:
44 case OpCode::SIN:
45 case OpCode::COS:
46 case OpCode::TAN:
47 case OpCode::NEGATE:
48 case OpCode::NOT:
49 case OpCode::IAND:
50 case OpCode::IOR:
51 case OpCode::IEQUAL:
57 case OpCode::FLEQUAL:
63 case OpCode::PRINT:
66 case OpCode::HALT:
67 case OpCode::RETURN:
68 case OpCode::TRUE_P:
69 case OpCode::FALSE_P:
71 case OpCode::LEN:
72 case OpCode::CHAR_AT:
73 case OpCode::SUBSTR:
74 return 0;
75
76 // 1 operand
78 case OpCode::JUMP:
84 case OpCode::IMPORT:
86 case OpCode::CALL:
87 case OpCode::SYSTEM:
90 case OpCode::PUSH_R:
91 case OpCode::POP_R:
92 case OpCode::PRINT_R:
102 return 1;
103
104 // 2 operands
105 case OpCode::MOV:
109 case OpCode::SQRT_R:
110 case OpCode::LOG_R:
111 case OpCode::EXP_R:
112 case OpCode::SIN_R:
113 case OpCode::COS_R:
114 case OpCode::TAN_R:
115 case OpCode::NEG_R:
116 case OpCode::NOT_R:
117 case OpCode::PUSH2_R:
118 case OpCode::POP2_R:
121 return 2;
122
123 // 3 operands
124 case OpCode::IADD_R:
125 case OpCode::ISUB_R:
126 case OpCode::IMUL_R:
127 case OpCode::IDIV_R:
128 case OpCode::IMOD_R:
129 case OpCode::FLADD_R:
130 case OpCode::FLSUB_R:
131 case OpCode::FLMUL_R:
132 case OpCode::FLDIV_R:
133 case OpCode::FLMOD_R:
134 case OpCode::POW_R:
135 case OpCode::IAND_R:
136 case OpCode::IOR_R:
137 case OpCode::IEQ_R:
138 case OpCode::INE_R:
139 case OpCode::ILT_R:
140 case OpCode::IGT_R:
141 case OpCode::ILE_R:
142 case OpCode::IGE_R:
143 case OpCode::FLAND_R:
144 case OpCode::FLOR_R:
145 case OpCode::FLEQ_R:
146 case OpCode::FLNE_R:
147 case OpCode::FLLT_R:
148 case OpCode::FLGT_R:
149 case OpCode::FLLE_R:
150 case OpCode::FLGE_R:
151 return 3;
152
153 default:
154 return 0;
155 }
156}
157
159{
160 // Stack operations with special indices
161 if (op == OpCode::PUSH_CONST && operandIndex == 0)
163 if (op == OpCode::STORE_VAR && operandIndex == 0)
165 if (op == OpCode::LOAD_VAR && operandIndex == 0)
167 if (op == OpCode::IMPORT && operandIndex == 0)
169 if (op == OpCode::CALL_NATIVE && operandIndex == 0)
171 if (op == OpCode::CALL && operandIndex == 0)
173 if (op == OpCode::SYSTEM && operandIndex == 0)
175
176 // Register operations with mixed types
177 if (op == OpCode::LOAD_CONST_R)
178 {
179 if (operandIndex == 0)
181 if (operandIndex == 1)
183 }
184 if (op == OpCode::LOAD_VAR_R)
185 {
186 if (operandIndex == 0)
188 if (operandIndex == 1)
190 }
191 if (op == OpCode::STORE_VAR_R)
192 {
193 if (operandIndex == 0)
195 if (operandIndex == 1)
197 }
198
199 // JUMP instructions take an offset (INT)
201 {
202 return OperandType::INT;
203 }
204
205 // Register ops use REGISTER for all operands
206 if (static_cast<int>(op) >= static_cast<int>(OpCode::MOV))
207 {
209 }
210
211 return OperandType::INT;
212}
213
214std::string PhasorIR::escapeString(const std::string &str)
215{
216 std::stringstream ss;
217 for (char c : str)
218 {
219 switch (c)
220 {
221 case '\n':
222 ss << "\\n";
223 break;
224 case '\r':
225 ss << "\\r";
226 break;
227 case '\t':
228 ss << "\\t";
229 break;
230 case '\\':
231 ss << "\\\\";
232 break;
233 case '"':
234 ss << "\\\"";
235 break;
236 default:
237 ss << c;
238 break;
239 }
240 }
241 return ss.str();
242}
243
244std::string PhasorIR::unescapeString(const std::string &str)
245{
246 std::string result;
247 for (size_t i = 0; i < str.length(); ++i)
248 {
249 if (str[i] == '\\' && i + 1 < str.length())
250 {
251 switch (str[i + 1])
252 {
253 case 'n':
254 result += '\n';
255 break;
256 case 'r':
257 result += '\r';
258 break;
259 case 't':
260 result += '\t';
261 break;
262 case '\\':
263 result += '\\';
264 break;
265 case '"':
266 result += '"';
267 break;
268 default:
269 result += str[i];
270 result += str[i + 1];
271 break;
272 }
273 i++;
274 }
275 else
276 {
277 result += str[i];
278 }
279 }
280 return result;
281}
282
283std::vector<uint8_t> PhasorIR::serialize(const Bytecode &bytecode)
284{
285 std::stringstream ss;
286
287 // Write Header
288 ss << ".PHIR 3.0.0" << "\n";
289
290 // Build reverse lookup maps for inline comments
291 std::map<int, std::string> indexToVarName;
292 for (const auto &[name, index] : bytecode.variables)
293 {
294 indexToVarName[index] = name;
295 }
296 std::map<int, std::string> addressToFuncName;
297 for (const auto &[name, address] : bytecode.functionEntries)
298 {
299 addressToFuncName[address] = name;
300 }
301
302 // Constants Section
303 ss << ".CONSTANTS " << bytecode.constants.size() << "\n";
304 for (const auto &val : bytecode.constants)
305 {
306 switch (val.getType())
307 {
308 case ValueType::Null:
309 ss << "NULL\n";
310 break;
311 case ValueType::Bool:
312 ss << "BOOL " << (val.asBool() ? "true" : "false") << "\n";
313 break;
314 case ValueType::Int:
315 ss << "INT " << val.asInt() << "\n";
316 break;
317 case ValueType::Float:
318 ss << "FLOAT " << val.asFloat() << "\n";
319 break;
321 ss << "STRING \"" << escapeString(val.asString()) << "\"\n";
322 break;
324 COMPILE_MESSAGE("Warning: PHS_01 Structs have not been fully implemented! Line " STR(__LINE__))
325 throw std::runtime_error("Structs not implemented!");
326 break;
327 case ValueType::Array:
328 COMPILE_MESSAGE("Warning: PHS_02 Arrays have not been implemented! Line " STR(__LINE__))
329 throw std::runtime_error("Arrays not implemented!");
330 }
331 }
332
333 // Variables Section
334 ss << ".VARIABLES " << bytecode.variables.size() << " " << bytecode.nextVarIndex << "\n";
335 for (const auto &[name, index] : bytecode.variables)
336 {
337 ss << name << " " << index << "\n";
338 }
339
340 // Functions Section
341 ss << ".FUNCTIONS " << bytecode.functionEntries.size() << "\n";
342 for (const auto &[name, address] : bytecode.functionEntries)
343 {
344 ss << name << " " << address << "\n";
345 }
346
347 // Structs Section
348 ss << ".STRUCTS " << bytecode.structs.size() << "\n";
349 for (const auto &info : bytecode.structs)
350 {
351 // name firstConstIndex fieldCount fieldName0 fieldName1 ...
352 ss << info.name << " " << info.firstConstIndex << " " << info.fieldCount;
353 for (const auto &fieldName : info.fieldNames)
354 {
355 ss << " " << fieldName;
356 }
357 ss << "\n";
358 }
359
360 // Instructions Section
361 ss << ".INSTRUCTIONS " << bytecode.instructions.size() << "\n";
362 for (const auto &instr : bytecode.instructions)
363 {
364 std::stringstream instrLine;
365 instrLine << opCodeToString(instr.op);
366
367 int operandCount = getOperandCount(instr.op);
368 int32_t operands[3] = {instr.operand1, instr.operand2, instr.operand3};
369
370 std::string comment;
371
372 for (int i = 0; i < operandCount; ++i)
373 {
374 OperandType type = getOperandType(instr.op, i);
375
376 if (i > 0)
377 instrLine << ",";
378 instrLine << " ";
379
380 switch (type)
381 {
383 instrLine << "r" << operands[i];
384 break;
386 instrLine << operands[i];
387 if (operands[i] >= 0 && operands[i] < static_cast<int>(bytecode.constants.size()))
388 {
389 const Value &val = bytecode.constants[operands[i]];
390 if (val.getType() == ValueType::String)
391 {
392 std::string str = val.asString();
393 if (str.length() > 20)
394 str = str.substr(0, 20) + "...";
395 comment = "const[" + std::to_string(operands[i]) + "]=\"" + escapeString(str) + "\"";
396 }
397 else if (val.getType() == ValueType::Int)
398 {
399 comment = "const[" + std::to_string(operands[i]) + "]=" + std::to_string(val.asInt());
400 }
401 else if (val.getType() == ValueType::Float)
402 {
403 comment = "const[" + std::to_string(operands[i]) + "]=" + std::to_string(val.asFloat());
404 }
405 }
406 break;
408 instrLine << operands[i];
409 if (indexToVarName.count(operands[i]))
410 {
411 comment = "var=" + indexToVarName[operands[i]];
412 }
413 break;
415 instrLine << operands[i];
416 if (addressToFuncName.count(operands[i]))
417 {
418 comment = "func=" + addressToFuncName[operands[i]];
419 }
420 break;
421 default:
422 instrLine << operands[i];
423 break;
424 }
425 }
426
427 std::string lineStr = instrLine.str();
428 if (!comment.empty())
429 {
430 const size_t commentColumn = 40;
431 if (lineStr.length() < commentColumn)
432 {
433 lineStr.append(commentColumn - lineStr.length(), ' ');
434 }
435 else
436 {
437 lineStr += " ";
438 }
439
440 lineStr += "; " + comment;
441 }
442 ss << lineStr << "\n";
443 }
444
445 std::string textData = ss.str();
446 std::vector<uint8_t> buffer;
447
448 // Append text data
449 buffer.insert(buffer.end(), textData.begin(), textData.end());
450
451 return buffer;
452}
453
454Bytecode PhasorIR::deserialize(const std::vector<uint8_t> &data)
455{
456 if (data.size() < 8)
457 {
458 throw std::runtime_error("Invalid Phasor IR file: too small");
459 }
460
461 // Parse text data
462 std::string textData(data.begin() + 8, data.end());
463 std::stringstream ss(textData);
464 std::string line;
465 Bytecode bytecode;
466
467 std::string section;
468 while (ss >> section)
469 {
470 if (section == ".PHIR")
471 {
472 std::string version;
473 ss >> version;
474 if (version < "3.0.0")
475 {
476 throw std::runtime_error("Incompatible Phasor IR version");
477 }
478 }
479 if (section == ".CONSTANTS")
480 {
481 int count;
482 ss >> count;
483 bytecode.constants.reserve(count);
484 for (int i = 0; i < count; ++i)
485 {
486 std::string type;
487 ss >> type;
488 if (type == "NULL")
489 {
490 bytecode.constants.push_back(Value());
491 }
492 else if (type == "BOOL")
493 {
494 std::string valStr;
495 ss >> valStr;
496 bytecode.constants.push_back(Value(valStr == "true"));
497 }
498 else if (type == "INT")
499 {
500 int64_t val;
501 ss >> val;
502 bytecode.constants.push_back(Value(val));
503 }
504 else if (type == "FLOAT")
505 {
506 double val;
507 ss >> val;
508 bytecode.constants.push_back(Value(val));
509 }
510 else if (type == "STRING")
511 {
512 std::string valStr;
513 // Read quoted string, potentially with spaces
514 char c;
515 while (ss.get(c) && c != '"')
516 ; // Skip until opening quote
517 std::getline(ss, valStr, '"'); // Read until closing quote
518 bytecode.constants.push_back(Value(unescapeString(valStr)));
519 }
520 }
521 }
522 else if (section == ".VARIABLES")
523 {
524 int count;
525 ss >> count >> bytecode.nextVarIndex;
526 for (int i = 0; i < count; ++i)
527 {
528 std::string name;
529 int index;
530 ss >> name >> index;
531 bytecode.variables[name] = index;
532 }
533 }
534 else if (section == ".FUNCTIONS")
535 {
536 int count;
537 ss >> count;
538 for (int i = 0; i < count; ++i)
539 {
540 std::string name;
541 int address;
542 ss >> name >> address;
543 bytecode.functionEntries[name] = address;
544 }
545 }
546 else if (section == ".STRUCTS")
547 {
548 int count;
549 ss >> count;
550 for (int i = 0; i < count; ++i)
551 {
552 StructInfo info;
553 ss >> info.name >> info.firstConstIndex >> info.fieldCount;
554 info.fieldNames.clear();
555 for (int f = 0; f < info.fieldCount; ++f)
556 {
557 std::string fieldName;
558 ss >> fieldName;
559 info.fieldNames.push_back(fieldName);
560 }
561 int index = static_cast<int>(bytecode.structs.size());
562 bytecode.structs.push_back(std::move(info));
563 bytecode.structEntries[bytecode.structs.back().name] = index;
564 }
565 }
566 else if (section == ".INSTRUCTIONS")
567 {
568 int count;
569 ss >> count;
570 bytecode.instructions.reserve(count);
571 for (int i = 0; i < count; ++i)
572 {
573 std::string opStr;
574 ss >> opStr;
575
576 OpCode op = stringToOpCode(opStr);
577 int operandCount = getOperandCount(op);
578 int32_t operands[3] = {0, 0, 0};
579
580 for (int j = 0; j < operandCount; ++j)
581 {
582 std::string token;
583 ss >> token;
584
585 // Skip if we hit a comment
586 if (token.empty() || token[0] == ';')
587 {
588 // Skip rest of line
589 std::getline(ss, token);
590 break;
591 }
592
593 // Strip trailing comma if present
594 if (!token.empty() && token.back() == ',')
595 {
596 token.pop_back();
597 }
598
599 // Parse register format "rN" or plain integer
600 if (!token.empty() && token[0] == 'r')
601 {
602 operands[j] = std::stoi(token.substr(1));
603 }
604 else
605 {
606 operands[j] = std::stoi(token);
607 }
608 }
609
610 // Skip any remaining content on the line (comments)
611 char c;
612 while (ss.get(c) && c != '\n')
613 ;
614
615 bytecode.instructions.push_back(
616 Instruction(op, operands[0], operands[1], operands[2]));
617 }
618 }
619 }
620
621 return bytecode;
622}
623
624bool PhasorIR::saveToFile(const Bytecode &bytecode, const std::filesystem::path &filename)
625{
626 try
627 {
628 std::vector<uint8_t> data = serialize(bytecode);
629 std::ofstream file(filename, std::ios::binary);
630 if (!file.is_open())
631 return false;
632 file.write(reinterpret_cast<const char *>(data.data()), (std::streamsize)data.size());
633 return true;
634 }
635 catch (...)
636 {
637 return false;
638 }
639}
640
641Bytecode PhasorIR::loadFromFile(const std::filesystem::path &filename)
642{
643 std::ifstream file(filename, std::ios::binary | std::ios::ate);
644 if (!file.is_open())
645 throw std::runtime_error("Cannot open file");
646 std::streamsize size = file.tellg();
647 file.seekg(0, std::ios::beg);
648 std::vector<uint8_t> buffer(size);
649 if (!file.read(reinterpret_cast<char *>(buffer.data()), size))
650 throw std::runtime_error("Cannot read file");
651 return deserialize(buffer);
652}
653} // namespace Phasor
#define COMPILE_MESSAGE(msg)
#define STR(x)
static std::vector< uint8_t > serialize(const Bytecode &bytecode)
Serialize bytecode to Phasor IR format.
Definition PhasorIR.cpp:283
static std::string unescapeString(const std::string &str)
Helper to unescape strings from text format.
Definition PhasorIR.cpp:244
static Bytecode deserialize(const std::vector< uint8_t > &data)
Deserialize Phasor IR format to bytecode.
Definition PhasorIR.cpp:454
OperandType
Operand types for instructions.
Definition PhasorIR.hpp:41
@ VARIABLE_IDX
Index into variable mapping.
Definition PhasorIR.hpp:46
@ CONSTANT_IDX
Index into constant pool.
Definition PhasorIR.hpp:45
@ FUNCTION_IDX
Index into function entries.
Definition PhasorIR.hpp:47
@ REGISTER
Register operand.
Definition PhasorIR.hpp:44
static OperandType getOperandType(OpCode op, int operandIndex)
Definition PhasorIR.cpp:158
static Bytecode loadFromFile(const std::filesystem::path &filename)
Load bytecode from .phir file.
Definition PhasorIR.cpp:641
static int getOperandCount(OpCode op)
Definition PhasorIR.cpp:24
static std::string escapeString(const std::string &str)
Helper to escape strings for text format.
Definition PhasorIR.cpp:214
static bool saveToFile(const Bytecode &bytecode, const std::filesystem::path &filename)
Save bytecode to .phir file.
Definition PhasorIR.cpp:624
A value in the Phasor VM.
Definition Value.hpp:67
double asFloat() const
Get the value as a double.
Definition Value.hpp:214
std::string asString() const
Get the value as a string.
Definition Value.hpp:223
int64_t asInt() const
Get the value as an integer.
Definition Value.hpp:205
ValueType getType() const
Get the type of the value.
Definition Value.hpp:121
The Phasor Programming Language and Runtime.
Definition AST.hpp:11
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
OpCode stringToOpCode(const std::string &str)
Definition map.cpp:136
std::string opCodeToString(OpCode op)
Definition map.cpp:126
Complete bytecode structure.
Definition CodeGen.hpp:47
std::vector< StructInfo > structs
List of struct descriptors.
Definition CodeGen.hpp:56
std::vector< Value > constants
Constant pool.
Definition CodeGen.hpp:49
std::map< std::string, int > functionEntries
Function name -> instruction index mapping.
Definition CodeGen.hpp:51
int nextVarIndex
Next available variable index.
Definition CodeGen.hpp:53
std::map< std::string, int > structEntries
Struct name -> index in structs.
Definition CodeGen.hpp:57
std::map< std::string, int > variables
Variable name -> index mapping.
Definition CodeGen.hpp:50
std::vector< Instruction > instructions
List of instructions.
Definition CodeGen.hpp:48
Instruction with up to 5 operands Format: instruction operand1, operand2, operand3 Each instruction u...
Definition CodeGen.hpp:18
Struct metadata stored alongside bytecode (struct section).
Definition CodeGen.hpp:38
int firstConstIndex
Index into constants for the first default value.
Definition CodeGen.hpp:40
std::vector< std::string > fieldNames
Field names in declaration order.
Definition CodeGen.hpp:42
int fieldCount
Number of fields in this struct.
Definition CodeGen.hpp:41
std::string name
Struct name.
Definition CodeGen.hpp:39