diff options
-rw-r--r-- | main.c | 5 | ||||
-rw-r--r-- | parse.c | 1 | ||||
-rw-r--r-- | test.toc | 54 | ||||
-rwxr-xr-x | tests/test.sh | 2 | ||||
-rw-r--r-- | types.c | 104 |
5 files changed, 75 insertions, 91 deletions
@@ -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 @@ -199,6 +199,7 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) { break; } } + written += type_to_str_(¶m_types[i], buffer + written, bufsize - written); } written += str_copy(buffer + written, bufsize - written, ")"); @@ -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; } @@ -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, ¶m->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, ¶m->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, ©, ¶m->expr); - if (!types_expr(tr, ©)) - return false; - if (!eval_expr(tr->evalr, ©, &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, ¶m_decl->expr)) + return false; + if (!eval_expr(tr->evalr, ¶m_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, ¶m_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; } |