Introduce VariableAssignment
This commit is contained in:
parent
a4111d0622
commit
3836c35723
@ -104,6 +104,29 @@ Value FunctionDefinition::eval(VM& vm) {
|
||||
return vm.get_return_value();
|
||||
}
|
||||
|
||||
VariableAssignment::VariableAssignment(VarType type, Location location, unsigned offset, std::unique_ptr<Expression> rhs) :
|
||||
Expression(var_type_to_value_type(type)),
|
||||
m_var_type(type),
|
||||
m_location(location),
|
||||
m_offset(offset),
|
||||
m_rhs(std::move(rhs))
|
||||
{}
|
||||
|
||||
Value VariableAssignment::eval(VM& vm) {
|
||||
const Value rhs_value = m_rhs->eval(vm);
|
||||
unsigned addr;
|
||||
switch(m_location) {
|
||||
case Location::LOCATION_STACK:
|
||||
addr = vm.get_stack_ptr()-m_offset;
|
||||
break;
|
||||
case Location::LOCATION_STATIC:
|
||||
addr = m_offset;
|
||||
break;
|
||||
}
|
||||
vm.set_value_at(m_location, addr, rhs_value, m_var_type);
|
||||
return rhs_value;
|
||||
}
|
||||
|
||||
FunctionCall::FunctionCall(VM& vm, FunctionType func_type, unsigned address, std::vector<std::unique_ptr<Expression>> arguments) :
|
||||
Expression(ValueType::VALUE_TYPE_VOID),
|
||||
m_func_type(func_type),
|
||||
|
@ -101,6 +101,19 @@ namespace polygun::server::as {
|
||||
std::unique_ptr<StatementBlock> m_body;
|
||||
};
|
||||
|
||||
class VariableAssignment final : public Expression {
|
||||
public:
|
||||
VariableAssignment(VarType type, Location location, unsigned offset, std::unique_ptr<Expression> rhs);
|
||||
|
||||
virtual Value eval(VM& vm) override;
|
||||
|
||||
private:
|
||||
VarType m_var_type;
|
||||
Location m_location;
|
||||
unsigned m_offset;
|
||||
std::unique_ptr<Expression> m_rhs;
|
||||
};
|
||||
|
||||
class FunctionCall final : public Expression {
|
||||
public:
|
||||
FunctionCall(VM& vm, FunctionType func_type, unsigned address, std::vector<std::unique_ptr<Expression>> arguments);
|
||||
|
@ -70,6 +70,11 @@ namespace polygun::server::as {
|
||||
FUNCTION_NATIVE
|
||||
};
|
||||
|
||||
enum Location {
|
||||
LOCATION_STACK,
|
||||
LOCATION_STATIC
|
||||
};
|
||||
|
||||
ValueType get_wider_type(ValueType first, ValueType second);
|
||||
ValueType var_type_to_value_type(VarType var_type);
|
||||
template<typename T>
|
||||
|
@ -49,6 +49,115 @@ void VM::register_function(const std::string& name, VarType result_type, const s
|
||||
m_native_functions.push_back(native_function);
|
||||
}
|
||||
|
||||
void VM::set_value_at(Location location, unsigned addr, const Value& value, VarType type) {
|
||||
assert(addr<m_storage_size);
|
||||
uint8_t* mem;
|
||||
switch(location) {
|
||||
case Location::LOCATION_STACK:
|
||||
mem = m_stack;
|
||||
break;
|
||||
case Location::LOCATION_STATIC:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
case VarType::VAR_TYPE_VOID:
|
||||
break;
|
||||
case VarType::VAR_TYPE_BOOL:
|
||||
mem[addr] = value.b;
|
||||
break;
|
||||
case VarType::VAR_TYPE_UINT8:
|
||||
mem[addr] = value.u;
|
||||
break;
|
||||
case VarType::VAR_TYPE_UINT16:
|
||||
*reinterpret_cast<uint16_t*>(&mem[addr]) = value.u;
|
||||
break;
|
||||
case VarType::VAR_TYPE_UINT32:
|
||||
*reinterpret_cast<uint32_t*>(&mem[addr]) = value.u;
|
||||
break;
|
||||
case VarType::VAR_TYPE_UINT64:
|
||||
*reinterpret_cast<uint64_t*>(&mem[addr]) = value.u;
|
||||
break;
|
||||
case VarType::VAR_TYPE_INT8:
|
||||
mem[addr] = value.i;
|
||||
break;
|
||||
case VarType::VAR_TYPE_INT16:
|
||||
*reinterpret_cast<int16_t*>(&mem[addr]) = value.i;
|
||||
break;
|
||||
case VarType::VAR_TYPE_INT32:
|
||||
*reinterpret_cast<int32_t*>(&mem[addr]) = value.i;
|
||||
break;
|
||||
case VarType::VAR_TYPE_INT64:
|
||||
*reinterpret_cast<int64_t*>(&mem[addr]) = value.i;
|
||||
break;
|
||||
case VarType::VAR_TYPE_FLOAT:
|
||||
*reinterpret_cast<float*>(&mem[addr]) = value.d;
|
||||
break;
|
||||
case VarType::VAR_TYPE_DOUBLE:
|
||||
*reinterpret_cast<double*>(&mem[addr]) = value.d;
|
||||
break;
|
||||
case VarType::VAR_TYPE_PTR:
|
||||
*reinterpret_cast<void**>(&mem[addr]) = value.p.m_ptr;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VM::get_value_at(Location location, unsigned addr, VarType type, Value& value) {
|
||||
assert(addr<m_storage_size);
|
||||
uint8_t* mem;
|
||||
switch(location) {
|
||||
case Location::LOCATION_STACK:
|
||||
mem = m_stack;
|
||||
break;
|
||||
case Location::LOCATION_STATIC:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
case VarType::VAR_TYPE_VOID:
|
||||
break;
|
||||
case VarType::VAR_TYPE_BOOL:
|
||||
value.b = mem[addr];
|
||||
break;
|
||||
case VarType::VAR_TYPE_UINT8:
|
||||
value.u = mem[addr];
|
||||
break;
|
||||
case VarType::VAR_TYPE_UINT16:
|
||||
value.u = *reinterpret_cast<uint16_t*>(&mem[addr]);
|
||||
break;
|
||||
case VarType::VAR_TYPE_UINT32:
|
||||
value.u = *reinterpret_cast<uint32_t*>(&mem[addr]);
|
||||
break;
|
||||
case VarType::VAR_TYPE_UINT64:
|
||||
value.u = *reinterpret_cast<uint64_t*>(&mem[addr]);
|
||||
break;
|
||||
case VarType::VAR_TYPE_INT8:
|
||||
value.i = mem[addr];
|
||||
break;
|
||||
case VarType::VAR_TYPE_INT16:
|
||||
value.i = *reinterpret_cast<int16_t*>(&mem[addr]);
|
||||
break;
|
||||
case VarType::VAR_TYPE_INT32:
|
||||
value.i = *reinterpret_cast<int32_t*>(&mem[addr]);
|
||||
break;
|
||||
case VarType::VAR_TYPE_INT64:
|
||||
value.i = *reinterpret_cast<int64_t*>(&mem[addr]);
|
||||
break;
|
||||
case VarType::VAR_TYPE_FLOAT:
|
||||
value.d = *reinterpret_cast<float*>(&mem[addr]);
|
||||
break;
|
||||
case VarType::VAR_TYPE_DOUBLE:
|
||||
value.d = *reinterpret_cast<double*>(&mem[addr]);
|
||||
break;
|
||||
case VarType::VAR_TYPE_PTR:
|
||||
*reinterpret_cast<void**>(&mem[addr]) = value.p.m_ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const VM::NativeFunction& VM::get_native_function_by_address(unsigned address) {
|
||||
assert(address<m_native_functions.size());
|
||||
return m_native_functions[address];
|
||||
|
@ -36,10 +36,6 @@ SOFTWARE.
|
||||
namespace polygun::server::as {
|
||||
class VM final {
|
||||
public:
|
||||
enum Location {
|
||||
LOCATION_STACK,
|
||||
LOCATION_STATIC
|
||||
};
|
||||
struct NativeFunction {
|
||||
VarType m_result_type;
|
||||
std::vector<VarType> m_argument_types;
|
||||
@ -52,30 +48,9 @@ namespace polygun::server::as {
|
||||
|
||||
void register_function(const std::string& name, VarType result_type, const std::vector<VarType>& argument_types, Value(*func)(VM&, const std::vector<Value>&));
|
||||
|
||||
template<typename T>
|
||||
void set_value_at(Location location, unsigned addr, T value) {
|
||||
assert(addr<m_storage_size);
|
||||
switch(location) {
|
||||
case Location::LOCATION_STACK:
|
||||
*reinterpret_cast<T*>(&m_stack[addr]) = value;
|
||||
break;
|
||||
case Location::LOCATION_STATIC:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
void set_value_at(Location location, unsigned addr, const Value& value, VarType type);
|
||||
void set_return_value(const Value& value) { m_return_value = value; }
|
||||
template<typename T>
|
||||
T get_value_at(Location location, unsigned addr) {
|
||||
assert(addr<m_storage_size);
|
||||
switch(location) {
|
||||
case Location::LOCATION_STACK:
|
||||
return *&m_stack[addr];
|
||||
case Location::LOCATION_STATIC:
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
void get_value_at(Location location, unsigned addr, VarType type, Value& value);
|
||||
unsigned get_stack_ptr() const { return m_stack_ptr; }
|
||||
const Value& get_return_value() const { return m_return_value; }
|
||||
const NativeFunction& get_native_function_by_address(unsigned address);
|
||||
|
@ -92,10 +92,14 @@ Server::Server(std::atomic<bool>* running_atomic, std::optional<unsigned short>
|
||||
val2.i = 5;
|
||||
as::VM vm(1024);
|
||||
vm.register_function("test_native_function", as::VarType::VAR_TYPE_VOID, std::vector<as::VarType>{as::VarType::VAR_TYPE_INT32}, test_native_function);
|
||||
|
||||
std::unique_ptr<as::StatementBlock> block = std::make_unique<as::StatementBlock>();
|
||||
std::vector<std::unique_ptr<as::Expression>> arguments;
|
||||
arguments.push_back(std::make_unique<as::BinaryExpression>(as::BinaryExpression::Operation::OPERATION_MUL, std::make_unique<as::LiteralExpression>(val1, as::ValueType::VALUE_TYPE_INT), std::make_unique<as::LiteralExpression>(val2, as::ValueType::VALUE_TYPE_INT)));
|
||||
block->add_expression(std::make_unique<as::FunctionCall>(vm, as::FunctionType::FUNCTION_NATIVE, 0, std::move(arguments)));
|
||||
|
||||
block->add_expression(std::make_unique<as::VariableAssignment>(as::VarType::VAR_TYPE_UINT8, as::Location::LOCATION_STACK, 0, std::make_unique<as::LiteralExpression>(val1, as::ValueType::VALUE_TYPE_INT)));
|
||||
|
||||
block->eval(vm);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user