From 8dd389a5f7db1c8ef9e60d900104fef99f25645f Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Fri, 3 Jul 2020 18:49:28 -0400 Subject: io is working but slow --- std/base.toc | 13 +++++++ std/io.toc | 115 ++++++++++++++++++++++++++++++++++++++++++++--------------- std/mem.toc | 15 ++++++-- 3 files changed, 113 insertions(+), 30 deletions(-) (limited to 'std') diff --git a/std/base.toc b/std/base.toc index 54d64d6..950f817 100644 --- a/std/base.toc +++ b/std/base.toc @@ -23,4 +23,17 @@ PLATFORM ::= #builtin("platform"); PLATFORM_IS_UNIX :: bool = PLATFORM == PLATFORM_LINUX || PLATFORM == PLATFORM_OSX || PLATFORM == PLATFORM_FREEBSD || PLATFORM == PLATFORM_OPENBSD || PLATFORM == PLATFORM_MISC_UNIX; +fwrite ::= #foreign("fwrite", libc) fn(#C &"const void", #C size_t, #C size_t, &void) #C size_t; +stderr_write ::= fn(s: []char) { + fwrite(&s[0], 1, s.len as #C size_t, #builtin("stderr")); +} + +exit ::= #foreign("exit", libc) fn(#C int); +error ::= fn(s: []char) { + stderr_write("Fatal error: "); + stderr_write(s); + // @TODO: backtrace + stderr_write("\nExiting.\n"); + exit(1); +} diff --git a/std/io.toc b/std/io.toc index acba673..932cf45 100644 --- a/std/io.toc +++ b/std/io.toc @@ -1,16 +1,36 @@ + #include "std/base.toc", base; #include "std/mem.toc", mem; str_to_cstr ::= fn(s: []char) []char { ret := mem.news(char, s.len+1); mem.mem_copy(&ret[0], &s[0], s.len); - ret + return ret; } +// @TODO(eventually): enum +FileError ::= int; +FILE_ERR_OK ::= 0; +FILE_ERR_MISC ::= 1; +// @TODO: more of these + +/* +the raw file interface: +raw_stdout - standard output +raw_stderr - standard error +raw_file_write - write to a raw file +raw_file_open_write - open a raw file for writing +raw_file_close - flush and close a raw file +*/ + + #if base.PLATFORM_IS_UNIX { - // @TODO: use syscall instead + // @TODO: use syscall instead (it'll allow other functions called write) write ::= #foreign("write", base.libc) fn(#C int, #C &"const void", #C size_t) #C long; - open ::= #foreign("open", base.libc) fn (#C &"const char", #C int) #C int; + open ::= #foreign("open", base.libc) fn (#C &"const char", #C int, #C unsigned) #C int; + close ::= #foreign("close", base.libc) fn (#C int) #C int; + + DEFAULT_MODE ::= 0o644; O_RDONLY ::= 0x00; O_WRONLY ::= 0x01; @@ -26,20 +46,27 @@ str_to_cstr ::= fn(s: []char) []char { size -= bytes_written; buf += bytes_written; } - true + return true; } raw_stdout ::= fn() RawFile { - 1 + return 1; } raw_stderr ::= fn() RawFile { - 2 + return 2; } - file_open_write ::= fn(name: []char) f: RawFile, success: bool { + raw_file_open_write ::= fn(name: []char) f: RawFile, err := FILE_ERR_OK { cstr := str_to_cstr(name); defer mem.dels(cstr); // @TODO: switch to bitwise or when that exists - f = open(&cstr[0], (O_WRONLY + O_CREAT) as #C int) as RawFile; - success = f != -1; + f = open(&cstr[0], (O_WRONLY + O_CREAT) as #C int, DEFAULT_MODE as #C unsigned) as RawFile; + if f == -1 { + err = FILE_ERR_MISC; // @TODO + } + } + raw_file_close ::= fn(f: RawFile) err := FILE_ERR_OK { + if close(f as #C int) == -1 { + err = FILE_ERR_MISC; // @TODO + } } } else { // @TODO: on windows, use WriteFile @@ -47,65 +74,97 @@ str_to_cstr ::= fn(s: []char) []char { RawFile ::= &void; raw_file_write ::= fn(file: RawFile, buf: &void, size: int) bool { bytes_written := fwrite(buf, 1, size, file) as int; - bytes_written == size + return bytes_written == size; } raw_stdout ::= fn() RawFile { - #builtin("stdout") + return #builtin("stdout"); } raw_stderr ::= fn() RawFile { - #builtin("stdout") + return #builtin("stderr"); } - file_open_write ::= fn(name: []char) f: RawFile, success: bool { + raw_file_open_write ::= fn(name: []char) f: RawFile, err := FILE_ERR_OK { cstr := base.str_to_cstr(name); defer mem.dels(cstr); mode := "w\0"; f = fopen(&cstr[0], &mode[0]); - success = f != null; + if f == null { + err = FILE_ERR_MISC; // @TODO + } + } + raw_file_close ::= fn(f: RawFile) err := FILE_ERR_OK { + if fclose(f) != 0 { + err = FILE_ERR_MISC; // @TODO + } } } - File ::= struct { BUFSZ ::= 4096; raw : RawFile; - written : int; // ranges from 0 to FILE_BUFSZ-1 + buffer_used : int; // ranges from 0 to FILE_BUFSZ-1 nobuffer : bool; // if true, flush after every write buffer : [BUFSZ]char; } -raw_file_to_file ::= fn(raw : RawFile) f: File { +raw_file_to_file ::= fn(raw : RawFile, f: &File) { f.raw = raw; } std_out, std_err : File; -file_flush ::= fn(use f: &File) { - raw_file_write(raw, &buffer[0], written); - written = 0; +fopen_write ::= fn(name: []char) f: &File, error: FileError { + raw : RawFile; + raw, error = raw_file_open_write(name); + if !error { + f = mem.new(File); + raw_file_to_file(raw, f); + } +} + +flush ::= fn(use f: &File) { + raw_file_write(raw, &buffer[0], buffer_used); + buffer_used = 0; +} + +fclose ::= fn(f: &File) err: FileError { + err = raw_file_close(f.raw); + mem.del(f); } -file_writes ::= fn(use f: &File, s : []char) { +fwrites ::= fn(use f: &File, s : []char) { if f.nobuffer { raw_file_write(raw, &s[0], s.len); return; } - if written + s.len > BUFSZ { - file_flush(f); + if buffer_used + s.len > BUFSZ { + flush(f); if s.len > BUFSZ { raw_file_write(raw, &s[0], s.len); } else { mem.mem_copy(&buffer[0], &s[0], s.len); - written = s.len; + buffer_used = s.len; } } else { - mem.mem_copy(&buffer[written], &s[0], s.len); - written += s.len; + mem.mem_copy(&buffer[buffer_used], &s[0], s.len); + buffer_used += s.len; } } +fputs ::= fn(f: &File, s: []char) { + fwrites(f, s); + fwrites(f, "\n"); +} + +puts ::= fn(s: []char) { + fputs(&std_out, s); +} + + io_init ::= fn() { - std_out = raw_file_to_file(raw_stdout()); + raw_file_to_file(raw_stdout(), &std_out); std_out.nobuffer = true; - std_err = raw_file_to_file(raw_stderr()); + raw_file_to_file(raw_stderr(), &std_err); std_err.nobuffer = true; } + +#init io_init(); diff --git a/std/mem.toc b/std/mem.toc index 9ea9b12..b6af0fe 100644 --- a/std/mem.toc +++ b/std/mem.toc @@ -1,6 +1,6 @@ #include "std/base.toc", base; -// TODO: check for failed calloc +// @TODO: check for failed calloc calloc ::= #foreign("calloc", base.libc) fn(#C size_t, #C size_t) #C &"void"; free ::= #foreign("free", base.libc) fn(#C &"void"); @@ -15,7 +15,6 @@ news ::= fn(t :: Type, n : int) []t { return s; } -// TODO(eventually): use type information to make this just one function del ::= fn(t::=, x: &t) { free(x); } @@ -23,3 +22,15 @@ del ::= fn(t::=, x: &t) { dels ::= fn(t::=, x: []t) { free(x.data); } + + +// @OPTIM @OPTIM @OPTIM +mem_copy ::= fn(out: &void, in: &void, n : int) { + out_u8 : &u8 = out; + in_u8 : &u8 = in; + for i := 0..n-1 { + *out_u8 = *in_u8; + out_u8 += 1; + in_u8 += 1; + } +} -- cgit v1.2.3