summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-07-09 11:02:34 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-07-09 11:02:34 -0400
commit4310752e123b110ab7e13b8c8f2b29eeb83ce7b3 (patch)
tree45d1fdb025daacb4fb841dd4bd8d3626bf175516
parent6574c6862b03fc4ad126222e314c17a2c1d821e0 (diff)
fixed some bugs with tuples, new version of writei
-rw-r--r--cgen.c16
-rw-r--r--eval.c4
-rw-r--r--main.c3
-rw-r--r--std/io.toc90
-rw-r--r--test.toc31
-rw-r--r--types.c55
6 files changed, 145 insertions, 54 deletions
diff --git a/cgen.c b/cgen.c
index 9bed06c..a04319c 100644
--- a/cgen.c
+++ b/cgen.c
@@ -57,9 +57,6 @@ static inline void cgen_write(CGenerator *g, const char *fmt, ...) {
va_start(args, fmt);
vfprintf(cgen_writing_to(g), fmt, args);
va_end(args);
-#ifdef TOC_DEBUG
- fflush(cgen_writing_to(g));
-#endif
}
static inline void cgen_nl(CGenerator *g) {
@@ -708,7 +705,7 @@ static void cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
Constness *constness = fn_type->constness;
int i = 0;
IdentID *underscore_ids = NULL;
- int nout_params = (int)(exprs ? arr_len(exprs) : arr_len(idents));
+ int nout_params = (int)arr_len(ret_type->tuple);
if (idents) {
for (i = 0; i < nout_params; ++i) {
@@ -749,7 +746,7 @@ static void cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
}
/* out params */
IdentID *u = underscore_ids;
- for (i = 0; i < (int)nout_params; ++i) {
+ for (i = 0; i < nout_params; ++i) {
if (any_args || i > 0)
cgen_write(g, ", ");
if (exprs) {
@@ -762,7 +759,7 @@ static void cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
else
cgen_ident(g, idents[i]);
} else {
- cgen_write(g, "&(%s%d_)", prefix, i);
+ cgen_write(g, "&(%s%d)", prefix, i);
}
}
arr_clear(underscore_ids);
@@ -966,6 +963,8 @@ static void cgen_expr(CGenerator *g, Expression *e) {
break;
case EXPR_LITERAL_INT:
cgen_write(g, U64_FMT, e->intl);
+ if (e->intl > I64_MAX)
+ cgen_write(g, "U"); /* prevent GCC warnings */
break;
case EXPR_LITERAL_STR: {
char *p = e->strl.str;
@@ -1973,7 +1972,10 @@ static void cgen_file(CGenerator *g, ParsedFile *f, Typer *tr) {
g->nms = NULL;
g->fn = NULL;
g->file = f;
-
+ #ifdef TOC_DEBUG
+ /* if in debug mode, don't buffer output C file */
+ setbuf(cgen_writing_to(g), NULL);
+ #endif
cgen_write(g,
"#include <stdint.h>\n"
"#include <stddef.h>\n"
diff --git a/eval.c b/eval.c
index 4292f65..2b65637 100644
--- a/eval.c
+++ b/eval.c
@@ -953,6 +953,10 @@ static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value
break;
case BINARY_SUB:
if (lhs_type->kind == TYPE_PTR) {
+ if (rhs_type->kind == TYPE_PTR) {
+ out->i64 = (I64)((char *)rhs.ptr - (char *)lhs.ptr) / (I64)compiler_sizeof(lhs_type);
+
+ }
out->ptr = (char *)lhs.ptr - val_to_i64(rhs, rhs_type->builtin)
* (I64)compiler_sizeof(lhs_type->ptr);
} else {
diff --git a/main.c b/main.c
index 9e5bb52..1b7c380 100644
--- a/main.c
+++ b/main.c
@@ -8,7 +8,7 @@
/*
@TODO:
-a ::= fn() (int, int) { return 3, 5; } b ::= fn() (int, int) { return a(); }
+figure out how printf is gonna work
if we do #include "foo.toc", bar; and foo.toc fails, bar should be declared as TYPE_UNKNOWN (right now it's undeclared)
fix #foreign not at global scope - right now the cgen'd definition doesn't use the proper type
find out why file output is really slow at compile time; try to improve it
@@ -22,6 +22,7 @@ unions
bitwise operations
---
#compile_only for functions only used at compile time
+warn about x : u8 = 1283;
switch to / add as an alternative: libffi
- better yet, inline assembly
don't bother generating ret_ if nothing's deferred
diff --git a/std/io.toc b/std/io.toc
index b220918..c61d174 100644
--- a/std/io.toc
+++ b/std/io.toc
@@ -42,7 +42,7 @@ raw_file_close - close a raw file
O_CREAT ::= 0x40;
RawFile ::= int;
- raw_file_write ::= fn(file: RawFile, buf: &void, size: int) err := FILE_ERR_OK {
+ raw_file_write ::= fn(file: RawFile, buf: &void, size: int) err : FileError {
while size > 0 {
bytes_written := write(file as #C int, buf, size as #C size_t);
if bytes_written < 0 {
@@ -53,7 +53,7 @@ raw_file_close - close a raw file
buf += bytes_written;
}
}
- raw_file_read ::= fn(file: RawFile, buf: &void, size: int) n: int, err := FILE_ERR_OK {
+ raw_file_read ::= fn(file: RawFile, buf: &void, size: int) n: int, err : FileError {
bytes_read := read(file as #C int, buf, size as #C size_t);
if bytes_read < 0 {
err = FILE_ERR_MISC;
@@ -70,7 +70,7 @@ raw_file_close - close a raw file
raw_stdin ::= fn() RawFile {
return 0;
}
- raw_file_open_write ::= fn(name: []char) f: RawFile, err := FILE_ERR_OK {
+ raw_file_open_write ::= fn(name: []char) f: RawFile, err : FileError {
cstr := str_to_cstr(name);
defer mem.dels(cstr);
// @TODO: switch to bitwise or when that exists
@@ -79,7 +79,7 @@ raw_file_close - close a raw file
err = FILE_ERR_MISC; // @TODO
}
}
- raw_file_open_read ::= fn(name: []char) f: RawFile, err := FILE_ERR_OK {
+ raw_file_open_read ::= fn(name: []char) f: RawFile, err : FileError {
cstr := str_to_cstr(name);
defer mem.dels(cstr);
f = open(&cstr[0], O_RDONLY as #C int, 0) as RawFile;
@@ -87,7 +87,7 @@ raw_file_close - close a raw file
err = FILE_ERR_MISC; // @TODO
}
}
- raw_file_close ::= fn(f: RawFile) err := FILE_ERR_OK {
+ raw_file_close ::= fn(f: RawFile) err : FileError {
if close(f as #C int) == -1 {
err = FILE_ERR_MISC; // @TODO
}
@@ -117,7 +117,7 @@ raw_file_close - close a raw file
raw_stdin ::= fn() RawFile {
return #builtin("stdin");
}
- raw_file_open_write ::= fn(name: []char) f: RawFile, err := FILE_ERR_OK {
+ raw_file_open_write ::= fn(name: []char) f: RawFile, err : FileError {
cstr := base.str_to_cstr(name);
defer mem.dels(cstr);
mode := "wb\0";
@@ -126,7 +126,7 @@ raw_file_close - close a raw file
err = FILE_ERR_MISC; // @TODO
}
}
- raw_file_open_read ::= fn(name: []char) f: RawFile, err := FILE_ERR_OK {
+ raw_file_open_read ::= fn(name: []char) f: RawFile, err : FileError {
cstr := base.str_to_cstr(name);
defer mem.dels(cstr);
mode := "rb\0";
@@ -135,7 +135,7 @@ raw_file_close - close a raw file
err = FILE_ERR_MISC; // @TODO
}
}
- raw_file_close ::= fn(f: RawFile) err := FILE_ERR_OK {
+ raw_file_close ::= fn(f: RawFile) err : FileError {
if fclose(f) != 0 {
err = FILE_ERR_MISC; // @TODO
}
@@ -206,9 +206,17 @@ fclose ::= fn(f: &File) err: FileError {
mem.del(f);
}
+can_write ::= fn(mode: FileMode) bool {
+ return mode == MODE_WRITE;
+}
+
+can_read ::= fn(mode: FileMode) bool {
+ return mode == MODE_READ;
+}
+
fwrites ::= fn(use f: &File, s : []char) FileError {
#if IO_DEBUG {
- if mode != MODE_WRITE {
+ if !can_write(mode) {
base.error("Writing to file which wasn't opened for writing.");
}
}
@@ -247,10 +255,72 @@ puts ::= fn(s: []char) FileError {
return fputs(&std_out, s);
}
+fwritei ::= fn(use f: &File, x: int) err : FileError {
+ #if IO_DEBUG {
+ if !can_write(mode) {
+ base.error("Writing to file which wasn't opened for writing.");
+ }
+ }
+ max_int_len ::= 20; // maximum length of a 64-bit integer, converted to a string
+ if buffer_used > BUFSZ - max_int_len {
+ err = flush(f);
+ if err { return; }
+ }
+
+ out := &buffer[buffer_used];
+ start := out;
+
+ defer buffer_used = out - start;
+
+ // flush at end if file is not buffered
+ defer if nobuffer {
+ err = flush(f);
+ }
+
+
+ x_unsigned : u64;
+
+ if x > 0 {
+ x_unsigned = x as u64;
+ } elif x < 0 {
+ *out = '-';
+ out += 1;
+ // get the absolute value of x in a u64. this complicated stuff is needed because -INT_MIN doesn't fit in a 64-bit signed integer
+ x_unsigned = (x as u64) - 18446744073709551615 - 1;
+ } else {
+ *out = '0';
+ out += 1;
+ return;
+ }
+
+ scan_digit : u64 = 1000000000000000000;
+ started := false;
+ while scan_digit > 0 {
+ digit := (x_unsigned / scan_digit) % 10;
+ if digit > 0 { started = true; }
+ if started {
+ *out = (('0' as u64) + digit) as char;
+ out += 1;
+ }
+ scan_digit /= 10;
+ }
+}
+
+writei ::= fn(x: int) FileError {
+ return fwritei(&std_out, x);
+}
+
+puti ::= fn(x: int) err : FileError {
+ err = writei(x);
+ if !err {
+ err = writes("\n");
+ }
+}
+
// read into out, set its length appropriately
fread ::= fn(use f: &File, out: &[]char) FileError {
#if IO_DEBUG {
- if mode != MODE_READ {
+ if !can_read(mode) {
base.error("Reading from file which wasn't opened for reading.");
}
}
diff --git a/test.toc b/test.toc
index afb40bb..0ceb47c 100644
--- a/test.toc
+++ b/test.toc
@@ -1,32 +1,15 @@
-#include "std/mem.toc", mem;
#include "std/io.toc", io;
-#include "std/base.toc", base;
-main ::= fn() {
- file, err := io.fopen_read("test.txt");
- if err {
- base.error("Couldn't open file.");
- }
- defer io.fclose(file);
- buf : [3]char;
- while !err {
- s := buf[:];
- err = io.fread(file, &s);
- io.writes(s);
- }
-}
-
-/*
-// @TODO: fix this
-
-bar ::= fn() (int, int) {
+bar ::= fn() (int, int, int) {
return foo();
}
-foo ::= fn() (int, int) {
- return 3, 5;
+foo ::= fn() (int, int, int) {
+ return -9223372036854775808, 32, 0;
}
main ::= fn() {
- a, b := foo();
+ a, b, c := foo();
+ io.puti(a);
+ io.puti(b);
+ io.puti(c);
}
-*/
diff --git a/types.c b/types.c
index 17ac556..01a5c50 100644
--- a/types.c
+++ b/types.c
@@ -1842,7 +1842,14 @@ static Status types_expr(Typer *tr, Expression *e) {
if (expr_is_definitely_const(f) || type_is_builtin(&f->type, BUILTIN_TYPE) || has_varargs) {
Value val;
-
+ if (f->kind == EXPR_IDENT) {
+ /*
+ @TODO(eventually): this is a sort of cheat to avoid the fact that we can't evaluate future identifiers
+ this will cause problems
+ */
+ if (!types_decl(tr, f->ident->decl))
+ return false;
+ }
if (!eval_expr(tr->evalr, f, &val))
return false;
if (type_is_builtin(&f->type, BUILTIN_TYPE)) {
@@ -2604,9 +2611,11 @@ static Status types_expr(Typer *tr, Expression *e) {
case BINARY_GE:
case BINARY_EQ:
case BINARY_NE: {
- bool valid = false;
+ bool valid = false, errored = false;
assert(lhs_type->flags & TYPE_IS_RESOLVED);
assert(rhs_type->flags & TYPE_IS_RESOLVED);
+
+ t->kind = TYPE_UNKNOWN;
if (o == BINARY_SET) {
valid = type_eq_implicit(lhs_type, rhs_type);
@@ -2622,6 +2631,23 @@ static Status types_expr(Typer *tr, Expression *e) {
type_builtin_is_numerical(rhs_type->builtin)) {
valid = true;
}
+
+ if (o == BINARY_SUB && lhs_type->kind == TYPE_PTR
+ && rhs_type->kind == TYPE_PTR) {
+ if (type_eq_exact(lhs_type->ptr, rhs_type->ptr)) {
+ valid = true;
+ t->kind = TYPE_BUILTIN;
+ t->builtin = BUILTIN_I64;
+ } else {
+ char *s1, *s2;
+ s1 = type_to_str(lhs_type);
+ s2 = type_to_str(rhs_type);
+ err_print(e->where, "Pointer subtraction between distinct types %s and %s.");
+ free(s1); free(s2);
+ errored = true;
+ valid = false;
+ }
+ }
}
if (o == BINARY_LT || o == BINARY_GT || o == BINARY_LE || o == BINARY_GE
|| o == BINARY_EQ || o == BINARY_NE) {
@@ -2654,21 +2680,26 @@ static Status types_expr(Typer *tr, Expression *e) {
t->builtin = BUILTIN_BOOL;
break;
default: {
- *t = *overriding_type(lhs_type, rhs_type);
- if ((o == BINARY_MOD || o == BINARY_SET_MOD)
- && type_builtin_is_float(t->builtin)) {
- err_print(e->where, "Cannot use operator % on floating-point numbers.");
- valid = false;
+ if (t->kind == TYPE_UNKNOWN) { /* have not yet determined type */
+ *t = *overriding_type(lhs_type, rhs_type);
+ if ((o == BINARY_MOD || o == BINARY_SET_MOD)
+ && type_builtin_is_float(t->builtin)) {
+ err_print(e->where, "Cannot use operator % on floating-point numbers.");
+ errored = true;
+ valid = false;
+ }
}
} break;
}
}
if (!valid) {
- char *s1, *s2;
- s1 = type_to_str(lhs_type);
- s2 = type_to_str(rhs_type);
- const char *op = binary_op_to_str(o);
- err_print(e->where, "Invalid types to operator %s: %s and %s", op, s1, s2);
+ if (!errored) {
+ char *s1, *s2;
+ s1 = type_to_str(lhs_type);
+ s2 = type_to_str(rhs_type);
+ const char *op = binary_op_to_str(o);
+ err_print(e->where, "Invalid types to operator %s: %s and %s", op, s1, s2);
+ }
return false;
}
if (o == BINARY_SET_ADD ||