summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c5
-rw-r--r--parse.c1
-rw-r--r--test.toc54
-rwxr-xr-xtests/test.sh2
-rw-r--r--types.c104
5 files changed, 75 insertions, 91 deletions
diff --git a/main.c b/main.c
index 33562d0..24cdc47 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,8 @@
/*
TODO:
-check fn(x :: int, y := x)
-check fn(x :: int) y := x
+check fn(x :: int, y := x) (run + compile)
+check fn(x :: int) y := x (run + compile)
+check arr @ compile
new version of copy_val for copying types??
there are probably places where we enter a function and never exit (in typing?) if there's an error
diff --git a/parse.c b/parse.c
index d066959..5b6beff 100644
--- a/parse.c
+++ b/parse.c
@@ -199,6 +199,7 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) {
break;
}
}
+
written += type_to_str_(&param_types[i], buffer + written, bufsize - written);
}
written += str_copy(buffer + written, bufsize - written, ")");
diff --git a/test.toc b/test.toc
index a999512..143dc0b 100644
--- a/test.toc
+++ b/test.toc
@@ -7,45 +7,19 @@ putf ::= fn(x: float) {
");
};
-// it would be nice if Arr.data.len == Arr.len (: but this will require some C code...
-Arr ::= fn (t :: Type) Type {
- struct {
- data : []t;
- len, cap : int;
- }
-};
-
-arr_add ::= fn(t :: Type, a : &Arr(t), x : t) {
- if a.len >= a.cap {
- a.cap = a.cap * 2 + 2;
- new_data := new(t, a.cap);
- each i := 0..a.len-1 {
- new_data[i] = a.data[i];
- }
- a.data = new_data;
- }
- a.data[a.len] = x;
- a.len += 1;
-};
-
-
-ArrInt ::= Arr(int);
+main ::= fn() {
+ puti(f(3));
+ puti(f(7));
+ puti(f(3,4));
-inc ::= fn(t :: Type, x : t) t {
- x + 1
-};
+// TODO: semiconst breaks this for some reason
+ f ::= fn(x :: int, y := x) int { y };
-main ::= fn() {
- arr : ArrInt;
- farr : Arr(float);
- each i := 1..100 {
- arr_add(int, &arr, inc(int, i*i));
- arr_add(float, &farr, inc(float, (i*i) as float));
- }
- each i := 0..arr.len - 1 {
- puti(arr.data[i]);
- }
- each i := 0..farr.len - 1 {
- putf(farr.data[i]);
- }
-};
+ r ::= f(3);
+ puti(r);
+ s ::= f(7);
+ puti(s);
+ t ::= f(3,4);
+ puti(t);
+
+}; \ No newline at end of file
diff --git a/tests/test.sh b/tests/test.sh
index 0b10981..4fe800e 100755
--- a/tests/test.sh
+++ b/tests/test.sh
@@ -17,7 +17,7 @@ do_tests() {
for CC in $COMPILERS; do
for EXTRA_CFLAGS in "-O0 -g" "-O3 -s"; do
- printf "Running test $1 C compiler $CC and flags $EXTRA_CFLAGS... "
+ printf "Running test $1 with C compiler $CC and flags $EXTRA_CFLAGS... "
compile "$1"
cd "$DIR/$1"
./test.sh || { printf "\x1b[91mfailed!\x1b[0m\n"; exit 1; }
diff --git a/types.c b/types.c
index 0797679..9a17ed5 100644
--- a/types.c
+++ b/types.c
@@ -216,20 +216,31 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags)
entered_fn = true;
for (param_idx = 0; param_idx < nparams; param_idx++) {
Declaration *param = &f->params[param_idx];
- U16 types_decl_flags = 0;
- if (generic) {
- types_decl_flags |= TYPES_DECL_DONT_RESOLVE;
- }
- if (!types_decl(tr, param, types_decl_flags)) {
- success = false;
- goto ret;
- }
- if (param->type.kind == TYPE_TUPLE) {
- err_print(param->where, "Functions can't have tuple parameters.");
- success = false;
- goto ret;
- }
+ if (!generic) {
+ U16 types_decl_flags = 0;
+ if (!types_decl(tr, param, types_decl_flags)) {
+ success = false;
+ goto ret;
+ }
+ if (param->type.kind == TYPE_TUPLE) {
+ err_print(param->where, "Functions can't have tuple parameters.");
+ success = false;
+ goto ret;
+ }
+ if (param->flags & DECL_HAS_EXPR) {
+ if (param->expr.kind != EXPR_VAL) {
+ Value val;
+ if (!eval_expr(tr->evalr, &param->expr, &val)) {
+ info_print(param->where, "Was trying to evaluate default arguments (which must be constants!)");
+ success = false;
+ goto ret;
+ }
+ param->expr.kind = EXPR_VAL;
+ param->expr.val = val;
+ }
+ }
+ }
U32 is_at_all_const = param->flags & (DECL_IS_CONST | DECL_SEMI_CONST);
if (is_at_all_const) {
if (!t->fn.constness) {
@@ -239,21 +250,14 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags)
}
}
}
- if (param->flags & DECL_HAS_EXPR) {
- if (param->expr.kind != EXPR_VAL) {
- Value val;
- if (!eval_expr(tr->evalr, &param->expr, &val)) {
- info_print(param->where, "Was trying to evaluate default arguments (which must be constants!)");
- success = false;
- goto ret;
- }
- param->expr.kind = EXPR_VAL;
- param->expr.val = val;
- }
- }
for (size_t i = 0; i < arr_len(param->idents); i++) {
Type *param_type = typer_arr_add(tr, &t->fn.types);
- *param_type = param->type;
+ if (!generic) {
+ *param_type = param->type;
+ } else {
+ param_type->flags = 0;
+ param_type->kind = TYPE_UNKNOWN;
+ }
if (has_constant_params) {
Constness constn;
if (param->flags & DECL_IS_CONST) {
@@ -1101,7 +1105,6 @@ static bool types_expr(Typer *tr, Expression *e) {
arr_foreach(fn_decl->params, Declaration, param) {
bool is_required = !(param->flags & DECL_HAS_EXPR);
int ident_idx = 0;
- assert(param->type.kind != TYPE_TUPLE);
arr_foreach(param->idents, Identifier, ident) {
if (index == i) {
@@ -1111,26 +1114,8 @@ static bool types_expr(Typer *tr, Expression *e) {
free(s);
return false;
} else {
- Value default_val;
- if (fn_type->constness) {
- /* TODO: evaluate once per decl, not once per ident */
- Expression copy;
- /* make a copy of the default argument, and type and evaluate it. */
- Copier cop = copier_create(tr->allocr, tr->block);
- copy_expr(&cop, &copy, &param->expr);
- if (!types_expr(tr, &copy))
- return false;
- if (!eval_expr(tr->evalr, &copy, &default_val))
- return false;
- assert(copy.type.kind != TYPE_TUPLE);
- new_args[i].kind = EXPR_VAL;
- new_args[i].flags = copy.flags;
- new_args[i].type = copy.type;
-
- copy_val(tr->allocr, &new_args[i].val,
- &default_val, &new_args[i].type);
- } else {
- /* it's already been evaluated */
+ if (!fn_type->constness) {
+ /* default arg */
assert(param->expr.kind == EXPR_VAL); /* evaluated in type_of_fn */
new_args[i].kind = EXPR_VAL;
new_args[i].flags = param->expr.flags;
@@ -1185,6 +1170,23 @@ static bool types_expr(Typer *tr, Expression *e) {
size_t ident_idx = 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 (!params_set[i] && (param_decl->flags & DECL_HAS_EXPR)) {
+ /* create copy of default arg */
+ Value default_arg;
+ if (!types_expr(tr, &param_decl->expr))
+ return false;
+ if (!eval_expr(tr->evalr, &param_decl->expr, &default_arg)) {
+ return false;
+ }
+
+
+ new_args[i].kind = EXPR_VAL;
+ new_args[i].flags = param_decl->expr.flags;
+ new_args[i].type = param_decl->expr.type;
+ copy_val(tr->allocr, &new_args[i].val, &default_arg, &param_decl->expr.type);
+ } else assert(params_set[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)) {
@@ -1219,14 +1221,20 @@ static bool types_expr(Typer *tr, Expression *e) {
ident_idx++;
if (ident_idx >= arr_len(param_decl->idents)) {
ident_idx = 0;
+ /* TODO: remove decls on failure */
+ /* these are added for default arguments */
+ add_ident_decls(&fn->body, param_decl, SCOPE_CHECK_REDECL);
param_decl++;
}
}
-
+ arr_foreach(fn->params, Declaration, param) {
+ remove_ident_decls(&fn->body, param);
+ }
/* type param declarations, etc */
if (!type_of_fn(tr, &fn_copy, e->where, &f->type, TYPE_OF_FN_IS_INSTANCE))
return false;
+
ret_type = f->type.fn.types;
param_types = ret_type + 1;
}