adding more core functionality and bugfixes
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 23 Aug 2020 04:28:48 +0000 (23:28 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 23 Aug 2020 04:28:48 +0000 (23:28 -0500)
core/string.onyx
core/wasi.onyx
docs/plan
onyx
progs/wasi_test.onyx
src/onyxparser.c
src/onyxutils.c
src/onyxwasm.c

index 8f58d66b321de4011fe00ba90a2e0d56ccc1a69e..4ff1f2fd4604628d81f3fd54e46f2fb34d49bc36 100644 (file)
@@ -1,17 +1,18 @@
 package core
 
-use package builtin { string }
+use package builtin { string, cstring }
 use package memory
+use package wasi
 
 Buffer :: struct {
     data   : rawptr = null;
-    length : u32    = 0;
+    len    : u32    = 0;
 }
 
-string_make :: proc #overloaded { string_make_from_u8 }
+string_make :: proc #overloaded { string_make_from_cstring }
 
 #private
-string_make_from_u8 :: proc (s: ^u8) -> string {
+string_make_from_cstring :: proc (s: cstring) -> string {
     len :: string_length(s);
 
     return string.{ len = len, data = s };
@@ -51,3 +52,158 @@ string_concat :: proc (a: Allocator, s1: string, s2: string) -> string {
 
 string_free :: proc (a: Allocator, s: string) do free(a, s.data);
 
+StringSplitResult :: struct {
+    tokens: ^string;
+    count: u32;
+}
+
+string_split :: proc (a: Allocator, str: string, delim: u8) -> StringSplitResult {
+    delim_count := 0;
+    for i: 0, str.len do if str.data[i] == delim do delim_count += 1;
+
+    strarr := cast(^string) alloc(a, sizeof string * (delim_count + 1));
+
+    curr_str := 0;
+    begin := str.data;
+
+    for i: 0, str.len {
+        if str.data[i] == delim {
+            strarr[curr_str] = string.{ begin, cast(u32) ^str.data[i] - cast(u32) begin };
+            begin = ^str.data[i + 1];
+            curr_str += 1;
+        }
+    }
+
+    strarr[curr_str] = string.{ begin, cast(u32) str.data + str.len - cast(u32) begin };
+
+    return StringSplitResult.{ strarr, delim_count + 1 };
+}
+
+
+
+StringBuilder :: struct {
+    // FIX(nested-structs): This should not be a pointer eventually.
+    // Currently nested structures cannot be passed as arguments or returned from procedures.
+    // When this issue is fixed, change this to Allocator.
+    alloc : ^Allocator;
+
+    data  : ^u8 = null;
+    len   : u32 = 0;
+    cap   : u32 = 0;
+}
+
+string_builder_make :: proc (a: ^Allocator, initial_cap: u32) -> StringBuilder {
+    data: ^u8 = null;
+
+    if initial_cap > 0 {
+        data = cast(^u8) alloc(*a, initial_cap);
+    }
+
+    return StringBuilder.{
+        alloc = a,
+        data  = data,
+        cap   = initial_cap,
+    };
+}
+
+string_builder_add_string :: proc (use sb: ^StringBuilder, str: string) -> ^StringBuilder {
+    len_total :: len + str.len;
+
+    if cap >= len_total {
+        for i: 0, str.len do data[len + i] = str.data[i];
+        len += str.len;
+        return sb;
+    }
+
+    new_cap := cap;
+    while new_cap < len_total do new_cap <<= 1;
+
+    new_data := cast(^u8) resize(*alloc, data, new_cap);
+    if new_data == null do return sb;
+
+    data = new_data;
+    cap = new_cap;
+
+    for i: 0, str.len do data[len + i] = str.data[i];
+    len += str.len;
+    return sb;
+}
+
+string_builder_add_cstring :: proc (use sb: ^StringBuilder, cstr: cstring) -> ^StringBuilder {
+    s := string_make(cstr);
+    return string_builder_add_string(sb, s);
+}
+
+u64_to_string :: proc (n_: u64, base: u64, buf: Buffer) -> string {
+    n := n_;
+
+    str :: cast(^u8) buf.data;
+    for i: 0, buf.len do str[i] = #char "\0";
+
+    c := cast(^u8) ^str[buf.len - 1];
+    len := 0;
+
+    s :: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+
+    if n == 0l {
+        *c = #char "0";
+        len += 1;
+        c -= 1;
+    } else {
+        while n > 0l {
+            m :: n % base;
+
+            *c = s.data[cast(u32) m];
+            len += 1;
+            c -= 1;
+
+            n /= base;
+        }
+    }
+
+    if base == 16l {
+        *c = #char "x";
+        len += 1;
+        c -= 1;
+        *c = #char "0";
+        len += 1;
+        c -= 1;
+    }
+
+    if base == 2l {
+        *c = #char "b";
+        len += 1;
+        c -= 1;
+        *c = #char "0";
+        len += 1;
+        c -= 1;
+    }
+
+    return string.{ data = c + 1, len = len };
+}
+
+string_builder_add_u64 :: proc (use sb: ^StringBuilder, n: u64) -> ^StringBuilder {
+    return string_builder_add_u64_with_base(sb, n, 10l);
+}
+
+string_builder_add_u64_with_base :: proc (use sb: ^StringBuilder, n: u64, base: u64) -> ^StringBuilder {
+    buf : [256] u8;
+    s := u64_to_string(n, 10l, Buffer.{ cast(^u8) buf, 256 });
+    return string_builder_add_string(sb, s);
+}
+
+string_builder_append :: proc #overloaded {
+    string_builder_add_string,
+    string_builder_add_cstring,
+    string_builder_add_u64_with_base,
+    string_builder_add_u64,
+}
+
+string_builder_to_string :: proc (use sb: ^StringBuilder) -> string {
+    return string.{ data, len };
+}
+
+string_builder_clear :: proc (use sb: ^StringBuilder) -> ^StringBuilder {
+    len = 0;
+    return sb;
+}
\ No newline at end of file
index d26d9e967eefad8ac0e368a472bf5f4f90f75540..c146415ef6abdfa7e09df2e7860157536e2f67fd 100644 (file)
 package wasi
 
+use package main as main
+use package builtin { string }
+use package memory
+
 Size      :: #type u32;
 Filesize  :: #type u64;
 Timestamp :: #type u64;
 
 ClockID   :: enum (u32) {
-       Realtime         :: 0x00;
-       Monotonic        :: 0x01;
-       ProcessCPUTimeID :: 0x02;
-       ThreadCPUTimeID  :: 0x03;
+    Realtime         :: 0x00;
+    Monotonic        :: 0x01;
+    ProcessCPUTimeID :: 0x02;
+    ThreadCPUTimeID  :: 0x03;
 }
 
 Errno :: enum (u16) {
-       Success      :: 0x00;
-       TooBig       :: 0x01;
-       Access       :: 0x02;
-       AddrInUse    :: 0x03;
-       AddrNotAvail :: 0x04;
-       AFNoSupport  :: 0x05;
-       Again        :: 0x06;
-       Already      :: 0x07;
-       BadFile      :: 0x08;
-       BadMsg       :: 0x09;
-       Busy         :: 0x0a;
-       Canceled     :: 0x0b;
-       Child        :: 0x0c;
-       ConnAborted  :: 0x0d;
-       ConnRefused  :: 0x0e;
-       ConnReset    :: 0x0f;
-       DeadLock     :: 0x10;
-       DestAddrReq  :: 0x11;
-       Domain       :: 0x12;
-       DQUOT        :: 0x13;
-       Exist        :: 0x14;
-       Fault        :: 0x15;
-       FileTooBig   :: 0x16;
-       HostUnreach  :: 0x17;
-       IdentRemoved :: 0x18;
-       IllegalSeq   :: 0x19;
-       InProgress   :: 0x1a;
-       Interrupt    :: 0x1b;
-       Invalid      :: 0x1c;
-       IO           :: 0x1d;
-       IsConnection :: 0x1e;
-       IsDirectory  :: 0x1f;
-       Loop         :: 0x20;
-       MFile        :: 0x21;
-       MLink        :: 0x22;
-       MsgSize      :: 0x23;
-       MultiHop     :: 0x24;
-       NameTooLong  :: 0x25;
-       NetDown      :: 0x26;
-       NetReset     :: 0x27;
-       NetUnreach   :: 0x28;
-       NFile        :: 0x29;
-       NoBufs       :: 0x2a;   
-       NoDev        :: 0x2b;
-       NoEntry      :: 0x2c;
-       NoExec       :: 0x2d;
-       NoLock       :: 0x2e;
-       NoLink       :: 0x2f;
-       NoMemory     :: 0x30;
-       NoMsg        :: 0x31;
-       NoProtoOpt   :: 0x32;
-       NoSpace      :: 0x33;
-       NoSys        :: 0x34;
-       NotConn      :: 0x35;
-       NotDir       :: 0x36;
-       NotEmpty     :: 0x37;
-       NotRecover   :: 0x38;
-       NotSock      :: 0x39;
-       NotSupported :: 0x3a;
-       NoTTY        :: 0x3b;
-       NXIO         :: 0x3c;
-       Overflow     :: 0x3d;
-       OwnerDead    :: 0x3e;
-       Permission   :: 0x3f;
-       Pipe         :: 0x40;
-       Protocol     :: 0x41;
-       ProtoNoSup   :: 0x42;
-       Prototype    :: 0x43;
-       Range        :: 0x44;
-       ReadonlyFS   :: 0x45;
-       SeekPipe     :: 0x46;
-       Search       :: 0x47;
-       Stale        :: 0x48;
-       Timedout     :: 0x49;
-       TextBusy     :: 0x4a;
-       XDev         :: 0x4b;
-
-       NotCapable   :: 0x4c;
+    Success      :: 0x00;
+    TooBig       :: 0x01;
+    Access       :: 0x02;
+    AddrInUse    :: 0x03;
+    AddrNotAvail :: 0x04;
+    AFNoSupport  :: 0x05;
+    Again        :: 0x06;
+    Already      :: 0x07;
+    BadFile      :: 0x08;
+    BadMsg       :: 0x09;
+    Busy         :: 0x0a;
+    Canceled     :: 0x0b;
+    Child        :: 0x0c;
+    ConnAborted  :: 0x0d;
+    ConnRefused  :: 0x0e;
+    ConnReset    :: 0x0f;
+    DeadLock     :: 0x10;
+    DestAddrReq  :: 0x11;
+    Domain       :: 0x12;
+    DQUOT        :: 0x13;
+    Exist        :: 0x14;
+    Fault        :: 0x15;
+    FileTooBig   :: 0x16;
+    HostUnreach  :: 0x17;
+    IdentRemoved :: 0x18;
+    IllegalSeq   :: 0x19;
+    InProgress   :: 0x1a;
+    Interrupt    :: 0x1b;
+    Invalid      :: 0x1c;
+    IO           :: 0x1d;
+    IsConnection :: 0x1e;
+    IsDirectory  :: 0x1f;
+    Loop         :: 0x20;
+    MFile        :: 0x21;
+    MLink        :: 0x22;
+    MsgSize      :: 0x23;
+    MultiHop     :: 0x24;
+    NameTooLong  :: 0x25;
+    NetDown      :: 0x26;
+    NetReset     :: 0x27;
+    NetUnreach   :: 0x28;
+    NFile        :: 0x29;
+    NoBufs       :: 0x2a;   
+    NoDev        :: 0x2b;
+    NoEntry      :: 0x2c;
+    NoExec       :: 0x2d;
+    NoLock       :: 0x2e;
+    NoLink       :: 0x2f;
+    NoMemory     :: 0x30;
+    NoMsg        :: 0x31;
+    NoProtoOpt   :: 0x32;
+    NoSpace      :: 0x33;
+    NoSys        :: 0x34;
+    NotConn      :: 0x35;
+    NotDir       :: 0x36;
+    NotEmpty     :: 0x37;
+    NotRecover   :: 0x38;
+    NotSock      :: 0x39;
+    NotSupported :: 0x3a;
+    NoTTY        :: 0x3b;
+    NXIO         :: 0x3c;
+    Overflow     :: 0x3d;
+    OwnerDead    :: 0x3e;
+    Permission   :: 0x3f;
+    Pipe         :: 0x40;
+    Protocol     :: 0x41;
+    ProtoNoSup   :: 0x42;
+    Prototype    :: 0x43;
+    Range        :: 0x44;
+    ReadonlyFS   :: 0x45;
+    SeekPipe     :: 0x46;
+    Search       :: 0x47;
+    Stale        :: 0x48;
+    Timedout     :: 0x49;
+    TextBusy     :: 0x4a;
+    XDev         :: 0x4b;
+
+    NotCapable   :: 0x4c;
 }
 
 Rights :: enum #flags (u64) {
-       DataSync;
-       Read;
-       Seek;
-       FdStatSetFlags;
-       Sync;
-       Tell;
-       Write;
-       Advise;
-       Allocate;
-       PathCreateDirectory;
-       PathCreateFile;
-       PathLinkSource;
-       PathLinkTarget;
-       PathOpen;
-       ReadDir;
-       PathReadlink;
-       PathRenameSource;
-       PathRenameTarget;
-       PathFilestatGet;
-       PathFilestateSetSize;
-       PathFilestateSetTimes;
-       FilestatGet;
-       FilestatSetSize;
-       FilestatSetTimes;
-       PathSymlink;
-       PathRemoveDirectory;
-       PathUnlinkFile;
-       PollFDReadWrite;
-       SockShutdown;
+    DataSync;
+    Read;
+    Seek;
+    FdStatSetFlags;
+    Sync;
+    Tell;
+    Write;
+    Advise;
+    Allocate;
+    PathCreateDirectory;
+    PathCreateFile;
+    PathLinkSource;
+    PathLinkTarget;
+    PathOpen;
+    ReadDir;
+    PathReadlink;
+    PathRenameSource;
+    PathRenameTarget;
+    PathFilestatGet;
+    PathFilestateSetSize;
+    PathFilestateSetTimes;
+    FilestatGet;
+    FilestatSetSize;
+    FilestatSetTimes;
+    PathSymlink;
+    PathRemoveDirectory;
+    PathUnlinkFile;
+    PollFDReadWrite;
+    SockShutdown;
 }
 
 FileDescriptor :: #type i32;
 
 IOVec :: struct {
-       buf : ^u8;
-       len : u32;
+    buf : ^u8;
+    len : u32;
 }
 
 CIOVec :: #type IOVec; // Constant IOVec
@@ -136,9 +140,9 @@ CIOVec :: #type IOVec; // Constant IOVec
 FileDelta :: #type i64;
 
 Whence :: enum (u8) {
-       Set :: 0x00;
-       Cur :: 0x01;
-       End :: 0x02;
+    Set :: 0x00;
+    Cur :: 0x01;
+    End :: 0x02;
 }
 
 DirCookie  :: #type u64;
@@ -146,205 +150,205 @@ DirNameLen :: #type u32;
 INode      :: #type u64;
 
 Filetype :: enum (u8) {
-       Unknown      :: 0x00;
-       BlockDevice  :: 0x01;
-       CharDevice   :: 0x02;
-       Directory    :: 0x03;
-       RegularFile  :: 0x04;
-       SocketDgram  :: 0x05;
-       SocketStream :: 0x06;   
-       SymLink      :: 0x07;
+    Unknown      :: 0x00;
+    BlockDevice  :: 0x01;
+    CharDevice   :: 0x02;
+    Directory    :: 0x03;
+    RegularFile  :: 0x04;
+    SocketDgram  :: 0x05;
+    SocketStream :: 0x06;   
+    SymLink      :: 0x07;
 }
 
 DirEnt :: struct {
-       d_next   : DirCookie;
-       d_ino    : INode;
-       d_namlen : DirNameLen;
-       d_type   : Filetype;
+    d_next   : DirCookie;
+    d_ino    : INode;
+    d_namlen : DirNameLen;
+    d_type   : Filetype;
 }
 
 Advice :: enum (u8) {
-       Normal     :: 0x00;     
-       Sequential :: 0x01;
-       Random     :: 0x02;
-       WillNeed   :: 0x03;
-       DontNeed   :: 0x04;
-       NoReuse    :: 0x05;
+    Normal     :: 0x00; 
+    Sequential :: 0x01;
+    Random     :: 0x02;
+    WillNeed   :: 0x03;
+    DontNeed   :: 0x04;
+    NoReuse    :: 0x05;
 }
 
 FDFlags :: enum #flags (u16) {
-       Append;
-       DSync;
-       NonBlock;
-       RSync;
-       Sync;
+    Append;
+    DSync;
+    NonBlock;
+    RSync;
+    Sync;
 }
 
 FDStat :: struct {
-       fs_filetype          : Filetype;
-       fs_flags             : FDFlags;
-       fs_rights_base       : Rights;
-       fs_rights_inheriting : Rights;
+    fs_filetype          : Filetype;
+    fs_flags             : FDFlags;
+    fs_rights_base       : Rights;
+    fs_rights_inheriting : Rights;
 }
 
 Device :: #type u64;
 
 FSTFlags :: enum #flags (u16) {
-       ATIM;
-       ATIM_NOW;
-       MTIM;
-       MTIM_NOW;
+    ATIM;
+    ATIM_NOW;
+    MTIM;
+    MTIM_NOW;
 }
 
 LookupFlags :: enum #flags (u32) {
