Introduce FunctionCall and way to register native functions
This commit is contained in:
parent
4a1deea89e
commit
f975cebeb5
@ -103,3 +103,35 @@ Value FunctionDefinition::eval(VM& vm) {
|
|||||||
m_body->eval(vm);
|
m_body->eval(vm);
|
||||||
return vm.get_return_value();
|
return vm.get_return_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),
|
||||||
|
m_address(address),
|
||||||
|
m_arguments(std::move(arguments))
|
||||||
|
{
|
||||||
|
switch(func_type) {
|
||||||
|
case FunctionType::FUNCTION_NORMAL:
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
case FunctionType::FUNCTION_NATIVE:
|
||||||
|
m_result_type = var_type_to_value_type(vm.get_native_function_by_address(address).m_result_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Value FunctionCall::eval(VM& vm) {
|
||||||
|
std::vector<Value> argument_values;
|
||||||
|
argument_values.reserve(m_arguments.size());
|
||||||
|
for(std::unique_ptr<Expression>& arg : m_arguments)
|
||||||
|
argument_values.push_back(arg->eval(vm));
|
||||||
|
|
||||||
|
switch(m_func_type) {
|
||||||
|
case FunctionType::FUNCTION_NORMAL:
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
case FunctionType::FUNCTION_NATIVE:
|
||||||
|
return vm.get_native_function_by_address(m_address).m_func(vm, argument_values);
|
||||||
|
}
|
||||||
|
return Value{};
|
||||||
|
}
|
||||||
|
@ -100,6 +100,18 @@ namespace polygun::server::as {
|
|||||||
std::vector<VarType> m_argument_types;
|
std::vector<VarType> m_argument_types;
|
||||||
std::unique_ptr<StatementBlock> m_body;
|
std::unique_ptr<StatementBlock> m_body;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FunctionCall final : public Expression {
|
||||||
|
public:
|
||||||
|
FunctionCall(VM& vm, FunctionType func_type, unsigned address, std::vector<std::unique_ptr<Expression>> arguments);
|
||||||
|
|
||||||
|
virtual Value eval(VM& vm) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
FunctionType m_func_type;
|
||||||
|
unsigned m_address;
|
||||||
|
std::vector<std::unique_ptr<Expression>> m_arguments;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // POLYGUN_SERVER_AS_AST_HPP
|
#endif // POLYGUN_SERVER_AS_AST_HPP
|
||||||
|
@ -29,3 +29,13 @@ SOFTWARE.
|
|||||||
polygun::server::as::ValueType polygun::server::as::get_wider_type(polygun::server::as::ValueType first, polygun::server::as::ValueType second) {
|
polygun::server::as::ValueType polygun::server::as::get_wider_type(polygun::server::as::ValueType first, polygun::server::as::ValueType second) {
|
||||||
return static_cast<ValueType>(std::max(first, second));
|
return static_cast<ValueType>(std::max(first, second));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
polygun::server::as::ValueType polygun::server::as::var_type_to_value_type(polygun::server::as::VarType var_type) {
|
||||||
|
if(var_type<=VarType::VAR_TYPE_BOOL)
|
||||||
|
return static_cast<ValueType>(var_type);
|
||||||
|
if(var_type<=VarType::VAR_TYPE_UINT64)
|
||||||
|
return ValueType::VALUE_TYPE_UINT;
|
||||||
|
if(var_type<=VarType::VAR_TYPE_INT64)
|
||||||
|
return ValueType::VALUE_TYPE_INT;
|
||||||
|
return ValueType::VALUE_TYPE_DOUBLE;
|
||||||
|
}
|
||||||
|
@ -44,6 +44,7 @@ namespace polygun::server::as {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum VarType {
|
enum VarType {
|
||||||
|
VAR_TYPE_VOID,
|
||||||
VAR_TYPE_BOOL,
|
VAR_TYPE_BOOL,
|
||||||
VAR_TYPE_UINT8,
|
VAR_TYPE_UINT8,
|
||||||
VAR_TYPE_UINT16,
|
VAR_TYPE_UINT16,
|
||||||
@ -57,7 +58,13 @@ namespace polygun::server::as {
|
|||||||
VAR_TYPE_DOUBLE
|
VAR_TYPE_DOUBLE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum FunctionType {
|
||||||
|
FUNCTION_NORMAL,
|
||||||
|
FUNCTION_NATIVE
|
||||||
|
};
|
||||||
|
|
||||||
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);
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T value_as(const Value& value, ValueType type) {
|
T value_as(const Value& value, ValueType type) {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
|
@ -30,9 +30,26 @@ VM::VM(unsigned storage_size) :
|
|||||||
m_storage_size(storage_size),
|
m_storage_size(storage_size),
|
||||||
m_stack(new uint8_t[storage_size]),
|
m_stack(new uint8_t[storage_size]),
|
||||||
m_stack_ptr(0),
|
m_stack_ptr(0),
|
||||||
m_return_value()
|
m_return_value(),
|
||||||
|
m_native_functions(),
|
||||||
|
m_native_function_addresses()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
VM::~VM() {
|
VM::~VM() {
|
||||||
delete[] m_stack;
|
delete[] m_stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VM::register_function(const std::string& name, VarType result_type, const std::vector<VarType>& argument_types, Value(*func)(VM&, const std::vector<Value>&)) {
|
||||||
|
m_native_function_addresses[name] = m_native_functions.size();
|
||||||
|
const NativeFunction native_function {
|
||||||
|
result_type,
|
||||||
|
argument_types,
|
||||||
|
func
|
||||||
|
};
|
||||||
|
m_native_functions.push_back(native_function);
|
||||||
|
}
|
||||||
|
|
||||||
|
const VM::NativeFunction& VM::get_native_function_by_address(unsigned address) {
|
||||||
|
assert(address<m_native_functions.size());
|
||||||
|
return m_native_functions[address];
|
||||||
|
}
|
||||||
|
@ -27,6 +27,9 @@ SOFTWARE.
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "server/as/value.hpp"
|
#include "server/as/value.hpp"
|
||||||
|
|
||||||
@ -37,11 +40,18 @@ namespace polygun::server::as {
|
|||||||
LOCATION_STACK,
|
LOCATION_STACK,
|
||||||
LOCATION_STATIC
|
LOCATION_STATIC
|
||||||
};
|
};
|
||||||
|
struct NativeFunction {
|
||||||
|
VarType m_result_type;
|
||||||
|
std::vector<VarType> m_argument_types;
|
||||||
|
Value(*m_func)(VM&, const std::vector<Value>&);
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VM(unsigned storage_size);
|
VM(unsigned storage_size);
|
||||||
~VM();
|
~VM();
|
||||||
|
|
||||||
|
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>
|
template<typename T>
|
||||||
void set_value_at(Location location, unsigned addr, T value) {
|
void set_value_at(Location location, unsigned addr, T value) {
|
||||||
assert(addr<m_storage_size);
|
assert(addr<m_storage_size);
|
||||||
@ -68,12 +78,16 @@ namespace polygun::server::as {
|
|||||||
}
|
}
|
||||||
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);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned m_storage_size;
|
unsigned m_storage_size;
|
||||||
uint8_t* m_stack;
|
uint8_t* m_stack;
|
||||||
unsigned m_stack_ptr;
|
unsigned m_stack_ptr;
|
||||||
Value m_return_value;
|
Value m_return_value;
|
||||||
|
std::vector<NativeFunction> m_native_functions;
|
||||||
|
// Maps function name to index in std::vector above
|
||||||
|
std::map<std::string, unsigned> m_native_function_addresses;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,8 @@ SOFTWARE.
|
|||||||
#include "common/math/rect3d.hpp"
|
#include "common/math/rect3d.hpp"
|
||||||
#include "common/logger.hpp"
|
#include "common/logger.hpp"
|
||||||
#include "common/world/chunk.hpp"
|
#include "common/world/chunk.hpp"
|
||||||
|
#include "server/as/ast.hpp"
|
||||||
|
#include "server/as/vm.hpp"
|
||||||
|
|
||||||
using namespace polygun::server;
|
using namespace polygun::server;
|
||||||
|
|
||||||
@ -46,6 +48,11 @@ static const float DAY_TIME_INTERVAL = 10.0f*60.0f/65536.0f;
|
|||||||
|
|
||||||
static Server* g_current_server = nullptr;
|
static Server* g_current_server = nullptr;
|
||||||
|
|
||||||
|
as::Value test_native_function(as::VM& vm, const std::vector<as::Value>& args) {
|
||||||
|
LOG_INFO("%d", args[0].i);
|
||||||
|
return as::Value{};
|
||||||
|
}
|
||||||
|
|
||||||
Server::Server(std::atomic<bool>* running_atomic, std::optional<unsigned short> port_override) :
|
Server::Server(std::atomic<bool>* running_atomic, std::optional<unsigned short> port_override) :
|
||||||
m_config(),
|
m_config(),
|
||||||
m_running(running_atomic?running_atomic:new std::atomic<bool>),
|
m_running(running_atomic?running_atomic:new std::atomic<bool>),
|
||||||
@ -78,6 +85,18 @@ Server::Server(std::atomic<bool>* running_atomic, std::optional<unsigned short>
|
|||||||
m_player_storage.load();
|
m_player_storage.load();
|
||||||
m_chunk_manager.load_map_from_file(m_config.m_default_map);
|
m_chunk_manager.load_map_from_file(m_config.m_default_map);
|
||||||
m_mod_manager.enumerate_modules();
|
m_mod_manager.enumerate_modules();
|
||||||
|
|
||||||
|
as::Value val1;
|
||||||
|
val1.i = 10;
|
||||||
|
as::Value val2;
|
||||||
|
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::NumericExpression>(val1, as::ValueType::VALUE_TYPE_INT), std::make_unique<as::NumericExpression>(val2, as::ValueType::VALUE_TYPE_INT)));
|
||||||
|
block->add_expression(std::make_unique<as::FunctionCall>(vm, as::FunctionType::FUNCTION_NATIVE, 0, std::move(arguments)));
|
||||||
|
block->eval(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
Server::~Server() {
|
Server::~Server() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user