diff options
| author | Cliff Click <cliffc@acm.org> | 2025-05-06 13:44:10 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2025-07-08 20:29:09 -0700 |
| commit | 664761624f4b0e3d6d1593b99e576854beec5949 (patch) | |
| tree | edff0e36e07cdc5aa82c8f7d144d68c52d5a4365 /src/main/smp/sys.smp | |
| parent | 018379b0cf4e286ceacb1e39f34dd80f770e381e (diff) | |
| download | Simple-linear-chapter23.tar.gz Simple-linear-chapter23.zip | |
Chapter 23: Methods and Revisiting Typeslinear-chapter23
Diffstat (limited to 'src/main/smp/sys.smp')
| -rw-r--r-- | src/main/smp/sys.smp | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/src/main/smp/sys.smp b/src/main/smp/sys.smp index ede08d63..cda93abe 100644 --- a/src/main/smp/sys.smp +++ b/src/main/smp/sys.smp @@ -29,6 +29,148 @@ struct sys { return dst; }; }; + + // Ary/Vector of u8s - a resizable array of bytes. + struct aryu8 { + u32 !len = 0; + u8[] !buf; + // Grow as needed + val _grow = { int len2 -> + if( len+len2 < buf# ) return self; + int newlen = buf# * 2; + while( len+len2 >= newlen ) newlen *= 2; + u8[] buf2 = new u8[newlen]; + sys.ary.copy(buf2,0,buf,0,buf#); + buf = buf2; + self; + }; + + // Add a character to aryu8 + val add = { u8 c -> + _grow(1).buf[len++] = c; + self; + }; + + // Add a plain array to the aryu8 + val addAry = { u8[~] ary -> + _grow(ary#); + sys.ary.copy(buf,len,ary,0,ary#); + len += ary#; + self; + }; + + // Remove x chars from the tail. + val undo = { int x -> + len = len >= x ? len-x : 0; + self; + }; + + // Print ASCII number into aryu8 + val num = { i64 x -> + if( !x ) { add('0'); return self; } + if( x < 0 ) { add('-'); x = -x; } + i64 ten = 1, log = 0; + while( ten <= x ) { ten *= 10; log++; } + for( int i=0; i<log; i++ ) { + ten /= 10; + i64 q = x/ten; + u8 digit = q+'0'; + add(digit); + x -= q*ten; + } + self; + }; + + // Write to fd, returns the number of bytes written (len). + val write = { i32 fd -> i64 ptr = buf; sys.libc.write(fd,ptr,len); }; + }; + + + // Scanner; a simple string parser. + struct Scan { + int !x; + u8[~] buf; + + // Skip whitespace + val skip = { -> + while( buf[x] <= ' ' ) + x++; + return self; + }; + + // True if find required character, and skip it; else False. + val match = { u8 c -> + skip(); + if( buf[x] != c ) return false; + x++; + return true; + }; + + // Parse a simple number + val number = { -> + skip(); + bool neg = match('-'); + i64 n = 0; + while( '0' <= buf[x] & buf[x] <= '9' ) + n = n*10 + (buf[x++] - '0'); + return neg ? -n : n; + }; + }; + + // Ary/Vector of i64s + struct aryi64 { + u32 !len = 0; + i64[] !buf; + // Grow as needed + val _grow = { int len2 -> + if( len+len2 < buf# ) return self; + int newlen = buf# * 2; + while( len+len2 >= newlen ) newlen *= 2; + i64[] buf2 = new i64[newlen]; + for( int i=0; i<buf#; i++ ) + buf2[i] = buf[i]; + buf = buf2; + self; + }; + + // Add a i64 to aryu8 + val add = { i64 c -> + _grow(1).buf[len++] = c; + self; + }; + + // Write to aryu8 + val str = { -> + // TODO: clunky default constructor syntax + var str = new sys.aryu8 { buf = new u8[1]; }.add('['); + for( int i=0; i<len; i++ ) + str.num(buf[i]).add(',').add(' '); + str.undo(2).add(']'); + }; + }; + + // Parse a comma-separated list of numbers, wrapped with square brackets, + // with optional whitespace e.g. "[ -17, 0,99,12456789 ] ". + // parseAryI64 & aryi64.str are bijections modulo whitespace. + // Returns null if the parse failed. + val parseAryI64 = { u8[~] str -> + sys.Scan !s = new sys.Scan{ buf = str; }; + if( !s.match('[') ) return null; + // Array of parsed results + var nums = new sys.aryi64{ buf=new i64[1]; }; + // Parse a list of numbers + if( !s.match(']') ) { // Handle the empty list + // Parse "123, " until a something else + while( s.x < s.buf# ) { + nums.add(s.number()); + if( !s.match(',') ) + break; + }; + if( !s.match(']') ) return null; // Close the list + } + return nums; + }; + struct io { // Print string to stdout val p = { u8[~] str -> |