-       SymLinkFollow;
+    SymLinkFollow;
 }
 
 OFlags :: enum #flags (u16) {
-       Creat;
-       Directory;
-       FailIfExists;
-       Trunc;
+    Creat;
+    Directory;
+    FailIfExists;
+    Trunc;
 }
 
 LinkCount :: #type u64;
 
 FileStat :: struct {
-       dev      : Device;
-       ino      : INode;
-       filetype : Filetype;
-       nlink    : LinkCount;
-       size     : Filesize;
-       atim     : Timestamp;
-       mtim     : Timestamp;
-       ctim     : Timestamp;
+    dev      : Device;
+    ino      : INode;
+    filetype : Filetype;
+    nlink    : LinkCount;
+    size     : Filesize;
+    atim     : Timestamp;
+    mtim     : Timestamp;
+    ctim     : Timestamp;
 }
 
 Userdata :: #type u64;
 
 EventType :: enum (u8) {
-       Clock;
-       FDRead;
-       FDWrite;
+    Clock;
+    FDRead;
+    FDWrite;
 }
 
 EventRWFlags :: enum #flags (u16) {
-       ReadWriteHangUp;
+    ReadWriteHangUp;
 }
 
 EventFDReadWrite :: struct {
-       nbytes : Filesize;
-       flags  : EventRWFlags;
+    nbytes : Filesize;
+    flags  : EventRWFlags;
 }
 
 Event :: struct {
-       userdata     : Userdata;
-       error        : Errno;
-       type         : EventType;
-       fd_readwrite : EventFDReadWrite;
+    userdata     : Userdata;
+    error        : Errno;
+    type         : EventType;
+    fd_readwrite : EventFDReadWrite;
 }
 
 SubClockFlags :: enum #flags (u16) {
