diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-07-13 19:01:37 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-07-13 19:01:37 -0400 |
commit | a1afddbf8843d01c93cad0735fce4417318a096e (patch) | |
tree | 462c2ef16087bb7ae1aa2dc8cee173631f1472b9 | |
parent | a12739cd3f2ae5c78eca04cb3a1b30243db4f4fe (diff) |
started #for, also fixed some other stuff (including io.puti)
-rw-r--r-- | parse.c | 10 | ||||
-rw-r--r-- | std/io.toc | 2 | ||||
-rw-r--r-- | test.toc | 24 | ||||
-rw-r--r-- | types.c | 200 | ||||
-rw-r--r-- | types.h | 15 |
5 files changed, 143 insertions, 108 deletions
@@ -2395,16 +2395,20 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) { if (!cond_success) return false; w->body.kind = BLOCK_WHILE; } break; - case KW_FOR: { + case KW_FOR: + for_stmt: { s->kind = STMT_FOR; For *fo = s->for_ = parser_malloc(p, sizeof *fo); fo->flags = 0; + if (t->token->kind == TOKEN_DIRECT) { + fo->flags |= FOR_STATIC; + } Block *prev_block = p->block; fo->body.parent = p->block; p->block = &fo->body; Declaration *header_decl = &fo->header; idents_create(&p->block->idents, p->allocr, p->block); - ++t->token; + ++t->token; // move past 'for' if (!parse_decl(p, header_decl, PARSE_DECL_IGNORE_EXPR | DECL_CAN_END_WITH_LBRACE)) { tokr_skip_to_eof(t); goto for_fail; @@ -2514,6 +2518,8 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) { } break; case DIRECT_IF: goto if_stmt; + case DIRECT_FOR: + goto for_stmt; case DIRECT_ERROR: case DIRECT_WARN: case DIRECT_INFO: { @@ -285,7 +285,7 @@ fwritei ::= fn(use f: &File, x: int) err : FileError { *out = '-'; out += 1; // get the absolute value of x in a u64. this complicated stuff is needed because -INT_MIN doesn't fit in a 64-bit signed integer - x_unsigned = (x as u64) - 18446744073709551615 - 1; + x_unsigned = (18446744073709551615 - (x as u64)) + 1; } else { *out = '0'; out += 1; @@ -1,3 +1,25 @@ +#include "std/io.toc"; + +putis ::= fn(x: ..) { + for a := x { + #if typeof(a) != int { + #error "Arguments to putis must all be ints."; + } + puti(a); + } +} + +main ::= fn() { + puti(-12); + putis(3,4,5); + putis(3,4,5,-12); + putis(3,4,5,565); +} +main(); + + + +/* #include "std/io.toc", io; #include "std/types.toc"; @@ -99,4 +121,4 @@ main ::= fn() { print_typeof(v); } main(); - +*/ @@ -2385,7 +2385,7 @@ static Status types_expr(Typer *tr, Expression *e) { copy_block(&cop, &fn_copy->body, &original_fn->body, COPY_BLOCK_DONT_CREATE_IDENTS); c->instance->fn = fn_copy; // fix parameter and return types (they were kind of problematic before, because we didn't know about the instance) - fn_copy->instance_id = 1+original_fn->instances->n; // let's help cgen out and assign a non-zero ID to this + fn_copy->instance_id = original_fn->instances->n; // let's help cgen out and assign a non-zero ID to this // type this instance // if anything happens, make sure we let the user know that this happened while generating a fn @@ -3164,8 +3164,8 @@ static Status types_block(Typer *tr, Block *b) { arr_foreach(b->stmts, Statement, s) { if (!types_stmt(tr, s)) { success = false; - if (tr->had_include_err) { - // stop immediately; prevent too many "undeclared identifier" errors + if (tr->had_fatal_err) { + // stop immediately break; } continue; @@ -3488,8 +3488,9 @@ top: bool in_header = true; Block *prev_block = tr->block; { // additional block because c++ For *fo = s->for_; + ForFlags flags = fo->flags; Declaration *header = &fo->header; - U32 is_range = fo->flags & FOR_IS_RANGE; + U32 is_range = flags & FOR_IS_RANGE; typer_arr_add(tr, tr->in_decls, header); fo->body.uses = NULL; typer_block_enter(tr, &fo->body); @@ -3553,6 +3554,100 @@ top: construct_resolved_builtin_type(index_type, BUILTIN_I64); } + if (flags & FOR_STATIC) { + static_for: + // exit for body + tr->block = prev_block; + arr_remove_lasta(tr->in_decls, tr->allocr); + // create one block, containing a block for each vararg + // e.g. for x := varargs { total += x; } => { { x := varargs[0]; total += x; } { x := varargs[0]; total += x; } } + assert(fo->of->kind == EXPR_IDENT); + Identifier varargs_ident = fo->of->ident; + Declaration *idecl = varargs_ident->decl; + VarArg *varargs = idecl->val.varargs; + size_t nvarargs = arr_len(varargs); + // create surrounding block + s->kind = STMT_BLOCK; + Block *b = s->block = typer_calloc(tr, 1, sizeof *s->block); + idents_create(&b->idents, tr->allocr, b); + b->stmts = NULL; + b->parent = tr->block; + b->where = s->where; + arr_set_lena(b->stmts, nvarargs, tr->allocr); + Statement *stmt = b->stmts; + size_t nstmts = arr_len(fo->body.stmts); + Declaration *header_decl = &fo->header; + + assert(arr_len(header_decl->idents) == 2); + Identifier val_ident = header_decl->idents[0]; + Identifier index_ident = header_decl->idents[1]; + bool has_val = !ident_eq_str(val_ident, "_"); + bool has_index = !ident_eq_str(index_ident, "_"); + + for (size_t i = 0; i < nvarargs; ++i, ++stmt) { + // create sub-block #i + memset(stmt, 0, sizeof *stmt); + stmt->kind = STMT_BLOCK; + Block *sub = stmt->block = typer_calloc(tr, 1, sizeof *sub); + sub->parent = b; + idents_create(&sub->idents, tr->allocr, sub); + sub->stmts = NULL; + sub->where = s->where; + size_t total_nstmts = nstmts + has_val + has_index; + arr_set_lena(sub->stmts, total_nstmts, tr->allocr); + Copier copier = copier_create(tr->allocr, sub); + if (has_val) { + // @TODO(eventually): don't put a decl in each block, just put one at the start + Statement *decl_stmt = &sub->stmts[0]; + decl_stmt->flags = 0; + decl_stmt->kind = STMT_DECL; + decl_stmt->where = s->where; + + // declare value + Declaration *decl = decl_stmt->decl = typer_calloc(tr, 1, sizeof *decl); + decl->where = fo->of->where; + Identifier ident = ident_translate_forced(val_ident, &sub->idents); + typer_arr_add(tr, decl->idents, ident); + ident->decl = decl; + + decl->flags |= DECL_HAS_EXPR; + decl->expr.kind = EXPR_BINARY_OP; + decl->expr.binary.op = BINARY_AT_INDEX; + decl->expr.binary.lhs = fo->of; + decl->expr.where = fo->of->where; + Expression *index = decl->expr.binary.rhs = typer_calloc(tr, 1, sizeof *decl->expr.binary.rhs); + index->kind = EXPR_LITERAL_INT; + index->intl = (U64)i; + index->where = fo->of->where; + } + if (has_index) { + // @TODO(eventually): don't put a decl in each block, just put one at the start + Statement *decl_stmt = &sub->stmts[has_val]; + decl_stmt->flags = 0; + decl_stmt->kind = STMT_DECL; + decl_stmt->where = s->where; + + // declare value + Declaration *decl = decl_stmt->decl = typer_calloc(tr, 1, sizeof *decl); + decl->where = fo->of->where; + Identifier ident = ident_translate_forced(index_ident, &sub->idents); + typer_arr_add(tr, decl->idents, ident); + ident->decl = decl; + + decl->flags |= DECL_HAS_EXPR; + decl->expr.kind = EXPR_LITERAL_INT; + decl->expr.intl = (U64)i; + decl->expr.where = fo->of->where; + } + + size_t start = total_nstmts - nstmts; + for (size_t idx = start; idx < total_nstmts; ++idx) { + copy_stmt(&copier, &sub->stmts[idx], &fo->body.stmts[idx-start]); + } + } + goto top; + } + if (is_range) { if (!types_expr(tr, fo->range.from)) goto for_fail; { @@ -3657,96 +3752,8 @@ top: case TYPE_BUILTIN: switch (iter_type->builtin) { case BUILTIN_VARARGS: { - // exit for body - tr->block = prev_block; - arr_remove_lasta(tr->in_decls, tr->allocr); - // create one block, containing a block for each vararg - // e.g. for x := varargs { total += x; } => { { x := varargs[0]; total += x; } { x := varargs[0]; total += x; } } - assert(fo->of->kind == EXPR_IDENT); - Identifier varargs_ident = fo->of->ident; - Declaration *idecl = varargs_ident->decl; - VarArg *varargs = idecl->val.varargs; - size_t nvarargs = arr_len(varargs); - // create surrounding block - s->kind = STMT_BLOCK; - Block *b = s->block = typer_calloc(tr, 1, sizeof *s->block); - idents_create(&b->idents, tr->allocr, b); - b->stmts = NULL; - b->parent = tr->block; - b->where = s->where; - arr_set_lena(b->stmts, nvarargs, tr->allocr); - Statement *stmt = b->stmts; - size_t nstmts = arr_len(fo->body.stmts); - Declaration *header_decl = &fo->header; - - assert(arr_len(header_decl->idents) == 2); - Identifier val_ident = header_decl->idents[0]; - Identifier index_ident = header_decl->idents[1]; - bool has_val = !ident_eq_str(val_ident, "_"); - bool has_index = !ident_eq_str(index_ident, "_"); - - for (size_t i = 0; i < nvarargs; ++i, ++stmt) { - // create sub-block #i - memset(stmt, 0, sizeof *stmt); - stmt->kind = STMT_BLOCK; - Block *sub = stmt->block = typer_calloc(tr, 1, sizeof *sub); - sub->parent = b; - idents_create(&sub->idents, tr->allocr, sub); - sub->stmts = NULL; - sub->where = s->where; - size_t total_nstmts = nstmts + has_val + has_index; - arr_set_lena(sub->stmts, total_nstmts, tr->allocr); - Copier copier = copier_create(tr->allocr, sub); - if (has_val) { - // @TODO(eventually): don't put a decl in each block, just put one at the start - Statement *decl_stmt = &sub->stmts[0]; - decl_stmt->flags = 0; - decl_stmt->kind = STMT_DECL; - decl_stmt->where = s->where; - - // declare value - Declaration *decl = decl_stmt->decl = typer_calloc(tr, 1, sizeof *decl); - decl->where = fo->of->where; - Identifier ident = ident_translate_forced(val_ident, &sub->idents); - typer_arr_add(tr, decl->idents, ident); - ident->decl = decl; - - decl->flags |= DECL_HAS_EXPR; - decl->expr.kind = EXPR_BINARY_OP; - decl->expr.binary.op = BINARY_AT_INDEX; - decl->expr.binary.lhs = fo->of; - decl->expr.where = fo->of->where; - Expression *index = decl->expr.binary.rhs = typer_calloc(tr, 1, sizeof *decl->expr.binary.rhs); - index->kind = EXPR_LITERAL_INT; - index->intl = (U64)i; - index->where = fo->of->where; - } - if (has_index) { - // @TODO(eventually): don't put a decl in each block, just put one at the start - Statement *decl_stmt = &sub->stmts[has_val]; - decl_stmt->flags = 0; - decl_stmt->kind = STMT_DECL; - decl_stmt->where = s->where; - - // declare value - Declaration *decl = decl_stmt->decl = typer_calloc(tr, 1, sizeof *decl); - decl->where = fo->of->where; - Identifier ident = ident_translate_forced(index_ident, &sub->idents); - typer_arr_add(tr, decl->idents, ident); - ident->decl = decl; - - decl->flags |= DECL_HAS_EXPR; - decl->expr.kind = EXPR_LITERAL_INT; - decl->expr.intl = (U64)i; - decl->expr.where = fo->of->where; - } - - size_t start = total_nstmts - nstmts; - for (size_t idx = start; idx < total_nstmts; ++idx) { - copy_stmt(&copier, &sub->stmts[idx], &fo->body.stmts[idx-start]); - } - } - goto top; + fo->flags = flags |= FOR_STATIC; + goto static_for; } default: break; } @@ -4070,7 +4077,7 @@ top: if (inc_f) inc_f->flags &= (IncFileFlags)~(IncFileFlags)INC_FILE_INCLUDING; if (!success) { // give up on typing if #include failed - tr->had_include_err = true; + tr->had_fatal_err = true; return false; } } break; @@ -4088,6 +4095,7 @@ top: break; case MESSAGE_ERROR: err_print(s->where, "%s", text); + tr->had_fatal_err = true; // consider #error to be a fatal error (stop typing) return false; } } break; @@ -4200,7 +4208,7 @@ static Status types_file(Typer *tr, ParsedFile *f) { tr->uses = NULL; arr_foreach(f->stmts, Statement, s) { if (!types_stmt(tr, s)) { - if (tr->had_include_err) { + if (tr->had_fatal_err) { // stop immediately; prevent too many "undeclared identifier" errors return false; } @@ -234,6 +234,7 @@ typedef enum { DIRECT_INCLUDE, DIRECT_FORCE, DIRECT_IF, + DIRECT_FOR, DIRECT_ERROR, DIRECT_WARN, DIRECT_INFO, @@ -243,8 +244,8 @@ typedef enum { } Directive; static const char *directives[DIRECT_COUNT] = { - "C", "sizeof", "alignof", "export", "foreign", "builtin", "include", "force", "if", "error", "warn", - "info", "no_warn", "init" + "C", "sizeof", "alignof", "export", "foreign", "builtin", "include", "force", "if", "for", + "error", "warn", "info", "no_warn", "init" }; typedef enum { @@ -874,7 +875,8 @@ typedef struct While { enum { FOR_IS_RANGE = 0x01, FOR_INCLUDES_FROM = 0x02, - FOR_INCLUDES_TO = 0x04 + FOR_INCLUDES_TO = 0x04, + FOR_STATIC = 0x08 }; typedef U8 ForFlags; typedef struct For { @@ -1080,11 +1082,8 @@ typedef struct Typer { IdentID lbl_counter; unsigned long nms_counter; // counter for namespace IDs StrHashTable included_files; // maps to IncludedFile - /* - have we had an error because we couldn't find a file that was #include'd - (so that we can stop compiling immediately) - */ - bool had_include_err; + // did we get an error which is bad enough that we should stop typing? + bool had_fatal_err; } Typer; typedef struct CGenerator { |