summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-09-27 23:34:29 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2019-09-27 23:34:29 -0400
commit991d739bb02b3506da5a0af0edd9a4fd505373a3 (patch)
tree75b32cd37e9a99f5609171f2a9156d2f2dc3f13f
parent685460f382e2e7039bd6ddf5c336abdb803a0372 (diff)
added converter from named arguments to non-named
-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.c8
-rw-r--r--parse.c41
-rw-r--r--str.c (renamed from util/str.c)0
-rw-r--r--test.toc4
-rw-r--r--toc.c11
-rw-r--r--types.c76
10 files changed, 126 insertions, 19 deletions
diff --git a/util/arr.c b/arr.c
index e3f5b8c..2555d72 100644
--- a/util/arr.c
+++ b/arr.c
@@ -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/err.c b/err.c
index ac620ec..ac620ec 100644
--- a/util/err.c
+++ b/err.c
diff --git a/util/location.c b/location.c
index 4b450ce..4b450ce 100644
--- a/util/location.c
+++ b/location.c
diff --git a/main.c b/main.c
index 7375c89..6dc7f4d 100644
--- a/main.c
+++ b/main.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);
diff --git a/parse.c b/parse.c
index f7407fd..872c0ae 100644
--- a/parse.c
+++ b/parse.c
@@ -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);
}
diff --git a/util/str.c b/str.c
index ac4fb26..ac4fb26 100644
--- a/util/str.c
+++ b/str.c
diff --git a/test.toc b/test.toc
index 4646541..a925583 100644
--- a/test.toc
+++ b/test.toc
@@ -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);
};
diff --git a/toc.c b/toc.c
index d20868d..2fd7e86 100644
--- a/toc.c
+++ b/toc.c
@@ -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"
diff --git a/types.c b/types.c
index 896a480..7cb48e7 100644
--- a/types.c
+++ b/types.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(&param->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 = &param_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(&param->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;
}