-       ClockAbsTime;
+    ClockAbsTime;
 }
 
 SubscriptionClock :: struct {
-       id        : ClockID;
-       timeout   : Timestamp;
-       precision : Timestamp;
-       flags     : SubClockFlags;
+    id        : ClockID;
+    timeout   : Timestamp;
+    precision : Timestamp;
+    flags     : SubClockFlags;
 }
 
 SubscriptionFDReadWrite :: struct {
-       file_descriptor : FileDescriptor;
+    file_descriptor : FileDescriptor;
 }
 
 SubscriptionTagged :: struct {
-       tag : EventType;
+    tag : EventType;
 
-       u : struct #union {
-               clock    : SubscriptionClock;
-               fd_read  : SubscriptionFDReadWrite;
-               fd_write : SubscriptionFDReadWrite;
-       };
+    u : struct #union {
+        clock    : SubscriptionClock;
+        fd_read  : SubscriptionFDReadWrite;
+        fd_write : SubscriptionFDReadWrite;
+    };
 }
 
 Subscription :: struct {
-       userdata : Userdata;
+    userdata : Userdata;
 
-       u : SubscriptionTagged;
+    u : SubscriptionTagged;
 }
 
 ExitCode :: #type u32;
 Signal :: enum (u8) {
-       None;
-       Hup;
-       Int;
-       Quit;
-       Ill;
-       Trap;
-       Abrt;
-       Bus;
-       Fpe;
-       Kill;
-       USR1;
-       Segv;
-       USR2;
-       Pipe;
-       Alrm;
-       Term;
-       Chld;
-       Stop;
-       Tstp;
-       Ttin;
-       Urg;
-       Xcpu;
-       Xfsz;
-       Vtalrm;
-       Prof;
-       Winch;
-       Poll;
-       Pwr;
-       Sys;
+    None;
+    Hup;
+    Int;
+    Quit;
+    Ill;
+    Trap;
+    Abrt;
+    Bus;
+    Fpe;
+    Kill;
+    USR1;
+    Segv;
+    USR2;
+    Pipe;
+    Alrm;
+    Term;
+    Chld;
+    Stop;
+    Tstp;
+    Ttin;
+    Urg;
+    Xcpu;
+    Xfsz;
+    Vtalrm;
+    Prof;
+    Winch;
+    Poll;
+    Pwr;
+    Sys;
 }
 
 RIFlags :: enum #flags (u16) {
