Introduce VariableAssignment

This commit is contained in:
mrkubax10 2024-08-18 22:56:46 +02:00
parent a4111d0622
commit 3836c35723
6 changed files with 156 additions and 27 deletions

View File

@ -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),

View File

@ -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);

View File

@ -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>

View File

@ -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];

View File

@ -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);

View File

@ -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);
}