diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-07-09 11:02:34 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-07-09 11:02:34 -0400 |
commit | 4310752e123b110ab7e13b8c8f2b29eeb83ce7b3 (patch) | |
tree | 45d1fdb025daacb4fb841dd4bd8d3626bf175516 | |
parent | 6574c6862b03fc4ad126222e314c17a2c1d821e0 (diff) |
fixed some bugs with tuples, new version of writei
-rw-r--r-- | cgen.c | 16 | ||||
-rw-r--r-- | eval.c | 4 | ||||
-rw-r--r-- | main.c | 3 | ||||
-rw-r--r-- | std/io.toc | 90 | ||||
-rw-r--r-- | test.toc | 31 | ||||
-rw-r--r-- | types.c | 55 |
6 files changed, 145 insertions, 54 deletions
@@ -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" @@ -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 { @@ -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 @@ -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."); } } @@ -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); } -*/ @@ -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 || |