export module kym.environment; import coral; import coral.sequence; import kym; using loggable = coral::callable const &)>; export namespace kym { struct vm; } enum class token_kind { end, }; struct token { coral::slice text; token_kind kind; }; struct tokenizer { coral::slice source; tokenizer(coral::slice 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 const & arguments) { return {}; } private: coral::stack error_message_buffer; }; export namespace kym { value default_call(vm & owning_vm, void * userdata, coral::slice const & arguments) { return {}; } coral::expected default_stringify(vm & owning_vm, void * userdata, coral::writer & output) { return output.write(coral::slice{"[object]"}.as_bytes()); } struct bound_object { void * userdata; struct { void(*cleanup)(vm &, void *); value(*call)(vm &, void *, coral::slice const &); coral::expected(*stringify)(vm &, void *, coral::writer &); } 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 const & arguments) { return this->behavior.call(*this->owning_vm, this->userdata, arguments); } coral::expected stringify(coral::writer & output) { return this->behavior.stringify(*this->owning_vm, this->userdata, output); } value get_field(coral::slice const & field_name) { return {}; } 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 (this->data_stack.pointer), options.datastack_size * sizeof(value)); if (data_stack_buffer == nullptr) return false; this->data_stack = { reinterpret_cast(data_stack_buffer), options.datastack_size}; return true; } value compile(coral::slice const & source) { bytecode * source_bytecode = new (*this->allocator) bytecode{allocator}; if (source_bytecode == nullptr) return {}; if (!source_bytecode->compile(tokenizer{source}, [&](coral::slice error_message) { this->log(error_message); })) { this->allocator->deallocate(source_bytecode); return {}; } 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 const & arguments) -> value { return reinterpret_cast(userdata)->execute(owning_vm, arguments); }; this->allocator->deallocate(source_bytecode); }); } value new_object(coral::callable const & then) { return {}; } void with_object(value object_value, coral::callable const & then) { } private: coral::slice data_stack; loggable log; coral::allocator * allocator; }; }