summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c7
-rw-r--r--main.c3
-rw-r--r--parse.c94
-rw-r--r--test.toc29
-rw-r--r--types.c5
5 files changed, 80 insertions, 58 deletions
diff --git a/cgen.c b/cgen.c
index 80507ee..50389f6 100644
--- a/cgen.c
+++ b/cgen.c
@@ -214,6 +214,9 @@ static inline void cgen_write(CGenerator *g, const char *fmt, ...) {
va_start(args, fmt);
vfprintf(cgen_writing_to(g), fmt, args);
va_end(args);
+#ifdef TOC_DEBUG
+ fflush(cgen_writing_to(g));
+#endif
}
static inline void cgen_nl(CGenerator *g) {
@@ -2120,8 +2123,9 @@ static bool cgen_defs_stmt(CGenerator *g, Statement *s) {
static bool cgen_defs_block(CGenerator *g, Block *b) {
/*
NOTE: since we exit as soon as there's an error for cgen, we don't need to make sure we
- set g->block to the previous block
+ set g->block to the previous block if there's an error
*/
+ Block *prev_block = g->block;
g->block = b;
arr_foreach(b->stmts, Statement, s) {
if (!cgen_defs_stmt(g, s)) {
@@ -2131,6 +2135,7 @@ static bool cgen_defs_block(CGenerator *g, Block *b) {
if (b->ret_expr && !cgen_defs_expr(g, b->ret_expr)) {
return false;
}
+ g->block = prev_block;
return true;
}
diff --git a/main.c b/main.c
index 4975b99..67fa99b 100644
--- a/main.c
+++ b/main.c
@@ -18,12 +18,15 @@
/*
TODO:
+the problem right now is that we're copying blocks but not updating our references to the copy
+
make eval_ptr_to_struct_field return a bool (just in case it successfully returns a NULL pointer)
nms["foo"]
make sure #export still works properly
fix cgen_ident_to_str for unicode idents
check for leaks
---
+allow for circular dependencies in functions returning types---this will be complicated
nice syntax for #including something into a namespace
run stuff at compile time without assigning it to a constant
#compile_only declarations
diff --git a/parse.c b/parse.c
index 0d4100d..4853848 100644
--- a/parse.c
+++ b/parse.c
@@ -779,12 +779,16 @@ static bool parser_is_definitely_type(Parser *p, Token **end) {
return ret;
}
-static bool parse_block(Parser *p, Block *b) {
+enum {
+ PARSE_BLOCK_DONT_CREATE_IDENTS = 0x01
+};
+static bool parse_block(Parser *p, Block *b, U8 flags) {
Tokenizer *t = p->tokr;
Block *prev_block = p->block;
b->flags = 0;
b->ret_expr = NULL;
- idents_create(&b->idents, p->allocr, p->block);
+ if (!(flags & PARSE_BLOCK_DONT_CREATE_IDENTS))
+ idents_create(&b->idents, p->allocr, p->block);
if (!token_is_kw(t->token, KW_LBRACE)) {
tokr_err(t, "Expected '{' to open block.");
return false;
@@ -865,7 +869,11 @@ static bool parse_fn_expr(Parser *p, FnExpr *f) {
}
++t->token;
f->params = NULL;
- bool ret = true;
+ bool success = true;
+ Block *prev_block = p->block;
+ /* enter block so that parameters' scope will be the function body */
+ p->block = &f->body;
+ idents_create(&f->body.idents, p->allocr, &f->body);
if (token_is_kw(t->token, KW_RPAREN)) {
++t->token;
} else {
@@ -874,14 +882,15 @@ static bool parse_fn_expr(Parser *p, FnExpr *f) {
arr_foreach(f->params, Declaration, param) {
if (param->flags & DECL_FOREIGN) {
err_print(param->where, "Parameters cannot be foreign.");
- return false;
+ success = false;
+ goto ret;
}
}
}
if (t->token->kind == TOKEN_EOF) {
tokr_err(t, "End of file encountered while parsing parameter list.");
- return false;
+ success = false; goto ret;
}
if (token_is_kw(t->token, KW_LBRACE)) {
@@ -894,15 +903,15 @@ static bool parse_fn_expr(Parser *p, FnExpr *f) {
arr_foreach(f->ret_decls, Declaration, d) {
if ((d->flags & DECL_IS_CONST) || (d->flags & DECL_SEMI_CONST)) {
err_print(d->where, "Named return values cannot be constant.");
- return false;
+ success = false; goto ret;
}
if (d->flags & DECL_INFER) {
err_print(d->where, "Can't infer the value of a named return value!");
- return false;
+ success = false; goto ret;
}
if (d->flags & DECL_FOREIGN) {
err_print(d->where, "Named return values can't be foreign.");
- return false;
+ success = false; goto ret;
}
}
--t->token; /* move back to { */
@@ -911,13 +920,16 @@ static bool parse_fn_expr(Parser *p, FnExpr *f) {
f->ret_type.flags = 0;
} else {
if (!parse_type(p, &f->ret_type)) {
- ret = false;
+ success = false;
+ goto ret;
}
}
- if (!parse_block(p, &f->body))
- ret = false;
+ if (!parse_block(p, &f->body, PARSE_BLOCK_DONT_CREATE_IDENTS))
+ success = false;
+ ret:
f->body.flags |= BLOCK_IS_FN;
- return ret;
+ p->block = prev_block;
+ return success;
}
static void fprint_expr(FILE *out, Expression *e);
@@ -1070,7 +1082,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
e->kind = EXPR_NMS;
++t->token;
- if (!parse_block(p, &n->body))
+ if (!parse_block(p, &n->body, 0))
return false;
goto success;
}
@@ -1087,7 +1099,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
}
i->cond = parser_new_expr(p);
if (!parse_expr(p, i->cond, cond_end)) return false;
- if (!parse_block(p, &i->body)) return false;
+ if (!parse_block(p, &i->body, 0)) return false;
IfExpr *curr = i;
while (1) {
bool is_else = token_is_kw(t->token, KW_ELSE);
@@ -1110,7 +1122,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
if (is_else) {
++t->token;
nexti->cond = NULL;
- if (!parse_block(p, &nexti->body)) return false;
+ if (!parse_block(p, &nexti->body, 0)) return false;
} else {
/* elif */
++t->token;
@@ -1125,7 +1137,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
if (!parse_expr(p, cond, cond_end))
return false;
nexti->cond = cond;
- if (!parse_block(p, &nexti->body)) return false;
+ if (!parse_block(p, &nexti->body, 0)) return false;
}
next->where.end = t->token;
curr = nexti;
@@ -1153,7 +1165,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
if (!parse_expr(p, cond, cond_end))
return false;
}
- if (!parse_block(p, &w->body)) return false;
+ if (!parse_block(p, &w->body, 0)) return false;
goto success;
}
case KW_FOR: {
@@ -1162,6 +1174,9 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
fo->flags = 0;
fo->value = NULL;
fo->index = NULL;
+ Block *prev_block = p->block;
+ p->block = &fo->body;
+ idents_create(&p->block->idents, p->allocr, p->block);
++t->token;
if (token_is_kw(t->token, KW_COLON)
|| (t->token->kind == TOKEN_IDENT
@@ -1171,6 +1186,8 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
&& token_is_kw(t->token + 3, KW_COLON))))) {
if (t->token->kind == TOKEN_IDENT) {
fo->value = parser_ident_insert(p, t->token->ident);
+ fo->value->decl_kind = IDECL_EXPR;
+ fo->value->expr = e;
if (ident_eq_str(fo->value, "_")) /* ignore value */
fo->value = NULL;
++t->token;
@@ -1178,39 +1195,41 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
++t->token;
if (t->token->kind == TOKEN_IDENT) {
fo->index = parser_ident_insert(p, t->token->ident);
+ fo->index->decl_kind = IDECL_EXPR;
+ fo->index->expr = e;
if (ident_eq_str(fo->index, "_")) /* ignore index */
fo->index = NULL;
++t->token;
} else {
tokr_err(t, "Expected identifier after , in for loop.");
- return false;
+ goto for_fail;
}
}
}
if (!token_is_kw(t->token, KW_COLON)) {
tokr_err(t, "Expected : following identifiers in for loop.");
- return false;
+ goto for_fail;
}
++t->token;
if (token_is_kw(t->token, KW_COLON)) {
tokr_err(t, "The variable(s) in a for loop cannot be constant.");
- return false;
+ goto for_fail;
}
if (!token_is_kw(t->token, KW_EQ)) {
fo->flags |= FOR_ANNOTATED_TYPE;
if (!parse_type(p, &fo->type))
- return false;
+ goto for_fail;
if (!token_is_kw(t->token, KW_EQ)) {
tokr_err(t, "Expected = in for statement.");
- return false;
+ goto for_fail;
}
}
++t->token;
}
- Token *first_end = expr_find_end(p, EXPR_CAN_END_WITH_COMMA|EXPR_CAN_END_WITH_DOTDOT|EXPR_CAN_END_WITH_LBRACE);
- Expression *first = parser_new_expr(p);
+ Token *first_end; first_end = expr_find_end(p, EXPR_CAN_END_WITH_COMMA|EXPR_CAN_END_WITH_DOTDOT|EXPR_CAN_END_WITH_LBRACE);
+ Expression *first; first = parser_new_expr(p);
if (!parse_expr(p, first, first_end))
- return false;
+ goto for_fail;
if (token_is_kw(first_end, KW_LBRACE)) {
fo->of = first;
} else if (token_is_kw(first_end, KW_DOTDOT) || token_is_kw(first_end, KW_COMMA)) {
@@ -1222,10 +1241,10 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
fo->range.step = parser_new_expr(p);
Token *step_end = expr_find_end(p, EXPR_CAN_END_WITH_LBRACE|EXPR_CAN_END_WITH_DOTDOT);
if (!parse_expr(p, fo->range.step, step_end))
- return false;
+ goto for_fail;
if (!token_is_kw(step_end, KW_DOTDOT)) {
err_print(token_location(p->file, step_end), "Expected .. to follow step in for statement.");
- return false;
+ goto for_fail;
}
} else {
fo->range.step = NULL;
@@ -1237,20 +1256,24 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
fo->range.to = parser_new_expr(p);
Token *to_end = expr_find_end(p, EXPR_CAN_END_WITH_LBRACE);
if (!parse_expr(p, fo->range.to, to_end))
- return false;
+ goto for_fail;
if (!token_is_kw(t->token, KW_LBRACE)) {
tokr_err(t, "Expected { to open body of for statement.");
- return false;
+ goto for_fail;
}
}
} else {
err_print(token_location(p->file, first_end), "Expected { or .. to follow expression in for statement.");
- return false;
+ goto for_fail;
}
- if (!parse_block(p, &fo->body))
- return false;
+ if (!parse_block(p, &fo->body, PARSE_BLOCK_DONT_CREATE_IDENTS))
+ goto for_fail;
+ p->block = prev_block;
goto success;
+ for_fail:
+ p->block = prev_block;
+ return false;
}
default: break;
}
@@ -1770,7 +1793,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
if (token_is_kw(t->token, KW_LBRACE)) {
/* it's a block */
e->kind = EXPR_BLOCK;
- if (!parse_block(p, &e->block)) return false;
+ if (!parse_block(p, &e->block, 0)) return false;
if (t->token != end) {
tokr_err(t, "Expression continues after end of block."); /* TODO: improve this err message */
return false;
@@ -2167,6 +2190,11 @@ static void fprint_block(FILE *out, Block *b) {
}
+static void print_block(Block *b) {
+ fprint_block(stdout, b);
+ printf("\n");
+}
+
static void fprint_fn_expr(FILE *out, FnExpr *f) {
fprintf(out, "fn (");
arr_foreach(f->params, Declaration, decl) {
diff --git a/test.toc b/test.toc
index fa9a336..bffe02a 100644
--- a/test.toc
+++ b/test.toc
@@ -1,27 +1,10 @@
-/*
-io ::= nms {
- #include "std/io.toc";
+// it would be nice if Arr.data.len == Arr.len (: but this will require some C code...
+Arr ::= fn (t :: Type) Type {
+ struct {
+ data : t;
+ }
};
-n ::= nms {
- x := 1;
- counter ::= fn() int { x += 1; x };
-};
-
-
main ::= fn() {
- a := n.counter();
- b := n.counter();
- n.counter();
- c := n.counter();
- io.puti(a);
- io.puti(b);
- io.puti(c);
+ arr : Arr(int);
};
-*/
-
-x := 5;
-main ::= fn() {
-
- x;
-}; \ No newline at end of file
diff --git a/types.c b/types.c
index b89eb9c..49023fe 100644
--- a/types.c
+++ b/types.c
@@ -374,7 +374,8 @@ static bool type_of_ident(Typer *tr, Location where, Identifier *ident, Type *t)
long nblocks = (long)arr_len(tr->blocks);
long idx;
for (idx = nblocks - 1; idx >= 0; --idx) {
- Identifier translated = ident_translate(i, &tr->blocks[idx]->idents);
+ Block *b = tr->blocks[idx];
+ Identifier translated = ident_translate(i, b ? &b->idents : tr->globals);
if (!translated) continue;
if (translated->decl_kind != IDECL_NONE) {
i = *ident = translated;
@@ -2184,6 +2185,7 @@ static bool types_expr(Typer *tr, Expression *e) {
static bool types_block(Typer *tr, Block *b) {
*(Block **)arr_add(&tr->blocks) = b;
+ tr->block = b;
if (b->flags & BLOCK_FOUND_TYPES)
return true;
@@ -2219,6 +2221,7 @@ static bool types_block(Typer *tr, Block *b) {
}
ret:
+ tr->block = *(Block **)arr_last(tr->blocks);
arr_remove_last(&tr->blocks);
b->flags |= BLOCK_FOUND_TYPES;
return success;