summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-12-12 18:55:32 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-12-12 18:55:32 -0500
commit7420a5126f78947e9c5a11e606d59f2ed6391079 (patch)
treee4f9915e3cee22915556689673d4b1327f0c1f4e
parent87c40c71774648edfd8234ec3d8f51411845dd7f (diff)
...
-rw-r--r--allocator.c29
-rw-r--r--err.c6
-rw-r--r--infer.c7
-rw-r--r--parse.c4
-rw-r--r--types.c35
5 files changed, 57 insertions, 24 deletions
diff --git a/allocator.c b/allocator.c
index 9f58ee4..4cde1a9 100644
--- a/allocator.c
+++ b/allocator.c
@@ -22,6 +22,8 @@ static void *allocr_malloc(Allocator *a, size_t bytes) {
(void)a;
return err_malloc(bytes);
#else
+ if (bytes == 0)
+ return NULL;
if (a == NULL)
return err_malloc(bytes);
/* position in this page to return */
@@ -52,6 +54,7 @@ static void *allocr_calloc(Allocator *a, size_t n, size_t sz) {
#if NO_ALLOCATOR
a = NULL;
#endif
+ if (n == 0 || sz == 0) return NULL;
if (a == NULL) return err_calloc(n, sz);
/* OPTIM: use calloc */
size_t bytes = n * sz;
@@ -60,27 +63,33 @@ static void *allocr_calloc(Allocator *a, size_t n, size_t sz) {
return data;
}
+static void allocr_free(Allocator *a, void *data, size_t size) {
+#if NO_ALLOCATOR
+ a = NULL;
+#endif
+ if (a == NULL) {
+ free(data);
+ }
+ /* OPTIM */
+ (void)size;
+}
+
/* OPTIM */
static void *allocr_realloc(Allocator *a, void *data, size_t old_size, size_t new_size) {
#if NO_ALLOCATOR
a = NULL;
#endif
+ if (new_size == 0) {
+ allocr_free(a, data, old_size);
+ return NULL;
+ }
if (a == NULL) return err_realloc(data, new_size);
void *ret = allocr_malloc(a, new_size);
memcpy(ret, data, old_size);
return ret;
}
-static void allocr_free(Allocator *a, void *data, size_t size) {
-#if NO_ALLOCATOR
- a = NULL;
-#endif
- if (a == NULL) {
- free(data);
- }
- /* OPTIM */
- (void)size;
-}
+
static void allocr_free_all(Allocator *a) {
for (Page *page = a->first; page;) {
diff --git a/err.c b/err.c
index fdebbfc..11a4863 100644
--- a/err.c
+++ b/err.c
@@ -158,6 +158,7 @@ static void warn_print(Location where, const char *fmt, ...) {
}
static void *err_malloc(size_t size) {
+ if (size == 0) return NULL;
void *ret = malloc(size);
if (!ret) {
fprintf(stderr, "Error: Out of memory.\n");
@@ -167,6 +168,7 @@ static void *err_malloc(size_t size) {
}
static void *err_calloc(size_t n, size_t size) {
+ if (n == 0 || size == 0) return NULL;
void *ret = calloc(n, size);
if (!ret) {
fprintf(stderr, "Error: Out of memory.\n");
@@ -176,6 +178,10 @@ static void *err_calloc(size_t n, size_t size) {
}
static void *err_realloc(void *data, size_t new_size) {
+ if (new_size == 0) {
+ free(data);
+ return NULL;
+ }
void *ret = realloc(data, new_size);
if (!ret) {
fprintf(stderr, "Error: Out of memory.\n");
diff --git a/infer.c b/infer.c
index 08eb5ab..6c2164a 100644
--- a/infer.c
+++ b/infer.c
@@ -1,9 +1,12 @@
/*
match and to are dynamic arrays of equal size
-find the value (and put it into val) of ident by matching match[i] to to[i], i = 0..arr_len(match)-1
+idents is a dyn array
+find the value of each ident by matching match[i] to to[i], i = 0..arr_len(match)-1
all the types in match must be resolved, and all the types in to must be unresolved
*/
-static bool infer(Type **match, Type **to, Identifier ident, Value *val, Type *type) {
+static bool infer(Type **match, Type **to, Identifier *idents, Value *vals, Type *types) {
+ Value *val = vals;
+ Type *type = types;
val->type = calloc(1,sizeof(Type));
val->type->flags = TYPE_IS_RESOLVED;
val->type->kind = TYPE_BUILTIN;
diff --git a/parse.c b/parse.c
index 1aa8c1a..78a5b1c 100644
--- a/parse.c
+++ b/parse.c
@@ -1798,6 +1798,10 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 fla
if ((flags & PARSE_DECL_ALLOW_INFER) && ends_decl(t->token, ends_with)) {
/* inferred expression */
d->flags |= DECL_INFER;
+ if (arr_len(d->idents) > 1) {
+ err_print(d->where, "Inferred declarations can only have one identifier. Please separate this declaration.");
+ goto ret_false;
+ }
if (!(d->flags & DECL_IS_CONST)) {
tokr_err(t, "Inferred parameters must be constant.");
goto ret_false;
diff --git a/types.c b/types.c
index 224c957..a9d5104 100644
--- a/types.c
+++ b/types.c
@@ -1257,20 +1257,12 @@ static bool types_expr(Typer *tr, Expression *e) {
i = 0;
Type **arg_types = NULL;
Type **decl_types = NULL;
+ Identifier *infer_idents = NULL;
+
arr_foreach(fn->params, Declaration, param) {
arr_foreach(param->idents, Identifier, ident) {
if (param->flags & DECL_INFER) {
- Value val;
- Type type;
- if (!infer(arg_types, decl_types, *ident, &val, &type))
- return false;
- param->expr.kind = EXPR_VAL;
- param->expr.flags = 0;
- param->expr.val = val;
- param->expr.type = type;
- param->expr.flags |= EXPR_FOUND_TYPE;
- param->type = param->expr.type;
- param->flags |= DECL_HAS_EXPR|DECL_FOUND_TYPE;
+ *(Identifier *)arr_add(&infer_idents) = *ident;
} else if ((param->flags & DECL_ANNOTATES_TYPE)
&& !(param->flags & DECL_HAS_EXPR)) {
@@ -1285,8 +1277,27 @@ static bool types_expr(Typer *tr, Expression *e) {
++i;
}
}
-
+ Value *inferred_vals = typer_malloc(tr, arr_len(infer_idents) * sizeof *inferred_vals);
+ Type *inferred_types = typer_malloc(tr, arr_len(infer_idents) * sizeof *inferred_types);
+ if (!infer(arg_types, decl_types, infer_idents, inferred_vals, inferred_types))
+ return false;
+
+ i = 0;
+ arr_foreach(fn->params, Declaration, param) {
+ arr_foreach(param->idents, Identifier, ident) {
+ if (param->flags & DECL_INFER) {
+ param->expr.kind = EXPR_VAL;
+ param->expr.flags = 0;
+ param->expr.val = inferred_vals[i];
+ param->expr.type = inferred_types[i];
+ param->expr.flags |= EXPR_FOUND_TYPE;
+ param->type = param->expr.type;
+ param->flags |= DECL_HAS_EXPR|DECL_FOUND_TYPE;
+ ++i;
+ }
+ }
+ }
/* type return declarations, etc */
if (!type_of_fn(tr, &fn_copy, e->where, &f->type, TYPE_OF_FN_IS_INSTANCE))
return false;