hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit bd39ecf5de04e2a1a501dc8af7b01c586abc0b8e
parent 4b68264ddce335f0d43f29c77219a5dad718eb3e
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 24 Feb 2021 12:03:27 -0500

bufio: flesh out bufio::fixed

Diffstat:
Mbufio/fixed.ha | 40+++++++++++++++++++++++++++++++++++-----
Mfs/fs.ha | 2+-
Mhare/lex/+test.ha | 10+++++++---
Mhare/parse/+test.ha | 15++++++++-------
4 files changed, 51 insertions(+), 16 deletions(-)

diff --git a/bufio/fixed.ha b/bufio/fixed.ha @@ -1,21 +1,30 @@ +use bytes; use io; -use rt; +use strings; -// XXX: All of this is temporary -export type fixed_stream = struct { +type fixed_stream = struct { stream: io::stream, buf: []u8, }; -export fn fixed(in: []u8) *io::stream = { +// Creates an [io::stream] for a fixed, caller-supplied buffer. Supports either +// read or write, but not both. +export fn fixed(in: []u8, mode: io::mode) *io::stream = { let s = alloc(fixed_stream { stream = io::stream { name = "<bufio::fixed>", - reader = &fixed_read, ... }, buf = in, }); + if (mode & io::mode::READ == io::mode::READ) { + assert(mode & io::mode::WRITE != io::mode::WRITE); + s.stream.reader = &fixed_read; + }; + if (mode & io::mode::WRITE == io::mode::WRITE) { + assert(mode & io::mode::READ != io::mode::READ); + s.stream.writer = &fixed_write; + }; return &s.stream; }; @@ -29,3 +38,24 @@ fn fixed_read(s: *io::stream, buf: []u8) (size | io::error | io::EOF) = { stream.buf = stream.buf[n..]; return n; }; + +fn fixed_write(s: *io::stream, buf: const []u8) (size | io::error) = { + let stream = s: *fixed_stream; + if (len(stream.buf) == 0) { + return 0z; + }; + const n = if (len(buf) > len(stream.buf)) len(stream.buf) else len(buf); + stream.buf[..n] = buf[..n]; + stream.buf = stream.buf[n..]; + return n; +}; + +@test fn fixed() void = { + // TODO: add a read test too + static let buf: [1024]u8 = [0...]; + let stream = fixed(buf, io::mode::WRITE); + let n = 0z; + n += io::write(stream, strings::to_utf8("hello ")) as size; + n += io::write(stream, strings::to_utf8("world")) as size; + assert(bytes::equal(buf[..n], strings::to_utf8("hello world"))); +}; diff --git a/fs/fs.ha b/fs/fs.ha @@ -16,7 +16,7 @@ export fn open(fs: *fs, path: path, mode: io::mode) (*io::stream | error) = { }; }; -// Creates a new file. +// Creates a new file. The default file permissions are implementation defined. export fn create(fs: *fs, path: path, mode: io::mode) (*io::stream | error) = { return match (fs.create) { null => io::unsupported, diff --git a/hare/lex/+test.ha b/hare/lex/+test.ha @@ -1,10 +1,12 @@ use bufio; use fmt; use io; +use io::{mode}; use strings; @test fn unget() void = { - let lexer = lexer_init(bufio::fixed(strings::to_utf8("z")), "<test>"); + let buf = bufio::fixed(strings::to_utf8("z"), mode::READ); + let lexer = lexer_init(buf, "<test>"); unget(&lexer, 'x'); unget(&lexer, 'y'); assert(next(&lexer) as rune == 'y'); @@ -55,7 +57,8 @@ fn liteq(expected: literal, actual: literal) bool = { }; fn lextest(in: str, expected: [](uint, uint, token)) void = { - let lexer = lexer_init(bufio::fixed(strings::to_utf8(in)), "<test>"); + let buf = bufio::fixed(strings::to_utf8(in), mode::READ); + let lexer = lexer_init(buf, "<test>"); for (let i = 0z; i < len(expected); i += 1) { let eline = expected[i].0, ecol = expected[i].1, etok = expected[i].2; @@ -189,7 +192,8 @@ fn lextest(in: str, expected: [](uint, uint, token)) void = { let keywords = bmap[..btoken::LAST_KEYWORD+1]; for (let i = 0z; i < len(keywords); i += 1) { let lexer = lexer_init(bufio::fixed( - strings::to_utf8(keywords[i])), "<test>"); + strings::to_utf8(keywords[i]), mode::READ), + "<test>"); let tl = match (lex(&lexer)) { tl: (token, location) => tl, * => abort(), diff --git a/hare/parse/+test.ha b/hare/parse/+test.ha @@ -1,13 +1,14 @@ use bufio; +use fmt; use hare::ast; use hare::lex; +use io::{mode}; use strings; -use fmt; @test fn ident() void = { { const in = "foo"; - let buf = bufio::fixed(strings::to_utf8(in)); + let buf = bufio::fixed(strings::to_utf8(in), mode::READ); let lexer = lex::lexer_init(buf, "<test>"); let ident = ident(&lexer) as ast::ident; defer ast::ident_free(ident); @@ -18,7 +19,7 @@ use fmt; { const in = "foo::bar"; - let buf = bufio::fixed(strings::to_utf8(in)); + let buf = bufio::fixed(strings::to_utf8(in), mode::READ); let lexer = lex::lexer_init(buf, "<test>"); let ident = ident(&lexer) as ast::ident; defer ast::ident_free(ident); @@ -29,7 +30,7 @@ use fmt; { const in = "foo::bar::baz"; - let buf = bufio::fixed(strings::to_utf8(in)); + let buf = bufio::fixed(strings::to_utf8(in), mode::READ); let lexer = lex::lexer_init(buf, "<test>"); let ident = ident(&lexer) as ast::ident; defer ast::ident_free(ident); @@ -41,7 +42,7 @@ use fmt; { const in = "foo::bar;"; - let buf = bufio::fixed(strings::to_utf8(in)); + let buf = bufio::fixed(strings::to_utf8(in), mode::READ); let lexer = lex::lexer_init(buf, "<test>"); let ident = ident(&lexer) as ast::ident; defer ast::ident_free(ident); @@ -55,7 +56,7 @@ use fmt; @test fn imports() void = { { const in = "use foo;"; - let buf = bufio::fixed(strings::to_utf8(in)); + let buf = bufio::fixed(strings::to_utf8(in), mode::READ); let lexer = lex::lexer_init(buf, "<test>"); let mods = imports(&lexer) as []ast::import; defer for (let i = 0z; i < len(mods); i += 1) { @@ -76,7 +77,7 @@ use fmt; "use bar;\n" "use baz::bat;\n\n" "export fn main() void = void;"; - let buf = bufio::fixed(strings::to_utf8(in)); + let buf = bufio::fixed(strings::to_utf8(in), mode::READ); let lexer = lex::lexer_init(buf, "<test>"); let mods = imports(&lexer) as []ast::import; defer for (let i = 0z; i < len(mods); i += 1) {