export module kym.environment; import core; import core.sequence; import kym; export namespace kym { struct vm; } enum class token_kind { end, }; struct token { core::slice text; token_kind kind; }; using tokenizable = core::callable; struct bytecode { bytecode(core::allocator * allocator) : error_message_buffer{allocator} { } bool compile(tokenizable const & bytecode_tokenizable) { for (;;) { token const initial_token = bytecode_tokenizable(); switch (initial_token.kind) { case token_kind::end: return true; default: core::unreachable(); } } } kym::value execute(kym::vm & vm, core::slice const & arguments) { return kym::nil; } core::slice error_message() const { return this->error_message_buffer.as_slice(); } private: core::stack error_message_buffer; }; export namespace kym { struct bound_object { core::callable cleanup; core::callable)> call; value get_field(core::slice const & field_name) { return nil; } bool is_string() { return false; } core::usize stringify(core::writable const & writable) { return 0; } }; struct vm { struct init_options { core::u16 datastack_size; core::u16 callstack_size; }; vm(core::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) { core::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(core::slice const & source) { bytecode * source_bytecode = new (*this->allocator) bytecode{allocator}; if (source_bytecode == nullptr) return nil; core::usize cursor = 0; if (source_bytecode->compile([]() { return token{ }; })) { this->log(source_bytecode->error_message()); this->allocator->deallocate(source_bytecode); return nil; } return this->new_object([this, source_bytecode](bound_object & object) { object.cleanup = [this, source_bytecode]() { this->allocator->deallocate(source_bytecode); }; object.call = [this, source_bytecode](core::slice const & arguments) { return source_bytecode->execute(*this, arguments); }; this->allocator->deallocate(source_bytecode); }); } value new_object(core::callable const & then) { return nil; } void with_object(value object_value, core::callable const & then) { } private: core::slice data_stack; core::callable)> log; core::allocator * allocator; }; }