diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-05-23 00:54:14 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-05-23 00:54:14 -0400 |
commit | 38da18a86693f4ee46952b49601438f8c73ef34c (patch) | |
tree | 66274c9b6519876629bd02045684ecfe85bf3023 | |
parent | f7de68fe80850c4058eb2c1f123ca0dad54abe9b (diff) |
started removing block ret_expr
-rw-r--r-- | cgen.c | 66 | ||||
-rw-r--r-- | copy.c | 2 | ||||
-rw-r--r-- | eval.c | 66 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | parse.c | 17 | ||||
-rw-r--r-- | test.toc | 12 | ||||
-rw-r--r-- | types.c | 147 | ||||
-rw-r--r-- | types.h | 8 |
8 files changed, 83 insertions, 239 deletions
@@ -19,7 +19,7 @@ static void cgen_stmt(CGenerator *g, Statement *s); enum { CGEN_BLOCK_NOBRACES = 0x01 /* should it use braces? */ }; -static void cgen_block(CGenerator *g, Block *b, const char *ret_name, uint16_t flags); +static void cgen_block(CGenerator *g, Block *b, uint16_t flags); static void cgen_expr_pre(CGenerator *g, Expression *e); static void cgen_expr(CGenerator *g, Expression *e); static void cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, Expression *to_expr, @@ -827,50 +827,16 @@ static void cgen_truthiness(CGenerator *g, Expression *e) { } static void cgen_expr_pre(CGenerator *g, Expression *e) { - IdentID id = 0; - char ret_name[CGEN_IDENT_ID_STR_SIZE+20]; - switch (e->kind) { - case EXPR_IF: - case EXPR_BLOCK: { - id = ++g->ident_counter; - - cgen_ident_id_to_str(ret_name, id); - char *p = ret_name + strlen(ret_name); - if (!type_is_void(&e->type)) { - if (e->type.kind == TYPE_TUPLE) { - for (unsigned long i = 0; i < arr_len(e->type.tuple); ++i) { - sprintf(p, "%lu", i); - cgen_type_pre(g, &e->type.tuple[i]); - cgen_write(g, " %s", ret_name); - cgen_type_post(g, &e->type.tuple[i]); - cgen_write(g, "; "); - } - - } else { - cgen_type_pre(g, &e->type); - cgen_write(g, " %s", ret_name); - cgen_type_post(g, &e->type); - cgen_write(g, ";"); - cgen_nl(g); - } - } - *p = 0; /* clear tuple suffixes */ - - } break; - default: break; - } - switch (e->kind) { case EXPR_IF: { IfExpr *curr = e->if_; - e->cgen.id = id; while (1) { if (curr->cond) { cgen_write(g, "if ("); cgen_truthiness(g, curr->cond); cgen_write(g, ") "); } - cgen_block(g, &curr->body, ret_name, 0); + cgen_block(g, &curr->body, 0); if (curr->next_elif) { cgen_write(g, " else "); curr = curr->next_elif->if_; @@ -878,8 +844,7 @@ static void cgen_expr_pre(CGenerator *g, Expression *e) { } } break; case EXPR_BLOCK: - e->cgen.id = id; - cgen_block(g, e->block, ret_name, 0); + cgen_block(g, e->block, 0); break; case EXPR_CALL: { cgen_expr_pre(g, e->call.fn); @@ -925,7 +890,7 @@ static void cgen_expr_pre(CGenerator *g, Expression *e) { } cgen_write(g, ");"); } else if (cgen_uses_ptr(&e->type)) { - e->cgen.id = id = ++g->ident_counter; + IdentID id = e->cgen.id = ++g->ident_counter; cgen_type_pre(g, &e->type); cgen_write(g, " "); cgen_ident_id(g, id); @@ -1286,7 +1251,7 @@ static void cgen_expr(CGenerator *g, Expression *e) { cgen_write(g, "while ("); cgen_expr(g, w->cond); cgen_write(g, ") "); - cgen_block(g, &w->body, NULL, 0); + cgen_block(g, &w->body, 0); } break; case EXPR_FOR: { ForExpr *fo = e->for_; @@ -1473,7 +1438,7 @@ static void cgen_expr(CGenerator *g, Expression *e) { } } } - cgen_block(g, &fo->body, NULL, CGEN_BLOCK_NOBRACES); + cgen_block(g, &fo->body, CGEN_BLOCK_NOBRACES); cgen_deferred_from_block(g, &fo->body); cgen_write(g, "}}"); if (fo->body.c.break_lbl) { @@ -1587,12 +1552,7 @@ static void cgen_expr(CGenerator *g, Expression *e) { } } -/* - ret_name = variable to store block return value in; NULL for none. NOTE: - functions always call with NULL as ret_name, even if they use out params, for now - at least. -*/ -static void cgen_block(CGenerator *g, Block *b, const char *ret_name, U16 flags) { +static void cgen_block(CGenerator *g, Block *b, U16 flags) { Block *prev_block = g->block; g->block = b; b->deferred = NULL; @@ -1605,15 +1565,6 @@ static void cgen_block(CGenerator *g, Block *b, const char *ret_name, U16 flags) arr_foreach(b->stmts, Statement, s) cgen_stmt(g, s); - if (b->ret_expr && ret_name) { - cgen_expr_pre(g, b->ret_expr); - if (b->ret_expr->type.kind == TYPE_TUPLE) { - cgen_set_tuple(g, NULL, NULL, ret_name, b->ret_expr); - } else { - cgen_set(g, NULL, ret_name, b->ret_expr, NULL); - } - cgen_nl(g); - } if (b->c.cont_lbl) { cgen_lbl(g, b->c.cont_lbl); cgen_writeln(g, ":;"); @@ -1720,8 +1671,7 @@ static void cgen_fn(CGenerator *g, FnExpr *f) { cgen_decl(g, d); } - cgen_block(g, &f->body, NULL, CGEN_BLOCK_NOBRACES); - cgen_ret(g, &f->body, f->body.ret_expr); + cgen_block(g, &f->body, CGEN_BLOCK_NOBRACES); cgen_writeln(g, "}"); g->block = prev_block; g->fn = prev_fn; @@ -430,8 +430,6 @@ static void copy_block(Copier *c, Block *out, Block *in, U8 flags) { out->stmts = NULL; Block *prev = c->block; c->block = out; - if (in->ret_expr) - out->ret_expr = copy_expr_(c, in->ret_expr); if (!(flags & COPY_BLOCK_DONT_CREATE_IDENTS)) idents_create(&out->idents, c->allocr, out); arr_set_lena(out->stmts, nstmts, c->allocr); @@ -4,7 +4,7 @@ You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>. */ -static Status eval_block(Evaluator *ev, Block *b, Value *v); +static Status eval_block(Evaluator *ev, Block *b); static Status eval_address_of(Evaluator *ev, Expression *e, void **ptr); static Value get_builtin_val(BuiltinVal val); @@ -22,7 +22,7 @@ static inline void *evalr_calloc(Evaluator *ev, size_t n, size_t bytes) { return allocr_calloc(ev->allocr, n, bytes); } -static bool builtin_truthiness(Value v, BuiltinType b) { +static inline bool builtin_truthiness(Value v, BuiltinType b) { switch (b) { case BUILTIN_I8: return v.i8 != 0; case BUILTIN_I16: return v.i16 != 0; @@ -45,7 +45,7 @@ static bool builtin_truthiness(Value v, BuiltinType b) { assert(0); return false; } -static bool val_truthiness(Value v, Type *t) { +static inline bool val_truthiness(Value v, Type *t) { assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_UNKNOWN: assert(0); return false; @@ -1024,7 +1024,12 @@ static Status eval_ident(Evaluator *ev, Identifier ident, Value *v, Location whe v->type->struc = d->expr.typeval->struc; return true; } else { + Typer *tr = ev->typer; + Block *prev_block = tr->block; + /* make sure we're in the right block for typing the declaration */ + tr->block = ident->idents->scope; if (!types_decl(ev->typer, d)) return false; + tr->block = prev_block; assert(d->type.flags & TYPE_IS_RESOLVED); } Value *ival = ident_val(ev, ident, where); @@ -1218,13 +1223,14 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { } if (!eval_expr(ev, i->cond, &cond)) return false; if (val_truthiness(cond, &i->cond->type)) { - if (!eval_block(ev, &i->body, v)) return false; + if (!eval_block(ev, &i->body)) return false; } else if (i->next_elif && !ev->returning) { if (!eval_expr(ev, i->next_elif, v)) return false; } } else { - if (!eval_block(ev, &i->body, v)) return false; + if (!eval_block(ev, &i->body)) return false; } + memset(v, 0, sizeof *v); } break; case EXPR_WHILE: { Value cond; @@ -1243,7 +1249,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { if (!val_truthiness(cond, cond_type)) break; } - if (!eval_block(ev, &w->body, v)) return false; + if (!eval_block(ev, &w->body)) return false; if (ev->returning) { if (ev->returning == &w->body) { ev->returning = NULL; @@ -1252,6 +1258,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { } else break; } } + memset(v, 0, sizeof *v); } break; case EXPR_FOR: { ForExpr *fo = e->for_; @@ -1292,7 +1299,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { } if (value_val) *value_val = x; - if (!eval_block(ev, &fo->body, v)) return false; + if (!eval_block(ev, &fo->body)) return false; if (ev->returning) { if (ev->returning == &fo->body) { @@ -1345,7 +1352,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { value_val->ptr = ptr; else eval_deref(value_val, ptr, value_type); - if (!eval_block(ev, &fo->body, v)) + if (!eval_block(ev, &fo->body)) return false; if (ev->returning) { if (ev->returning == &fo->body) { @@ -1359,9 +1366,10 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { } arr_remove_last(header->val_stack); free(for_valp); + memset(v, 0, sizeof *v); } break; case EXPR_BLOCK: - if (!eval_block(ev, e->block, v)) return false; + if (!eval_block(ev, e->block)) return false; break; case EXPR_LITERAL_BOOL: v->boolv = e->booll; @@ -1480,11 +1488,20 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { } } + + /* make sure function body is typed before calling it */ - if (!types_block(ev->typer, &fn->body)) - return false; - - if (!eval_block(ev, &fn->body, v)) { + /* @TODO: is this necessary? see also types_decl call in eval_ident */ + if (!(fn->body.flags & BLOCK_FOUND_TYPES)) { + Typer *tr = ev->typer; + Block *prev_block = tr->block; + tr->block = fn->declaration_block; + if (!types_block(tr, &fn->body)) + return false; + tr->block = prev_block; + } + + if (!eval_block(ev, &fn->body)) { return false; } if (fn->ret_decls) { @@ -1694,7 +1711,7 @@ static Status eval_stmt(Evaluator *ev, Statement *stmt) { return true; } -static Status eval_block(Evaluator *ev, Block *b, Value *v) { +static Status eval_block(Evaluator *ev, Block *b) { Block *prev = ev->typer->block; ev->typer->block = b; b->deferred = NULL; @@ -1710,27 +1727,6 @@ static Status eval_block(Evaluator *ev, Block *b, Value *v) { break; } } - if (b->ret_expr) { - if (ev->returning) { - /* return 0 from this block */ - *v = val_zero(&b->ret_expr->type); - } else { - Value r; - if (!eval_expr(ev, b->ret_expr, &r)) { - success = false; - goto ret; - } - if (!type_is_builtin(&b->ret_expr->type, BUILTIN_TYPE)) { - /* make a copy so that r's data isn't freed when we exit the block */ - copy_val(NULL, v, r, &b->ret_expr->type); - if (b->ret_expr->kind == EXPR_TUPLE) - free(r.tuple); - } else { - *v = r; - } - } - - } { /* deal with deferred stmts */ /* these could overwrite ev->returning, ev->ret_val, so we should save them */ @@ -9,6 +9,10 @@ /* @TODO: get rid of blocks returning values +turn if, while, for, block into statements +see if you can get rid of Expression.cgen.id--would mean that kind doesn't have to be a bitfield anymore +make sure functions which should return things do +check return #C("3"); initialization statements (maybe #init(-50), where -50 is the priority and <0 is reserved for standard library) if we do #include "foo.toc", bar; and foo.toc fails, bar should be declared as TYPE_UNKNOWN (right now it's undeclared) improve type_to_str: @@ -823,7 +823,6 @@ static Status parse_block(Parser *p, Block *b, U8 flags) { b->flags = 0; b->kind = BLOCK_OTHER; b->uses = NULL; - b->ret_expr = NULL; assert(p->block != b); b->parent = p->block; p->block = b; @@ -2295,7 +2294,8 @@ static Status parse_decl(Parser *p, Declaration *d, U16 flags) { tokr_err(t, "Expected %s at end of declaration.", end_str); goto ret_false; } - if (!parse_expr(p, &d->expr, end)) { + Expression *e = &d->expr; + if (!parse_expr(p, e, end)) { t->token = end; /* move to ; */ goto ret_false; } @@ -2322,6 +2322,7 @@ static Status parse_decl(Parser *p, Declaration *d, U16 flags) { tokr_err(t, "You must have an expression at the end of this constant declaration."); goto ret_false; } + parser_put_end(p, &d->where); if (!token_is_kw(t->token, KW_SEMICOLON)) @@ -2548,12 +2549,7 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) { bool valid = parse_expr(p, s->expr = parser_malloc(p, sizeof *s->expr), end); /* go past end of expr regardless of whether successful or not */ - if (token_is_kw(end, KW_SEMICOLON)) { - t->token = end + 1; /* skip ; */ - } else { - s->flags |= STMT_EXPR_NO_SEMICOLON; - t->token = end; - } + t->token = end + 1; /* skip ; */ if (!valid) return false; } @@ -2616,11 +2612,6 @@ static void fprint_block(FILE *out, Block *b) { fprint_stmt(out, stmt); } fprintf(out, "}"); - if (b->ret_expr) { - fprintf(out, " returns "); - fprint_expr(out, b->ret_expr); - } - } static void print_block(Block *b) { @@ -1,14 +1,10 @@ main ::= fn() { - nums : []int; - l := slice_to_ll(nums); + a ::= foo(3); + b := foo(5); } -slice_to_ll ::= fn(t::=, slice: []t) use ll: LinkedList(t) { -} - -LinkedList ::= struct (of :: Type) { - head: of; - tail: &LinkedList(of); +foo ::= fn(x: int) int { + return 3*x; } @@ -33,13 +33,11 @@ static inline void *typer_calloc(Typer *tr, size_t n, size_t sz) { #define typer_arr_add_ptr(tr, a) arr_adda_ptr(a, tr->allocr) static inline void typer_block_enter(Typer *tr, Block *b) { - typer_arr_add(tr, tr->blocks, b); tr->block = b; } static inline void typer_block_exit(Typer *tr) { - arr_remove_lasta(tr->blocks, tr->allocr); - tr->block = arr_last(tr->blocks); + tr->block = tr->block->parent; } static size_t compiler_sizeof_builtin(BuiltinType b) { @@ -628,7 +626,8 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { /* reserve space for return type */ typer_arr_add_ptr(tr, t->fn.types); tr->fn = f; - typer_block_enter(tr, &f->body); + Block *prev_block = tr->block; + tr->block = &f->body; f->body.uses = NULL; size_t nparams = arr_len(f->params); entered_fn = true; @@ -760,7 +759,7 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { ret: /* cleanup */ - typer_block_exit(tr); + tr->block = prev_block; if (entered_fn) { tr->fn = prev_fn; } @@ -779,9 +778,9 @@ top:; if (decl_scope && decl_scope->kind != BLOCK_NMS) { if (decl_scope->kind != BLOCK_NMS) { /* go back through scopes */ - arr_foreach_reversed(tr->blocks, BlockPtr, block) { - if (*block == NULL || *block == decl_scope) break; - if ((*block)->kind == BLOCK_FN) { + for (Block *block = tr->block; block; block = block->parent) { + if (block == decl_scope) break; + if (block->kind == BLOCK_FN) { captured = true; break; } @@ -1156,6 +1155,7 @@ static bool arg_is_const(Expression *arg, Constness constness) { /* pass NULL for instance if this isn't an instance */ static Status types_fn(Typer *tr, FnExpr *f, Type *t, Instance *instance) { + f->declaration_block = tr->block; if (f->flags & FN_EXPR_FOREIGN) { FnWithCtx fn_ctx = {f, tr->nms, tr->block}; typer_arr_add(tr, tr->all_fns, fn_ctx); @@ -1163,7 +1163,6 @@ static Status types_fn(Typer *tr, FnExpr *f, Type *t, Instance *instance) { } FnExpr *prev_fn = tr->fn; bool success = true; - Expression *ret_expr; Type *ret_type; bool has_named_ret_vals; assert(t->kind == TYPE_FN); @@ -1182,30 +1181,9 @@ static Status types_fn(Typer *tr, FnExpr *f, Type *t, Instance *instance) { success = false; goto ret; } - ret_expr = f->body.ret_expr; ret_type = t->fn.types; has_named_ret_vals = f->ret_decls != NULL; - if (ret_expr) { - if (ret_expr->type.kind == TYPE_UNKNOWN) { - if (ret_type->kind == TYPE_UNKNOWN) { - err_print(ret_expr->where, "Can't determine type of return value. Try assigning it to a variable before returning it."); - return false; - } - if (!tr->err_ctx->have_errored) /* if we've had an error, this could be a placeholder because something failed earlier */ - ret_expr->type = *ret_type; - } else if (!type_eq_implicit(&ret_expr->type, ret_type)) { - char *got = type_to_str(&ret_expr->type); - char *expected = type_to_str(ret_type); - err_print(ret_expr->where, "Returning type %s, but function returns type %s.", got, expected); - if (!instance) /* where will only actually be at the function declaration if it isn't - an instance. otherwise, where will be at the calling site, which will already be - printed */ - info_print(f->where, "Function declaration is here."); - free(got); free(expected); - success = false; - goto ret; - } - } else if (!type_is_builtin(ret_type, BUILTIN_VOID) && !has_named_ret_vals) { + if (!type_is_builtin(ret_type, BUILTIN_VOID) && !has_named_ret_vals) { Statement *stmts = f->body.stmts; if (arr_len(stmts)) { Statement *last_stmt = (Statement *)stmts + (arr_len(stmts) - 1); @@ -1985,16 +1963,12 @@ static Status types_expr(Typer *tr, Expression *e) { } if (!types_block(tr, &fo->body)) goto for_fail; - if (fo->body.ret_expr) { - err_print(fo->body.ret_expr->where, "for loops can't return values -- you're missing a semicolon (;)."); - goto for_fail; - } t->kind = TYPE_BUILTIN; t->builtin = BUILTIN_VOID; typer_block_exit(tr); - }break; + } break; for_fail: if (in_header) arr_remove_lasta(tr->in_decls, tr->allocr); @@ -2153,13 +2127,9 @@ static Status types_expr(Typer *tr, Expression *e) { err_print(e->where, "You can't use #if in this way. It has to be a statement on its own, and can't return a value."); return false; } - Type *curr_type = t; - bool has_else = false; if (!types_block(tr, &curr->body)) return false; - if (curr->body.ret_expr) { - *t = curr->body.ret_expr->type; - } else { + { t->kind = TYPE_BUILTIN; t->builtin = BUILTIN_VOID; t->flags |= TYPE_IS_RESOLVED; } @@ -2173,8 +2143,6 @@ static Status types_expr(Typer *tr, Expression *e) { free(s); return false; } - } else { - has_else = true; } if (curr->next_elif) { IfExpr *nexti = curr->next_elif->if_; @@ -2183,31 +2151,15 @@ static Status types_expr(Typer *tr, Expression *e) { if (!types_block(tr, &nexti->body)) { return false; } - if (nexti->body.ret_expr) { - *next_type = nexti->body.ret_expr->type; - } else { + { next_type->kind = TYPE_BUILTIN; next_type->builtin = BUILTIN_VOID; next_type->flags = TYPE_IS_RESOLVED; } - if (!type_eq_implicit(next_type, curr_type)) { - char *currstr = type_to_str(curr_type); - char *nextstr = type_to_str(next_type); - err_print(curr->next_elif->where, "Mismatched types in if/elif/else chain. Previous block was of type %s, but this one is of type %s.", currstr, nextstr); - free(currstr); - free(nextstr); - return false; - } curr = nexti; - } else { break; } } - - if (!has_else && !type_is_builtin(t, BUILTIN_VOID)) { - err_print(e->where, "Non-void if block with no else."); - return false; - } } break; case EXPR_WHILE: { WhileExpr *w = e->while_; @@ -2217,11 +2169,6 @@ static Status types_expr(Typer *tr, Expression *e) { if (!types_block(tr, &w->body)) ret = false; if (!ret) return false; - - if (w->body.ret_expr) { - err_print(w->body.ret_expr->where, "while loops can't return values -- you're missing a semicolon (;)"); - return false; - } t->kind = TYPE_BUILTIN; t->builtin = BUILTIN_VOID; } break; @@ -2816,12 +2763,8 @@ static Status types_expr(Typer *tr, Expression *e) { Block *b = e->block; if (!types_block(tr, b)) return false; - if (b->ret_expr) { - *t = b->ret_expr->type; - } else { - t->kind = TYPE_BUILTIN; - t->builtin = BUILTIN_VOID; - } + t->kind = TYPE_BUILTIN; + t->builtin = BUILTIN_VOID; } break; case EXPR_C: { Expression *code = e->c.code; @@ -3400,32 +3343,8 @@ static Status types_block(Typer *tr, Block *b) { } continue; } - if (s->kind == STMT_EXPR && (s->flags & STMT_EXPR_NO_SEMICOLON)) { - /* not voided */ - Expression *e = s->expr; - if (type_is_builtin(&e->type, BUILTIN_VOID)) { - if (!(e->kind == EXPR_BLOCK - || e->kind == EXPR_IF - || e->kind == EXPR_WHILE - || e->kind == EXPR_FOR)) { - err_print(e->where, "void expression must be followed by ;"); - success = false; - goto ret; - } - } else { - if (s != (Statement *)arr_last_ptr(b->stmts)) { - err_print(e->where, "Return value must be the last statement in a block."); - success = false; - goto ret; - } - b->ret_expr = typer_malloc(tr, sizeof *b->ret_expr); - *b->ret_expr = *e; - arr_remove_lasta(b->stmts, tr->allocr); - } - } - } - ret: + assert(tr->block == b); typer_block_exit(tr); b->flags |= BLOCK_FOUND_TYPES; b->flags &= (BlockFlags)~(BlockFlags)BLOCK_FINDING_TYPES; @@ -3434,8 +3353,8 @@ static Status types_block(Typer *tr, Block *b) { } static bool is_at_top_level(Typer *tr) { - arr_foreach(tr->blocks, BlockPtr, b) { - if (*b && (*b)->kind != BLOCK_NMS) { + for (Block *b = tr->block; b; b = b->parent) { + if (b && b->kind != BLOCK_NMS) { return false; } } @@ -3465,21 +3384,22 @@ static Status types_decl(Typer *tr, Declaration *d) { size_t n_idents; n_idents = arr_len(d->idents); if (e) { - if (e->kind == EXPR_FN && tr->block && tr->block->kind == BLOCK_STRUCT && !tr->in_decls /* don't include params */) { - warn_print(d->where, "This function is in the body of a struct. Are you trying to declare a method, because they don't exist in this language.\n" + if (e->kind == EXPR_FN) { + if (tr->block == NULL || tr->block->kind == BLOCK_NMS) { + e->fn->c.name = d->idents[0]; + } else if (tr->block->kind == BLOCK_STRUCT && !tr->in_decls /* don't include params */) { + warn_print(d->where, "This function is in the body of a struct. Are you trying to declare a method, because they don't exist in this language.\n" "Try moving the function outside of the struct, otherwise you might run into problems."); - } - if (e->kind == EXPR_TYPE + } + } else if (e->kind == EXPR_NMS) { + if (is_at_top_level(tr)) + e->nms->associated_ident = d->idents[0]; + } else if (e->kind == EXPR_TYPE && e->typeval->kind == TYPE_STRUCT && tr->fn == NULL) { e->typeval->struc->name = d->idents[0]; } - if (e->kind == EXPR_NMS) { - if (is_at_top_level(tr)) - e->nms->associated_ident = d->idents[0]; - } - if (!types_expr(tr, e)) { success = false; goto ret; @@ -3533,9 +3453,6 @@ static Status types_decl(Typer *tr, Declaration *d) { typer_arr_add(tr, d->val_stack, copy); } } - if ((tr->block == NULL || tr->block->kind == BLOCK_NMS) && e->kind == EXPR_FN && n_idents == 1) { - e->fn->c.name = d->idents[0]; - } } } else if (!tr->block || tr->block->kind == BLOCK_NMS) { /* give global variables without initializers a value stack */ @@ -3726,11 +3643,6 @@ static Status types_stmt(Typer *tr, Statement *s) { } if (!cond || val_truthiness(v, &cond->type)) { Block *true_block = &curr->body; - Statement *last = arr_last_ptr(true_block->stmts); - if (last && last->kind == STMT_EXPR && (last->flags & STMT_EXPR_NO_SEMICOLON)) { - err_print(last->where, "#ifs can't return values."); - return false; - } s->kind = STMT_INLINE_BLOCK; s->inline_block = true_block->stmts; if (!fix_ident_decls_inline_block(tr, s->inline_block)) @@ -3766,7 +3678,7 @@ static Status types_stmt(Typer *tr, Statement *s) { return false; } - if (!(s->flags & STMT_EXPR_NO_SEMICOLON)) { + { if (e->kind == EXPR_TUPLE) { err_print(s->where, "Statement of a tuple is not allowed. Use a semicolon instead of a comma here."); return false; @@ -3778,6 +3690,7 @@ static Status types_stmt(Typer *tr, Statement *s) { free(str); } } + if (tr->block == NULL) { /* evaluate expression statements at global scope */ if (e->kind != EXPR_C) { @@ -4041,7 +3954,6 @@ static void typer_create(Typer *tr, Evaluator *ev, ErrCtx *err_ctx, Allocator *a tr->err_ctx = err_ctx; tr->allocr = allocr; tr->globals = idents; - typer_arr_add(tr, tr->blocks, NULL); str_hash_table_create(&tr->included_files, sizeof(IncludedFile), tr->allocr); } @@ -4059,7 +3971,6 @@ static Status types_file(Typer *tr, ParsedFile *f) { } } assert(tr->block == NULL); - assert(arr_len(tr->blocks) && tr->blocks[0] == NULL); return ret; } @@ -519,7 +519,6 @@ typedef struct Block { Location where; Identifiers idents; struct Statement *stmts; - struct Expression *ret_expr; /* the return expression of this block, e.g. {foo(); 3} => 3 NULL for no expression. */ struct Block *parent; struct Statement **deferred; /* deferred stuff from this block; used by both eval and cgen */ struct Use **uses; /* use statements (for types.c) */ @@ -681,6 +680,7 @@ typedef struct { typedef struct FnExpr { Location where; + Block *declaration_block; /* block wherein this function is declared */ union { struct { struct Declaration *params; /* declarations of the parameters to this function */ @@ -713,7 +713,7 @@ typedef struct FnExpr { IdentID id; } c; U8 flags; -} FnExpr; /* an expression such as fn(x: int) int { 2 * x } */ +} FnExpr; /* an expression such as fn(x: int) int { return 2 * x; } */ typedef FnExpr *FnExprPtr; typedef struct Instance { @@ -982,8 +982,7 @@ typedef struct Use { typedef Use *UsePtr; enum { - STMT_EXPR_NO_SEMICOLON = 0x01, - STMT_TYPED = 0x02 + STMT_TYPED = 0x01 }; typedef struct Statement { Location where; @@ -1072,7 +1071,6 @@ typedef struct Typer { Use **uses; /* global used things */ Declaration **in_decls; /* array of declarations we are currently inside */ Block *block; - Block **blocks; /* dyn array of all the block's we're in ([0] = NULL for global scope) */ FnExpr *fn; /* the function we're currently parsing. */ ErrCtx *err_ctx; ParsedFile *parsed_file; |