diff options
-rw-r--r-- | cgen.c | 7 | ||||
-rw-r--r-- | eval.c | 41 | ||||
-rw-r--r-- | test.toc | 4 | ||||
-rw-r--r-- | types.c | 16 |
4 files changed, 43 insertions, 25 deletions
@@ -852,14 +852,15 @@ static bool cgen_expr(CGenerator *g, Expression *e) { cgen_write(g, ")"); handled = true; break; - case BINARY_DOT: + case BINARY_DOT: { cgen_write(g, "("); cgen_expr(g, e->binary.lhs); - cgen_write(g, "."); + bool is_ptr = type_inner(&e->binary.lhs->type)->kind == TYPE_PTR; + cgen_write(g, is_ptr ? "->" : "."); cgen_ident(g, e->binary.field->name); cgen_write(g, ")"); handled = true; - break; + } break; } if (handled) break; cgen_write(g, "("); @@ -655,6 +655,26 @@ static bool eval_expr_ptr_at_index(Evaluator *ev, Expression *e, void **ptr, Typ return eval_val_ptr_at_index(ev, e->where, &arr, i, ltype, rtype, ptr, type); } +static void *eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr) { + Type *struct_type = type_inner(&dot_expr->binary.lhs->type); + bool is_ptr = struct_type->kind == TYPE_PTR; + if (is_ptr) { + struct_type = type_inner(struct_type->ptr); + } + eval_struct_find_offsets(struct_type); + + Value struc; + if (!eval_expr(ev, dot_expr->binary.lhs, &struc)) + return false; + void *struc_data; + if (is_ptr) { + struc_data = *(void **)struc.ptr; + } else { + struc_data = struc.struc; + } + return (char *)struc_data + dot_expr->binary.field->offset; +} + static bool eval_set(Evaluator *ev, Expression *set, Value *to) { switch (set->kind) { case EXPR_IDENT: { @@ -687,11 +707,8 @@ static bool eval_set(Evaluator *ev, Expression *set, Value *to) { eval_deref_set(ptr, to, type); } break; case BINARY_DOT: { - Value struc; - if (!eval_expr(ev, set->binary.lhs, &struc)) - return false; - eval_struct_find_offsets(type_inner(&set->binary.lhs->type)); - void *ptr = (char *)struc.struc + set->binary.field->offset; + void *ptr = eval_ptr_to_struct_field(ev, set); + if (!ptr) return false; eval_deref_set(ptr, to, set->binary.field->type); } break; default: assert(0); break; @@ -852,8 +869,9 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { Value struc; if (!eval_expr(ev, o->binary.lhs, &struc)) return false; - eval_struct_find_offsets(type_inner(&o->binary.lhs->type)); - v->ptr = (char *)struc.struc + o->binary.field->offset; + v->ptr = eval_ptr_to_struct_field(ev, o); + if (!v->ptr) + return false; } break; default: assert(0); break; } @@ -895,12 +913,9 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { BuiltinType builtin = e->binary.lhs->type.builtin; switch (e->binary.op) { case BINARY_DOT: { - Type *inner_type = &e->binary.lhs->type; - while (inner_type->kind == TYPE_USER) - inner_type = ident_typeval(inner_type->user.name); - eval_struct_find_offsets(inner_type); - - eval_deref(v, (char *)lhs.struc + e->binary.field->offset, &e->type); + void *ptr = eval_ptr_to_struct_field(ev, e); + if (!ptr) return false; + eval_deref(v, ptr, &e->type); } break; case BINARY_ADD: if (e->binary.lhs->type.kind == TYPE_PTR) { @@ -7,9 +7,9 @@ puti @= fn(x: int) { }; main @= fn() { -// puti(somesum()); +puti(somesum()); foo @= somesum(); -// puti(foo); +puti(foo); }; Point @= struct { x, y : int; @@ -1081,14 +1081,16 @@ static bool types_expr(Typer *tr, Expression *e) { break; case BINARY_DOT: { if (!types_expr(tr, lhs)) return false; - Type *inner_type = lhs_type; - while (inner_type->kind == TYPE_USER) - inner_type = ident_typeval(inner_type->user.name); - if (inner_type->kind == TYPE_STRUCT) { + Type *struct_type = type_inner(lhs_type); + if (struct_type->kind == TYPE_PTR) + struct_type = struct_type->ptr; + struct_type = type_inner(struct_type); + + if (struct_type->kind == TYPE_STRUCT) { bool is_field = false; if (rhs->kind == EXPR_IDENT) { /* maybe accessing a field? */ - arr_foreach(inner_type->struc.fields, Field, f) { + arr_foreach(struct_type->struc.fields, Field, f) { if (f->name == rhs->ident) { is_field = true; *t = *f->type; @@ -1107,7 +1109,7 @@ static bool types_expr(Typer *tr, Expression *e) { } if (!eval_expr(tr->evalr, rhs, &field_name)) return false; - arr_foreach(inner_type->struc.fields, Field, f) { + arr_foreach(struct_type->struc.fields, Field, f) { if (ident_eq_str(f->name, field_name.slice.data)) { is_field = true; *t = *f->type; @@ -1126,7 +1128,7 @@ static bool types_expr(Typer *tr, Expression *e) { } } else { char *s = type_to_str(lhs_type); - err_print(e->where, "Operator . applied to type %s, which is not a structure.", s); + err_print(e->where, "Operator . applied to type %s, which is not a structure or pointer to structure.", s); free(s); return false; } |