-       RecvPeek;
-       RecvWaitAll;
+    RecvPeek;
+    RecvWaitAll;
 }
 
 ROFlags :: enum #flags (u16) {
-       RecvDataTruncated :: 1;
+    RecvDataTruncated :: 1;
 }
 
 SIFlags :: enum #flags (u16) {
-       None;
+    None;
 }
 
 SDFlags :: enum #flags (u16) {
-       RD;
-       WR;
+    RD;
+    WR;
 }
 
 PreopenType :: enum (u8) {
-       Dir :: 0x00;
+    Dir :: 0x00;
 }
 
 PrestatDir :: struct {
-       pr_name_len : Size;
+    pr_name_len : Size;
 }
 
 PrestatTagged :: struct {
-       tag : PreopenType;
+    tag : PreopenType;
 
-       u : struct #union {
-               dir : PrestatDir;
-       };
+    u : struct #union {
+        dir : PrestatDir;
+    };
 }
 
 IOVecArray :: struct {
-       iovs     : ^IOVec;
-       iovs_len : Size;
+    iovs     : ^IOVec;
+    iovs_len : Size;
 }
 
 
@@ -369,74 +373,73 @@ fd_filestat_get       :: proc #foreign "wasi_snapshot_preview1" "fd_filestat_get
 fd_filestat_set_size  :: proc #foreign "wasi_snapshot_preview1" "fd_filestat_set_size" (fd: FileDescriptor, size: Filesize) -> Errno ---
 fd_filestat_set_times :: proc #foreign "wasi_snapshot_preview1" "fd_filestat_set_times" (fd: FileDescriptor, atim: Timestamp, mtim: Timestamp, fst_flags: FSTFlags) -> Errno ---
 fd_pread ::
