Expressions #7
15
doc/OPCODES
15
doc/OPCODES
@@ -65,17 +65,20 @@ Logical/arithmetic:
|
|||||||
2b and Bitwise AND
|
2b and Bitwise AND
|
||||||
2c or Bitwise OR
|
2c or Bitwise OR
|
||||||
2d xor Bitwise XOR
|
2d xor Bitwise XOR
|
||||||
|
2e pow Power
|
||||||
|
2f shl Shift left
|
||||||
|
30 shr Shift right
|
||||||
|
|
||||||
Other value operations:
|
Other value operations:
|
||||||
30 len Get table, array or string size
|
40 len Get table, array or string size
|
||||||
31 type Get type from value at the top of the stack
|
41 type Get type from value at the top of the stack
|
||||||
b0 cast [type] Cast type to another type
|
b0 cast [type] Cast type to another type
|
||||||
32 ver Return VM version
|
42 ver Return VM version
|
||||||
|
|
||||||
External code:
|
External code:
|
||||||
38 cmpl Compile code to assembly
|
48 cmpl Compile code to assembly
|
||||||
39 asmbl Assemble code to bytecode format
|
49 asmbl Assemble code to bytecode format
|
||||||
3a load Load bytecode as function (will place function on stack)
|
4a load Load bytecode as function (will place function on stack)
|
||||||
|
|
||||||
Control flow:
|
Control flow:
|
||||||
a8 c8 e8 bz [pc] Branch if zero
|
a8 c8 e8 bz [pc] Branch if zero
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ std::string ByteArray::hexdump() const
|
|||||||
{
|
{
|
||||||
auto to_hex = [](uint32_t value, size_t n_chars) -> std::string {
|
auto to_hex = [](uint32_t value, size_t n_chars) -> std::string {
|
||||||
char buf[15];
|
char buf[15];
|
||||||
snprintf(buf, sizeof buf, (std::string("%0") + std::to_string(n_chars) + "X").c_str(), value);
|
snprintf(buf, sizeof buf, "%0*X", (int) n_chars, value);
|
||||||
return { buf };
|
return { buf };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ Operation Code::operation(Location const& location) const
|
|||||||
.operator_ = bytecode_.get_code_int32(location.function_id, location.pc + 1),
|
.operator_ = bytecode_.get_code_int32(location.function_id, location.pc + 1),
|
||||||
.next_location = { .function_id = location.function_id, .pc = location.pc + 5 },
|
.next_location = { .function_id = location.function_id, .pc = location.pc + 5 },
|
||||||
};
|
};
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::logic_error("Should not get here");
|
throw std::logic_error("Should not get here");
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "expr.hh"
|
#include "expr.hh"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include "vm_exceptions.hh"
|
#include "vm_exceptions.hh"
|
||||||
@@ -45,6 +46,12 @@ static int init_ = []() {
|
|||||||
|
|
||||||
BIN_OP(BitwiseXor, Integer, Integer) { return Value::CreateInteger(a.as_integer() ^ b.as_integer()); };
|
BIN_OP(BitwiseXor, Integer, Integer) { return Value::CreateInteger(a.as_integer() ^ b.as_integer()); };
|
||||||
|
|
||||||
|
BIN_OP(Power, Integer, Integer) { return Value::CreateInteger((int32_t) powl(a.as_integer(), b.as_integer())); };
|
||||||
|
|
||||||
|
BIN_OP(ShiftLeft, Integer, Integer) { return Value::CreateInteger(a.as_integer() << b.as_integer()); };
|
||||||
|
|
||||||
|
BIN_OP(ShiftRight, Integer, Integer) { return Value::CreateInteger(a.as_integer() >> b.as_integer()); };
|
||||||
|
|
||||||
#undef BIN_OP
|
#undef BIN_OP
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace tyche::vm {
|
|||||||
enum class BinaryOperationType
|
enum class BinaryOperationType
|
||||||
{
|
{
|
||||||
Sum, Subtraction, Multiplication, Division, IntegerDivision, Equality, Inequality, LessThan, LessThanOrEquals,
|
Sum, Subtraction, Multiplication, Division, IntegerDivision, Equality, Inequality, LessThan, LessThanOrEquals,
|
||||||
GreaterThan, GreaterThanOrEquals, BitwiseAnd, BitwiseOr, BitwiseXor,
|
GreaterThan, GreaterThanOrEquals, BitwiseAnd, BitwiseOr, BitwiseXor, Power, ShiftLeft, ShiftRight,
|
||||||
COUNT
|
COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,54 +5,57 @@
|
|||||||
|
|
||||||
namespace tyche::vm {
|
namespace tyche::vm {
|
||||||
|
|
||||||
const std::unordered_map<std::string, vm::Instruction> instruction_names = {
|
const std::unordered_map<std::string, Instruction> instruction_names = {
|
||||||
{ "pushi", vm::Instruction::PushInt8 },
|
{ "pushi", Instruction::PushInt8 },
|
||||||
{ "pushc", vm::Instruction::PushConstant8 },
|
{ "pushc", Instruction::PushConstant8 },
|
||||||
{ "pushz", vm::Instruction::PushZero },
|
{ "pushz", Instruction::PushZero },
|
||||||
{ "pusht", vm::Instruction::PushTrue },
|
{ "pusht", Instruction::PushTrue },
|
||||||
{ "newa", vm::Instruction::NewArray },
|
{ "newa", Instruction::NewArray },
|
||||||
{ "newt", vm::Instruction::NewTable },
|
{ "newt", Instruction::NewTable },
|
||||||
{ "pop", vm::Instruction::Pop },
|
{ "pop", Instruction::Pop },
|
||||||
{ "dup", vm::Instruction::Duplicate },
|
{ "dup", Instruction::Duplicate },
|
||||||
{ "setl", vm::Instruction::SetLocal8 },
|
{ "setl", Instruction::SetLocal8 },
|
||||||
{ "getl", vm::Instruction::GetLocal8 },
|
{ "getl", Instruction::GetLocal8 },
|
||||||
{ "setg", vm::Instruction::SetGlobal8 },
|
{ "setg", Instruction::SetGlobal8 },
|
||||||
{ "getl", vm::Instruction::GetGlobal8 },
|
{ "getl", Instruction::GetGlobal8 },
|
||||||
{ "call8", vm::Instruction::Call8 },
|
{ "call8", Instruction::Call8 },
|
||||||
{ "ret", vm::Instruction::Return },
|
{ "ret", Instruction::Return },
|
||||||
{ "retn", vm::Instruction::ReturnNil },
|
{ "retn", Instruction::ReturnNil },
|
||||||
{ "getkv", vm::Instruction::GetKeyValue },
|
{ "getkv", Instruction::GetKeyValue },
|
||||||
{ "setkv", vm::Instruction::SetKeyValue },
|
{ "setkv", Instruction::SetKeyValue },
|
||||||
{ "geta", vm::Instruction::GetArrayItem },
|
{ "geta", Instruction::GetArrayItem },
|
||||||
{ "seta", vm::Instruction::SetArrayItem },
|
{ "seta", Instruction::SetArrayItem },
|
||||||
{ "appnd", vm::Instruction::Append },
|
{ "appnd", Instruction::Append },
|
||||||
{ "next", vm::Instruction::Next },
|
{ "next", Instruction::Next },
|
||||||
{ "smt", vm::Instruction::SetMetatable },
|
{ "smt", Instruction::SetMetatable },
|
||||||
{ "mt", vm::Instruction::GetMetatable },
|
{ "mt", Instruction::GetMetatable },
|
||||||
{ "sum", vm::Instruction::Sum },
|
{ "sum", Instruction::Sum },
|
||||||
{ "sub", vm::Instruction::Subtract },
|
{ "sub", Instruction::Subtract },
|
||||||
{ "mul", vm::Instruction::Multiply },
|
{ "mul", Instruction::Multiply },
|
||||||
{ "div", vm::Instruction::Divide },
|
{ "div", Instruction::Divide },
|
||||||
{ "idiv", vm::Instruction::DivideInt },
|
{ "idiv", Instruction::DivideInt },
|
||||||
{ "eq", vm::Instruction::Equals },
|
{ "eq", Instruction::Equals },
|
||||||
{ "neq", vm::Instruction::NotEquals },
|
{ "neq", Instruction::NotEquals },
|
||||||
{ "lt", vm::Instruction::LessThan },
|
{ "lt", Instruction::LessThan },
|
||||||
{ "lte", vm::Instruction::LessThanEq },
|
{ "lte", Instruction::LessThanEq },
|
||||||
{ "gt", vm::Instruction::GreaterThan },
|
{ "gt", Instruction::GreaterThan },
|
||||||
{ "gte", vm::Instruction::GreaterThanEq },
|
{ "gte", Instruction::GreaterThanEq },
|
||||||
{ "and", vm::Instruction::And },
|
{ "and", Instruction::And },
|
||||||
{ "or", vm::Instruction::Or },
|
{ "or", Instruction::Or },
|
||||||
{ "xor", vm::Instruction::Xor },
|
{ "xor", Instruction::Xor },
|
||||||
{ "len", vm::Instruction::Len },
|
{ "pow", Instruction::Power },
|
||||||
{ "type", vm::Instruction::Type },
|
{ "shl", Instruction::ShiftLeft },
|
||||||
{ "cast", vm::Instruction::Cast },
|
{ "shr", Instruction::ShiftRight },
|
||||||
{ "ver", vm::Instruction::Version },
|
{ "len", Instruction::Len },
|
||||||
{ "bz", vm::Instruction::BranchIfZero8 },
|
{ "type", Instruction::Type },
|
||||||
{ "bnz", vm::Instruction::BranchIfNotZero8 },
|
{ "cast", Instruction::Cast },
|
||||||
{ "jmp", vm::Instruction::Jump8 },
|
{ "ver", Instruction::Version },
|
||||||
{ "cmpl", vm::Instruction::Compile },
|
{ "bz", Instruction::BranchIfZero8 },
|
||||||
{ "asmbl", vm::Instruction::Assemble },
|
{ "bnz", Instruction::BranchIfNotZero8 },
|
||||||
{ "load", vm::Instruction::Load },
|
{ "jmp", Instruction::Jump8 },
|
||||||
|
{ "cmpl", Instruction::Compile },
|
||||||
|
{ "asmbl", Instruction::Assemble },
|
||||||
|
{ "load", Instruction::Load },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -127,6 +130,9 @@ std::pair<std::string, size_t> debug_instruction(Instruction inst, int oper)
|
|||||||
case Instruction::And: out = "and"; break;
|
case Instruction::And: out = "and"; break;
|
||||||
case Instruction::Or: out = "or"; break;
|
case Instruction::Or: out = "or"; break;
|
||||||
case Instruction::Xor: out = "xor"; break;
|
case Instruction::Xor: out = "xor"; break;
|
||||||
|
case Instruction::Power: out = "pow"; break;
|
||||||
|
case Instruction::ShiftLeft: out = "shl"; break;
|
||||||
|
case Instruction::ShiftRight: out = "shr"; break;
|
||||||
case Instruction::Len: out = "len"; break;
|
case Instruction::Len: out = "len"; break;
|
||||||
case Instruction::Type: out = "type"; break;
|
case Instruction::Type: out = "type"; break;
|
||||||
case Instruction::Cast: out = "cast"; break;
|
case Instruction::Cast: out = "cast"; break;
|
||||||
|
|||||||
@@ -74,12 +74,15 @@ enum class Instruction : uint8_t {
|
|||||||
And = 0x2b,
|
And = 0x2b,
|
||||||
Or = 0x2c,
|
Or = 0x2c,
|
||||||
Xor = 0x2d,
|
Xor = 0x2d,
|
||||||
|
Power = 0x2e,
|
||||||
|
ShiftLeft = 0x2f,
|
||||||
|
ShiftRight = 0x30,
|
||||||
|
|
||||||
// other value operations
|
// other value operations
|
||||||
Len = 0x30,
|
Len = 0x40,
|
||||||
Type = 0x31,
|
Type = 0x41,
|
||||||
Cast = 0x32,
|
Cast = 0x42,
|
||||||
Version = 0x33,
|
Version = 0x43,
|
||||||
|
|
||||||
// control flow
|
// control flow
|
||||||
BranchIfZero8 = 0xa8,
|
BranchIfZero8 = 0xa8,
|
||||||
@@ -93,9 +96,9 @@ enum class Instruction : uint8_t {
|
|||||||
Jump32 = 0xea,
|
Jump32 = 0xea,
|
||||||
|
|
||||||
// external code
|
// external code
|
||||||
Compile = 0x38,
|
Compile = 0x48,
|
||||||
Assemble = 0x39,
|
Assemble = 0x49,
|
||||||
Load = 0x3a,
|
Load = 0x4a,
|
||||||
};
|
};
|
||||||
|
|
||||||
std::pair<std::string, size_t> debug_instruction(Instruction inst, int oper=0);
|
std::pair<std::string, size_t> debug_instruction(Instruction inst, int oper=0);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ std::string type_name(Type type)
|
|||||||
case Type::Table: return "table";
|
case Type::Table: return "table";
|
||||||
case Type::Function: return "function";
|
case Type::Function: return "function";
|
||||||
case Type::NativePointer: return "native pointer";
|
case Type::NativePointer: return "native pointer";
|
||||||
default: return "???";
|
case Type::COUNT: default: return "???";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -101,6 +101,15 @@ void VM::step()
|
|||||||
case Instruction::Xor:
|
case Instruction::Xor:
|
||||||
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::BitwiseXor));
|
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::BitwiseXor));
|
||||||
break;
|
break;
|
||||||
|
case Instruction::Power:
|
||||||
|
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::Power));
|
||||||
|
break;
|
||||||
|
case Instruction::ShiftLeft:
|
||||||
|
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::ShiftLeft));
|
||||||
|
break;
|
||||||
|
case Instruction::ShiftRight:
|
||||||
|
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::ShiftRight));
|
||||||
|
break;
|
||||||
case Instruction::Return: {
|
case Instruction::Return: {
|
||||||
Value v = stack_.pop();
|
Value v = stack_.pop();
|
||||||
stack_.pop_fp();
|
stack_.pop_fp();
|
||||||
|
|||||||
Reference in New Issue
Block a user