summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c1
-rw-r--r--copy.c2
-rw-r--r--eval.c2
-rw-r--r--parse.c9
-rw-r--r--std/arr.toc43
-rw-r--r--test.toc31
-rw-r--r--tests/misc.toc46
-rw-r--r--types.c28
-rw-r--r--types.h1
9 files changed, 107 insertions, 56 deletions
diff --git a/cgen.c b/cgen.c
index 36fdddd..0897a52 100644
--- a/cgen.c
+++ b/cgen.c
@@ -1219,6 +1219,7 @@ static void cgen_expr(CGenerator *g, Expression *e) {
Value fn_val = *decl_val_at_index(d, index);
FnExpr *fn = fn_val.fn;
Expression fn_expr;
+ /* TODO: is this all really necessary? */
fn_expr.kind = EXPR_FN;
fn_expr.fn = allocr_malloc(g->allocr, sizeof *fn_expr.fn);
diff --git a/copy.c b/copy.c
index b821750..ccbb4cb 100644
--- a/copy.c
+++ b/copy.c
@@ -420,9 +420,9 @@ static void copy_stmt(Copier *c, Statement *out, Statement *in) {
static void copy_block(Copier *c, Block *out, Block *in, U8 flags) {
assert(!(in->flags & BLOCK_FINDING_TYPES));
-
Identifiers out_idents = out->idents;
*out = *in;
+ out->parent = c->block;
if (flags & COPY_BLOCK_DONT_CREATE_IDENTS)
out->idents = out_idents; /* reset Identifiers */
size_t nstmts = arr_len(in->stmts);
diff --git a/eval.c b/eval.c
index 7d90c5f..f156bb3 100644
--- a/eval.c
+++ b/eval.c
@@ -645,6 +645,8 @@ static Value *ident_val(Identifier i) {
return valp;
} else {
/* struct parameter */
+ printf("--%p\n",decl);
+ assert(decl->flags & DECL_FOUND_VAL);
if (arr_len(decl->idents) > 1)
return &decl->val.tuple[idx];
else
diff --git a/parse.c b/parse.c
index 6a0ab41..d9af50e 100644
--- a/parse.c
+++ b/parse.c
@@ -612,6 +612,7 @@ static Status parse_type(Parser *p, Type *type, Location *where) {
memset(&struc->scope, 0, sizeof struc->scope);
idents_create(&struc->scope.idents, p->allocr, &struc->scope);
memset(&struc->instances, 0, sizeof struc->instances);
+ struc->scope.parent = p->block;
Block *prev_block = p->block;
p->block = &struc->scope;
@@ -852,6 +853,8 @@ static Status parse_block(Parser *p, Block *b, U8 flags) {
Block *prev_block = p->block;
b->flags = 0;
b->ret_expr = NULL;
+ assert(p->block != b);
+ b->parent = p->block;
p->block = b;
if (!(flags & PARSE_BLOCK_DONT_CREATE_IDENTS))
idents_create(&b->idents, p->allocr, p->block);
@@ -952,6 +955,7 @@ static Status parse_fn_expr(Parser *p, FnExpr *f) {
bool success = true;
Block *prev_block = p->block;
/* enter block so that parameters' scope will be the function body */
+ f->body.parent = p->block;
p->block = &f->body;
idents_create(&f->body.idents, p->allocr, &f->body);
if (token_is_kw(t->token, KW_RPAREN)) {
@@ -996,6 +1000,7 @@ static Status parse_fn_expr(Parser *p, FnExpr *f) {
goto ret;
}
}
+ p->block = prev_block; /* be nice to parse_block */
if (!parse_block(p, &f->body, PARSE_BLOCK_DONT_CREATE_IDENTS))
success = false;
ret:
@@ -1426,6 +1431,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
fo->value = NULL;
fo->index = NULL;
Block *prev_block = p->block;
+ fo->body.parent = p->block;
p->block = &fo->body;
idents_create(&p->block->idents, p->allocr, p->block);
++t->token;
@@ -1522,9 +1528,9 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
goto for_fail;
}
e->where.end = t->token; /* temporarily set end so that redeclaration errors aren't messed up */
+ p->block = prev_block;
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;
@@ -2445,6 +2451,7 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
Block *body = &e->nms->body;
body->flags |= BLOCK_IS_NMS;
body->where = s->where;
+ body->parent = p->block;
idents_create(&body->idents, p->allocr, body);
Statement *inc_stmt = parser_arr_add(p, &body->stmts);
inc_stmt->kind = STMT_INCLUDE;
diff --git a/std/arr.toc b/std/arr.toc
index 24fdf9f..779de48 100644
--- a/std/arr.toc
+++ b/std/arr.toc
@@ -1,20 +1,29 @@
-Arr ::= fn (t :: Type) Type {
- struct {
- data : []t;
- cap : int;
+// this could be made quite a bit faster with realloc
+
+Arr ::= struct (t :: Type) {
+ data : []t;
+ cap : int;
+};
+
+resv ::= fn(t ::=, a : &Arr(t), n: int) {
+ if a.cap >= n {
+ return;
+ }
+ new_data := new(t, a.cap);
+ new_data.len = a.data.len;
+ for x, i := &new_data {
+ *x = a.data[i];
}
+ a.data = new_data;
+ a.cap = n;
};
-arr_add ::= fn(t ::=, a : &Arr(t), x : t) {
- if a.data.len >= a.cap {
- a.cap = a.cap * 2 + 2;
- new_data := new(t, a.cap);
- new_data.len = a.data.len;
- for i := 0..a.data.len-1 {
- new_data[i] = a.data[i];
- }
- a.data = new_data;
- }
- a.data.len += 1;
- a.data[a.data.len-1] = x;
+
+add ::= fn(t ::=, a : &Arr(t), x : t) {
+ if a.data.len >= a.cap {
+ resv(&a, a.cap * 2 + 2);
+ }
+ a.data.len += 1;
+ a.data[a.data.len-1] = x;
};
-arr_len ::= fn(t ::=, a : Arr(t)) int { a.data.len };
+
+len ::= fn(t ::=, a : Arr(t)) int { a.data.len };
diff --git a/test.toc b/test.toc
index b4f3632..2eb2814 100644
--- a/test.toc
+++ b/test.toc
@@ -1,17 +1,34 @@
-arr_sum ::= fn(n::=, t::=, a:[n]t) t {
+/*
+#include "std/io.toc", io;
+#include "std/arr.toc", arr;
+
+arr_sum ::= fn(n::=, t::=, a:arr.Arr(t)) t {
total := 0 as t;
- for x := a {
+ for x := a.data {
total += x;
}
total
};
-mk_arr ::= fn(x:int, y:int, z:int) a:[3]int {
- a[0] = x;
- a[1] = y;
- a[2] = z;
+mk_arr ::= fn(x:int, y:int, z:int) a:arr.Arr(int) {
+ arr.add(&a, x);
+ arr.add(&a, y);
+ arr.add(&a, z);
+};
+
+main ::= fn() {
+ a := mk_arr(1,2,3);
+ io.puti(arr.len(a));
+ io.puti(arr_sum(a));
+};
+*/
+
+foo ::= fn(x::int) Type {
+ struct {
+ a: [x]int;
+ }
};
main ::= fn() {
- arr_sum(mk_arr(1,2,3));
+ f: foo(5);
}; \ No newline at end of file
diff --git a/tests/misc.toc b/tests/misc.toc
index d66972f..a9f6dc1 100644
--- a/tests/misc.toc
+++ b/tests/misc.toc
@@ -1,27 +1,29 @@
#include "io.toc", io;
-arr_sum ::= fn(n::=, t::=, a:[n]t) t {
- total := 0 as t;
- for x := a {
- total += x;
+main ::= fn() {
+ x ::= 3;
+ #if x > 2 {
+ io.puts("Hello!");
+ } else {
+ foo("yes");
}
- total
-};
-mk_arr ::= fn(x:int, y:int, z:int) a:[3]int {
- a[0] = x;
- a[1] = y;
- a[2] = z;
-};
+ io.puti(arr_sum(mk_arr(5,89,22)));
+ io.puti(arr_sum(mk_arr(1,2,3)));
+ io.puti(arr_sum(mk_arr(z=0, 0, 0)));
+
+ arr_sum ::= fn(n::=, t::=, a:[n]t) t {
+ total := 0 as t;
+ for x := a {
+ total += x;
+ }
+ total
+ };
-main ::= fn() {
- x ::= 3;
- #if x > 2 {
- io.puts("Hello!");
- } else {
- foo("yes");
- }
- io.puti(arr_sum(mk_arr(5,89,22)));
- io.puti(arr_sum(mk_arr(1,2,3)));
- io.puti(arr_sum(mk_arr(z=0, 0, 0)));
-}; \ No newline at end of file
+ mk_arr ::= fn(x:int, y:int, z:int) a:[3]int {
+ a[0] = x;
+ a[1] = y;
+ a[2] = z;
+ };
+
+};
diff --git a/types.c b/types.c
index 74c11ff..0fd160a 100644
--- a/types.c
+++ b/types.c
@@ -567,14 +567,12 @@ static Status type_of_ident(Typer *tr, Location where, Identifier *ident, Type *
#endif
#endif
if (i->decl_kind == IDECL_NONE) {
- long nblocks = (long)arr_len(tr->blocks);
- long idx;
- for (idx = nblocks - 1; idx >= 0; --idx) {
- Block *b = tr->blocks[idx];
+ Block *b = tr->block;
+ bool undeclared = false;
+ while (1) {
/* OPTIM: only hash once */
- Identifier translated = ident_translate(i, b ? &b->idents : tr->globals);
- if (!translated) continue;
- if (translated->decl_kind != IDECL_NONE) {
+ Identifier translated = ident_translate(i, b ? &b->idents : tr->globals);
+ if (translated && translated->decl_kind != IDECL_NONE) {
/* printf("translated %s from\n", ident_to_str(i)); */
/* print_block_location(i->idents->scope); */
/* printf(" to \n"); */
@@ -583,8 +581,14 @@ static Status type_of_ident(Typer *tr, Location where, Identifier *ident, Type *
i = *ident = translated;
break;
}
+ if (b) {
+ b = b->parent;
+ } else {
+ undeclared = true;
+ break;
+ }
}
- if (idx == -1) {
+ if (undeclared) {
char *s = ident_to_str(i);
err_print(where, "Undeclared identifier: %s", s);
free(s);
@@ -1649,6 +1653,7 @@ static Status types_expr(Typer *tr, Expression *e) {
e->kind = EXPR_BLOCK;
e->block = typer_calloc(tr, 1, sizeof *e->block);
e->block->where = e->where;
+ e->block->parent = tr->block;
idents_create(&e->block->idents, tr->allocr, e->block);
}
goto expr_block;
@@ -1858,7 +1863,10 @@ static Status types_expr(Typer *tr, Expression *e) {
struct_t.kind = TYPE_STRUCT;
struct_t.struc = &inst->struc;
*(Location *)arr_add(&err_ctx->instance_stack) = e->where;
+ Block *prev_block = tr->block;
+ tr->block = &inst->struc.scope;
bool success = type_resolve(tr, &struct_t, e->where); /* resolve the struct */
+ tr->block = prev_block;
arr_remove_last(&err_ctx->instance_stack);
if (!success) return false;
@@ -2062,6 +2070,7 @@ static Status types_expr(Typer *tr, Expression *e) {
arg_exprs[i].flags = EXPR_FOUND_TYPE;
arg_exprs[i].val = val_copy;
param_decl->flags |= DECL_FOUND_VAL;
+ printf("%p\n",param_decl);
copy_val(tr->allocr, &param_decl->val, &val_copy, type);
if (!(param_decl->flags & DECL_ANNOTATES_TYPE)) {
param_decl->type = *type;
@@ -2156,7 +2165,10 @@ static Status types_expr(Typer *tr, Expression *e) {
/* if anything happens, make sure we let the user know that this happened while generating a fn */
ErrCtx *err_ctx = e->where.file->ctx;
*(Location *)typer_arr_add(tr, &err_ctx->instance_stack) = e->where;
+ Block *prev_block = tr->block;
+ tr->block = fn_copy->body.parent;
bool success = types_fn(tr, c->instance->fn, &f->type, c->instance);
+ tr->block = prev_block;
arr_remove_lasta(&err_ctx->instance_stack, tr->allocr);
if (!success) return false;
arr_cleara(&table_index_type.tuple, tr->allocr);
diff --git a/types.h b/types.h
index 8d27695..2ac43ec 100644
--- a/types.h
+++ b/types.h
@@ -490,6 +490,7 @@ typedef struct Block {
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;
} Block;
enum {