diff options
Diffstat (limited to 'chapter25/src/main/smp/sys')
| -rw-r--r-- | chapter25/src/main/smp/sys/Ary.smp | 10 | ||||
| -rw-r--r-- | chapter25/src/main/smp/sys/Scan.smp | 36 | ||||
| -rw-r--r-- | chapter25/src/main/smp/sys/aryi64.smp | 63 | ||||
| -rw-r--r-- | chapter25/src/main/smp/sys/aryu8.smp | 66 | ||||
| -rw-r--r-- | chapter25/src/main/smp/sys/io.smp | 32 | ||||
| -rw-r--r-- | chapter25/src/main/smp/sys/libc.smp | 20 |
6 files changed, 227 insertions, 0 deletions
diff --git a/chapter25/src/main/smp/sys/Ary.smp b/chapter25/src/main/smp/sys/Ary.smp new file mode 100644 index 00000000..0f667695 --- /dev/null +++ b/chapter25/src/main/smp/sys/Ary.smp @@ -0,0 +1,10 @@ +// -*- mode: java; -*- + +// Array utilities + +// Copy byte array contents +val copy = { u8[] dst, int doff, u8[~] src, int soff, int len -> + for( int i=0; i<len; i++ ) + dst[i+doff] = src[i+soff]; + return dst; +}; diff --git a/chapter25/src/main/smp/sys/Scan.smp b/chapter25/src/main/smp/sys/Scan.smp new file mode 100644 index 00000000..acf366f7 --- /dev/null +++ b/chapter25/src/main/smp/sys/Scan.smp @@ -0,0 +1,36 @@ +// -*- mode: java; -*- + +// Scanner; a simple string parser. +struct Scan { + int !x; // Cursor + u8[~] buf; // Immutable byte array, must be set in 2nd constructor + + new Scan = { u8[~] b -> + buf = b; + }; + + // Skip whitespace + val skip = { -> + while( x < buf# && 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; + }; +}; diff --git a/chapter25/src/main/smp/sys/aryi64.smp b/chapter25/src/main/smp/sys/aryi64.smp new file mode 100644 index 00000000..499431d8 --- /dev/null +++ b/chapter25/src/main/smp/sys/aryi64.smp @@ -0,0 +1,63 @@ +// -*- mode: java; -*- + +// Ary/Vector of i64s +struct aryi64 { + u32 !len = 0; + i64[] !buf; + + new aryi64 = { i64[] b -> + buf = b; + }; + + // 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 aryu8(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, without giving a clue as to why. +val parseAryI64 = { u8[~] str -> + Scan !s = new Scan(str); + if( !s.match('[') ) return null; + // Array of parsed results + var nums = new aryi64(new i64[1]); + + // Parse a list of numbers + if( s.match(']') ) // Handle the empty list + return nums; + + // Parse number commas "123, " until something else + while( s.x < s.buf# ) { + nums.add(s.number()); + if( !s.match(',') ) + break; + }; + // Close the list + return s.match(']') ? nums : null; +}; diff --git a/chapter25/src/main/smp/sys/aryu8.smp b/chapter25/src/main/smp/sys/aryu8.smp new file mode 100644 index 00000000..0ce4bd23 --- /dev/null +++ b/chapter25/src/main/smp/sys/aryu8.smp @@ -0,0 +1,66 @@ +// -*- mode: java; -*- + +// Ary/Vector of u8s - a resizable array of bytes. +struct aryu8 { + u32 !len = 0; + u8[] !buf; + + new aryu8 = { u8[] b -> + buf = b; + }; + + // 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]; + Ary.copy(buf2,0,buf,0,buf#); + buf = buf2; + self; + }; + + val clear = { -> len = 0; self; }; + + // Add a character to aryu8 + val add = { u8 c -> + _grow(1).buf[len++] = c; + self; + }; + + // Add all of a plain array to the aryu8 + val addAry = { u8[~] ary -> + _grow(ary#); + Ary.copy(buf,len,ary,0,ary#); + len += ary#; + self; + }; + + // Remove x bytes 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; // Cast buffer pointer to i64 for native C call + libc.write(fd,ptr,len); + }; +}; diff --git a/chapter25/src/main/smp/sys/io.smp b/chapter25/src/main/smp/sys/io.smp new file mode 100644 index 00000000..b94e89fa --- /dev/null +++ b/chapter25/src/main/smp/sys/io.smp @@ -0,0 +1,32 @@ +// -*- mode: java; -*- + +// Simple I/O Library + +// Write byte array to stdout +val p = { u8[~] str -> + i64 ptr = str; // cast array base to i64 + return libc.write(1,ptr,str#); +}; + +val p_noInline = { u8[~] str -> + i64 ptr = str; // cast array base to i64 + return libc.write(1,ptr,str#); +}; + +// Return stdin as a u8[]. +val stdin = { -> + var buf = new u8[8*1024]; + i64 ptr = buf; + int len = 0; + while( true ) { + int rez = libc.read(0,ptr,buf#); + if( rez < 0 ) libc._exit(libc.errno); + len += rez; + if( rez < buf# ) + break; + libc._exit(-2); // Need to implement for more than 8K input + } + // Compress + var dst = new u8[len]; + return Ary.copy(dst,0,buf,0,len); +}; diff --git a/chapter25/src/main/smp/sys/libc.smp b/chapter25/src/main/smp/sys/libc.smp new file mode 100644 index 00000000..42fc7313 --- /dev/null +++ b/chapter25/src/main/smp/sys/libc.smp @@ -0,0 +1,20 @@ +// -*- mode: java; -*- + +// libc bindings: +// https://www.man7.org/linux/man-pages/man2/<libc call>.2.html + +// fd buf len -> len +{ i32 i64 u32 -> u32 } write = "C"; +// fd buf len -> len +{ i32 i64 u32 -> u32 } read = "C"; +// status +{ i32 -> i32 } _exit = "C"; +// addr len prot flags fd off -> void* +{ i64 i64 i32 i32 i32 i32 -> i64 } mmap = "C"; +// mmap flags +i32 PROT_EXEC = 4; +i32 PROT_READ = 1; +i32 PROT_WRITE= 2; +i32 PROT_NONE = 0; +i32 MAP_PRIVATE = 2; +i32 MAP_ANON = 32; |
