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();
|
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) :
|
FunctionCall::FunctionCall(VM& vm, FunctionType func_type, unsigned address, std::vector<std::unique_ptr<Expression>> arguments) :
|
||||||
Expression(ValueType::VALUE_TYPE_VOID),
|
Expression(ValueType::VALUE_TYPE_VOID),
|
||||||
m_func_type(func_type),
|
m_func_type(func_type),
|
||||||
|
@ -101,6 +101,19 @@ namespace polygun::server::as {
|
|||||||
std::unique_ptr<StatementBlock> m_body;
|
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 {
|
class FunctionCall final : public Expression {
|
||||||
public:
|
public:
|
||||||
FunctionCall(VM& vm, FunctionType func_type, unsigned address, std::vector<std::unique_ptr<Expression>> arguments);
|
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
|
FUNCTION_NATIVE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Location {
|
||||||
|
LOCATION_STACK,
|
||||||
|
LOCATION_STATIC
|
||||||
|
};
|
||||||
|
|
||||||
ValueType get_wider_type(ValueType first, ValueType second);
|
ValueType get_wider_type(ValueType first, ValueType second);
|
||||||
ValueType var_type_to_value_type(VarType var_type);
|
ValueType var_type_to_value_type(VarType var_type);
|
||||||
template<typename T>
|
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);
|
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) {
|
const VM::NativeFunction& VM::get_native_function_by_address(unsigned address) {
|
||||||
assert(address<m_native_functions.size());
|
assert(address<m_native_functions.size());
|
||||||
return m_native_functions[address];
|
return m_native_functions[address];
|
||||||
|
@ -36,10 +36,6 @@ SOFTWARE.
|
|||||||
namespace polygun::server::as {
|
namespace polygun::server::as {
|
||||||
class VM final {
|
class VM final {
|
||||||
public:
|
public:
|
||||||
enum Location {
|
|
||||||
LOCATION_STACK,
|
|
||||||
LOCATION_STATIC
|
|
||||||
};
|
|
||||||
struct NativeFunction {
|
struct NativeFunction {
|
||||||
VarType m_result_type;
|
VarType m_result_type;
|
||||||
std::vector<VarType> m_argument_types;
|
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>&));
|
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, const Value& value, VarType type);
|
||||||
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_return_value(const Value& value) { m_return_value = value; }
|
void set_return_value(const Value& value) { m_return_value = value; }
|
||||||
template<typename T>
|
void get_value_at(Location location, unsigned addr, VarType type, Value& value);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unsigned get_stack_ptr() const { return m_stack_ptr; }
|
unsigned get_stack_ptr() const { return m_stack_ptr; }
|
||||||
const Value& get_return_value() const { return m_return_value; }
|
const Value& get_return_value() const { return m_return_value; }
|
||||||
const NativeFunction& get_native_function_by_address(unsigned address);
|
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;
|
val2.i = 5;
|
||||||
as::VM vm(1024);
|
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);
|
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::unique_ptr<as::StatementBlock> block = std::make_unique<as::StatementBlock>();
|
||||||
std::vector<std::unique_ptr<as::Expression>> arguments;
|
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)));
|
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::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);
|
block->eval(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user