-       proc #foreign "wasi_snapshot_preview1" "fd_pread"
-       (fd: FileDescriptor, iovs: IOVecArray, offset: Filesize, nread: ^Size) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "fd_pread"
+    (fd: FileDescriptor, iovs: IOVecArray, offset: Filesize, nread: ^Size) -> Errno ---
 fd_prestat_get :: proc #foreign "wasi_snapshot_preview1" "fd_prestat_get" (fd: FileDescriptor, buf: ^PrestatTagged) -> Errno ---
-fd_prestat_dir_name :: proc #foreign "wasi_snapshot_preview1" "fd_prestat_dir_name" (fd: FileDescriptor, path: ^u8, path_len: Size) -> Errno ---
+fd_prestat_dir_name :: proc #foreign "wasi_snapshot_preview1" "fd_prestat_dir_name" (fd: FileDescriptor, path: string) -> Errno ---
 fd_pwrite ::
-       proc #foreign "wasi_snapshot_preview1" "fd_pwrite"
-       (fd: FileDescriptor, iovs: IOVecArray, offset: Filesize, nwritten: ^Size) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "fd_pwrite"
+    (fd: FileDescriptor, iovs: IOVecArray, offset: Filesize, nwritten: ^Size) -> Errno ---
 fd_read ::
-       proc #foreign "wasi_snapshot_preview1" "fd_read"
-       (fd: FileDescriptor, iovs: IOVecArray, nread: ^Size) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "fd_read"
+    (fd: FileDescriptor, iovs: IOVecArray, nread: ^Size) -> Errno ---
 fd_readdir ::
-       proc #foreign "wasi_snapshot_preview1" "fd_readdir"
-       (fd: FileDescriptor, buf: ^u8, buf_len: Size, cookie: DirCookie, bufused: ^Size) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "fd_readdir"
+    (fd: FileDescriptor, buf: ^u8, buf_len: Size, cookie: DirCookie, bufused: ^Size) -> Errno ---
 fd_renumber ::
-       proc #foreign "wasi_snapshot_preview1" "fd_renumber"
-       (fd: FileDescriptor, to: FileDescriptor) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "fd_renumber"
+    (fd: FileDescriptor, to: FileDescriptor) -> Errno ---
 fd_seek ::
-       proc #foreign "wasi_snapshot_preview1" "fd_seek"
-       (fd: FileDescriptor, offset: FileDelta, whence: Whence, newoffset: ^Filesize) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "fd_seek"
+    (fd: FileDescriptor, offset: FileDelta, whence: Whence, newoffset: ^Filesize) -> Errno ---
 fd_sync :: proc #foreign "wasi_snapshot_preview1" "fd_sync" (fd: FileDescriptor) -> Errno ---
 fd_tell :: proc #foreign "wasi_snapshot_preview1" "fd_tell" (fd: FileDescriptor, offset: ^Filesize) -> Errno ---
 fd_write ::
-       proc #foreign "wasi_snapshot_preview1" "fd_write"
-       (fd: FileDescriptor, iovs: IOVecArray, nwritten: ^Size) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "fd_write"
+    (fd: FileDescriptor, iovs: IOVecArray, nwritten: ^Size) -> Errno ---
 
 path_create_directory ::
-       proc #foreign "wasi_snapshot_preview1" "path_create_directory"
-       (fd: FileDescriptor, path: ^u8, path_len: Size) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "path_create_directory"
+    (fd: FileDescriptor, path: string) -> Errno ---
 path_filestat_get ::
