| // Copyright (c) 2019 Pantor. All rights reserved. |
| |
| #ifndef INCLUDE_INJA_BYTECODE_HPP_ |
| #define INCLUDE_INJA_BYTECODE_HPP_ |
| |
| #include <string> |
| #include <utility> |
| |
| #include <nlohmann/json.hpp> |
| |
| #include "string_view.hpp" |
| |
| |
| namespace inja { |
| |
| using json = nlohmann::json; |
| |
| |
| struct Bytecode { |
| enum class Op : uint8_t { |
| Nop, |
| // print StringRef (always immediate) |
| PrintText, |
| // print value |
| PrintValue, |
| // push value onto stack (always immediate) |
| Push, |
| |
| // builtin functions |
| // result is pushed to stack |
| // args specify number of arguments |
| // all functions can take their "last" argument either immediate |
| // or popped off stack (e.g. if immediate, it's like the immediate was |
| // just pushed to the stack) |
| Not, |
| And, |
| Or, |
| In, |
| Equal, |
| Greater, |
| GreaterEqual, |
| Less, |
| LessEqual, |
| At, |
| Different, |
| DivisibleBy, |
| Even, |
| First, |
| Float, |
| Int, |
| Last, |
| Length, |
| Lower, |
| Max, |
| Min, |
| Odd, |
| Range, |
| Result, |
| Round, |
| Sort, |
| Upper, |
| Exists, |
| ExistsInObject, |
| IsBoolean, |
| IsNumber, |
| IsInteger, |
| IsFloat, |
| IsObject, |
| IsArray, |
| IsString, |
| Default, |
| |
| // include another template |
| // value is the template name |
| Include, |
| |
| // callback function |
| // str is the function name (this means it cannot be a lookup) |
| // args specify number of arguments |
| // as with builtin functions, "last" argument can be immediate |
| Callback, |
| |
| // unconditional jump |
| // args is the index of the bytecode to jump to. |
| Jump, |
| |
| // conditional jump |
| // value popped off stack is checked for truthyness |
| // if false, args is the index of the bytecode to jump to. |
| // if true, no action is taken (falls through) |
| ConditionalJump, |
| |
| // start loop |
| // value popped off stack is what is iterated over |
| // args is index of bytecode after end loop (jumped to if iterable is |
| // empty) |
| // immediate value is key name (for maps) |
| // str is value name |
| StartLoop, |
| |
| // end a loop |
| // args is index of the first bytecode in the loop body |
| EndLoop, |
| }; |
| |
| enum Flag { |
| // location of value for value-taking ops (mask) |
| ValueMask = 0x03, |
| // pop value off stack |
| ValuePop = 0x00, |
| // value is immediate rather than on stack |
| ValueImmediate = 0x01, |
| // lookup immediate str (dot notation) |
| ValueLookupDot = 0x02, |
| // lookup immediate str (json pointer notation) |
| ValueLookupPointer = 0x03, |
| }; |
| |
| Op op {Op::Nop}; |
| uint32_t args: 30; |
| uint32_t flags: 2; |
| |
| json value; |
| std::string str; |
| |
| Bytecode(): args(0), flags(0) {} |
| explicit Bytecode(Op op, unsigned int args = 0): op(op), args(args), flags(0) {} |
| explicit Bytecode(Op op, nonstd::string_view str, unsigned int flags): op(op), args(0), flags(flags), str(str) {} |
| explicit Bytecode(Op op, json&& value, unsigned int flags): op(op), args(0), flags(flags), value(std::move(value)) {} |
| }; |
| |
| } // namespace inja |
| |
| #endif // INCLUDE_INJA_BYTECODE_HPP_ |