diff options
-rw-r--r-- | arr.c (renamed from util/arr.c) | 5 | ||||
-rw-r--r-- | blockarr.c (renamed from util/blockarr.c) | 0 | ||||
-rw-r--r-- | err.c (renamed from util/err.c) | 0 | ||||
-rw-r--r-- | location.c (renamed from util/location.c) | 0 | ||||
-rw-r--r-- | main.c | 8 | ||||
-rw-r--r-- | parse.c | 41 | ||||
-rw-r--r-- | str.c (renamed from util/str.c) | 0 | ||||
-rw-r--r-- | test.toc | 4 | ||||
-rw-r--r-- | toc.c | 11 | ||||
-rw-r--r-- | types.c | 76 |
10 files changed, 126 insertions, 19 deletions
@@ -14,7 +14,12 @@ static void arr_create(Array *arr, size_t item_sz) { static inline void arr_reserve(Array *arr, size_t n) { arr->cap = n; arr->data = err_realloc(arr->data, arr->item_sz * arr->cap); +} +/* like arr_reserve, but sets the length of the array too */ +static inline void arr_set_len(Array *arr, size_t n) { + arr->len = arr->cap = n; + arr->data = err_realloc(arr->data, arr->item_sz * arr->cap); } static inline void *arr_last(Array *arr) { diff --git a/util/blockarr.c b/blockarr.c index 38bbf1b..38bbf1b 100644 --- a/util/blockarr.c +++ b/blockarr.c diff --git a/util/location.c b/location.c index 4b450ce..4b450ce 100644 --- a/util/location.c +++ b/location.c @@ -2,8 +2,11 @@ TODO: named args optional params +char type +string constants are []char evaluator (simplify compile time constant expressions) re-do cgen +any odd number of "s for a string */ #include "toc.c" @@ -61,13 +64,16 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } + fprint_parsed_file(stdout, &f); + + printf("\n\n-----\n\n"); block_enter(NULL, &f.stmts); /* enter global scope */ if (!types_file(&f)) { err_fprint(TEXT_IMPORTANT("Errors occured while determining types.\n")); return EXIT_FAILURE; } - + parse_printing_after_types = true; fprint_parsed_file(stdout, &f); tokr_free(&t); @@ -109,7 +109,7 @@ typedef struct { typedef struct { struct Expression *fn; - Array args; /* of Argument */ + Array args; /* of Argument; after typing, becomes of Expression */ } CallExpr; typedef struct { @@ -168,6 +168,7 @@ typedef struct Expression { } Expression; typedef struct { + Location where; Identifier name; /* NULL = no name */ Expression val; } Argument; @@ -762,6 +763,7 @@ static bool parse_args(Parser *p, Array *args) { return false; } Argument *arg = arr_add(args); + arg->where = t->token->where; /* named arguments */ if (t->token->kind == TOKEN_IDENT && token_is_kw(t->token + 1, KW_EQ)) { arg->name = t->token->ident; @@ -1511,6 +1513,9 @@ static bool parse_file(Parser *p, ParsedFile *f) { #define PARSE_PRINT_LOCATION(l) //fprintf(out, "[l%lu]", (unsigned long)(l).line); +/* in theory, this shouldn't be global, but these functions are mostly for debugging anyways */ +static bool parse_printing_after_types; + static void fprint_expr(FILE *out, Expression *e); static void fprint_stmt(FILE *out, Statement *s); static void fprint_decl(FILE *out, Declaration *d); @@ -1537,6 +1542,8 @@ static void fprint_block(FILE *out, Block *b) { static void fprint_fn_expr(FILE *out, FnExpr *f) { fprintf(out, "fn ("); arr_foreach(&f->params, Declaration, decl) { + if (decl != f->params.data) + fprintf(out, ", "); fprint_decl(out, decl); } fprintf(out, ") "); @@ -1547,13 +1554,22 @@ static void fprint_fn_expr(FILE *out, FnExpr *f) { static void fprint_args(FILE *out, Array *args) { fprintf(out, "("); - arr_foreach(args, Argument, arg) { - if (arg != args->data) fprintf(out, ", "); - if (arg->name) { - fprint_ident(out, arg->name); - fprintf(out, " = "); + if (parse_printing_after_types) { + assert(args->item_sz == sizeof(Expression)); + arr_foreach(args, Expression, arg) { + if (arg != args->data) fprintf(out, ", "); + fprint_expr(out, arg); + } + } else { + assert(args->item_sz == sizeof(Argument)); + arr_foreach(args, Argument, arg) { + if (arg != args->data) fprintf(out, ", "); + if (arg->name) { + fprint_ident(out, arg->name); + fprintf(out, " = "); + } + fprint_expr(out, &arg->val); } - fprint_expr(out, &arg->val); } fprintf(out, ")"); } @@ -1629,8 +1645,10 @@ static void fprint_expr(FILE *out, Expression *e) { fprint_args(out, &e->direct.args); break; } - fprintf(out, ":"); - fprint_type(out, &e->type); + if (parse_printing_after_types) { + fprintf(out, ":"); + fprint_type(out, &e->type); + } } @@ -1641,9 +1659,10 @@ static void fprint_decl(FILE *out, Declaration *d) { fprint_ident(out, *ident); } if (d->flags & DECL_FLAG_CONST) { - fprintf(out, "[const]"); + fprintf(out, "@"); + } else { + fprintf(out, ":"); } - fprintf(out, ":"); if ((d->flags & DECL_FLAG_FOUND_TYPE) || (d->flags & DECL_FLAG_ANNOTATES_TYPE)) { fprint_type(out, &d->type); } @@ -4,7 +4,7 @@ main @= fn() { ret1 = x; }; a,b : i64; - // a, b = test(3,7,2,3); - a, b = test(x = 3, y = 7, z = 30, w = 20); + a, b = test(3,7,2,3); + a, b = test(x = 3, z = 7, w = 30, y = 20); }; @@ -2,6 +2,7 @@ #include <assert.h> #include <stdio.h> #include <stdlib.h> +#include <stddef.h> #include <stdarg.h> #include <string.h> #include <ctype.h> @@ -16,11 +17,11 @@ typedef long double Floating; /* OPTIM: Switch to double */ #define UINTEGER_FMT "%llu" #define INTEGER_FMT "%lld" -#include "util/location.c" -#include "util/err.c" -#include "util/arr.c" -#include "util/blockarr.c" -#include "util/str.c" +#include "location.c" +#include "err.c" +#include "arr.c" +#include "blockarr.c" +#include "str.c" #include "identifiers.c" #include "tokenizer.c" #include "parse.c" @@ -500,7 +500,56 @@ static bool types_expr(Typer *tr, Expression *e) { return false; } bool ret = true; + FnExpr *fn_decl = NULL; + Array new_args_arr; + size_t nargs = c->args.len; + arr_create(&new_args_arr, sizeof(Expression)); + arr_set_len(&new_args_arr, nargs); + Expression *new_args = new_args_arr.data; + bool *params_set = calloc(nargs, sizeof *params_set); + if (f->kind == EXPR_IDENT) { + IdentDecl *decl = ident_decl(f->ident); + assert(decl); + if (decl->decl->flags & DECL_FLAG_HAS_EXPR) { + Expression *expr = &decl->decl->expr; + if (expr->kind == EXPR_FN) + fn_decl = &decl->decl->expr.fn; + } + } + bool had_named_arg = false; for (size_t p = 0; p < nparams; 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; + } + long index = 0; + long arg_index = -1; + arr_foreach(&fn_decl->params, Declaration, param) { + arr_foreach(¶m->idents, Identifier, ident) { + if (*ident == args[p].name) { + arg_index = index; + break; + } + index++; + } + 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(ident_decl(f->ident)->decl->where, "Declaration is here."); + return false; + } + new_args[arg_index] = args[p].val; + params_set[arg_index] = true; + continue; + } + if (had_named_arg) { + err_print(args[p].where, "Unnamed argument after named argument."); + return false; + } Expression *val = &args[p].val; Type *expected = ¶m_types[p]; Type *got = &val->type; @@ -510,8 +559,31 @@ static bool types_expr(Typer *tr, Expression *e) { char *gstr = type_to_str(got); err_print(val->where, "Expected type %s as %lu%s argument to function, but got %s.", estr, 1+(unsigned long)p, ordinals(1+p), gstr); } + new_args[p] = args[p].val; + params_set[p] = true; } if (!ret) return false; + for (size_t i = 0; i < nargs; i++) { + if (!params_set[i]) { + size_t index = 0; + assert(fn_decl); /* we can only miss an arg if we're using named args */ + + arr_foreach(&fn_decl->params, Declaration, param) { + arr_foreach(¶m->idents, Identifier, ident) { + if (index == i) { + char *s = ident_to_str(*ident); + err_print(e->where, "Argument %lu (%s) not set in function call.", 1+(unsigned long)i, s); + free(s); + return false; + } + index++; + } + } + } + } + free(params_set); + arr_free(&c->args); + c->args = new_args_arr; *t = *ret_type; break; } @@ -528,6 +600,10 @@ static bool types_expr(Typer *tr, Expression *e) { case EXPR_DIRECT: t->kind = TYPE_UNKNOWN; arr_foreach(&e->direct.args, Argument, arg) { + if (arg->name) { + err_print(arg->where, "Directives should not have named arguments."); + return false; + } if (!types_expr(tr, &arg->val)) return false; } |