summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--instance_table.c3
-rw-r--r--main.c4
-rw-r--r--parse.c7
-rw-r--r--std/io.toc19
-rw-r--r--test.toc143
-rw-r--r--types.c114
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;
diff --git a/main.c b/main.c
index 78e79a9..8d8be18 100644
--- a/main.c
+++ b/main.c
@@ -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
diff --git a/parse.c b/parse.c
index c9867d5..4f733f6 100644
--- a/parse.c
+++ b/parse.c
@@ -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
diff --git a/std/io.toc b/std/io.toc
index 15314c9..96b0e21 100644
--- a/std/io.toc
+++ b/std/io.toc
@@ -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) {
diff --git a/test.toc b/test.toc
index 1d21ead..37f63f7 100644
--- a/test.toc
+++ b/test.toc
@@ -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();
-*/
diff --git a/types.c b/types.c
index 166bda0..423764f 100644
--- a/types.c
+++ b/types.c
@@ -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;
}
}