summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--parse.c10
-rw-r--r--std/io.toc2
-rw-r--r--test.toc24
-rw-r--r--types.c200
-rw-r--r--types.h15
5 files changed, 143 insertions, 108 deletions
diff --git a/parse.c b/parse.c
index 85479d1..42e8d4b 100644
--- a/parse.c
+++ b/parse.c
@@ -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: {
diff --git a/std/io.toc b/std/io.toc
index 10ec1d3..15314c9 100644
--- a/std/io.toc
+++ b/std/io.toc
@@ -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;
diff --git a/test.toc b/test.toc
index 597a41a..c5e3ba6 100644
--- a/test.toc
+++ b/test.toc
@@ -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();
-
+*/
diff --git a/types.c b/types.c
index 83e3a66..616245d 100644
--- a/types.c
+++ b/types.c
@@ -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;
}
diff --git a/types.h b/types.h
index 6c5907c..db2d5bd 100644
--- a/types.h
+++ b/types.h
@@ -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 {