summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--allocator.c3
-rw-r--r--copy.c19
-rw-r--r--err.c29
-rw-r--r--main.c5
-rw-r--r--parse.c8
-rwxr-xr-xrunv2
-rw-r--r--test.toc22
-rw-r--r--toc.c6
-rw-r--r--types.c33
-rw-r--r--types.h14
10 files changed, 89 insertions, 52 deletions
diff --git a/allocator.c b/allocator.c
index 4394201..202b238 100644
--- a/allocator.c
+++ b/allocator.c
@@ -1,3 +1,6 @@
+static void *err_malloc(size_t bytes);
+static void *err_calloc(size_t n, size_t sz);
+static void *err_realloc(void *prev, size_t new_size);
#define NO_ALLOCATOR 1 /* useful for debugging; valgrind (maybe) checks writing past the end of a malloc, but that won't work with an allocator */
/* number of bytes a page hold, not including the header */
#define PAGE_BYTES (16384 - sizeof(Page))
diff --git a/copy.c b/copy.c
index a296171..9f1acac 100644
--- a/copy.c
+++ b/copy.c
@@ -8,8 +8,9 @@ typedef struct {
static void copy_expr(Copier *c, Expression *out, Expression *in);
static void copy_decl(Copier *c, Declaration *out, Declaration *in);
static void copy_block(Copier *c, Block *out, Block *in);
+static void copy_type(Copier *c, Type *out, Type *in);
-static void copy_val(Allocator *allocr, Value *out, Value *in, Type *t) {
+static void copy_val(Copier *c, Value *out, Value *in, Type *t) {
switch (t->kind) {
case TYPE_BUILTIN:
case TYPE_FN:
@@ -17,27 +18,29 @@ static void copy_val(Allocator *allocr, Value *out, Value *in, Type *t) {
case TYPE_SLICE:
case TYPE_VOID:
case TYPE_UNKNOWN:
- case TYPE_TYPE:
*out = *in;
break;
case TYPE_ARR: {
size_t bytes = t->arr.n * compiler_sizeof(t->arr.of);
- out->arr = allocr_malloc(allocr, bytes);
+ out->arr = allocr_malloc(c->allocr, bytes);
memcpy(out->arr, in->arr, bytes);
} break;
case TYPE_TUPLE: {
size_t bytes = arr_len(t->tuple) * sizeof(*out->tuple);
- out->tuple = allocr_malloc(allocr, bytes);
+ out->tuple = allocr_malloc(c->allocr, bytes);
memcpy(out->tuple, in->tuple, bytes);
} break;
case TYPE_STRUCT: {
size_t bytes = compiler_sizeof(t);
- out->struc = allocr_malloc(allocr, bytes);
+ out->struc = allocr_malloc(c->allocr, bytes);
memcpy(out->struc, in->struc, bytes);
} break;
case TYPE_USER:
- copy_val(allocr, out, in, type_user_underlying(t));
+ copy_val(c, out, in, type_user_underlying(t));
break;
+ case TYPE_TYPE:
+ copy_type(c, out->type = allocr_malloc(c->allocr, sizeof *out->type), in->type);
+ break;
}
}
@@ -222,7 +225,7 @@ static void copy_expr(Copier *c, Expression *out, Expression *in) {
copy_type(c, &out->typeval, &in->typeval);
break;
case EXPR_VAL:
- copy_val(a, &out->val, &in->val, &in->type);
+ copy_val(c, &out->val, &in->val, &in->type);
break;
}
}
@@ -234,7 +237,7 @@ static void copy_decl(Copier *c, Declaration *out, Declaration *in) {
if (in->flags & DECL_HAS_EXPR)
copy_expr(c, &out->expr, &in->expr);
if (in->flags & DECL_FOUND_VAL) {
- copy_val(c->allocr, &out->val, &in->val, &in->type);
+ copy_val(c, &out->val, &in->val, &in->type);
}
if (in->flags & DECL_ANNOTATES_TYPE)
copy_type(c, &out->type, &in->type);
diff --git a/err.c b/err.c
index 85d386a..66feb5f 100644
--- a/err.c
+++ b/err.c
@@ -49,17 +49,30 @@ static void warn_print_header_(Location where) {
err_fprint(TEXT_WARN("warning:") " at line %lu of %s:\n", (unsigned long)where.line, where.ctx->filename);
}
-static void err_print_footer_(const char *context) {
- const char *end = strchr(context, '\n');
+static void err_print_location_text(Location where) {
+ const char *text = where.code;
+ const char *end = strchr(text, '\n');
int has_newline = end != NULL;
if (!has_newline)
- end = strchr(context, '\0');
+ end = strchr(text, '\0');
assert(end);
- err_fprint("\n\there: --> ");
- err_fwrite(context, 1, (size_t)(end - context));
+ err_fprint("\there: --> ");
if (!has_newline)
err_fprint("<end of file>");
+ else
+ err_fwrite(text, 1, (size_t)(end - text));
err_fprint("\n");
+
+}
+
+static void err_print_footer_(Location where) {
+ ErrCtx *ctx = where.ctx;
+ err_fprint("\n");
+ err_print_location_text(where);
+ arr_foreach(ctx->instance_stack, Location, inst) {
+ err_fprint("While generating the instance of a function\n");
+ err_print_location_text(*inst);
+ }
}
/* Write nicely-formatted errors to the error file */
@@ -69,7 +82,7 @@ static void err_vprint(Location where, const char *fmt, va_list args) {
if (!where.ctx->enabled) return;
err_print_header_(where);
err_vfprint(fmt, args);
- err_print_footer_(where.code);
+ err_print_footer_(where);
}
static void err_print_(int line, const char *file, Location where, const char *fmt, ...) {
@@ -90,7 +103,7 @@ static void info_print(Location where, const char *fmt, ...) {
va_start(args, fmt);
info_print_header_(where);
err_vfprint(fmt, args);
- err_print_footer_(where.code);
+ err_print_footer_(where);
va_end(args);
}
@@ -100,7 +113,7 @@ static void warn_print(Location where, const char *fmt, ...) {
va_start(args, fmt);
warn_print_header_(where);
err_vfprint(fmt, args);
- err_print_footer_(where.code);
+ err_print_footer_(where);
va_end(args);
}
diff --git a/main.c b/main.c
index ea6c724..fb2122b 100644
--- a/main.c
+++ b/main.c
@@ -1,9 +1,10 @@
/*
TODO:
-better errors (show where instance is)
+fix
alias type, instead of creating a new type.
make sure fn(t @ Type, x : t = 1598, y @ t = 9832) works
don't cgen decls etc. in parameter initializers
+check for leaks
struct parameters
don't allow while {3; 5} (once break is added)
@@ -60,7 +61,7 @@ int main(int argc, char **argv) {
Tokenizer t;
Allocator main_allocr;
allocr_create(&main_allocr);
- ErrCtx err_ctx;
+ ErrCtx err_ctx = {0};
err_ctx.filename = in_filename;
err_ctx.enabled = true;
tokr_create(&t, &file_idents, &err_ctx, &main_allocr);
diff --git a/parse.c b/parse.c
index 97d5f09..09767a7 100644
--- a/parse.c
+++ b/parse.c
@@ -1955,6 +1955,10 @@ static void fprint_block(FILE *out, Block *b) {
}
static void fprint_fn_expr(FILE *out, FnExpr *f) {
+ bool anyc = fn_has_any_const_params(f);
+ bool prev = parse_printing_after_types;
+ if (anyc)
+ parse_printing_after_types = false;
fprintf(out, "fn (");
arr_foreach(f->params, Declaration, decl) {
if (decl != f->params)
@@ -1964,10 +1968,6 @@ static void fprint_fn_expr(FILE *out, FnExpr *f) {
fprintf(out, ") ");
fprint_type(out, &f->ret_type);
fprintf(out, " ");
- bool anyc = fn_has_any_const_params(f);
- bool prev = parse_printing_after_types;
- if (anyc)
- parse_printing_after_types = false;
fprint_block(out, &f->body);
if (anyc)
parse_printing_after_types = prev;
diff --git a/runv b/runv
index b0a02f7..ccd621f 100755
--- a/runv
+++ b/runv
@@ -1,5 +1,5 @@
#!/bin/sh
-valgrind -q --track-origins=yes --error-exitcode=1 --malloc-fill=0xcd ./toc test.toc || exit 1
+valgrind -q --track-origins=yes --error-exitcode=1 --malloc-fill=0xcd --free-fill=0xef --num-callers=100 ./toc test.toc || exit 1
if [ "$1" = "c" ]; then
gcc out.c && ./a.out
elif [ "$1" = "pc" ]; then
diff --git a/test.toc b/test.toc
index 1d326d3..1fdab47 100644
--- a/test.toc
+++ b/test.toc
@@ -1,20 +1,20 @@
-puti @= fn(x: int) {
- #C("printf(\"%ld\\n\", (long)x);
-");
-};
-putf @= fn(x: float) {
- #C("printf(\"%f\\n\", (double)x);
-");
-};
+// puti @= fn(x: int) {
+// #C("printf(\"%ld\\n\", (long)x);
+// ");
+// };
+// putf @= fn(x: float) {
+// #C("printf(\"%f\\n\", (double)x);
+// ");
+// };
main @= fn() {
- puti(g(int));
- puti(g());
+ g(int);
+ g();
};
-g @= fn(t @= u8) int {
+g @= fn(t @= int) int {
87347 as t as int
};
diff --git a/toc.c b/toc.c
index 8a9bf5b..9577888 100644
--- a/toc.c
+++ b/toc.c
@@ -28,11 +28,11 @@ static Type *type_inner(Type *t) {
return t;
}
-#include "rand.c"
-#include "location.c"
-#include "err.c"
#include "allocator.c"
#include "arr.c"
+#include "location.c"
+#include "err.c"
+#include "rand.c"
#include "blockarr.c"
#include "str.c"
#include "instance_table.c"
diff --git a/types.c b/types.c
index 6e1f3bd..784c218 100644
--- a/types.c
+++ b/types.c
@@ -605,9 +605,11 @@ static bool types_fn(Typer *tr, FnExpr *f, Type *t, Location where,
Instance *instance) {
FnExpr *prev_fn = tr->fn;
bool success = true;
+ ErrCtx *err_ctx = where.ctx;
assert(t->kind == TYPE_FN);
if (instance) {
+ *(Location *)arr_add(&err_ctx->instance_stack) = where;
Copier cop = {.allocr = tr->allocr, .block = f->body.parent};
copy_fn_expr(&cop, &instance->fn, f, true);
f = &instance->fn;
@@ -630,8 +632,10 @@ static bool types_fn(Typer *tr, FnExpr *f, Type *t, Location where,
semi_const_arg_idx++;
}
}
- if (!type_of_fn(tr, f, where, t, TYPE_OF_FN_NO_COPY_EVEN_IF_CONST))
+ if (!type_of_fn(tr, f, where, t, TYPE_OF_FN_NO_COPY_EVEN_IF_CONST)) {
+ arr_remove_last(&err_ctx->instance_stack);
return false;
+ }
} else {
if (t->fn.constness)
return true; /* don't type function body yet; we need to do that for every instance */
@@ -688,6 +692,8 @@ static bool types_fn(Typer *tr, FnExpr *f, Type *t, Location where,
goto ret;
}
ret:
+ if (instance)
+ arr_remove_last(&err_ctx->instance_stack);
tr->fn = prev_fn;
return success;
}
@@ -1102,14 +1108,18 @@ static bool types_expr(Typer *tr, Expression *e) {
return false;
if (!eval_expr(tr->evalr, &copy, &default_val))
return false;
+
new_args[i].kind = EXPR_VAL;
new_args[i].flags = copy.flags;
new_args[i].type = copy.type.kind == TYPE_TUPLE
? copy.type.tuple[ident_idx]
: copy.type;
- new_args[i].val = copy.type.kind == TYPE_TUPLE
- ? default_val.tuple[ident_idx]
- : default_val;
+
+ copy_val(&cop, &new_args[i].val,
+ copy.type.kind == TYPE_TUPLE
+ ? &default_val.tuple[ident_idx]
+ : &default_val, &new_args[i].type);
+
} else {
/* it's already been evaluated */
assert(param->expr.kind == EXPR_VAL); /* evaluated in type_of_fn */
@@ -1149,7 +1159,6 @@ static bool types_expr(Typer *tr, Expression *e) {
int semi_const_index = 0;
for (size_t i = 0; i < arr_len(fn_type->types)-1; i++) {
bool should_be_evald = arg_is_const(&new_args[i], fn_type->constness[i]);
-
if (should_be_evald) {
Value *arg_val = typer_arr_add(tr, &table_index.tuple);
if (!eval_expr(tr->evalr, &new_args[i], arg_val)) {
@@ -1158,12 +1167,16 @@ static bool types_expr(Typer *tr, Expression *e) {
}
return false;
}
- new_args[i].kind = EXPR_VAL;
- new_args[i].flags = 0;
- new_args[i].val = *arg_val;
Type *type = arr_add(&table_index_type.tuple);
*type = fn_type->types[i+1];
+
+ new_args[i].kind = EXPR_VAL;
+ new_args[i].flags = EXPR_FOUND_TYPE;
+ Copier cop = {.allocr = tr->allocr, .block = tr->block};
+ copy_val(&cop, &new_args[i].val, arg_val, type);
+ new_args[i].val = *arg_val;
+ new_args[i].type = *type;
if (fn_type->constness[i] == CONSTNESS_SEMI) {
if (semi_const_index >= 64) {
@@ -1668,7 +1681,8 @@ static bool types_decl(Typer *tr, Declaration *d) {
success = false;
goto ret;
}
- copy_val(tr->allocr, &d->val, &val, &d->type);
+ Copier cop = {.block = tr->block, .allocr = tr->allocr};
+ copy_val(&cop, &d->val, &val, &d->type);
d->flags |= DECL_FOUND_VAL;
}
}
@@ -1779,6 +1793,7 @@ static void typer_create(Typer *tr, Evaluator *ev, Allocator *allocr) {
tr->in_decls = NULL;
tr->in_expr_decls = NULL;
tr->allocr = allocr;
+
}
static bool types_file(Typer *tr, ParsedFile *f) {
diff --git a/types.h b/types.h
index 91cda39..bd76826 100644
--- a/types.h
+++ b/types.h
@@ -49,16 +49,18 @@ typedef U32 IdentID; /* identifier ID for cgen (anonymous variables) */
typedef uint32_t LineNo;
-typedef struct {
+typedef struct Location {
+ LineNo line;
+ char *code;
+ struct ErrCtx *ctx;
+} Location;
+
+typedef struct ErrCtx {
const char *filename;
bool enabled;
+ Location *instance_stack; /* stack of locations which generate the instances we're dealing with */
} ErrCtx;
-typedef struct {
- LineNo line;
- char *code;
- ErrCtx *ctx;
-} Location;
typedef struct Page {
struct Page *next;