-       proc #foreign "wasi_snapshot_preview1" "path_filestat_get"
-       (fd: FileDescriptor, flags: LookupFlags, path: ^u8, path_len: Size, buf: ^FileStat) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "path_filestat_get"
+    (fd: FileDescriptor, flags: LookupFlags, path: string, buf: ^FileStat) -> Errno ---
 path_filestat_set_times ::
-       proc #foreign "wasi_snapshot_preview1" "path_filestat_set_times"
-       (fd: FileDescriptor, flags: LookupFlags, path: ^u8, path_len: Size, atim: Timestamp, mtim: Timestamp, fst_flags: FSTFlags) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "path_filestat_set_times"
+    (fd: FileDescriptor, flags: LookupFlags, path: string, atim: Timestamp, mtim: Timestamp, fst_flags: FSTFlags) -> Errno ---
 path_link ::
-       proc #foreign "wasi_snapshot_preview1" "path_link"
-       (fd: FileDescriptor, old_flags: LookupFlags, old_path: ^u8, old_path_len: Size, new_fd: FileDescriptor, new_path: ^u8, new_path_len: Size) -> Errno --- 
+    proc #foreign "wasi_snapshot_preview1" "path_link"
+    (fd: FileDescriptor, old_flags: LookupFlags, old_path: string, new_fd: FileDescriptor, new_path: string) -> Errno ---   
 path_open ::
-       proc #foreign "wasi_snapshot_preview1" "path_open"
-       ( fd: FileDescriptor
-       , dirflags: LookupFlags
-       , path: ^u8
-       , path_len: Size
-       , oflags: OFlags
-       , fs_rights_base: Rights
-       , fs_rights_inherting: Rights
-       , fdflags: FDFlags
-       , opened_fd: ^FileDescriptor
-       ) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "path_open"
+    ( fd: FileDescriptor
+    , dirflags: LookupFlags
+    , path: string
+    , oflags: OFlags
+    , fs_rights_base: Rights
+    , fs_rights_inherting: Rights
+    , fdflags: FDFlags
+    , opened_fd: ^FileDescriptor
+    ) -> Errno ---
 path_readlink ::
-       proc #foreign "wasi_snapshot_preview1" "path_readlink"
-       (fd: FileDescriptor, path: ^u8, path_len: Size, buf: ^u8, buf_len: Size, bufused: ^Size) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "path_readlink"
+    (fd: FileDescriptor, path: string, buf: ^u8, buf_len: Size, bufused: ^Size) -> Errno ---
 path_remove_directory ::
-       proc #foreign "wasi_snapshot_preview1" "path_remove_directory"
-       (fd: FileDescriptor, path: ^u8, path_len: Size) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "path_remove_directory"
+    (fd: FileDescriptor, path: string) -> Errno ---
 path_rename ::
-       proc #foreign "wasi_snapshot_preview1" "path_rename"
-       (fd: FileDescriptor, old_path: ^u8, old_path_len: Size, new_fd: FileDescriptor, new_path: ^u8, new_path_len: Size) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "path_rename"
+    (fd: FileDescriptor, old_path: string, new_fd: FileDescriptor, new_path: string) -> Errno ---
 path_symlink ::
-       proc #foreign "wasi_snapshot_preview1" "path_symlink"
-       (old_path: ^u8, old_path_len: Size, fd: FileDescriptor, new_path: ^u8, new_path_len: Size) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "path_symlink"
+    (old_path: ^u8, old_path_len: Size, fd: FileDescriptor, new_path: string) -> Errno ---
 path_unlink_file ::
-       proc #foreign "wasi_snapshot_preview1" "path_unlink_file"
-       (fd: FileDescriptor, path: ^u8, path_len: Size) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "path_unlink_file"
+    (fd: FileDescriptor, path: string) -> Errno ---
 
 poll_oneoff ::
-       proc #foreign "wasi_snapshot_preview1" "poll_oneoff"
-       (in: ^Subscription, out: ^Event, nsubscriptions: Size, nevents: ^Size) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "poll_oneoff"
+    (in: ^Subscription, out: ^Event, nsubscriptions: Size, nevents: ^Size) -> Errno ---
 
 proc_exit  :: proc #foreign "wasi_snapshot_preview1" "proc_exit" (rval: ExitCode) ---
 proc_raise :: proc #foreign "wasi_snapshot_preview1" "proc_raise" (sig: Signal) -> Errno ---
@@ -446,11 +449,31 @@ sched_yield :: proc #foreign "wasi_snapshot_preview1" "sched_yield" -> Errno ---
 random_get :: proc #foreign "wasi_snapshot_preview1" "random_get" (buf: ^u8, buf_len: Size) -> Errno ---
 
 sock_recv ::
-       proc #foreign "wasi_snapshot_preview1" "sock_recv"
-       (fd: FileDescriptor, ri_data: IOVecArray, ri_flags: RIFlags, ro_datalen: ^Size, ro_flags: ^ROFlags) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "sock_recv"
+    (fd: FileDescriptor, ri_data: IOVecArray, ri_flags: RIFlags, ro_datalen: ^Size, ro_flags: ^ROFlags) -> Errno ---
 sock_send ::
