From 4d39d9ac98e5a723c7e8cf96396df28602c9d11c Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Wed, 30 Oct 2019 11:19:37 -0400 Subject: fixed some problems with user-defined types --- eval.c | 34 ++++++++++++++++++++++++---------- identifiers.c | 4 +++- parse.c | 8 +++++--- test.toc | 23 +++++------------------ types.c | 50 +++++++++++++++++++++++++++++++++----------------- 5 files changed, 70 insertions(+), 49 deletions(-) diff --git a/eval.c b/eval.c index ad38f1d..a8a3fe0 100644 --- a/eval.c +++ b/eval.c @@ -707,6 +707,15 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { switch (e->unary.op) { case UNARY_ADDRESS: { Expression *o = e->unary.of; + if (o->type.kind == TYPE_TYPE) { + if (!eval_expr(ev, e->unary.of, &of)) return false; + /* "address" of type (pointer to type) */ + v->type = evalr_calloc(ev, 1, sizeof *v->type); /* TODO: this might be bad in the future; should free this at some point */ + /* v->type->flags = 0; */ + v->type->kind = TYPE_PTR; + v->type->ptr = of.type; + break; + } switch (o->kind) { case EXPR_IDENT: { IdentDecl *id = ident_decl(o->ident); @@ -888,18 +897,23 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { if (!eval_expr(ev, &d->expr, &d->val)) return false; d->flags |= DECL_FLAG_FOUND_VAL; } - if (d->type.kind == TYPE_TUPLE) { - long index = 0; - arr_foreach(d->idents, Identifier, decl_i) { - if (*decl_i == e->ident) { - break; - } - index++; - assert(index < (long)arr_len(d->idents)); /* identifier got its declaration set to here, but it's not here */ + + long index = 0; + arr_foreach(d->idents, Identifier, decl_i) { + if (*decl_i == e->ident) { + break; } - *v = d->val.tuple[index]; + index++; + assert(index < (long)arr_len(d->idents)); /* identifier got its declaration set to here, but it's not here */ + } + if (e->type.kind == TYPE_TYPE) { + /* set v to a user type, not the underlying type */ + v->type = evalr_malloc(ev, sizeof *v->type); /* TODO: fix this (free eventually) */ + v->type->flags = 0; + v->type->kind = TYPE_USER; + v->type->user.name = d->idents[index]; } else { - *v = d->val; + *v = d->type.kind == TYPE_TUPLE ? d->val.tuple[index] : d->val; } } else { char *s = ident_to_str(e->ident); diff --git a/identifiers.c b/identifiers.c index 3dc4099..c29f8ce 100644 --- a/identifiers.c +++ b/identifiers.c @@ -196,5 +196,7 @@ static Value *ident_decl_val(Identifier i) { } static inline Type *ident_typeval(Identifier i) { - return ident_decl_val(i)->type; + Value *val = ident_decl_val(i); + if (!val) return NULL; + return val->type; } diff --git a/parse.c b/parse.c index b9671ae..aa88283 100644 --- a/parse.c +++ b/parse.c @@ -333,6 +333,8 @@ static bool parse_type(Parser *p, Type *type, U16 flags) { Tokenizer *t = p->tokr; type->where = t->token->where; type->flags = 0; + U16 could_be_expr = flags & PARSE_TYPE_EXPR; + flags &= (U16)~PARSE_TYPE_EXPR; /* don't include this most of the time in children */ switch (t->token->kind) { case TOKEN_KW: type->kind = TYPE_BUILTIN; @@ -426,7 +428,7 @@ static bool parse_type(Parser *p, Type *type, U16 flags) { t->token++; /* move past ( */ while (1) { Type *child = parser_arr_add(p, &type->tuple); - if (!parse_type(p, child, flags)) return false; + if (!parse_type(p, child, flags | could_be_expr)) return false; /* if this could be an expression, it could just be (2, 3) */ if (child->kind == TYPE_TUPLE) { err_print(child->where, "Tuples cannot contain tuples."); return false; @@ -449,7 +451,7 @@ static bool parse_type(Parser *p, Type *type, U16 flags) { type->kind = TYPE_PTR; type->ptr = parser_malloc(p, sizeof *type->ptr); t->token++; /* move past & */ - if (!parse_type(p, type->ptr, flags)) return false; + if (!parse_type(p, type->ptr, flags | could_be_expr)) return false; /* if this could be an expression, it could just be &foo (where foo is a variable) */ if (type->ptr->kind == TYPE_TUPLE) { err_print(type->ptr->where, "You cannot have a pointer to a tuple."); return false; @@ -461,7 +463,7 @@ static bool parse_type(Parser *p, Type *type, U16 flags) { } break; case TOKEN_IDENT: - if (!(flags & PARSE_TYPE_EXPR)) { + if (!could_be_expr) { /* user-defined type */ type->kind = TYPE_USER; type->user.name = t->token->ident; diff --git a/test.toc b/test.toc index cb0e6ea..3f05dda 100644 --- a/test.toc +++ b/test.toc @@ -3,25 +3,12 @@ puti @= fn(x: int) { "); }; -Foo @= [3]int; - -f @= fn() Foo { - a : Foo; - (a as [3]int)[0] = 8; - (a as [3]int)[1] = 9; - (a as [3]int)[2] = 10; - a -}; - main @= fn() { - foo : Foo; - foo = f(); - puti((foo as [3]int)[0]); - puti((foo as [3]int)[1]); - puti((foo as [3]int)[2]); { - Foo, Bar @= int, float; - // Bar @= [3]Foo; - y: Bar = 0.342 as Bar; + Int @= int; + Ptr @= ∬ + asdf : Int = 1343 as Int; + p : Ptr = &asdf as Ptr; + // puti(*(p as &Int) as int); } }; diff --git a/types.c b/types.c index 76f5101..5f60845 100644 --- a/types.c +++ b/types.c @@ -2,7 +2,7 @@ static bool types_stmt(Typer *tr, Statement *s); static bool types_decl(Typer *tr, Declaration *d); static bool types_expr(Typer *tr, Expression *e); static bool types_block(Typer *tr, Block *b); -static bool type_resolve(Typer *tr, Type *t); +static bool type_resolve(Typer *tr, Type *t, Location where); static inline void *typer_malloc(Typer *tr, size_t bytes) { return allocr_malloc(&tr->allocr, bytes); @@ -200,16 +200,18 @@ static bool expr_must_lval(Expression *e) { return false; } -static bool type_of_fn(Typer *tr, FnExpr *f, Type *t) { +static bool type_of_fn(Typer *tr, Expression *e, Type *t) { + assert(e->kind == EXPR_FN); + FnExpr *f = &e->fn; t->kind = TYPE_FN; t->fn.types = NULL; Type *ret_type = typer_arr_add(tr, &t->fn.types); - if (!type_resolve(tr, &f->ret_type)) + if (!type_resolve(tr, &f->ret_type, e->where)) return false; *ret_type = f->ret_type; arr_foreach(f->params, Declaration, decl) { if (!types_decl(tr, decl)) return false; - if (!type_resolve(tr, &decl->type)) + if (!type_resolve(tr, &decl->type, e->where)) return false; for (size_t i = 0; i < arr_len(decl->idents); i++) { Type *param_type = typer_arr_add(tr, &t->fn.types); @@ -281,7 +283,7 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) { } else { if ((d->flags & DECL_FLAG_HAS_EXPR) && (d->expr.kind == EXPR_FN)) { /* allow using a function before declaring it */ - if (!type_of_fn(tr, &d->expr.fn, t)) return false; + if (!type_of_fn(tr, &d->expr, t)) return false; return true; } else { if (location_after(d->where, where)) { @@ -298,7 +300,7 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) { } /* fixes the type (replaces [5+3]int with [8]int, etc.) */ -static bool type_resolve(Typer *tr, Type *t) { +static bool type_resolve(Typer *tr, Type *t, Location where) { Evaluator *ev = tr->evalr; if (t->flags & TYPE_FLAG_RESOLVED) return true; switch (t->kind) { @@ -333,30 +335,38 @@ static bool type_resolve(Typer *tr, Type *t) { size = val_to_u64(&val, n_expr->type.builtin); } t->arr.n = (UInteger)size; - if (!type_resolve(tr, t->arr.of)) + if (!type_resolve(tr, t->arr.of, where)) return false; } break; case TYPE_FN: arr_foreach(t->fn.types, Type, child_type) { - if (!type_resolve(tr, child_type)) + if (!type_resolve(tr, child_type, where)) return false; } break; case TYPE_TUPLE: arr_foreach(t->tuple, Type, child_type) { - if (!type_resolve(tr, child_type)) + if (!type_resolve(tr, child_type, where)) return false; } break; case TYPE_PTR: - if (!type_resolve(tr, t->ptr)) + if (!type_resolve(tr, t->ptr, where)) return false; break; case TYPE_SLICE: - if (!type_resolve(tr, t->slice)) + if (!type_resolve(tr, t->slice, where)) return false; break; case TYPE_USER: + /* just check if it's actually defined */ + if (!ident_typeval(t->user.name)) { + char *s = ident_to_str(t->user.name); + err_print(where, "Use of undeclared type %s.", s); + free(s); + return false; + } + break; case TYPE_UNKNOWN: case TYPE_VOID: case TYPE_TYPE: @@ -484,11 +494,11 @@ static bool types_expr(Typer *tr, Expression *e) { Type prev_ret_type = tr->ret_type; bool prev_can_ret = tr->can_ret; FnExpr *f = &e->fn; - if (!type_of_fn(tr, f, t)) { + if (!type_of_fn(tr, e, t)) { success = false; goto fn_ret; } - bool has_named_ret_vals = e->fn.ret_decls != NULL; + bool has_named_ret_vals = f->ret_decls != NULL; if (has_named_ret_vals) { /* set return type to void to not allow return values */ tr->ret_type.kind = TYPE_VOID; @@ -580,13 +590,14 @@ static bool types_expr(Typer *tr, Expression *e) { CastExpr *c = &e->cast; if (!types_expr(tr, c->expr)) return false; - if (!type_resolve(tr, &c->type)) + if (!type_resolve(tr, &c->type, e->where)) return false; Status status = type_cast_status(&c->expr->type, &c->type); if (status != STATUS_NONE) { char *from = type_to_str(&c->expr->type); char *to = type_to_str(&c->type); if (status == STATUS_ERR) + err_print(e->where, "Cannot cast from type %s to %s.", from, to); else warn_print(e->where, "Casting from type %s to %s.", from, to); @@ -598,7 +609,7 @@ static bool types_expr(Typer *tr, Expression *e) { *t = c->type; } break; case EXPR_NEW: - if (!type_resolve(tr, &e->new.type)) + if (!type_resolve(tr, &e->new.type, e->where)) return false; if (e->new.n) { if (!types_expr(tr, e->new.n)) return false; @@ -861,6 +872,11 @@ static bool types_expr(Typer *tr, Expression *e) { *t = *of_type; break; case UNARY_ADDRESS: + if (of_type->kind == TYPE_TYPE) { + /* oh it's a type! */ + t->kind = TYPE_TYPE; + break; + } if (!expr_must_lval(of)) { err_print(e->where, "Cannot take address of non-lvalue."); /* FEATURE: better err */ return false; @@ -1116,7 +1132,7 @@ static bool types_decl(Typer *tr, Declaration *d) { if (d->flags & DECL_FLAG_ANNOTATES_TYPE) { /* type supplied */ assert(d->type.kind != TYPE_VOID); /* there's no way to annotate void */ - if (!type_resolve(tr, &d->type)) { + if (!type_resolve(tr, &d->type, d->where)) { success = false; goto ret; } @@ -1163,7 +1179,7 @@ static bool types_decl(Typer *tr, Declaration *d) { success = false; goto ret; } - if (!type_resolve(tr, val->type)) { + if (!type_resolve(tr, val->type, d->where)) { success = false; goto ret; } -- cgit v1.2.3