From 52ef74ffdc93c9f0f6ead8852b8164d9e650a66c Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Sat, 4 Mar 2023 22:23:50 -0600 Subject: [PATCH] cleanup: restructured platform layer code Platform layer code was scattered and undocumented what was expected. This has been remedied, and a good baseline has been defined. --- core/io/stdio.onyx | 16 +-- core/net/net.onyx | 9 ++ core/net/tcp.onyx | 4 + core/os/dir.onyx | 56 +++++++- core/os/file.onyx | 7 +- core/os/os.onyx | 66 ++------- core/os/process.onyx | 28 ++-- core/runtime/common.onyx | 9 +- .../{js.onyx => platform/js/platform.onyx} | 24 +++- core/{ => runtime/platform}/onyx/fs.onyx | 66 +++++---- .../onyx/platform.onyx} | 60 ++++++-- core/{ => runtime/platform}/wasi/clock.onyx | 0 core/{ => runtime/platform}/wasi/env.onyx | 0 .../wasi/platform.onyx} | 33 ++++- .../platform/wasi/wasi_defs.onyx} | 0 core/{ => runtime/platform}/wasi/wasi_fs.onyx | 2 +- core/std.onyx | 68 ++++++--- core/threads/thread.onyx | 6 +- core/time/date.onyx | 7 +- core/time/time.onyx | 17 +-- core/wasi/README.md | 1 - docs/ideas/platform_layer.md | 132 ++++++++++++++++++ 22 files changed, 439 insertions(+), 172 deletions(-) rename core/runtime/{js.onyx => platform/js/platform.onyx} (65%) rename core/{ => runtime/platform}/onyx/fs.onyx (56%) rename core/runtime/{onyx_run.onyx => platform/onyx/platform.onyx} (56%) rename core/{ => runtime/platform}/wasi/clock.onyx (100%) rename core/{ => runtime/platform}/wasi/env.onyx (100%) rename core/runtime/{wasi.onyx => platform/wasi/platform.onyx} (80%) rename core/{wasi/wasi.onyx => runtime/platform/wasi/wasi_defs.onyx} (100%) rename core/{ => runtime/platform}/wasi/wasi_fs.onyx (99%) delete mode 100644 core/wasi/README.md create mode 100644 docs/ideas/platform_layer.md diff --git a/core/io/stdio.onyx b/core/io/stdio.onyx index 42355ee3..4aeefbc9 100644 --- a/core/io/stdio.onyx +++ b/core/io/stdio.onyx @@ -53,7 +53,7 @@ __flush_stdio :: () { ^stdio.print_stream |> io.buffer_stream_to_str() - |> runtime.__output_string(); + |> runtime.platform.__output_string(); ^stdio.print_stream |> io.stream_flush(); } @@ -92,17 +92,17 @@ printf :: (format: str, va: ..any) { print(conv.format_va(buffer, format, va, .{null, flush})); } -#if #defined(runtime.__output_error) { +#if #defined(runtime.platform.__output_error) { // // Prints to standard error, if available. eprintf :: (format: str, va: ..any) -> str { flush :: (_, to_output) => { - runtime.__output_error(to_output); + runtime.platform.__output_error(to_output); return true; } buffer: [1024] u8; - runtime.__output_error(conv.format_va(buffer, format, va, .{null, flush})); + runtime.platform.__output_error(conv.format_va(buffer, format, va, .{null, flush})); } } @@ -141,9 +141,9 @@ __byte_dump :: (ptr: rawptr, byte_count: u32, bytes_per_line := 8) { temp[1] = map_to_ascii(val & 15); temp[2] = #char " "; - runtime.__output_string(~~temp); + runtime.platform.__output_string(~~temp); - if i % bytes_per_line == (bytes_per_line - 1) do runtime.__output_string("\n"); + if i % bytes_per_line == (bytes_per_line - 1) do runtime.platform.__output_string("\n"); } @@ -180,7 +180,7 @@ __byte_dump :: (ptr: rawptr, byte_count: u32, bytes_per_line := 8) { #local stdio_vtable := io.Stream_Vtable.{ read = (_: ^io.Stream, buffer: [] u8) -> (io.Error, u32) { __flush_stdio(); - bytes_read := runtime.__read_from_input(buffer); + bytes_read := runtime.platform.__read_from_input(buffer); if bytes_read == 0 do return .ReadPending, 0; if bytes_read < 0 do return .EOF, 0; @@ -190,7 +190,7 @@ __byte_dump :: (ptr: rawptr, byte_count: u32, bytes_per_line := 8) { read_byte = (_: ^io.Stream) -> (io.Error, u8) { __flush_stdio(); buf: [1] u8; - bytes_read := runtime.__read_from_input(buf); + bytes_read := runtime.platform.__read_from_input(buf); if bytes_read <= 0 do return .EOF, 0; return .None, buf[0]; diff --git a/core/net/net.onyx b/core/net/net.onyx index 51d4d719..1b2569b4 100644 --- a/core/net/net.onyx +++ b/core/net/net.onyx @@ -1,5 +1,9 @@ package core.net +#if !runtime.platform.Supports_Networking { + #error "Cannot include this file. Platform not supported."; +} + use core Socket :: struct { @@ -281,6 +285,11 @@ network_to_host :: #match #local {} } }; +// +// This will be moved into the platform layer later. +// I think this is most everything you would need, but +// I need to see how WASI does sockets to see if this +// makes sense as an abstraction. #foreign "onyx_runtime" { #package __net_create_socket :: (out_handle: ^Socket.Handle, domain: SocketDomain, type: SocketType) -> SocketError --- #package __net_close_socket :: (handle: Socket.Handle) -> void --- diff --git a/core/net/tcp.onyx b/core/net/tcp.onyx index 696501b9..98479904 100644 --- a/core/net/tcp.onyx +++ b/core/net/tcp.onyx @@ -1,5 +1,9 @@ package core.net +#if !runtime.platform.Supports_Networking { + #error "Cannot include this file. Platform not supported."; +} + use core {sync, thread, array, memory, alloc, os, iter} #if !runtime.Multi_Threading_Enabled { diff --git a/core/os/dir.onyx b/core/os/dir.onyx index 4ec08942..a8aaeeac 100644 --- a/core/os/dir.onyx +++ b/core/os/dir.onyx @@ -1,6 +1,11 @@ package core.os -use runtime {fs} +#if !runtime.platform.Supports_Directories { + #error "Cannot include this file. Platform not supported."; +} + +use core {string} +#local fs :: runtime.platform Directory :: fs.DirectoryData; @@ -31,3 +36,52 @@ dir_create :: fs.__dir_create dir_exists :: fs.__file_exists dir_remove :: fs.__dir_remove dir_rename :: fs.__file_rename + +list_directory :: (path: str) -> Iterator(DirectoryEntry) { + Context :: struct { + dir: Directory; + opened := false; + } + + next :: (use c: ^Context) -> (DirectoryEntry, bool) { + if !opened do return .{}, false; + + entry: DirectoryEntry; + if !dir_read(dir, ^entry) { + return .{}, false; + } + + return entry, true; + } + + close :: (use c: ^Context) { + dir_close(dir); + cfree(c); + } + + c := new(Context); + if dir, success := dir_open(path); success { + c.dir = dir; + c.opened = true; + } + + return .{ c, next, close }; +} + +remove_directory :: (path: str) -> bool { + // This is quite a bit of space, and could result in a stack overrun + // if the directory being deleted has a lot of descendents. + full_path_buffer: [512] u8; + + for list_directory(path) { + full_path := string.concat(full_path_buffer, path, "/", it->name()); + + if it.type == .Directory { + if !remove_directory(full_path) do return false; + } else { + remove_file(full_path); + } + } + + return dir_remove(path); +} diff --git a/core/os/file.onyx b/core/os/file.onyx index 277f99df..8d663c74 100644 --- a/core/os/file.onyx +++ b/core/os/file.onyx @@ -1,7 +1,12 @@ package core.os +#if !runtime.platform.Supports_Files { + #error "Cannot include this file. Platform not supported."; +} + use core -use runtime {fs} +#local fs :: package runtime.platform + FileError :: enum { None :: 0x00; diff --git a/core/os/os.onyx b/core/os/os.onyx index 171c193e..03c183e1 100644 --- a/core/os/os.onyx +++ b/core/os/os.onyx @@ -1,69 +1,21 @@ package core.os -#if runtime.runtime != .Wasi - && runtime.runtime != .Onyx { - #error "The os library is currently only available on the WASI runtime, and should only be included if that is the chosen runtime." -} - use core {string} -list_directory :: (path: str) -> Iterator(DirectoryEntry) { - Context :: struct { - dir: Directory; - opened := false; - } - - next :: (use c: ^Context) -> (DirectoryEntry, bool) { - if !opened do return .{}, false; - - entry: DirectoryEntry; - if !dir_read(dir, ^entry) { - return .{}, false; - } - - return entry, true; - } - - close :: (use c: ^Context) { - dir_close(dir); - cfree(c); - } - - c := new(Context); - if dir, success := dir_open(path); success { - c.dir = dir; - c.opened = true; - } - - return .{ c, next, close }; -} - -remove_directory :: (path: str) -> bool { - // This is quite a bit of space, and could result in a stack overrun - // if the directory being deleted has a lot of descendents. - full_path_buffer: [512] u8; - - for list_directory(path) { - full_path := string.concat(full_path_buffer, path, "/", it->name()); - - if it.type == .Directory { - if !remove_directory(full_path) do return false; - } else { - remove_file(full_path); - } - } - - return dir_remove(path); +#if !runtime.platform.Supports_Os { + #error "Cannot include this file. Platform not supported."; } exit :: (exitcode: i32) { - runtime.__exit(exitcode); + runtime.platform.__exit(exitcode); } -#if #defined(runtime.__sleep) { - sleep :: runtime.__sleep +#if #defined(runtime.platform.__sleep) { + sleep :: runtime.platform.__sleep } -#if #defined(runtime.__time) { - time :: runtime.__time +#if #defined(runtime.platform.__time) { + time :: runtime.platform.__time +} else { + time :: () => u64.{0}; } diff --git a/core/os/process.onyx b/core/os/process.onyx index 08ed4785..bc511ee8 100644 --- a/core/os/process.onyx +++ b/core/os/process.onyx @@ -1,16 +1,23 @@ package core.os -#if runtime.runtime != .Onyx { - #error "This file can only be included in the 'onyx' runtime, because Wasi has not defined how to spawn and manage processes."; +#if !runtime.platform.Supports_Processes { + #error "Cannot include this file. Platform not supported."; } use core {io} +use runtime.platform { + __process_spawn, + __process_destroy, + __process_kill, + __process_read, + __process_write, + __process_wait, + ProcessData +} Process :: struct { - Handle :: #distinct i64; - use stream: io.Stream; - process_handle: Handle; + process_handle: ProcessData; } process_spawn :: (path: str, args: [] str, non_blocking_io := false, starting_directory := "") -> Process { @@ -70,19 +77,10 @@ process_destroy :: (use p: ^Process) => { } } -#local ProcessResult :: enum { +ProcessResult :: enum { Success :: 0x00; FailedToRun :: 0x01; Error :: 0x02; InternalErr :: 0x03; } -#foreign "onyx_runtime" { - __process_spawn :: (path: str, args: [] str, non_blocking_io: bool, starting_directory: str) -> Process.Handle --- - __process_read :: (handle: Process.Handle, buffer: [] u8) -> i32 --- - __process_write :: (handle: Process.Handle, buffer: [] u8) -> i32 --- - __process_kill :: (handle: Process.Handle) -> bool --- - __process_wait :: (handle: Process.Handle) -> ProcessResult --- - __process_destroy :: (handle: Process.Handle) -> void --- -} - diff --git a/core/runtime/common.onyx b/core/runtime/common.onyx index bee7072e..759973b1 100644 --- a/core/runtime/common.onyx +++ b/core/runtime/common.onyx @@ -2,6 +2,13 @@ package runtime use core use core.intrinsics.onyx { __initialize } +use platform { __output_string } + +// +// Export the __start function from the platform layer. +// Every platform should define this, even if is it just '() {}'. +#export "_start" platform.__start + // The default assert handler. This assumes that __output_string // and __exit are defined in the 'runtime' package. @@ -83,4 +90,4 @@ __thread_initialize :: () { raw_free(alloc.heap_allocator, __tls_base); core.thread.__exited(id); } -} +} \ No newline at end of file diff --git a/core/runtime/js.onyx b/core/runtime/platform/js/platform.onyx similarity index 65% rename from core/runtime/js.onyx rename to core/runtime/platform/js/platform.onyx index f13a5e7f..aa304e2a 100644 --- a/core/runtime/js.onyx +++ b/core/runtime/platform/js/platform.onyx @@ -1,16 +1,30 @@ -package runtime - -#load "core/runtime/common" +package runtime.platform use core +use runtime { + __runtime_initialize, + Multi_Threading_Enabled, + _thread_start, + _thread_exit +} + +// Platform supports +Supports_Files :: false +Supports_Directories :: false +Supports_Os :: false +Supports_Processes :: false +Supports_Time :: false +Supports_Networking :: false +Supports_Type_Info :: true +Supports_Threads :: true __output_string :: (s: str) -> u32 #foreign "host" "print_str" --- +__output_error :: (s: str) -> u32 #foreign "host" "print_str" --- __exit :: (status: i32) -> void #foreign "host" "exit" --- __read_from_input :: (buf: [] u8) -> u32 do return 0; -// The builtin _start proc. // Sets up everything needed for execution. -#export "_start" () { +__start :: () { __runtime_initialize(); context.thread_id = 0; diff --git a/core/onyx/fs.onyx b/core/runtime/platform/onyx/fs.onyx similarity index 56% rename from core/onyx/fs.onyx rename to core/runtime/platform/onyx/fs.onyx index 7e431798..f122de60 100644 --- a/core/onyx/fs.onyx +++ b/core/runtime/platform/onyx/fs.onyx @@ -1,43 +1,57 @@ -package runtime.fs +package runtime.platform -use package core +use core FileData :: #distinct i64 DirectoryData :: #distinct u64 -__file_open :: (path: str, mode := os.OpenMode.Read) -> (FileData, os.FileError) { - handle: FileData; - error := __file_open_impl(path, mode, ^handle); +#local { + #foreign "onyx_runtime" { + __file_open_impl :: (path: str, mode: os.OpenMode, out_handle: ^FileData) -> os.FileError --- - return handle, error; -} + __file_close :: (fd: FileData) -> os.FileError --- + __file_stat :: (path: str, stat: ^os.FileStat) -> bool --- + __file_exists :: (path: str) -> bool --- + __file_remove :: (path: str) -> bool --- + __file_rename :: (old_path: str, new_path: str) -> bool --- -#foreign "onyx_runtime" { - __file_open_impl :: (path: str, mode: os.OpenMode, out_handle: ^FileData) -> os.FileError --- + __file_seek :: (handle: FileData, to: i32, whence: io.SeekFrom) -> i32 --- + __file_tell :: (handle: FileData) -> u32 --- + __file_read :: (handle: FileData, output_buffer: [] u8, bytes_read: ^u64) -> io.Error --- + __file_write :: (handle: FileData, input_buffer: [] u8, bytes_wrote: ^u64) -> io.Error --- + __file_flush :: (handle: FileData) -> io.Error --- + __file_size :: (handle: FileData) -> u32 --- - __file_close :: (fd: FileData) -> os.FileError --- - __file_stat :: (path: str, stat: ^os.FileStat) -> bool --- - __file_exists :: (path: str) -> bool --- - __file_remove :: (path: str) -> bool --- - __file_rename :: (old_path: str, new_path: str) -> bool --- + __dir_open :: (path: str, dir: ^DirectoryData) -> bool --- + __dir_close :: (dir: DirectoryData) -> void --- + __dir_read :: (dir: DirectoryData, out_entry: ^os.DirectoryEntry) -> bool --- + __dir_create :: (path: str) -> bool --- + __dir_remove :: (path: str) -> bool --- - __file_seek :: (handle: FileData, to: i32, whence: io.SeekFrom) -> i32 --- - __file_tell :: (handle: FileData) -> u32 --- - __file_read :: (handle: FileData, output_buffer: [] u8, bytes_read: ^u64) -> io.Error --- - __file_write :: (handle: FileData, input_buffer: [] u8, bytes_wrote: ^u64) -> io.Error --- - __file_flush :: (handle: FileData) -> io.Error --- - __file_size :: (handle: FileData) -> u32 --- - __dir_open :: (path: str, dir: ^DirectoryData) -> bool --- - __dir_close :: (dir: DirectoryData) -> void --- - __dir_read :: (dir: DirectoryData, out_entry: ^os.DirectoryEntry) -> bool --- - __dir_create :: (path: str) -> bool --- - __dir_remove :: (path: str) -> bool --- + __enable_non_blocking_stdin :: () -> void --- + } +} +__file_open :: (path: str, mode := os.OpenMode.Read) -> (FileData, os.FileError) { + handle: FileData; + error := __file_open_impl(path, mode, ^handle); - __enable_non_blocking_stdin :: () -> void --- + return handle, error; } +// Export symbols from #foreign table +__file_close :: __file_close +__file_stat :: __file_stat +__file_exists :: __file_exists +__file_remove :: __file_remove +__file_rename :: __file_rename +__dir_open :: __dir_open +__dir_close :: __dir_close +__dir_read :: __dir_read +__dir_create :: __dir_create +__dir_remove :: __dir_remove + __file_stream_vtable := io.Stream_Vtable.{ seek = (use fs: ^os.File, to: i32, whence: io.SeekFrom) -> io.Error { now := __file_seek(data, to, whence); diff --git a/core/runtime/onyx_run.onyx b/core/runtime/platform/onyx/platform.onyx similarity index 56% rename from core/runtime/onyx_run.onyx rename to core/runtime/platform/onyx/platform.onyx index 3a827aaf..f30c47bd 100644 --- a/core/runtime/onyx_run.onyx +++ b/core/runtime/platform/onyx/platform.onyx @@ -1,8 +1,28 @@ -package runtime - -#load "core/runtime/common" +package runtime.platform use core +use runtime { + __runtime_initialize, + Multi_Threading_Enabled, + _thread_start, + _thread_exit +} + +#load "./fs" + + +// Platform supports +Supports_Files :: true +Supports_Directories :: true +Supports_Os :: true +Supports_Processes :: true +Supports_Time :: true +Supports_Networking :: true +Supports_Type_Info :: true +Supports_Threads :: true + + +#library "onyx_runtime" #local { __stdout: os.File; @@ -27,38 +47,54 @@ __read_from_input :: (buffer: [] u8) -> i32 { return read; } -#library "onyx_runtime" -#foreign "onyx_runtime" { - __file_get_standard :: (fd: i32, out: ^fs.FileData) -> bool --- +ProcessData :: #distinct u64 +#foreign "onyx_runtime" { + // Arguments __args_get :: (argv: ^^u8, arg_buf: ^u8) -> void --- __args_sizes_get :: (argc: ^i32, arg_buf_size: ^i32) -> void --- + // OS __exit :: (status: i32) -> void --- - __sleep :: (milliseconds: i32) -> void --- + // Time and sleep __time :: () -> u64 --- + __time_localtime :: (time: u64, tm: ^core.time.Timestamp) -> void --- + __time_gmtime :: (time: u64, tm: ^core.time.Timestamp) -> void --- + __time_mktime :: (tm: ^time.Timestamp) -> i64 --- + __time_strftime :: (buf: [] u8, format: cstr, tm: ^time.Timestamp) -> u32 --- + + // Processes + __process_spawn :: (path: str, args: [] str, non_blocking_io: bool, starting_directory: str) -> ProcessData --- + __process_read :: (handle: ProcessData, buffer: [] u8) -> i32 --- + __process_write :: (handle: ProcessData, buffer: [] u8) -> i32 --- + __process_kill :: (handle: ProcessData) -> bool --- + __process_wait :: (handle: ProcessData) -> os.ProcessResult --- + __process_destroy :: (handle: ProcessData) -> void --- + + // Misc + __file_get_standard :: (fd: i32, out: ^FileData) -> bool --- } -#export "_start" () { - fd: fs.FileData; +__start :: () { + fd: FileData; __file_get_standard(1, ^fd); __stdout = .{ - .{ ^fs.__file_stream_vtable }, + .{ ^__file_stream_vtable }, fd }; __file_get_standard(2, ^fd); __stderr = .{ - .{ ^fs.__file_stream_vtable }, + .{ ^__file_stream_vtable }, fd }; __file_get_standard(0, ^fd); __stdin = .{ - .{ ^fs.__file_stream_vtable, .Block_On_Read }, + .{ ^__file_stream_vtable, .Block_On_Read }, fd }; diff --git a/core/wasi/clock.onyx b/core/runtime/platform/wasi/clock.onyx similarity index 100% rename from core/wasi/clock.onyx rename to core/runtime/platform/wasi/clock.onyx diff --git a/core/wasi/env.onyx b/core/runtime/platform/wasi/env.onyx similarity index 100% rename from core/wasi/env.onyx rename to core/runtime/platform/wasi/env.onyx diff --git a/core/runtime/wasi.onyx b/core/runtime/platform/wasi/platform.onyx similarity index 80% rename from core/runtime/wasi.onyx rename to core/runtime/platform/wasi/platform.onyx index f94874de..4e01eb0a 100644 --- a/core/runtime/wasi.onyx +++ b/core/runtime/platform/wasi/platform.onyx @@ -1,10 +1,32 @@ -package runtime +package runtime.platform -#load "core/wasi/wasi" -#load "core/runtime/common" +#load "./wasi_defs" +#load "./wasi_fs" -use wasi use core +use wasi { + IOVec, SubscriptionTagged, Subscription, Event, Size, + poll_oneoff, fd_write, fd_datasync, fd_read, + args_get, args_sizes_get, + proc_exit +} +use runtime { + __runtime_initialize, + Multi_Threading_Enabled, +} + + +// Platform supports +Supports_Files :: true +Supports_Directories :: true +Supports_Os :: true +Supports_Processes :: false +Supports_Time :: false +Supports_Networking :: false +Supports_Type_Info :: true +Supports_Threads :: false + + __output_string :: (s: str) -> u32 { STDOUT_FILENO :: 1 @@ -51,9 +73,8 @@ __sleep :: (milliseconds: u32) { } -// The builtin _start proc. // Sets up everything needed for execution. -#export "_start" () { +__start :: () { __runtime_initialize(); context.thread_id = 0; diff --git a/core/wasi/wasi.onyx b/core/runtime/platform/wasi/wasi_defs.onyx similarity index 100% rename from core/wasi/wasi.onyx rename to core/runtime/platform/wasi/wasi_defs.onyx diff --git a/core/wasi/wasi_fs.onyx b/core/runtime/platform/wasi/wasi_fs.onyx similarity index 99% rename from core/wasi/wasi_fs.onyx rename to core/runtime/platform/wasi/wasi_fs.onyx index 7bc6e7e6..8e427280 100644 --- a/core/wasi/wasi_fs.onyx +++ b/core/runtime/platform/wasi/wasi_fs.onyx @@ -1,4 +1,4 @@ -package runtime.fs +package runtime.platform #local runtime :: package runtime #if runtime.runtime != .Wasi { diff --git a/core/std.onyx b/core/std.onyx index 2df668c5..fc938665 100644 --- a/core/std.onyx +++ b/core/std.onyx @@ -49,42 +49,45 @@ package core #load "./misc/arg_parse" #load "./misc/method_ops" -#if runtime.runtime == .Wasi || runtime.runtime == .Onyx { +#load "./time/date" +#load "./encoding/base64" + +#load "./runtime/common" + +#if runtime.platform.Supports_Files { #load "./os/file" - #load "./os/os" +} + +#if runtime.platform.Supports_Directories { #load "./os/dir" } -#if runtime.runtime == .Onyx { - #load "./runtime/onyx_run" +#if runtime.platform.Supports_Os { + #load "./os/os" +} +#if runtime.platform.Supports_Processes { #load "./os/process" +} + +#if runtime.platform.Supports_Time { #load "./time/time" - #load "./time/date" +} +#if runtime.platform.Supports_Networking { #load "./net/net" #load "./net/tcp" - - #load "./onyx/fs" - #load "./onyx/cptr" - #load "./onyx/cbindgen" - #load "./onyx/fault_handling" -} -#if runtime.runtime == .Wasi { - #load "./wasi/wasi" - #load "./runtime/wasi" - #load "./wasi/clock" - #load "./wasi/env" - #load "./wasi/wasi_fs" } -#if runtime.runtime == .Js { #load "./runtime/js" } -#if runtime.runtime != .Custom { + +#if runtime.platform.Supports_Type_Info { #load "./runtime/info/helper" #load "./io/stdio" - - #load "./encoding/base64" - #load "./encoding/csv" #load "./misc/any_utils" + #load "./encoding/csv" +} + +#if runtime.platform.Supports_Threads && runtime.Multi_Threading_Enabled { + #load "./threads/thread" } #if runtime.Multi_Threading_Enabled { @@ -95,6 +98,25 @@ package core #load "./sync/semaphore" #load "./sync/barrier" #load "./sync/once" +} - #load "./threads/thread" + +// +// Load platform files +// + +#if runtime.runtime == .Onyx { + #load "./runtime/platform/onyx/platform" + + #load "./onyx/cptr" + #load "./onyx/cbindgen" + #load "./onyx/fault_handling" } + +#if runtime.runtime == .Wasi { + #load "./runtime/platform/wasi/platform" +} + +#if runtime.runtime == .Js { + #load "./runtime/platform/js/platform" +} \ No newline at end of file diff --git a/core/threads/thread.onyx b/core/threads/thread.onyx index c234a834..c7152f16 100644 --- a/core/threads/thread.onyx +++ b/core/threads/thread.onyx @@ -41,7 +41,7 @@ spawn :: (t: ^Thread, data: ^$T, func: (^T) -> void) { stack_base := raw_alloc(alloc.heap_allocator, 1 << 20); - runtime.__spawn_thread(t.id, tls_base, stack_base, func, data); + runtime.platform.__spawn_thread(t.id, tls_base, stack_base, func, data); } // @@ -54,7 +54,7 @@ join :: (t: ^Thread) { __atomic_wait(^t.id, t.id); } else { // To not completely kill the CPU. - runtime.__sleep(1); + runtime.platform.__sleep(1); } } } @@ -65,7 +65,7 @@ join :: (t: ^Thread) { kill :: (t: ^Thread) -> i32 { if !t.alive do return -1; - ret := runtime.__kill_thread(t.id); + ret := runtime.platform.__kill_thread(t.id); if ret > 0 do __exited(t.id); return 1; diff --git a/core/time/date.onyx b/core/time/date.onyx index 74bc8249..42944419 100644 --- a/core/time/date.onyx +++ b/core/time/date.onyx @@ -16,8 +16,11 @@ Date :: struct { return .{ year, month - 1, day }; } - today :: () -> Date { - return now()->as_date(); + + #if runtime.platform.Supports_Time { + today :: () -> Date { + return now()->as_date(); + } } add_months :: (d: Date, days: i32) -> Date { diff --git a/core/time/time.onyx b/core/time/time.onyx index b61975d0..5d4ad95f 100644 --- a/core/time/time.onyx +++ b/core/time/time.onyx @@ -1,8 +1,14 @@ package core.time use core {os, conv} +use runtime.platform { + __time_gmtime, + __time_localtime, + __time_mktime, + __time_strftime +} -#if runtime.runtime != .Onyx { +#if !runtime.platform.Supports_Time { #error "'core.time' should only be used with the Onyx runtime, for now."; } @@ -328,12 +334,3 @@ strptime :: (buf_: [] u8, format_: [] u8, tm: ^Timestamp) -> bool { } } -#local { - #foreign "onyx_runtime" { - __time_localtime :: (time: u64, tm: ^Timestamp) -> void --- - __time_gmtime :: (time: u64, tm: ^Timestamp) -> void --- - __time_mktime :: (tm: ^Timestamp) -> i64 --- - __time_strftime :: (buf: [] u8, format: cstr, tm: ^Timestamp) -> u32 --- - } -} - diff --git a/core/wasi/README.md b/core/wasi/README.md deleted file mode 100644 index 3c3e6ee2..00000000 --- a/core/wasi/README.md +++ /dev/null @@ -1 +0,0 @@ -These files are only available on the 'wasi' runtime. In a C compilation, other files will be included, and the API between them will have to remain the same. \ No newline at end of file diff --git a/docs/ideas/platform_layer.md b/docs/ideas/platform_layer.md new file mode 100644 index 00000000..e14cee2c --- /dev/null +++ b/docs/ideas/platform_layer.md @@ -0,0 +1,132 @@ +Onyx Standard Library Platform Layer +==================================== + +Onyx has *soft* definition for what is expected from the supporting +platform within its standard library. This should be solidified into +a concrete set of types and functions that are expected to be implemented, +or _explicity not_ implemented for a given platform. + +This is where not having header files and having a fluid definition of +functions does hurt a little bit, because it is not possible to say +"This set of files should define all of these functions". Nonetheless, +this document will serve as that "header file" + +## Always Expected +- `__start() -> void` + + +## Files + +### Types +- `FileData` + +### Procedures +- `__file_open(path: str, mode: core.os.OpenMode) -> (FileData, core.os.FileError)` +- `__file_close(fd: FileData) -> core.os.FileError` +- `__file_stat(path: str, stat: ^os.FileStat) -> bool` +- `__file_exists(path: str) -> bool` +- `__file_remove(path: str) -> bool` +- `__file_rename(old_path, new_path: str) -> bool` + +### Values +- `__file_stream_vtable: io.Stream_Vtable` + + +## Directories + +### Types +- `DirectoryData` + +- `__dir_open(path: str, dir: ^DirectoryData) -> bool` +- `__dir_close(dir: DirectoryData) -> void` +- `__dir_read(dir: DirectoryData, out_entry: ^os.DirectoryEntry) -> bool` +- `__dir_create(path: str) -> bool` +- `__dir_remove(path: str) -> bool` + +### Values + + + +## Standard I/O + +### Types + +### Procedures +- `__output_string(s: str) -> u32` +- `__output_error(s: str) -> u32` +- `__read_from_input(buffer: [] u8) -> i32` + - `> 0` on success. Returns number of bytes + - `0` on no-input, but not error. + - `< 0` on error. + +### Values + + +## OS + +### Types + +### Procedures +- `__exit(code: i32) -> void` +- `__sleep(milliseconds: i32) -> void` + +### Values + + +## Time + +### Types + +### Procedures +- `__time() -> u64` +- `__time_localtime(time: u64, tm: ^core.time.Timestamp) -> void` +- `__time_gmtime(time: u64, tm: ^core.time.Timestamp) -> void` +- `__time_gmtime(tm: ^core.time.Timestamp) -> i64` +- `__time_strftime(buf: [] u8, format: cstr, tm: ^core.time.Timestamp) -> u32` + +### Values + + +## Threads + +### Types + +### Procedures +- `__spawn_thread(id: i32, tls_base, stack_base: rawptr, func: (rawptr) -> void, data: rawptr) -> bool` +- `__kill_thread(id: i32) -> i32` + +### Values + + +## Processes + +### Types +- `ProcessData` + +### Procedures +- `__process_spawn(path: str, args: [] str, non_blocking_io: bool, starting_directory: str) -> ProcessData` +- `__process_read(handle: ProcessData, buffer: [] u8) -> i32` +- `__process_write(handle: ProcessData, buffer: [] u8) -> i32` +- `__process_kill(handle: ProcessData) -> bool` +- `__process_wait(handle: ProcessData) -> os.ProcessResult` +- `__process_destroy(handle: ProcessData) -> void` + +### Values + + +## Platform Support Flags + +### Types + +### Procedures + +### Values + +- `Supports_Files :: bool` +- `Supports_Directories :: bool` +- `Supports_Os :: bool` +- `Supports_Processes :: bool` +- `Supports_Time :: bool` +- `Supports_Networking :: bool` +- `Supports_Type_Info :: bool` +- `Supports_Threads :: bool` -- 2.25.1