-       proc #foreign "wasi_snapshot_preview1" "sock_send"
-       (fd: FileDescriptor, si_data: IOVecArray, si_flags: SIFlags, so_datalen: ^Size) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "sock_send"
+    (fd: FileDescriptor, si_data: IOVecArray, si_flags: SIFlags, so_datalen: ^Size) -> Errno ---
 sock_shutdown ::
-       proc #foreign "wasi_snapshot_preview1" "sock_shutdown"
-       (fd: FileDescriptor, how: SDFlags) -> Errno ---
+    proc #foreign "wasi_snapshot_preview1" "sock_shutdown"
+    (fd: FileDescriptor, how: SDFlags) -> Errno ---
+
+
+
+// The builtin _start proc.
+// Sets up everything needed for execution.
+proc #export "_start" {
+       memory_init();
+
+       argc : Size;
+       argv_buf_size : Size;
+
+       args_sizes_get(^argc, ^argv_buf_size);
+
+       argv := cast(^^u8) malloc(sizeof ^u8 * argc);
+       argv_buf := cast(^u8) malloc(argv_buf_size);
+
+       args_get(argv, argv_buf);
+
+       main.main(argc, argv);
+}
index bdc1b957b04e3fd98a084b936d850cca8a9dd973..a3e2cb00bca64b2c1f9115a933dc0654c837b7c5 100644 (file)
--- a/docs/plan
+++ b/docs/plan
@@ -187,6 +187,10 @@ HOW:
         [X] returning structs
             - This will put forward a lot of the work that will be done for multiple return values
 
+        [ ] implicit overloading
+
+        [ ] 'use' enums and packages at an arbitrary scope
+
         [ ] convert to using an 'atom' like table
             - All identifier tokens are given a unique atom ptr, up to string equality.
             - This means identifiers can be compared using ptr comparison, instead of string comparison
@@ -208,14 +212,12 @@ HOW:
             - Arrays without a size
             - Converted to a struct that looks like:    
                 []T :: struct {
-                    count : u32;
                     data  : ^T;
+                    count : u32;
                 }
 
         [ ] Variadic arguments
 
-        [ ] 'use' enums and packages at an arbitrary scope
-
         [ ] 'when' statements
             - Compile time conditions
             - Only evalutate code blocks that evaluate to be true
diff --git a/onyx b/onyx
index 54e07f57d9affbbe60a5d45bcb1976b995835fe2..fc892e9a2dd75a61d07eeb80ed4ff661d685e5c0 100755 (executable)
Binary files a/onyx and b/onyx differ
index 9f4f7c3645faa3c7e0f252b279679097c97c93c8..d0fbf8da8edf4b0c6ad09595f6f6e976e821b8e1 100644 (file)
@@ -10,7 +10,11 @@ package main
 #include_file "string"
 
 use package builtin
+
+// NOTE: Didn't realize this would work so easily
+use package core { string_builder_append as sba }
 use package core
+
 use package memory
 use package wasi
 use package intrinsics
@@ -59,7 +63,7 @@ print_u64_with_base :: proc (n_: u64, base: u64) {
 
 print_string :: proc (s: string) {
        vec := IOVec.{ buf = s.data, len = s.len };
-       tmp : Size;     
+       tmp : Size;
        fd_write(1, IOVecArray.{ ^vec, 1 }, ^tmp);
        fd_datasync(1);
 }
@@ -141,32 +145,63 @@ readdir :: proc (fd: FileDescriptor) {
        }
 }
 
-main :: proc #export "_start" {
-       memory_init();
+timer_start :: proc -> Timestamp {
+       curr_time: Timestamp;
+       clock_time_get(ClockID.Realtime, cast(Timestamp) 1, ^curr_time);
+       return curr_time;
+}
 
+timer_end :: proc (start_time: Timestamp) -> Timestamp {
        curr_time: Timestamp;
        clock_time_get(ClockID.Realtime, cast(Timestamp) 1, ^curr_time);
-       print_u64_with_base(cast(u64) curr_time, 10l);
-       print("\n");
+       return (curr_time - start_time) / 1000000l;
+}
 
