diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-12-08 14:17:20 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-12-08 14:17:20 -0500 |
commit | 3db3e1a84fcded750ccf45732c6527e1581bc36e (patch) | |
tree | de1a4fb46c4272a7c6bb4678e2837df7999f9dbb | |
parent | 5fd1048555c003c98633482ee4fb4b9df80fb455 (diff) |
discovered a bug with flexible types while cleaning up args
-rw-r--r-- | README.md | 3 | ||||
-rwxr-xr-x | runv | 2 | ||||
-rw-r--r-- | test.toc | 4 | ||||
-rw-r--r-- | test2.toc | 22 | ||||
-rw-r--r-- | types.c | 123 |
5 files changed, 69 insertions, 85 deletions
@@ -46,9 +46,8 @@ On other systems, you can just compile main.c with a C compiler. toc uses severa Here are all the C99 features which `toc` depends on (I might have forgotten some...): - Declare anywhere -- `stdint.h` +- `inttypes.h` - Non-constant struct literal initializers (e.g. `int x[2] = {y, z};`) -- Variadic macros and `__VA_ARGS__` - Flexible array members The last three of those could all be removed fairly easily. @@ -10,7 +10,7 @@ else FLAGS="-q" fi -valgrind $FLAGS --track-origins=yes --error-exitcode=1 --malloc-fill=0xcd --free-fill=0xef --num-callers=100 ./toc $tocf || exit 1 +valgrind $FLAGS --track-origins=yes --exit-on-first-error=yes --error-exitcode=1 --malloc-fill=0xcd --free-fill=0xef --num-callers=100 ./toc $tocf || exit 1 if [ "$1" = "c" ]; then gcc out.c -g && ./a.out elif [ "$1" = "pc" ]; then @@ -1,7 +1,7 @@ -f ::= fn(x := 3, y:int) { +f ::= fn(y:f64=19.2) { }; main ::= fn() { - f(5); + f(); }; diff --git a/test2.toc b/test2.toc deleted file mode 100644 index b32d203..0000000 --- a/test2.toc +++ /dev/null @@ -1,22 +0,0 @@ -puti ::= fn(x: int) { - #C("printf(\"%ld\\n\", (long)x); -"); -}; -putf ::= fn(x: float) { - #C("printf(\"%f\\n\", (double)x); -"); -}; - -// f ::= fn(t ::= int, x : t) t { -// x + 1 -// }; - -f ::= fn(x : t, t ::= float) t { - x+1 -}; - -main ::= fn() { - putf(f(3.321)); - puti(f(3, int)); - putf(f(3.3421, float)); -};
\ No newline at end of file @@ -1039,9 +1039,8 @@ static bool types_expr(Typer *tr, Expression *e) { Argument *args = c->args; size_t nparams = arr_len(f->type.fn.types) - 1; size_t nargs = arr_len(c->args); - bool ret = true; - Expression *new_args = NULL; - arr_set_lena(&new_args, nparams, tr->allocr); + Expression *arg_exprs = NULL; + arr_set_lena(&arg_exprs, nparams, tr->allocr); bool *params_set = nparams ? typer_calloc(tr, nparams, sizeof *params_set) : NULL; if (f->kind == EXPR_IDENT) { IdentDecl *decl = ident_decl(f->ident); @@ -1054,50 +1053,60 @@ static bool types_expr(Typer *tr, Expression *e) { } } } - if (!fn_decl && nargs != nparams) { - err_print(e->where, "Expected %lu arguments to function call, but got %lu.", (unsigned long)nparams, (unsigned long)nargs); - return false; - } - bool had_named_arg = false; - for (size_t p = 0; p < nargs; p++) { - if (args[p].name) { - if (!fn_decl) { - err_print(args[p].where, "You must call a function directly by its name to use named arguments."); - return false; - } - had_named_arg = true; - long index = 0; - long arg_index = -1; - arr_foreach(fn_decl->params, Declaration, param) { - arr_foreach(param->idents, Identifier, ident) { - if (*ident == args[p].name) { - arg_index = index; - break; + + if (fn_decl) { + Argument *arg = args; + Argument *arg_end = args + nargs; + size_t p = 0; + if (args) arr_foreach(fn_decl->params, Declaration, param) { + arr_foreach(param->idents, Identifier, ident) { + if (arg->name) { + /* named argument */ + long index = 0; + bool found = false; + arr_foreach(fn_decl->params, Declaration, pa) { + arr_foreach(pa->idents, Identifier, id) { + if (*id == args[index].name) { + found = true; + break; + } + index++; + } + if (found) break; + index++; } - index++; + if (!found) { + char *s = ident_to_str(arg->name); + err_print(arg->where, "Argument '%s' does not appear in declaration of function.", s); + free(s); + info_print(idecl_where(ident_decl(f->ident)), "Declaration is here."); + return false; + } + params_set[index] = true; + arg_exprs[index] = arg->val; + } else { + params_set[p] = true; + arg_exprs[p] = arg->val; + p++; } - if (arg_index != -1) break; - } - if (arg_index == -1) { - char *s = ident_to_str(args[p].name); - err_print(args[p].where, "Argument '%s' does not appear in declaration of function.", s); - free(s); - info_print(idecl_where(ident_decl(f->ident)), "Declaration is here."); - return false; + arg++; + if (arg == arg_end) break; } - new_args[arg_index] = args[p].val; - params_set[arg_index] = true; - continue; + if (arg == arg_end) break; } - if (had_named_arg) { - err_print(args[p].where, "Unnamed argument after named argument."); + } else { + if (nargs != nparams) { + err_print(e->where, "Expected %lu arguments to function call, but got %lu.", (unsigned long)nparams, (unsigned long)nargs); return false; } - new_args[p] = args[p].val; - /* we will check the type of the argument later */ - params_set[p] = true; + for (size_t p = 0; p < nargs; p++) { + if (args[p].name) { + err_print(args[p].where, "You can only use named arguments if you directly call a function."); + } + arg_exprs[p] = args[p].val; + params_set[p] = true; + } } - if (!ret) return false; FnType *fn_type = &f->type.fn; for (size_t i = 0; i < nparams; i++) { @@ -1120,10 +1129,10 @@ static bool types_expr(Typer *tr, Expression *e) { 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; - new_args[i].type = param->type; - new_args[i].val = param->expr.val; + arg_exprs[i].kind = EXPR_VAL; + arg_exprs[i].flags = param->expr.flags; + arg_exprs[i].type = param->type; + arg_exprs[i].val = param->expr.val; } } } @@ -1176,15 +1185,15 @@ static bool types_expr(Typer *tr, Expression *e) { /* eval compile time arguments */ for (i = 0; i < nparams; i++) { - bool should_be_evald = arg_is_const(&new_args[i], fn_type->constness[i]); + bool should_be_evald = arg_is_const(&arg_exprs[i], fn_type->constness[i]); if (should_be_evald && params_set[i]) { - Expression *expr = &new_args[i]; + Expression *expr = &arg_exprs[i]; Value *arg_val = typer_arr_add(tr, &table_index.tuple); if (!eval_expr(tr->evalr, expr, arg_val)) { if (tr->evalr->enabled) { - info_print(new_args[i].where, "(error occured while trying to evaluate compile-time argument, argument #%lu)", 1+(unsigned long)i); + info_print(arg_exprs[i].where, "(error occured while trying to evaluate compile-time argument, argument #%lu)", 1+(unsigned long)i); } return false; } @@ -1192,11 +1201,11 @@ static bool types_expr(Typer *tr, Expression *e) { Type *type = &expr->type; *(Type *)typer_arr_add(tr, &table_index_type.tuple) = *type; - new_args[i].kind = EXPR_VAL; - new_args[i].flags = EXPR_FOUND_TYPE; - copy_val(tr->allocr, &new_args[i].val, arg_val, type); - new_args[i].val = *arg_val; - new_args[i].type = *type; + arg_exprs[i].kind = EXPR_VAL; + arg_exprs[i].flags = EXPR_FOUND_TYPE; + copy_val(tr->allocr, &arg_exprs[i].val, arg_val, type); + arg_exprs[i].val = *arg_val; + arg_exprs[i].type = *type; copy_val(tr->allocr, ¶m_decl->val, arg_val, type); param_decl->flags |= DECL_FOUND_VAL; @@ -1234,9 +1243,9 @@ static bool types_expr(Typer *tr, Expression *e) { if (!params_set[i]) { assert(param->flags & DECL_HAS_EXPR); assert(param->expr.kind == EXPR_VAL); /* this was done by type_of_fn */ - new_args[i] = param->expr; + arg_exprs[i] = param->expr; /* make sure value is copied */ - copy_val(tr->allocr, &new_args[i].val, ¶m->expr.val, ¶m->expr.type); + copy_val(tr->allocr, &arg_exprs[i].val, ¶m->expr.val, ¶m->expr.type); Value *arg_val = &table_index.tuple[i+1]; copy_val(tr->allocr, arg_val, ¶m->expr.val, ¶m->expr.type); table_index_type.tuple[i+1] = param->expr.type; @@ -1251,11 +1260,10 @@ static bool types_expr(Typer *tr, Expression *e) { /* check types of arguments */ for (size_t p = 0; p < nparams; p++) { - Expression *arg = &new_args[p]; + Expression *arg = &arg_exprs[p]; Type *expected = ¶m_types[p]; Type *got = &arg->type; if (!type_eq(expected, got)) { - ret = false; char *estr = type_to_str(expected); char *gstr = type_to_str(got); err_print(arg->where, "Expected type %s as %lu%s argument to function, but got %s.", estr, 1+(unsigned long)p, ordinals(1+p), gstr); @@ -1286,9 +1294,8 @@ static bool types_expr(Typer *tr, Expression *e) { } } - if (!ret) return false; *t = *ret_type; - c->arg_exprs = new_args; + c->arg_exprs = arg_exprs; break; } case EXPR_BLOCK: { |