diff options
-rw-r--r-- | cgen.c | 2 | ||||
-rw-r--r-- | eval.c | 98 | ||||
-rw-r--r-- | identifiers.c | 14 | ||||
-rw-r--r-- | location.c | 6 | ||||
-rw-r--r-- | package.c | 24 | ||||
-rw-r--r-- | test.toc | 4 | ||||
-rw-r--r-- | tokenizer.c | 6 | ||||
-rw-r--r-- | types.c | 24 | ||||
-rw-r--r-- | types.h | 5 |
9 files changed, 117 insertions, 66 deletions
@@ -1280,7 +1280,7 @@ static bool cgen_expr(CGenerator *g, Expression *e) { cgen_expr(g, e->binary.lhs); bool is_ptr = e->binary.lhs->type.kind == TYPE_PTR; cgen_write(g, is_ptr ? "->" :"."); - cgen_ident(g, e->binary.field->name); + cgen_ident(g, e->binary.dot.field->name); cgen_write(g, ")"); handled = true; } break; @@ -736,7 +736,7 @@ static void *eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr) { } else { struc_data = struc.struc; } - return (char *)struc_data + dot_expr->binary.field->offset; + return (char *)struc_data + dot_expr->binary.dot.field->offset; } static bool eval_address_of(Evaluator *ev, Expression *e, void **ptr) { @@ -843,7 +843,7 @@ static bool eval_set(Evaluator *ev, Expression *set, Value *to) { case BINARY_DOT: { void *ptr = eval_ptr_to_struct_field(ev, set); if (!ptr) return false; - eval_deref_set(ptr, to, &set->binary.field->type); + eval_deref_set(ptr, to, &set->binary.dot.field->type); } break; default: assert(0); break; } @@ -1019,6 +1019,51 @@ static bool val_is_nonnegative(Value *v, Type *t) { return val_to_i64(v, t->builtin) >= 0; } +static bool eval_ident(Evaluator *ev, Identifier ident, Value *v, Location where) { + IdentDecl *idecl = ident_decl(ident); + if (!idecl) { + char *s = ident_to_str(ident); + err_print(where, "Undeclared identifier: %s.", s); + free(s); + return false; + } + bool is_decl = idecl->kind == IDECL_DECL; + Declaration *d = NULL; + if (is_decl) { + d = idecl->decl; + + if ((d->flags & DECL_FOUND_VAL) && type_is_builtin(&d->type, BUILTIN_TYPE) && d->val.type->kind == TYPE_STRUCT) { + v->type = allocr_malloc(ev->allocr, sizeof *v->type); + v->type->flags = TYPE_IS_RESOLVED; + v->type->kind = TYPE_STRUCT; + v->type->struc = d->val.type->struc; + return true; + } else { + if (!types_decl(ev->typer, d)) return false; + assert(d->type.flags & TYPE_IS_RESOLVED); + } + } + if (idecl->flags & IDECL_HAS_VAL) { + *v = idecl->val; + } else if (is_decl && (d->flags & DECL_IS_CONST)) { + if (!(d->flags & DECL_FOUND_VAL)) { + assert(d->flags & DECL_HAS_EXPR); + if (!eval_expr(ev, &d->expr, &d->val)) return false; + d->flags |= DECL_FOUND_VAL; + } + int index = ident_index_in_decl(ident, d); + assert(index != -1); + *v = *decl_val_at_index(d, index); + } else { + char *s = ident_to_str(ident); + + err_print(where, "Cannot evaluate non-constant '%s' at compile time.", s); + free(s); + return false; + } + return true; +} + static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { #define eval_unary_op_one(low, up, op) \ @@ -1109,6 +1154,11 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { if (!eval_expr(ev, rhs_expr, &rhs)) return false; switch (e->binary.op) { case BINARY_DOT: { + if (type_is_builtin(&lhs_expr->type, BUILTIN_PKG)) { + if (!eval_ident(ev, e->binary.dot.pkg_ident, v, rhs_expr->where)) + return false; + break; + } void *ptr = eval_ptr_to_struct_field(ev, e); if (!ptr) return false; eval_deref(v, ptr, &e->type); @@ -1332,48 +1382,10 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { case EXPR_FN: v->fn = e->fn; break; - case EXPR_IDENT: { - IdentDecl *idecl = ident_decl(e->ident); - if (!idecl) { - char *s = ident_to_str(e->ident); - err_print(e->where, "Undeclared identifier: %s.", s); - free(s); - return false; - } - bool is_decl = idecl->kind == IDECL_DECL; - Declaration *d = NULL; - if (is_decl) { - d = idecl->decl; - if ((d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_TYPE && d->expr.typeval.kind == TYPE_STRUCT) { - v->type = allocr_malloc(ev->allocr, sizeof *v->type); - v->type->flags = TYPE_IS_RESOLVED; - v->type->kind = TYPE_STRUCT; - v->type->struc = d->expr.typeval.struc; - break; - } else { - if (!types_decl(ev->typer, d)) return false; - assert(d->type.flags & TYPE_IS_RESOLVED); - } - } - if (idecl->flags & IDECL_HAS_VAL) { - *v = idecl->val; - } else if (is_decl && (d->flags & DECL_IS_CONST)) { - if (!(d->flags & DECL_FOUND_VAL)) { - assert(d->flags & DECL_HAS_EXPR); - if (!eval_expr(ev, &d->expr, &d->val)) return false; - d->flags |= DECL_FOUND_VAL; - } - int index = ident_index_in_decl(e->ident, d); - assert(index != -1); - *v = *decl_val_at_index(d, index); - } else { - char *s = ident_to_str(e->ident); - - err_print(e->where, "Cannot evaluate non-constant '%s' at compile time.", s); - free(s); + case EXPR_IDENT: + if (!eval_ident(ev, e->ident, v, e->where)) return false; - } - } break; + break; case EXPR_TUPLE: { size_t i, n = arr_len(e->tuple); v->tuple = err_malloc(n * sizeof *v->tuple); diff --git a/identifiers.c b/identifiers.c index de8a106..c562d52 100644 --- a/identifiers.c +++ b/identifiers.c @@ -9,7 +9,7 @@ #endif /* can this character be used in an identifier? */ -static int isident(int c) { +static int is_ident(int c) { if (c >= 'a' && c <= 'z') return 1; if (c >= 'A' && c <= 'Z') @@ -71,7 +71,7 @@ static void idents_create(Identifiers *ids) { static Identifier ident_insert(Identifiers *ids, char **s) { IdentTree *tree = ids->root; while (1) { - if (!isident(**s)) { + if (!is_ident(**s)) { return tree; } int c = ident_char_to_uchar(**s); @@ -117,6 +117,7 @@ static char *ident_to_str(Identifier i) { return str; } + static void fprint_ident(FILE *out, Identifier id) { char *str = ident_to_str(id); fprintf(out, "%s", str); @@ -172,6 +173,15 @@ static Identifier ident_get(Identifiers *ids, const char *s) { return tree; } +static Identifier ident_translate(Identifier i, Identifiers *to_idents) { + /* OPTIM */ + if (!i || i->anonymous) return NULL; + char *s = ident_to_str(i); + Identifier new_ident = ident_get(to_idents, s); + free(s); + return new_ident; +} + static IdentDecl *ident_add_decl(Identifier i, struct Declaration *d, struct Block *b) { IdentDecl *id_decl = arr_add(&i->decls); id_decl->decl = d; @@ -9,7 +9,11 @@ static Location const LOCATION_NONE = {0}; /* for debugging */ static void fprint_location(FILE *out, Location location) { if (!location.start) { - fprintf(out, "No location available."); + if (location.simple_location) { + fprintf(out, "Line %lu of %s\n", (unsigned long)location.simple_location->line, location.simple_location->ctx->filename); + } else { + fprintf(out, "No location available."); + } return; } /* TODO: show end */ @@ -199,7 +199,7 @@ static void exptr_start(Exporter *ex, const char *pkg_name, size_t pkg_name_len) } } -/* where = where was this imported */ +/* where = where was this imported. don't free fname while imported stuff is in use. */ static bool import_pkg(Allocator *allocr, Package *p, FILE *f, const char *fname, Identifiers *parent_idents, ErrCtx *parent_ctx, Location where) { Importer i = {0}; ErrCtx *err_ctx = &i.err_ctx; @@ -246,11 +246,18 @@ static bool import_pkg(Allocator *allocr, Package *p, FILE *f, const char *fname return false; fseek(f, decls_offset, SEEK_SET); /* read declarations */ + Statement *stmts = NULL; while (import_u8(&i)) { - import_decl(&i, arr_add(&i.decls)); + Statement *s = arr_add(&stmts); + s->kind = STMT_DECL; + import_decl(&i, &s->decl); } free(i.ident_map); + /* TOOD: LEAK! exit at some point */ + if (!block_enter(NULL, stmts, 0)) + return false; + return true; } @@ -960,14 +967,12 @@ static void import_decl(Importer *im, Declaration *d) { } if (d->flags & DECL_FOUND_VAL) { d->val = import_val(im, &d->type); - printf("TYPE: "); - print_type(&d->type); - printf("VALUE: "); - print_val(d->val, &d->type); + if (d->flags & DECL_HAS_EXPR) { + d->expr.kind = EXPR_VAL; + d->expr.val = d->val; + } } else if (d->flags & DECL_HAS_EXPR) { import_expr(im, &d->expr); - printf("EXPRESSION: "); - print_expr(&d->expr); } } @@ -1182,8 +1187,9 @@ static bool import_footer(Importer *im) { import_struct(im, s); import_arr(im, &im->fns); - arr_foreach(im->fns, FnExpr, f) + arr_foreach(im->fns, FnExpr, f) { import_fn(im, f); + } if (ferror(im->in)) { warn_print(im->import_location, "An error occured while reading the package. It may be incorrect."); @@ -11,4 +11,6 @@ putf ::= fn(x: float) { point ::= pkg "point"; -main ::= fn() {};
\ No newline at end of file +main ::= fn() { + x : point.Point; +};
\ No newline at end of file diff --git a/tokenizer.c b/tokenizer.c index b3e300b..48579bc 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -32,7 +32,7 @@ static Keyword tokenize_kw(char **s) { /* it's not a symbol, so we need to check if it's something like "intfoo" */ - if (isident((*s)[len])) { + if (is_ident((*s)[len])) { continue; } } @@ -50,7 +50,7 @@ static Directive tokenize_direct(char **s) { for (Directive d = 0; d < DIRECT_COUNT; d = d + 1) { size_t len = strlen(directives[d]); if (strncmp(*s, directives[d], len) == 0) { - if (isident((*s)[len])) { + if (is_ident((*s)[len])) { continue; } *s += len; @@ -517,7 +517,7 @@ static bool tokenize_string(Tokenizer *t, char *str) { continue; } - if (isident(*t->s)) { + if (is_ident(*t->s)) { /* it's an identifier */ Token *token = tokr_add(t); Identifier ident = ident_insert(t->idents, &t->s); @@ -987,7 +987,7 @@ static bool types_expr(Typer *tr, Expression *e) { free(name_cstr); e->pkg.name_ident = name_ident; if (!name_ident->pkg) { - char *filename = err_malloc(name_str_len + 5); + char *filename = typer_malloc(tr, name_str_len + 5); Package *pkg = name_ident->pkg = allocr_calloc(tr->allocr, 1, sizeof *pkg); memcpy(filename, name_str.data, name_str_len); strcpy(filename + name_str.n, ".top"); @@ -999,10 +999,8 @@ static bool types_expr(Typer *tr, Expression *e) { return false; } if (!import_pkg(tr->allocr, pkg, fp, filename, tr->idents, tr->err_ctx, e->where)) { - free(filename); return false; } - free(filename); fclose(fp); } } break; @@ -1901,7 +1899,7 @@ static bool types_expr(Typer *tr, Expression *e) { if (ident_eq_str(f->name, field_name.slice.data)) { is_field = true; *t = f->type; - e->binary.field = f; + e->binary.dot.field = f; } } if (!is_field) { @@ -1925,6 +1923,22 @@ static bool types_expr(Typer *tr, Expression *e) { case BINARY_DOT: { if (!types_expr(tr, lhs)) return false; Type *struct_type = lhs_type; + if (type_is_builtin(struct_type, BUILTIN_PKG)) { + if (rhs->kind != EXPR_IDENT) { + err_print(rhs->where, "Expected identifier for package access, but got %s.", + expr_kind_to_str(rhs->kind)); + return false; + } + Value pkg_val; + if (!eval_expr(tr->evalr, lhs, &pkg_val)) + return false; + e->binary.dot.pkg_ident = ident_translate(rhs->ident, &pkg_val.pkg->idents); + if (!type_of_ident(tr, e->where, e->binary.dot.pkg_ident, t)) { + return false; + } + break; + } + if (struct_type->kind == TYPE_PTR) struct_type = struct_type->ptr; if (rhs->kind != EXPR_IDENT) { @@ -1940,7 +1954,7 @@ static bool types_expr(Typer *tr, Expression *e) { if (f->name == rhs->ident) { is_field = true; *t = f->type; - e->binary.field = f; + e->binary.dot.field = f; } } } @@ -651,7 +651,10 @@ typedef struct Expression { BinaryOp op; struct Expression *lhs; struct Expression *rhs; - Field *field; /* for . only */ + union { + Field *field; /* for struct. */ + Identifier pkg_ident; /* for Package. */ + } dot; } binary; CallExpr call; struct { |