-       print("Hello World!\n");
-       print_u64_with_base(cast(u64) 0x624abd, 16l);
-       print("\n");
-       print_u64_with_base(cast(u64) __stack_top, 16l);
-       print("\n");
-       print_u64_with_base(cast(u64) __heap_start, 16l);
-       print("\n");
+is_prime :: proc (n: u32) -> bool {
+    sqrt :: cast(i32) (sqrt_f32(cast(f32) n));
+    for i: 2, sqrt + 1 do if n % i == 0 do return false;
+    return true;
+}
+
+main :: proc (argc: u32, argv: ^cstring) {
+       sb := string_builder_make(^heap_allocator, 16);
+
+       timer := timer_start();
+       defer {
+               ^sb |> string_builder_clear()
+                       |> sba("Time taken: ")
+                       |> sba(cast(u64) timer_end(timer), 10l)
+                       |> sba("ms\n")
+                       |> string_builder_to_string()
+                       |> print();
+       }
+
+       ^sb |> sba("\x01\x02\x03There are ")
+               |> sba(cast(u64) argc)
+               |> sba(" arguments.\n")
+               |> string_builder_to_string()
+               |> print();
+
+       string_builder_clear(^sb);
+
+       for i: 0, argc do ^sb |> sba(argv[i]) |> sba(" ");
+       ^sb |> sba("\n")
+               |> string_builder_to_string()
+               |> print();
 
-       fd : FileDescriptor;
+       fd: FileDescriptor = -1;
        err := path_open(3,
                LookupFlags.SymLinkFollow,
-               "./src/onyxmsgs.c".data, 16,
+               string_make(argv[1]),
                cast(OFlags) 0,
                Rights.DataSync | Rights.Write | Rights.Read | Rights.Tell | Rights.Seek | Rights.Advise | Rights.PathOpen | Rights.PathCreateFile,
                Rights.DataSync | Rights.Write | Rights.Read | Rights.Tell | Rights.Seek | Rights.Advise | Rights.PathOpen | Rights.PathCreateFile,
                FDFlags.Sync,
                ^fd);
 
+       defer if fd != -1 do fd_close(fd);
+
+
        if err != Errno.Success {
                print("Failed to open file\n");
                print("Error code: ");
@@ -184,19 +219,42 @@ main :: proc #export "_start" {
        }
        print("the size is: ");
        print_u64_with_base(cast(u64) filelen, 10l);
+       print("\n");
+
+       sum := 0l;
+       for i: 0, 20000 do if is_prime(i) do sum += cast(u64) i;
+       print("Sum of primes less than 20000 is: ");
+       print_u64_with_base(sum, 10l);
+       print("\n");
+
 
-       //buf : [128] u8;
-       //hello_vec := IOVec.{ buf = cast(^u8) buf, len = 128 };
-       //nread : Size;
-       //if fd_read(fd, IOVecArray.{ ^hello_vec, 1 }, ^nread) != Errno.Success {
-       //      print("Failed to read from file\n");
-       //      print("Error code: ");
-       //      print_u64_with_base(cast(u64) err, 10l);
-       //      proc_exit(1);
-       //      return;
-       //}
-//
-       //print(string.{ nread, cast(^u8) buf });
-
-       fd_close(fd);
-}
\ No newline at end of file
+       matches := string_split(heap_allocator, "This is a test string to test splitting. It surprisingly works very well.", #char " ");
+       defer free(heap_allocator, matches.tokens);
+
+       string_builder_clear(^sb);
+       for i: 0, matches.count {
+               ^sb |> sba(matches.tokens[i])
+                       |> sba("\n");
+       }
+
+       ^sb |> string_builder_to_string() |> print();
+
+       program := "+ + * s - /";
+       tokens := string_split(heap_allocator, program, #char " ");
+       defer free(heap_allocator, tokens.tokens);
+
+       acc := 0;
+       for i: 0, tokens.count {
+               tok :: tokens.tokens[i].data[0];
+
+               if     tok == #char "+" do acc += 1;
+               elseif tok == #char "-" do acc -= 1;
+               elseif tok == #char "*" do acc *= 2;
+               elseif tok == #char "/" do acc /= 2;
+               elseif tok == #char "s" do acc *= acc;
+       }
+
+       string_builder_clear(^sb);
+       ^sb |> sba("The program evaluated to '") |> sba(cast(u64) acc) |> sba("'\n");
+       ^sb |> string_builder_to_string() |> print();
+}
index 2ae55a9162f16dbd08559e97c756c416831250e4..1794b7f09fdeefa463985b151db8fbae62082d5e 100644 (file)
@@ -440,6 +440,15 @@ static AstTyped* parse_factor(OnyxParser* parser) {
                         case 'r': char_lit->value.i = '\r'; break;
                         case 'v': char_lit->value.i = '\v'; break;
                         case 'e': char_lit->value.i = '\e'; break;
+                        case 'x': {
+                            // HACK: This whole way of doing this
+                            u8 buf[3];
+                            buf[0] = char_lit->token->text[2];
+                            buf[1] = char_lit->token->text[3];
+                            buf[2] = 0;
+                            char_lit->value.i = strtol((const char *) buf, NULL, 16);
+                            break;
+                        }
                         default: {
                             onyx_message_add(Msg_Type_Literal,
                                     char_lit->token->pos,
@@ -889,6 +898,7 @@ static AstNode* parse_statement(OnyxParser* parser) {
         case '-':
         case '!':
         case '*':
+        case '^':
         case Token_Type_Literal_Integer:
         case Token_Type_Literal_Float:
         case Token_Type_Literal_String:
index 9733d625e570f644f64feda5276ca26e178fd73c..8dbacf26efdb1ce7c3ebda474a75e5db5d11b083 100644 (file)
@@ -184,6 +184,7 @@ AstNode* symbol_resolve(Scope* start_scope, OnyxToken* tkn) {
 
     if (res == NULL) {
         onyx_message_add(Msg_Type_Unknown_Symbol, tkn->pos, tkn->text);
+        token_toggle_end(tkn);
         return &empty_node;
     }
 
index 0eec5286f66cd93b66962cdcc0aa5bc1606ed47d..8133520ac589f6bc314a1d1de9042805f5263305 100644 (file)
@@ -1916,6 +1916,17 @@ static void compile_string_literal(OnyxWasmModule* mod, AstStrLit* strlit) {
             case 'r': *des++ = '\r'; break;
             case 'v': *des++ = '\v'; break;
             case 'e': *des++ = '\e'; break;
+            case 'x': {
+                // HACK: This whole way of doing this
+                i++;
+                u8 buf[3];
+                buf[0] = src[i + 0];
+                buf[1] = src[i + 1];
+                buf[2] = 0;
+                *des++ = strtol((const char *) buf, NULL, 16);
+                i++;
+                break;
+            }
             default:  *des++ = '\\';
                       *des++ = src[i];
             }