860 lines · 24.6 KB · C++
RawDownload
voidSys_millisec(vm_registers_t &r, vm_t &vm){    const auto current_time = std::chrono::steady_clock::now();    const auto current_time_in_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time.time_since_epoch());     auto &fp = r.stack.peek_frame()->base<F_Sys_millisec>();    *fp.ret = static_cast<word_t>(current_time_in_ms.count());} voidSys_mount(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_mount>();    throw vm_system_exception{ "Instruction not implemented" };} voidSys_open(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_open>();     auto path = vm_alloc_t::from_allocation<vm_string_t>(fp.s);    const auto open_mode = convert_to_openmode(fp.mode);     // [TODO] Handle opening devices - not just files (i.e. /dev/random, /dev/source, /proc/1234)    auto file_stream = sys::create_file_stream(path->str(), (open_mode | std::ios::binary));     // Return null if file stream is not open.    if (file_stream == nullptr)    {        *fp.ret = nullptr;        return;    }     vm_alloc_t *fd_alloc;    auto fd = word_t{};    std::tie(fd, fd_alloc) = vm_fd_t::create(std::move(file_stream), fp.mode, path);     if (debug::is_component_tracing_enabled<debug::component_trace_t::builtin>())    {        debug::log_msg(            debug::component_trace_t::builtin,            debug::log_level_t::debug,            "sys: open: %d >>%s<< %#x\n",            fd,            path->str(),            fp.mode);    }     *fp.ret = fd_alloc->get_allocation();} voidSys_pctl(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_pctl>();    throw vm_system_exception{ "Instruction not implemented" };} voidSys_pipe(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_pipe>();    throw vm_system_exception{ "Instruction not implemented" };} voidSys_pread(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_pread>();    throw vm_system_exception{ "Instruction not implemented" };} voidSys_print(vm_registers_t &r, vm_t &vm){    auto fp_base = r.stack.peek_frame()->base();    auto &fp = r.stack.peek_frame()->base<F_Sys_print>();    auto str = vm_alloc_t::from_allocation<vm_string_t>(fp.s);     if (str == nullptr)        throw dereference_nil{ "Print string" };     auto static_buffer = std::array<char, 1024>{};    auto msg_args = &fp.vargs;    auto written = sys::printf_to_buffer(*str, msg_args, fp_base, static_buffer.size(), static_buffer.data());    if (written >= 0)    {        fd_stdout->write(written, static_buffer.data());    }    else    {        auto dynamic_buffer = std::vector<char>(static_buffer.size() * 2);        written = sys::printf_to_dynamic_buffer(*str, msg_args, fp_base, dynamic_buffer);        fd_stdout->write(written, dynamic_buffer.data());    }     *fp.ret = written;} voidSys_pwrite(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_pwrite>();    throw vm_system_exception{ "Instruction not implemented" };} voidSys_read(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_read>();     const auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.buf);    assert(buffer->get_element_type()->size_in_bytes == intrinsic_type_desc::type<byte_t>()->size_in_bytes);     auto n = fp.n;    if (buffer == nullptr || n <= 0)    {        *fp.ret = 0;        return;    }     // [SPEC] Supplying a size greater than the buffer length is    // equivalent to indicating the entire buffer should be filled.    n = std::min(n, buffer->get_length());     auto fd_alloc = vm_alloc_t::from_allocation(fp.fd);    assert(fd_alloc->alloc_type == T_FD);     auto fd = fd_alloc->get_allocation<vm_fd_t>();    *fp.ret = fd->read(n, buffer->at(0));} voidSys_readn(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_readn>();    throw vm_system_exception{ "Instruction not implemented" };} voidSys_remove(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_remove>();    throw vm_system_exception{ "Instruction not implemented" };} voidSys_seek(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_seek>();    throw vm_system_exception{ "Instruction not implemented" };} voidSys_sleep(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_sleep>();     const auto period_ms = fp.period;     // [TODO] Thread should yield to another according to the sleep() specification.    std::this_thread::sleep_for(std::chrono::milliseconds(period_ms));     *fp.ret = 0;} voidSys_sprint(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_sprint>();    throw vm_system_exception{ "Instruction not implemented" };} voidSys_stat(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_stat>();    throw vm_system_exception{ "Instruction not implemented" };} voidSys_stream(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_stream>();    throw vm_system_exception{ "Instruction not implemented" };} namespace{    bool is_delim(const rune_t c, const vm_string_t &delim)    {        const auto max = delim.get_length();        assert(max > 0);         // Optimization for 3 or less delimiters        switch (max)        {        default:            break;        case 1:            return (delim.get_rune(0) == c);        case 2:            return (delim.get_rune(0) == c) || (delim.get_rune(1) == c);        case 3:            return (delim.get_rune(0) == c) || (delim.get_rune(1) == c) || (delim.get_rune(2) == c);        }         for (auto i = word_t{ 0 }; i < max; ++i)        {            if (delim.get_rune(i) == c)                return true;        }         return false;    }} voidSys_tokenize(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_tokenize>();     // Initialize for failure.    fp.ret->t0 = 0;    dec_ref_count_and_free(vm_alloc_t::from_allocation(fp.ret->t1));    fp.ret->t1 = nullptr;     auto s = vm_alloc_t::from_allocation<vm_string_t>(fp.s);    if (s == nullptr || s->get_length() == 0)        return;     auto curr_node = new vm_list_t{ intrinsic_type_desc::type<pointer_t>() };     // Set the head of the list    fp.ret->t1 = curr_node->get_allocation();     auto delim = vm_alloc_t::from_allocation<vm_string_t>(fp.delim);    if (delim == nullptr || delim->get_length() == 0)    {        // Add supplied string to list        pt_ref(curr_node->value()) = s->get_allocation();        s->add_ref();         fp.ret->t0 = 1;        return;    }     // Tokenize the string    vm_list_t *prev_node = nullptr;    auto n = word_t{ 0 };    auto begin = word_t{ 0 };    auto end = word_t{ 0 };    const auto len = s->get_length();    while (begin < len)    {        // Consume delimiters        while (begin < len)        {            const auto rune = s->get_rune(begin);            if (!is_delim(rune, *delim))                break;            ++begin;        }         end = begin;         // Consume non-delimiters        while (end < len)        {            const auto rune = s->get_rune(end);            if (is_delim(rune, *delim))                break;            ++end;        }         // No progress - It is and isn't a delimiter (i.e. no more characters).        if (begin == end)            break;         // Current node is initially non-null        if (curr_node == nullptr)            curr_node = new vm_list_t{ intrinsic_type_desc::type<pointer_t>() };         const auto token = new vm_string_t{ *s, begin, end };        pt_ref(curr_node->value()) = token->get_allocation();         // Previous node is initially null        if (prev_node != nullptr)        {            prev_node->set_tail(curr_node);            curr_node->release();        }         prev_node = curr_node;        curr_node = nullptr;         begin = end;        ++n;    }     fp.ret->t0 = n;} voidSys_unmount(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_unmount>();    throw vm_system_exception{ "Instruction not implemented" };} voidSys_utfbytes(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_utfbytes>();    throw vm_system_exception{ "Instruction not implemented" };} voidSys_werrstr(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_werrstr>();    throw vm_system_exception{ "Instruction not implemented" };} voidSys_write(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_write>();     const auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.buf);    assert(buffer->get_element_type()->size_in_bytes == intrinsic_type_desc::type<byte_t>()->size_in_bytes);     auto n = fp.n;    if (buffer == nullptr || n <= 0)    {        *fp.ret = 0;        return;    }     // [SPEC] Supplying a size greater than the buffer length is    // equivalent to indicating the entire buffer should be written.    n = std::min(n, buffer->get_length());     auto fd_alloc = vm_alloc_t::from_allocation(fp.fd);    assert(fd_alloc->alloc_type == T_FD);     auto fd = fd_alloc->get_allocation<vm_fd_t>();    fd->write(n, buffer->at(0));     *fp.ret = n;} voidSys_wstat(vm_registers_t &r, vm_t &vm){    auto &fp = r.stack.peek_frame()->base<F_Sys_wstat>();    throw vm_system_exception{ "Instruction not implemented" };}

Lines 501–860 of 860. Previous lines