summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-04-23 15:00:37 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-04-23 15:00:37 -0400
commit44f477931801e5d30db344d740ad2bededadc01c (patch)
treedde3a438801309dac177343778fe1d73767c3ebe
parentf7bfb9492ab546e886fd40bda1a0ab25fcb05247 (diff)
got rid of call inference; now inference is much simpler
-rw-r--r--cgen.c1
-rw-r--r--eval.c2
-rw-r--r--infer.c136
-rw-r--r--main.c1
-rw-r--r--parse.c15
-rw-r--r--test.toc11
-rw-r--r--types.c26
-rw-r--r--types.h2
8 files changed, 47 insertions, 147 deletions
diff --git a/cgen.c b/cgen.c
index 08631f5..b2d64f2 100644
--- a/cgen.c
+++ b/cgen.c
@@ -263,6 +263,7 @@ static bool cgen_fn_is_direct(CGenerator *g, Declaration *d) {
}
static bool fn_has_instances(FnExpr *f) {
+ if (f->flags & FN_EXPR_FOREIGN) return false;
if (fn_has_any_const_params(f)) return true;
if (!arr_len(f->params)) return false;
return type_is_builtin(&arr_last(f->params).type, BUILTIN_VARARGS);
diff --git a/eval.c b/eval.c
index cb74e0f..8b0c552 100644
--- a/eval.c
+++ b/eval.c
@@ -1065,7 +1065,7 @@ static void decl_remove_val(Declaration *d) {
}
static Status eval_expr(Evaluator *ev, Expression *e, Value *v) {
-
+ assert(e->flags & EXPR_FOUND_TYPE);
#define eval_unary_op_one(low, up, op) \
case BUILTIN_##up: \
v->low = (up)(op of.low); break
diff --git a/infer.c b/infer.c
index fceeaa4..e131583 100644
--- a/infer.c
+++ b/infer.c
@@ -2,7 +2,7 @@ static bool call_arg_param_order(FnExpr *fn, Type *fn_type, Argument *args, Loca
static bool parameterized_struct_arg_order(StructDef *struc, Argument *args, I16 **order, Location where);
static bool types_expr(Typer *tr, Expression *e);
-static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identifier *idents, Value *vals, Type *types) {
+static bool infer_from_expr(Typer *tr, Expression *match, Value to, Type *to_type, Location to_where, Identifier *idents, Value *vals, Type *types) {
#if 0
printf("Matching ");
fprint_expr(stdout, match);
@@ -12,20 +12,15 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi
#endif
assert(!(match->flags & EXPR_FOUND_TYPE));
- assert(to->flags & EXPR_FOUND_TYPE);
+ assert(to_type->flags & TYPE_IS_RESOLVED);
switch (match->kind) {
case EXPR_IDENT:
/* an identifier! maybe it's one of idents... */
arr_foreach(idents, Identifier, ident) {
if (*ident == match->ident) {
long idx = ident - idents;
- types[idx] = to->type;
- if (!eval_expr(tr->evalr, to, &vals[idx]))
- return false;
- Copier c = copier_create(tr->allocr, tr->block);
- Value new_val;
- copy_val_full(&c, &new_val, vals[idx], &to->type);
- vals[idx] = new_val;
+ types[idx] = *to_type;
+ vals[idx] = to;
break;
}
}
@@ -35,20 +30,18 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi
return false;
if (type_is_builtin(&match->call.fn->type, BUILTIN_TYPE)) {
/* it's a parameterized struct */
- Value fn_val;
- if (!eval_expr(tr->evalr, to, &fn_val))
- return false;
- if (!type_is_builtin(&to->type, BUILTIN_TYPE) || fn_val.type->kind != TYPE_STRUCT) {
- err_print(to->where, "Wrong argument type. Expected this to be a struct, but it's not.");
+ if (!type_is_builtin(to_type, BUILTIN_TYPE) || to.type->kind != TYPE_STRUCT) {
+ err_print(to_where, "Wrong argument type. Expected this to be a struct, but it's not.");
info_print(match->where, "Parameter was declared here.");
return false;
}
+ Type *fn_type = to.type;
I16 *order;
- if (!parameterized_struct_arg_order(fn_val.type->struc, match->call.args, &order, match->where)) {
+ if (!parameterized_struct_arg_order(fn_type->struc, match->call.args, &order, match->where)) {
free(order);
return false;
}
- Declaration *params = to->typeval->struc->params;
+ Declaration *params = fn_type->struc->params;
int arg_idx = 0;
arr_foreach(params, Declaration, param) {
int ident_idx = 0;
@@ -56,12 +49,7 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi
if (order[arg_idx] != -1) {
Expression *arg = &match->call.args[order[arg_idx]].val;
Value val = *decl_val_at_index(param, ident_idx);
- Expression val_expr = {0};
- val_expr.kind = EXPR_VAL;
- val_expr.val = val;
- val_expr.type = *decl_type_at_index(param, ident_idx);
- val_expr.flags = EXPR_FOUND_TYPE;
- if (!infer_from_expr(tr, arg, &val_expr, idents, vals, types)) {
+ if (!infer_from_expr(tr, arg, val, decl_type_at_index(param, ident_idx), param->where, idents, vals, types)) {
free(order);
return false;
}
@@ -72,74 +60,7 @@ static bool infer_from_expr(Typer *tr, Expression *match, Expression *to, Identi
}
free(order);
}
-
- while (to->kind == EXPR_IDENT) {
- Identifier i = to->ident;
- Declaration *decl = i->decl;
- int index = ident_index_in_decl(i, decl);
- Expression *expr = NULL;
- if (decl->type.kind == TYPE_TUPLE) {
- if (decl->expr.kind == EXPR_TUPLE) {
- expr = &decl->expr.tuple[index];
- }
- } else {
- expr = &decl->expr;
- }
- if (expr) to = expr;
- }
- if (to->kind != EXPR_CALL) {
- if (to->kind == EXPR_TYPE) {
- to = to->typeval->was_expr;
- }
- if (!to || to->kind != EXPR_CALL) {
- return true;
- }
- }
-
- Argument *m_args = match->call.args;
- size_t nargs = arr_len(m_args);
- Expression *t_args = to->call.arg_exprs;
- I16 *order = NULL;
- Expression *f = match->call.fn;
- Identifier ident = f->ident;
- bool is_direct_fn = f->kind == EXPR_IDENT && (ident->decl->flags & DECL_HAS_EXPR) && ident->decl->expr.kind == EXPR_FN;
- if (!types_expr(tr, f))
- return false;
- if (f->type.kind != TYPE_FN) {
- char *s = type_to_str(&f->type);
- err_print(f->where, "Calling non-function type %s.", s);
- return false;
- }
- if (is_direct_fn) {
- FnExpr *fn_decl = ident->decl->expr.fn;
- if (!call_arg_param_order(fn_decl, &f->type, m_args, match->where, &order)) {
- free(order);
- return false;
- }
- }
- size_t nparams = arr_len(f->type.fn.types) - 1;
- if (!order && nparams != nargs) {
- /* wrong number of parameters? let typing deal with it... */
- free(order);
- return true;
- }
- for (size_t i = 0; i < nparams; ++i) {
- if (!order || order[i] != -1) {
- Argument *m_arg = &m_args[order ? (size_t)order[i] : i];
- Expression *t_arg;
- if (is_direct_fn) {
- t_arg = &t_args[i];
- } else {
- t_arg = &t_args[i];
- }
- if (t_arg->kind == EXPR_VAL) {
- /* was evaluated, because it's const */
- if (!infer_from_expr(tr, &m_arg->val, t_arg, idents, vals, types))
- return false;
- }
- }
- }
- free(order);
+ /* don't try to match other kinds of function calls. it's impossible to get any information out of it. */
} break;
default: break;
}
@@ -200,34 +121,21 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents
no sane person will ever write something that needs this */
break;
case TYPE_EXPR: {
- Expression *to_expr = to->was_expr;
- Expression e = {0};
- e.kind = EXPR_TYPE;
- e.typeval = allocr_malloc(tr->allocr, sizeof *e.typeval);
- *e.typeval = *to;
- e.flags = EXPR_FOUND_TYPE;
- e.where = where;
- Type *type = &e.type;
- type->flags = TYPE_IS_RESOLVED;
- type->kind = TYPE_BUILTIN;
- type->builtin = BUILTIN_TYPE;
- if (!to_expr) {
- to_expr = &e;
- }
- if (!infer_from_expr(tr, match->expr, to_expr, idents, vals, types))
+ Type type;
+ construct_resolved_builtin_type(&type, BUILTIN_TYPE);
+ Value val = {0};
+ val.type = to;
+ if (!infer_from_expr(tr, match->expr, val, &type, where, idents, vals, types))
return false;
} break;
case TYPE_ARR: {
if (to->kind != TYPE_ARR) return true;
- Expression to_n_expr = {0};
- to_n_expr.kind = EXPR_LITERAL_INT;
- to_n_expr.intl = to->arr.n;
- to_n_expr.flags = EXPR_FOUND_TYPE;
- Type *n_type = &to_n_expr.type;
- n_type->kind = TYPE_BUILTIN;
- n_type->builtin = BUILTIN_I64;
- n_type->flags = TYPE_IS_RESOLVED;
- if (!infer_from_expr(tr, match->arr.n_expr, &to_n_expr, idents, vals, types))
+ Type n_type;
+ construct_resolved_builtin_type(&n_type, BUILTIN_I64);
+ Value val;
+ val.i64 = (I64)to->arr.n;
+ /* try to match match's n expr to to's value */
+ if (!infer_from_expr(tr, match->arr.n_expr, val, &n_type, where, idents, vals, types))
return false;
if (!infer_from_type(tr, match->arr.of, to->arr.of, idents, vals, types, where))
return false;
diff --git a/main.c b/main.c
index b3508da..1529b68 100644
--- a/main.c
+++ b/main.c
@@ -8,7 +8,6 @@
/*
@TODO:
-consider: don't do inference for function calls; get rid of was_expr -- now that we have struct params
EXPR_IDENT should be a string before typing, also struct member accesses
do we need the possibility that IdentSlot.decl is NULL?
use
diff --git a/parse.c b/parse.c
index 9a4d57f..0de36f8 100644
--- a/parse.c
+++ b/parse.c
@@ -27,6 +27,8 @@ static bool is_decl(Tokenizer *t);
static inline bool ends_decl(Token *t, U16 flags);
static bool fn_has_any_const_params(FnExpr *f) {
+ if (f->flags & FN_EXPR_FOREIGN)
+ return false;
arr_foreach(f->params, Declaration, param)
if (param->flags & (DECL_IS_CONST | DECL_SEMI_CONST))
return true;
@@ -633,7 +635,7 @@ static Status parse_type(Parser *p, Type *type, Location *where) {
p->block = prev_block;
if (!parse_block(p, &struc->body, PARSE_BLOCK_DONT_CREATE_IDENTS))
return false;
- struc->where = struc->body.where;
+ parser_put_end(p, &struc->where);
break;
struct_fail:
@@ -1211,6 +1213,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
}
{
Token *before = t->token;
+ /* @OPTIM very few expressions are types */
if (parser_is_definitely_type(p, NULL)) {
/* it's a type! */
e->kind = EXPR_TYPE;
@@ -1536,13 +1539,11 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
ret_ctype->kind = CTYPE_NONE;
ret_type->kind = TYPE_VOID;
ret_type->flags = 0;
- ret_type->was_expr = NULL;
} else {
if (!parse_c_type(p, ret_ctype, ret_type))
return false;
}
- parser_put_end(p, &fn->where);
- return true;
+ goto success;
}
/* NOTE: the . operator is not handled here, but further down, in order to allow some_struct.fn_member() */
@@ -2173,7 +2174,6 @@ static Status parse_decl(Parser *p, Declaration *d, U16 flags) {
if (token_is_kw(t->token, KW_DOTDOT)) {
d->type.kind = TYPE_BUILTIN;
d->type.flags = 0;
- d->type.was_expr = NULL;
d->type.builtin = BUILTIN_VARARGS;
is_varargs = true;
if (d->flags & DECL_SEMI_CONST) {
@@ -2987,3 +2987,8 @@ static bool expr_is_definitely_const(Expression *e) {
return false;
}
+static inline void construct_resolved_builtin_type(Type *t, BuiltinType builtin) {
+ t->kind = TYPE_BUILTIN;
+ t->builtin = builtin;
+ t->flags = TYPE_IS_RESOLVED;
+}
diff --git a/test.toc b/test.toc
index 843b3ad..e2e5a57 100644
--- a/test.toc
+++ b/test.toc
@@ -1,4 +1,11 @@
-#include "io.toc", io;
+Point ::= struct {
+ a ::= 3;
+}
-#include "mem.toc", mem;
+
+main ::= fn() {
+ use p: Point;
+ a;
+
+}
diff --git a/types.c b/types.c
index d8998d2..183f350 100644
--- a/types.c
+++ b/types.c
@@ -32,13 +32,6 @@ static inline void typer_block_exit(Typer *tr) {
tr->block = arr_last(tr->blocks);
}
-static inline void construct_resolved_builtin_type(Type *t, BuiltinType builtin) {
- t->kind = TYPE_BUILTIN;
- t->builtin = builtin;
- t->was_expr = NULL;
- t->flags = TYPE_IS_RESOLVED;
-}
-
static size_t compiler_sizeof_builtin(BuiltinType b) {
switch (b) {
case BUILTIN_I8: return sizeof(I8);
@@ -558,7 +551,6 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) {
} else {
f->ret_type.kind = TYPE_TUPLE;
f->ret_type.flags = TYPE_IS_RESOLVED;
- f->ret_type.was_expr = NULL;
f->ret_type.tuple = NULL;
arr_foreach(f->ret_decls, Declaration, d) {
arr_foreach(d->idents, Identifier, i) {
@@ -768,7 +760,6 @@ static Status add_block_to_struct(Typer *tr, Block *b, StructDef *s, Statement *
static Status type_resolve(Typer *tr, Type *t, Location where) {
Evaluator *ev = tr->evalr;
if (t->flags & TYPE_IS_RESOLVED) return true;
- t->was_expr = NULL;
switch (t->kind) {
case TYPE_ARR: {
/* it's an array */
@@ -872,7 +863,6 @@ static Status type_resolve(Typer *tr, Type *t, Location where) {
}
if (is_tuple_of_types) {
t->kind = TYPE_TUPLE;
- t->was_expr = expr;
t->flags = TYPE_IS_RESOLVED;
t->tuple = tuple;
break;
@@ -901,7 +891,6 @@ static Status type_resolve(Typer *tr, Type *t, Location where) {
if (!type_resolve(tr, t, where))
return false;
}
- t->was_expr = expr;
} break;
case TYPE_UNKNOWN:
case TYPE_VOID:
@@ -1571,7 +1560,6 @@ static Status types_expr(Typer *tr, Expression *e) {
if (e->flags & EXPR_FOUND_TYPE) return true;
Type *t = &e->type;
t->flags = TYPE_IS_RESOLVED;
- t->was_expr = NULL;
t->kind = TYPE_UNKNOWN; /* default to unknown type (in the case of an error) */
e->flags |= EXPR_FOUND_TYPE; /* even if failed, pretend we found the type */
switch (e->kind) {
@@ -1597,7 +1585,6 @@ static Status types_expr(Typer *tr, Expression *e) {
t->kind = TYPE_SLICE;
t->slice = typer_malloc(tr, sizeof *t->slice);
t->slice->flags = TYPE_IS_RESOLVED;
- t->slice->was_expr = NULL;
t->slice->kind = TYPE_BUILTIN;
t->slice->builtin = BUILTIN_CHAR;
break;
@@ -1671,7 +1658,6 @@ static Status types_expr(Typer *tr, Expression *e) {
}
Type *fo_type = &header->type;
fo_type->flags = TYPE_IS_RESOLVED;
- fo_type->was_expr = NULL;
fo_type->kind = TYPE_TUPLE;
fo_type->tuple = fo_type_tuple;
@@ -2138,7 +2124,6 @@ static Status types_expr(Typer *tr, Expression *e) {
} else {
next_type->kind = TYPE_VOID;
next_type->flags = TYPE_IS_RESOLVED;
- next_type->was_expr = NULL;
}
if (!type_eq_implicit(next_type, curr_type)) {
char *currstr = type_to_str(curr_type);
@@ -2682,10 +2667,7 @@ static Status types_expr(Typer *tr, Expression *e) {
table_index_type.kind = TYPE_TUPLE;
table_index_type.tuple = NULL;
Type *u64t = typer_arr_add_ptr(tr, table_index_type.tuple);
- u64t->was_expr = NULL;
- u64t->flags = TYPE_IS_RESOLVED;
- u64t->kind = TYPE_BUILTIN;
- u64t->builtin = BUILTIN_U64;
+ construct_resolved_builtin_type(u64t, BUILTIN_U64);
table_index.tuple = NULL;
Value *which_are_const_val = typer_arr_add_ptr(tr, table_index.tuple);
U64 *which_are_const = &which_are_const_val->u64;
@@ -3135,9 +3117,10 @@ static Status types_expr(Typer *tr, Expression *e) {
break;
} else if (struct_type->kind == TYPE_STRUCT) {
StructDef *struc = struct_type->struc;
+ assert(struc->flags & STRUCT_DEF_RESOLVED);
Identifier struct_ident = ident_translate(rhs->ident, &struc->body.idents);
- Field *field = NULL;
- if (ident_is_declared(struct_ident) && (field = struct_ident->decl->field)) {
+ if (ident_is_declared(struct_ident) && !(struct_ident->decl->flags & DECL_IS_CONST)) {
+ Field *field = struct_ident->decl->field;
field += ident_index_in_decl(struct_ident, struct_ident->decl);
e->binary.dot.field = field;
*t = *field->type;
@@ -3489,7 +3472,6 @@ static Status types_decl(Typer *tr, Declaration *d) {
if (!success) {
/* use unknown type if we didn't get the type */
d->type.flags = TYPE_IS_RESOLVED;
- d->type.was_expr = NULL;
d->type.kind = TYPE_UNKNOWN;
}
arr_remove_lasta(tr->in_decls, tr->allocr);
diff --git a/types.h b/types.h
index 92a4a5c..aabf246 100644
--- a/types.h
+++ b/types.h
@@ -437,7 +437,6 @@ enum {
};
typedef U8 TypeFlags;
typedef struct Type {
- struct Expression *was_expr; /* if non-NULL, indicates that this type used to be an expression (TYPE_EXPR) */
TypeKind kind;
TypeFlags flags;
union {
@@ -507,7 +506,6 @@ enum {
typedef struct StructDef {
/* these two only exist after resolving (before then, it's scope.stmts) */
Field *fields;
-
Location where;
U8 flags;
/*