#include "vm.hh" #include "vm_exceptions.hh" #include "expr.hh" namespace tyche::vm { VM& VM::load_bytecode(ByteArray const& ba) { FunctionId f_id = code_.import_bytecode(ba); stack_.push(Value::CreateFunctionId(f_id)); return *this; } VM& VM::call(size_t n_params) { // TODO - parameters Value f = stack_.pop(); if (f.type() != Type::Function) throw VMTypeError(Type::Function, f.type()); loc_.emplace(f.as_function_id(), 0); stack_.push_fp(); run_until_return(); // stack_.pop_fp(); loc_.pop(); return *this; } int32_t VM::to_integer(int index) const { Value i = stack_.at(index); assert_type(i, Type::Integer); return i.as_integer(); } float VM::to_float(int index) const { Value i = stack_.at(index); assert_type(i, Type::Float); return i.as_float(); } VM& VM::push_integer(int32_t value) { stack_.push(Value::CreateInteger(value)); return *this; } VM& VM::push_float(float value) { stack_.push(Value::CreateFloat(value)); return *this; } void VM::run_until_return() { size_t level = stack_.fp_level(); while (stack_.fp_level() >= level) step(); } void VM::step() { Operation op = code_.operation(loc_.top()); switch (op.instruction) { // // stack management // case Instruction::PushInt8: case Instruction::PushInt16: case Instruction::PushInt32: push_integer(op.operator_); break; // // logical/arithmetic // #define BIN_OP(op) { Value a = stack_.pop(); Value b = stack_.pop(); stack_.push(binary_operation(a, b, BinaryOperationType::op)); } case Instruction::Sum: BIN_OP(Sum) break; case Instruction::Subtract: BIN_OP(Subtraction) break; case Instruction::Multiply: BIN_OP(Multiplication) break; case Instruction::Divide: BIN_OP(Division) break; case Instruction::DivideInt: BIN_OP(IntegerDivision) break; case Instruction::Equals: BIN_OP(Equality) break; case Instruction::NotEquals: BIN_OP(Inequality) break; case Instruction::LessThan: BIN_OP(LessThan) break; case Instruction::LessThanEq: BIN_OP(LessThanOrEquals) break; case Instruction::GreaterThan: BIN_OP(GreaterThan) break; case Instruction::GreaterThanEq: BIN_OP(GreaterThanOrEquals) break; case Instruction::And: BIN_OP(BitwiseAnd) break; case Instruction::Or: BIN_OP(BitwiseOr) break; case Instruction::Xor: BIN_OP(BitwiseXor) break; case Instruction::Power: BIN_OP(Power) break; case Instruction::ShiftLeft: BIN_OP(ShiftLeft) break; case Instruction::ShiftRight: BIN_OP(ShiftRight) break; case Instruction::Modulo: BIN_OP(Modulo) break; #undef BIN_OP // // function operations // case Instruction::Return: { Value v = stack_.pop(); stack_.pop_fp(); stack_.push(v); return; } default: throw VMInvalidOpcode((uint8_t) op.instruction); } loc_.top() = op.next_location; } void VM::assert_type(Value const& val, Type type) { if (val.type() != type) throw VMTypeError(type, val.type()); } } // tyche