summaryrefslogtreecommitdiff
path: root/std
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-07-03 18:49:28 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-07-03 18:49:28 -0400
commit8dd389a5f7db1c8ef9e60d900104fef99f25645f (patch)
tree74e07d438e3c30fed3cdb7eec50b37936c4cfc7f /std
parent119950ebde3c9f096d1866ba6448d6bd9b22d063 (diff)
io is working but slow
Diffstat (limited to 'std')
-rw-r--r--std/base.toc13
-rw-r--r--std/io.toc115
-rw-r--r--std/mem.toc15
3 files changed, 113 insertions, 30 deletions
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;
+ }
+}