summaryrefslogtreecommitdiff
path: root/docs/2026_REBASE/stdlib.js
blob: 22c92fe4d34635e044572482b7792e1d64421964 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* Generated by tools/snapshot-library.py; local source snapshot. */
window.REBASE.library = {
  "origin": "chapter25/src/main/smp",
  "files": {
    "sys.smp": "\n// top-level default standard library import\n\nval adt = adt;                  // Abstract Data Types\nval ary = ary;                  // Array utilities\nval aryi64 = aryi64;            // Variable sized array of i64\nval aryu8 = aryu8;              // Variable sized array of u8\nval char = char;                // Character utilities\nval io = io;                    // IO library\nval libc = libc;                // libc FFI bindings\nval scan = scan;                // A simple string parser\n",
    "sys/adt/bitset.smp": "\n// A set of non-negative integers, represented one bit per value.\nstruct bitset {\n    i64[] !_bits;\n\n    new bitset = { ->\n        _bits = new i64[1];\n    };\n\n    // Return 0 for missing, non-zero for true\n    val get = { int bit ->\n        if( (bit >> 6) >= _bits# ) return false;\n        i64 mask = 1 << (bit & 63);\n        return (_bits[bit >> 6] & mask);\n    };\n\n    val _grow = { int bit ->\n        int x = bit >> 6;\n        int len = _bits#;\n        if( x < len ) return self;\n        while( x >= len ) len *= 2;\n        var bits = new i64[len];\n        for( int i=0; i<_bits#; i++ )\n            bits[i] = _bits[i];\n        _bits = bits;\n        return self;\n    };\n\n    // Set\n    val set = { int bit ->\n        i64 mask = 1 << (bit & 63);\n        _grow(bit)._bits[bit >> 6] |= mask;\n        return self;\n    };\n\n    // Test and set\n    val tset = { int bit ->\n        int idx = bit >> 6;\n        i64 mask = 1 << (bit & 63);\n        if( _grow(bit)._bits[idx] & mask )\n          return true;          // Already set\n        _bits[idx] |= mask;\n        return false;           // Was false (and now set)\n    };\n\n    val clr = { int bit ->\n        if( (bit >> 6) >= _bits# ) return self;\n        i64 mask = 1 << (bit & 63);\n        _bits[bit >> 6] &= (mask ^ -1);\n        return self;\n    };\n\n    val clear = { ->\n        for( int i=0; i<_bits#; i++ ) _bits[i] = 0;\n        return self;\n    };\n};\n",
    "sys/adt.smp": "\n// Abstract data types.\nval bitset = bitset;\n",
    "sys/ary.smp": "\n// Array utilities\n\n// Copy byte array contents.  Copies the shorter of the buffers and len\nval copy = { u8[] dst, int doff, u8[~] src, int soff, int len ->\n    if( len > dst# - doff ) len = dst# - doff;\n    if( len > src# - soff ) len = src# - soff;\n    for( int i=0; i<len; i++ )\n        dst[i+doff] = src[i+soff];\n    return dst;\n};\n\n// Compare lexigraphically array contents.  Compares up to shorter array or\n// len.  Returns <0 or >0 for first non-matching byte.  Returns <0 or >0 for\n// the larger array after that, or 0 if both arrays are fully equal.\nval cmp = { u8[~] src1, u32 off1, u8[~] src2, u32 off2, u32 len ->\n    u32 len1 = len > src1# - off1 ? src1# - off1 : len;\n    u32 len2 = len > src2# - off2 ? src2# - off2 : len;\n    u32 max = len1 > len2 ? len2 : len1;\n    for( int i=0; i<max; i++ )\n        if( src1[off1+i] != src2[off2+i] )\n            return src1[off1+i] - src2[off2+i]; // Bytes determine compare\n    return len1 - len2;                         // Length determines compare\n};\n",
    "sys/aryi64.smp": "\n// Ary/Vector of i64s\nstruct aryi64 {\n    u32 !len = 0;\n    i64[] !buf;\n\n    new aryi64 = { i64[] b ->\n        buf = b;\n    };\n\n    // Grow as needed\n    val _grow = { int len2 ->\n        if( len+len2 < buf# ) return self;\n        int newlen = buf# * 2;\n        while( len+len2 >= newlen ) newlen *= 2;\n        i64[] !buf2 = new i64[newlen];\n        for( int i=0; i<buf#; i++ )\n            buf2[i] = buf[i];\n        buf = buf2;\n        self;\n    };\n\n    // Add a i64 to aryu8\n    val add = { i64 c ->\n        _grow(1).buf[len++] = c;\n        self;\n    };\n\n    val get = { int index -> return buf[index]; };\n\n    // Write the bracketed array-list form to aryu8.\n    val str = { ->\n        // TODO: clunky default constructor syntax\n        var str = new aryu8().add('[');\n        for( int i=0; i<len; i++ )\n            str.num(buf[i]).add(',').add(' ');\n        if( len ) str.undo(2);\n        return str.add(']');\n    };\n\n    val swap = { int i, int j ->\n        i64 tmp = buf[i];\n        buf[i] = buf[j];\n        buf[j] = tmp;\n        self;\n    };\n};\n\n\n\n// Parse a comma-separated list of numbers, wrapped with square brackets,\n// with optional whitespace  e.g. \"[ -17, 0,99,12456789   ]  \".\n// parseAryI64 & aryi64.str are bijections modulo whitespace.\n// Returns null if the parse failed, without giving a clue as to why.\nval parseAryI64 = { u8[~] str ->\n    !scan !s = new scan(str);\n    if( !s.match('[') ) return null;\n    // Array of parsed results\n    var nums = new aryi64(new i64[1]);\n\n    // Parse a list of numbers\n    if( s.match(']') )          // Handle the empty list\n        return nums;\n\n    // Parse number commas \"123, \" until something else\n    while( s.x < s.buf# ) {\n        nums.add(s.number());\n        if( s.bad ) return null;\n        if( !s.match(',') )\n            break;\n    };\n    // Close the list\n    if( !s.match(']') ) return null;\n    s.skip();\n    return s.x == s.buf# ? nums : null;\n};\n\nval copy = { i64[] dst, int doff, i64[~] src, int soff, int len ->\n    for( int i=0; i<len; i++ )\n        dst[i+doff] = src[i+soff];\n    return dst;\n};\n",
    "sys/aryu8.smp": "\n// Ary/Vector of u8s - a resizable array of bytes.\nstruct aryu8 {\n    u32 !len = 0;\n    u8[] !buf;\n\n    new aryu8 = { -> buf = new u8[1]; };\n\n    // Grow as needed\n    val _grow = { int len2 ->\n        if( len+len2 < buf# ) return self;\n        int newlen = buf# * 2;\n        while( len+len2 >= newlen ) newlen *= 2;\n        u8[] !buf2 = new u8[newlen];\n        ary.copy(buf2,0,buf,0,buf#);\n        buf = buf2;\n        self;\n    };\n\n    val clear = { -> len = 0; self; };\n\n    // Add a character to aryu8\n    val add = { u8 c ->\n        _grow(1).buf[len++] = c;\n        self;\n    };\n\n    // Add all of a plain array to the aryu8\n    val addAry = { u8[~] xs ->\n        _grow(xs#);\n        ary.copy(buf,len,xs,0,xs#);\n        len += xs#;\n        self;\n    };\n\n    // Remove x bytes from the tail.\n    val undo = { int x ->\n        len = len >= x ? len-x : 0;\n        self;\n    };\n\n    // Print ASCII number into aryu8\n    val num = { i64 x ->\n        if( !x ) { add('0'); return self; }\n        if( x < 0 ) { add('-'); x = -x; }\n        i64 ten = 1, log = 0;\n        while( ten <= x ) { ten *= 10; log++; }\n        for( int i=0; i<log; i++ ) {\n            ten /= 10;\n            i64 q = x/ten;\n            u8 digit = q+'0';\n            add(digit);\n            x -= q*ten;\n        }\n        self;\n    };\n\n    // Write to fd, returns the number of bytes written (len).\n    val write = { i32 fd ->\n        i64 ptr = buf; // Cast buffer pointer to i64 for native C call\n        libc.write(fd,ptr,len);\n    };\n};\n\n\n// Parse one integer, ignore trailing data; returns 0 with an empty string.\n// If you want a more robust parsing, use the `scan` class\nval atoi = { u8[~] str ->\n    int x = 0;\n    while( x < str# && str[x] <= ' ' ) x++;\n    if( x == str# ) return 0;\n    bool neg = false;\n    if( str[x]=='-' ) { neg=true; x++; }\n    i64 n = 0;\n    while( x < str# && '0' <= str[x] <= '9' )\n        n = n*10 + str[x++]-'0';\n    return neg ? -n : n;\n};\n\n// Zero-terminate string for libc strings.  No error checking, just copies and\n// appends a zero.\n{ u8[~] -> u8[] } str0 = { u8[~] str ->\n  u8[] !strz = new u8[str#+1];\n  ary.copy(strz,0,str,0,str#);\n  strz[str#] = '\\0';\n  strz;\n};\n",
    "sys/char.smp": "\nval toupper = { u8 c ->\n    return c >= 'a' && c <= 'z' ? c - ('a' - 'A') : c;\n};\n\nval tolower = { u8 c ->\n    return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c;\n};\n",
    "sys/io.smp": "\n// Simple I/O Library\n\n// Write byte array to stdout\nval p          = { u8[~] str -> write(1,str); };\nval p_noInline = { u8[~] str -> write(1,str); };\n\n// Return fd contents as a u8[].\nval read = { i32 fd ->\n    var buf = new u8[8*1024];\n    i64 ptr = buf;\n    int len = 0;\n    while( true ) {\n        i32 rez = libc.read(fd,ptr,buf#);\n        if( rez > buf# ) libc._exit(libc.errno());\n        len += rez;\n        if( rez < buf# )\n            break;\n        libc._exit(-2); // Need to implement for more than 8K input\n    }\n    var out = new u8[len];\n    ary.copy(out,0,buf,0,len);\n};\n\n// Write all of str to fd.\nval write = { i32 fd, u8[~] str ->\n  i64 ptr = str;                // Convert array pointer to a i64 for the native call\n  libc.write(fd,ptr,str#);\n};\n\n// Write all of str to fd.\nval writeOff = { i32 fd, u8[~] str, u32 off, u32 len ->\n  i64 ptr = str;                // Convert array pointer to a i64 for the native call\n  ptr += off;                   // Skip offset\n  // Cap at available length\n  if( len > str# - off ) len = str# - off;\n  // Do the write\n  libc.write(fd,ptr,len);\n};\n\n// Return stdin as a u8[].\nval stdin = { -> read(0); };\n\n// Create file for writing.  Return fd, or -1 and errno has the error code\nval create = { u8[~] str ->\n    i64 ptr = sys.aryu8.str0(str);\n    i32 perms = 6*64 + 6*8 + 6; // 0666\n    return libc.creat(ptr, perms);\n};\n\n// Open file for reading.  Return fd, or -1 and errno has the error code\nval open = { u8[~] str ->\n    i64 ptr = sys.aryu8.str0(str);\n    return libc.open(ptr, sys.libc.O_RDONLY, 0);\n};\n\n// Close an open fd.  Return 0, or -1 and errno has the error code\nval close = { i32 fd -> return libc.close(fd); };\n\n// Remove a file.  Return 0, or -1 and errno has the error code\nval remove = { u8[~] str ->\n    i64 ptr = sys.aryu8.str0(str);\n    return libc.unlink(ptr);\n};\n",
    "sys/libc.smp": "\n// libc bindings:\n//   https://www.man7.org/linux/man-pages/man2/<libc call>.2.html\n\n// The buffers are int-versions of zero-terminated strings.\n//     int buf = aryu8.str0(\"some_file\");\n// buf mode perm-> fd\n{  i64 i32  i32 -> i32 } open = \"C\";\n// buf perm -> fd\n{  i64 i32 -> i32 } creat = \"C\";\n\n// fd  buf len -> len\n{  i32 i64 u32 -> i32 } write = \"C\";\n// fd  buf len -> len\n{  i32 i64 u32 -> i32 } read = \"C\";\n// fd  -> err\n{  i32 -> i32 } close = \"C\";\n// path -> err\n{  i64 -> i32 } unlink = \"C\";\n\ni32 O_RDONLY = 0;\ni32 O_WRONLY = 1;\ni32 O_RDWR   = 2;\ni32 O_CREAT = 512; // 02000 on x86_64-pc-cygwin\ni32 O_TRUNC = 1024; // 04000 on x86_64-pc-cygwin\n\ni32 STDIN  = 0;\ni32 STDOUT = 1;\ni32 STDERR = 2;\n\n// status\n{  i32 -> i32 } _exit = \"C\";\n// errno is not an ordinary C data symbol; read it through the native runtime.\n{ i32 } simple_errno = \"C\";\nval errno = { -> simple_errno(); };\n// addr len prot flags fd  off -> void*\n{  i64  i64 i32  i32   i32 i32 -> i64 } mmap = \"C\";\n// mmap flags\ni32 PROT_EXEC = 4;\ni32 PROT_READ = 1;\ni32 PROT_WRITE= 2;\ni32 PROT_NONE = 0;\ni32 MAP_PRIVATE = 2;\ni32 MAP_ANON = 32;\n",
    "sys/scan.smp": "\n// Scanner; a simple string parser.\nstruct scan {\n    int !x;                     // Cursor\n    bool !bad;                  // True after a malformed token\n    u8[~] buf;                  // Buffer to parse\n\n    new scan = { u8[~] b -> buf = b; };\n\n    // Skip whitespace\n    val skip = { ->\n        while( x < buf# && buf[x] <= ' ' )\n            x++;\n        return self;\n    };\n\n    // True if find required character, and skip it; else False.\n    val match = { u8 c ->\n        skip();\n        if( x >= buf# ) return false;\n        if( buf[x] != c ) return false;\n        x++;\n        return true;\n    };\n\n    // Parse a simple number\n    val number = { ->\n        skip();\n        bool neg = match('-');\n        if( x >= buf# || buf[x] < '0' || '9' < buf[x] ) {\n            bad = true;\n            return 0;\n        }\n        i64 n = 0;\n        while( x < buf# && '0' <= buf[x] & buf[x] <= '9' )\n            n = n*10 + (buf[x++] - '0');\n        return neg ? -n : n;\n    };\n};\n"
  },
  "methods": "struct Counter {\n    int n;\n    val add = { int delta ->\n        n += delta;\n        return self;\n    };\n    val get = { -> return n; };\n};\n!Counter c = new Counter { n = arg; };\nc.add(3).add(4);\nreturn c.get();\n"
};