diff options
-rw-r--r-- | instance_table.c | 3 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | parse.c | 7 | ||||
-rw-r--r-- | std/io.toc | 19 | ||||
-rw-r--r-- | test.toc | 143 | ||||
-rw-r--r-- | types.c | 114 |
6 files changed, 217 insertions, 73 deletions
diff --git a/instance_table.c b/instance_table.c index 3a7c87e..f40ffeb 100644 --- a/instance_table.c +++ b/instance_table.c @@ -97,8 +97,9 @@ static U64 type_hash(Type *t) { hash = hash * type_hash(sub) + 0x16225b0aa9993299; return hash; case TYPE_FN: - arr_foreach(t->fn->types, Type, sub) + arr_foreach(t->fn->types, Type, sub) { hash = hash * type_hash(sub) + 0x2092d851ab2008de; + } return hash; case TYPE_PTR: hash += type_hash(t->ptr) * 0x277caae472151119 + 0xf5c6ae7b4dae3bcf; @@ -8,8 +8,10 @@ see development.md for development information @TODO: +see todo in test.toc see note in types.c : we probably shouldn't go to the trouble of evaluating this (just do this stuff if it's an ident) -ensure that in s[a:b] s is an l-value +ensure that in s[a:b] s is an l-value if it's an array +make sure you can't pass a function template or a tuple to varargs figure out how printf is gonna work make error when you give too few arguments better when putf is done, migrate tests to new std @@ -3079,6 +3079,13 @@ static inline void construct_resolved_builtin_type(Type *t, BuiltinType builtin) t->flags = TYPE_IS_RESOLVED; } +static inline void construct_resolved_slice_of_builtin(Allocator *a, Type *t, BuiltinType builtin) { + t->kind = TYPE_SLICE; + t->flags = TYPE_IS_RESOLVED; + t->slice = allocr_malloc(a, sizeof *t->slice); + construct_resolved_builtin_type(t->slice, builtin); +} + #ifndef TOC_DEBUG static #endif @@ -239,10 +239,21 @@ fwrites ::= fn(use f: &File, s : []char) FileError { } } +fwritec ::= fn(use f: &File, c : char) err : FileError { + if buffer_used > BUFSZ-1 { + flush(f); + buffer[0] = c; + } else { + buffer[buffer_used] = c; + buffer_used += 1; + } + if nobuffer { flush(f); } +} + fputs ::= fn(f: &File, s: []char) err : FileError { err = fwrites(f, s); if !err { - err = fwrites(f, "\n"); + err = fwritec(f, '\n'); } } @@ -250,6 +261,10 @@ writes ::= fn(s: []char) { fwrites(&std_out, s); } +writec ::= fn(c: char) { + fwritec(&std_out, c); +} + puts ::= fn(s: []char) { fputs(&std_out, s); } @@ -311,7 +326,7 @@ writei ::= fn(x: int) { puti ::= fn(x: int) { writei(x); - writes("\n"); + writec('\n'); } putb ::= fn(x: bool) { @@ -1,95 +1,135 @@ #include "std/io.toc"; -main ::= fn() { - a : [5]int; - for i ::= 1..10 { - a : [i]int; - a[0] = 7; - for j ::= 0.,i { - puti(a[j]); - } - } -} -main(); - - - -/* #include "std/io.toc", io; #include "std/types.toc"; -print_type ::= fn(t :: Type) { +write_type ::= fn(f : &File, t :: Type) { k ::= t._kind; use TypeKind; #if k == UNKNOWN { - io.puts("???"); + io.fwrites(f, "???"); } elif k == BUILTIN { b ::= t._builtin; use BuiltinType; #if b == I8 { - io.puts("i8"); + io.fwrites(f, "i8"); } elif b == U8 { - io.puts("u8"); + io.fwrites(f, "u8"); } elif b == I16 { - io.puts("i16"); + io.fwrites(f, "i16"); } elif b == U16 { - io.puts("u16"); + io.fwrites(f, "u16"); } elif b == I32 { - io.puts("i32"); + io.fwrites(f, "i32"); } elif b == U32 { - io.puts("u32"); + io.fwrites(f, "u32"); } elif b == I64 { - io.puts("i64"); + io.fwrites(f, "i64"); } elif b == U64 { - io.puts("u64"); + io.fwrites(f, "u64"); } elif b == F32 { - io.puts("f32"); + io.fwrites(f, "f32"); } elif b == F64 { - io.puts("f64"); + io.fwrites(f, "f64"); } elif b == CHAR { - io.puts("char"); + io.fwrites(f, "char"); } elif b == BOOL { - io.puts("bool"); + io.fwrites(f, "bool"); } elif b == TYPE { - io.puts("Type"); + io.fwrites(f, "Type"); } elif b == VARARGS { - io.puts(".."); + io.fwrites(f, ".."); } elif b == NMS { - io.puts("Namespace"); + io.fwrites(f, "Namespace"); } elif b == VOID { - io.puts("void"); + io.fwrites(f, "void"); } else { - io.puts("<unknown builtin type>"); + io.fwrites(f, "<unknown builtin type>"); } } elif k == FN { - // @TODO + #if t._is_template { + io.fwrites(f, "<function template>"); + } else { + io.fwrites(f, "fn("); + param_types ::= t._of; + for i ::= 0.,param_types.len { + #if i > 0 { + io.fwrites(f, ", "); + } + write_type(f, param_types[i]); + } + io.fwritec(f, ')'); + ret ::= t._returns; + if ret != void { + io.fwritec(f, ' '); + write_type(f, ret); + } + } } elif k == TUPLE { - // @TODO + io.fwritec(f, '('); + sub_types ::= t._of; + for i ::= 0.,sub_types.len { + #if i > 0 { + io.fwrites(f, ", "); + } + write_type(f, sub_types[i]); + } + io.fwritec(f, ')'); } elif k == ARR { - io.writes("["); + io.fwritec(f, '['); io.writei(t._n); - io.writes("]"); - print_type(t._of); + io.fwritec(f, ']'); + write_type(f, t._of); } elif k == PTR { - io.writes("&"); - print_type(t._of); + io.fwritec(f, '&'); + write_type(f, t._of); } elif k == SLICE { - io.writes("[]"); - print_type(t._of); + io.fwrites(f, "[]"); + write_type(f, t._of); } elif k == EXPR { - io.puts("<type expression>"); + io.fwrites(f, "<type expression>"); } elif k == STRUCT { - // @TODO + if t._is_template { + io.fwrites(f, "<struct template>"); + } else { + io.fwrites(f, "struct { "); + member_names ::= t._member_names; + member_types ::= t._member_types; + for i ::= 0.,member_names.len { + io.fwrites(f, member_names[i]); + io.fwrites(f, ": "); + write_type(f, member_types[i]); + io.fwrites(f, "; "); + } + io.fwritec(f, '}'); + } } else { - io.puts("<unknown type kind>"); + io.fwrites(f, "<unknown type kind>"); } } +put_type ::= fn(t :: Type) { + write_type(&std_out, t); + writec('\n'); +} + print_typeof ::= fn (t ::=, x : t) { - print_type(t); + put_type(t); +} + + +some_fn ::= fn(a,b,c: int, d,e,f := 3.0) y : f64 = 3.111 { } main ::= fn() { + // @TODO: moving this to the bottom of main screws up the order the structs are generated in. + Point2D ::= struct { + x, y : int; + } + Point ::= struct { + use p: Point2D; + z: float; + } foo0 := int == int; bar0 := int == float; foo1 := &&&int == &&&u8; @@ -106,6 +146,7 @@ main ::= fn() { t : [x*x]int; u := &t; v : &void; + p: Point; print_typeof(x); print_typeof(y); @@ -114,6 +155,12 @@ main ::= fn() { print_typeof(t); print_typeof(u); print_typeof(v); + print_typeof(main); + print_typeof(some_fn); + print_typeof(xx); + print_typeof(p); + xx ::= fn() (int, int) { + return 3, 5; + } } main(); -*/ @@ -2275,7 +2275,11 @@ static Status types_expr(Typer *tr, Expression *e) { } if (fn_type->constness || (has_varargs && !is_foreign)) { // type params, return declarations, etc - if (!type_of_fn(tr, fn_copy, &f->type, TYPE_OF_FN_IS_INSTANCE)) + ErrCtx *err_ctx = e->where.file->ctx; + arr_add(err_ctx->instance_stack, e->where); + bool success = type_of_fn(tr, fn_copy, &f->type, TYPE_OF_FN_IS_INSTANCE); + arr_remove_last(err_ctx->instance_stack); + if (!success) return false; if (fn_type->constness) { @@ -2520,18 +2524,25 @@ static Status types_expr(Typer *tr, Expression *e) { t->builtin = BUILTIN_BOOL; break; case UNARY_TYPEOF: { - // @TODO: these should be removed, and you should make sure you can't do something like t ::= &typeof(some_tuple); - // (right now printf won't work with varargs/tuples) - if (type_is_builtin(&of->type, BUILTIN_VARARGS)) { + Type *of_t = &of->type; + if (type_is_builtin(of_t, BUILTIN_VARARGS)) { err_print(of->where, "You can't apply typeof to varargs."); return false; } - if (of->type.kind == TYPE_TUPLE) { + if (of_t->kind == TYPE_TUPLE) { err_print(of->where, "You can't apply typeof to a tuple."); return false; } + if (of_t->kind == TYPE_FN) { + arr_foreach(of_t->fn->types, Type, sub) { + if (!(sub->flags & TYPE_IS_RESOLVED)) { + err_print(of->where, "You can't apply typeof to a function template."); + return false; + } + } + } e->kind = EXPR_TYPE; - e->typeval = &of->type; + e->typeval = of_t; t->kind = TYPE_BUILTIN; t->builtin = BUILTIN_TYPE; } break; @@ -2890,9 +2901,7 @@ static Status types_expr(Typer *tr, Expression *e) { e->val.type = ltype->ptr; break; case TYPE_TUPLE: { - t->kind = TYPE_SLICE; - t->slice = typer_malloc(tr, sizeof *t->slice); - construct_resolved_builtin_type(t->slice, BUILTIN_TYPE); + construct_resolved_slice_of_builtin(tr->allocr, t, BUILTIN_TYPE); Type *tuple_types = ltype->tuple; size_t ntypes = arr_len(tuple_types); e->val.slice.len = (I64)ntypes; @@ -2903,9 +2912,7 @@ static Status types_expr(Typer *tr, Expression *e) { e->val.slice.data = type_ptrs; } break; case TYPE_FN: { - t->kind = TYPE_SLICE; - t->slice = typer_malloc(tr, sizeof *t->slice); - construct_resolved_builtin_type(t->slice, BUILTIN_TYPE); + construct_resolved_slice_of_builtin(tr->allocr, t, BUILTIN_TYPE); Type *param_types = ltype->fn->types + 1; size_t nparams = arr_len(ltype->fn->types) - 1; e->val.slice.len = (I64)nparams; @@ -2942,19 +2949,23 @@ static Status types_expr(Typer *tr, Expression *e) { } break; } else if (str_eq_cstr(member, "_is_template")) { - if (ltype->kind != TYPE_FN) { - err_print(e->where, "This type doesn't have a '_is_template' member (only functions do)."); - return false; - } construct_resolved_builtin_type(t, BUILTIN_BOOL); e->kind = EXPR_VAL; - e->val.boolv = false; - arr_foreach(ltype->fn->types, Type, sub) { - if (!(sub->flags & TYPE_IS_RESOLVED)) { - e->val.boolv = true; - break; + if (ltype->kind == TYPE_FN) { + e->val.boolv = false; + arr_foreach(ltype->fn->types, Type, sub) { + if (!(sub->flags & TYPE_IS_RESOLVED)) { + e->val.boolv = true; + break; + } } + } else if (ltype->kind == TYPE_STRUCT) { + e->val.boolv = ltype->struc->params != NULL; + } else { + err_print(e->where, "This type doesn't have a '_is_template' member (only functions and structs do)."); + return false; } + break; } else if (str_eq_cstr(member, "_n")) { if (ltype->kind == TYPE_ARR) { construct_resolved_builtin_type(t, BUILTIN_I64); @@ -2967,6 +2978,67 @@ static Status types_expr(Typer *tr, Expression *e) { free(s); return false; } + } else if (str_eq_cstr(member, "_member_names")) { + // access a slice of the names of the fields of this struct + // @TODO: cache this stuff + if (ltype->kind != TYPE_STRUCT) { + err_print(e->where, "This type doesn't have a '_member_names' member (only structs do)."); + return false; + } + StructDef *struc = ltype->struc; + if (struc->params) { + err_print(e->where, "You can't access the '_member_names' type information from a struct template."); + return false; + } + if (!(struc->flags & STRUCT_DEF_RESOLVED)) { + if (!struct_resolve(tr, struc)) + return false; + } + + t->kind = TYPE_SLICE; + t->flags = TYPE_IS_RESOLVED; + Type *slicechar = t->slice = typer_malloc(tr, sizeof *t->slice); + construct_resolved_slice_of_builtin(tr->allocr, slicechar, BUILTIN_CHAR); + Field *fields = struc->fields; + size_t nfields = arr_len(fields); + Slice *names = typer_malloc(tr, nfields * sizeof *names); + Slice *name = names; + arr_foreach(fields, Field, f) { + // point directly to the identifier's internal string + name->len = (I64)f->name->len; + name->data = f->name->str; + ++name; + } + e->kind = EXPR_VAL; + e->val.slice.len = (I64)nfields; + e->val.slice.data = names; + break; + } else if (str_eq_cstr(member, "_member_types")) { + // access a slice of the types of the fields of this struct + // @TODO: cache this stuff + if (ltype->kind != TYPE_STRUCT) { + err_print(e->where, "This type doesn't have a '_member_types' member (only structs do)."); + return false; + } + StructDef *struc = ltype->struc; + if (struc->params) { + err_print(e->where, "You can't access the '_member_types' type information from a struct template."); + return false; + } + + construct_resolved_slice_of_builtin(tr->allocr, t, BUILTIN_TYPE); + + Field *fields = struc->fields; + size_t nfields = arr_len(fields); + Type **type_ptrs = typer_malloc(tr, nfields * sizeof *type_ptrs); + size_t i = 0; + arr_foreach(fields, Field, f) { + type_ptrs[i++] = f->type; + } + e->kind = EXPR_VAL; + e->val.slice.len = (I64)nfields; + e->val.slice.data = type_ptrs; + break; } } |