ona/source/kym/environment.cpp

183 lines
4.2 KiB
C++

export module kym.environment;
import coral;
import coral.sequence;
import kym;
using loggable = coral::callable<void(coral::slice<char const> const &)>;
export namespace kym {
struct vm;
}
enum class token_kind {
end,
};
struct token {
coral::slice<char const> text;
token_kind kind;
};
struct tokenizer {
coral::slice<char const> source;
tokenizer(coral::slice<char const> const & source) : source{source} {}
token next() {
coral::usize cursor = 0;
while (cursor < source.length) {
}
return token{
.kind = token_kind::end,
};
}
};
struct bytecode {
bytecode(coral::allocator * allocator) : error_message_buffer{allocator} {
}
bool compile(tokenizer bytecode_tokenizer, loggable const & log_error) {
for (;;) {
token const initial_token = bytecode_tokenizer.next();
switch (initial_token.kind) {
case token_kind::end: return true;
default: coral::unreachable();
}
}
}
kym::value execute(kym::vm & vm, coral::slice<kym::value const> const & arguments) {
return kym::nil;
}
private:
coral::stack<char> error_message_buffer;
};
export namespace kym {
value default_call(vm & owning_vm, void * userdata, coral::slice<value const> const & arguments) {
return nil;
}
coral::expected<coral::usize, coral::io_error> default_stringify(vm & owning_vm, void * userdata, coral::writable const & output) {
return output(coral::slice{"[object]"}.as_bytes());
}
struct bound_object {
void * userdata;
struct {
void(*cleanup)(vm &, void *);
value(*call)(vm &, void *, coral::slice<value const> const &);
coral::expected<coral::usize, coral::io_error>(*stringify)(vm &, void *, coral::writable const &);
} behavior;
bound_object(vm * owning_vm) : userdata{nullptr}, owning_vm{owning_vm}, behavior{
.cleanup = [](vm & owning_vm, void * userdata) {},
.call = default_call,
.stringify = default_stringify,
} {}
void cleanup() {
this->behavior.cleanup(*this->owning_vm, this->userdata);
}
value call(coral::slice<value const> const & arguments) {
return this->behavior.call(*this->owning_vm, this->userdata, arguments);
}
coral::expected<coral::usize, coral::io_error> stringify(coral::writable const & output) {
return this->behavior.stringify(*this->owning_vm, this->userdata, output);
}
value get_field(coral::slice<char const> const & field_name) {
return nil;
}
private:
vm * owning_vm;
};
struct vm {
struct init_options {
coral::u16 datastack_size;
coral::u16 callstack_size;
};
vm(coral::allocator * allocator, auto log) : allocator{allocator}, log{log}, data_stack{} {}
~vm() {
if (this->data_stack.pointer != nullptr)
this->allocator->deallocate(this->data_stack.pointer);
}
bool init(init_options const & options) {
coral::u8 * const data_stack_buffer = this->allocator->reallocate(reinterpret_cast
<coral::u8 *>(this->data_stack.pointer), options.datastack_size * sizeof(value));
if (data_stack_buffer == nullptr) return false;
this->data_stack = {
reinterpret_cast<value * >(data_stack_buffer), options.datastack_size};
return true;
}
value compile(coral::slice<char const> const & source) {
bytecode * source_bytecode = new (*this->allocator) bytecode{allocator};
if (source_bytecode == nullptr) return nil;
if (!source_bytecode->compile(tokenizer{source}, [&](coral::slice<char const> error_message) {
this->log(error_message);
})) {
this->allocator->deallocate(source_bytecode);
return nil;
}
return this->new_object([this, source_bytecode](bound_object & object) {
object.userdata = source_bytecode;
object.behavior.cleanup = [](vm & owning_vm, void * userdata) {
owning_vm.allocator->deallocate(userdata);
};
object.behavior.call = [](vm & owning_vm, void * userdata, coral::slice<value const> const & arguments) -> value {
return reinterpret_cast<bytecode *>(userdata)->execute(owning_vm, arguments);
};
this->allocator->deallocate(source_bytecode);
});
}
value new_object(coral::callable<void(bound_object &)> const & then) {
return nil;
}
void with_object(value object_value, coral::callable<void(bound_object &)> const & then) {
}
private:
coral::slice<value> data_stack;
loggable log;
coral::allocator * allocator;
};
}