summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-10-25 09:57:28 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2019-10-25 09:57:52 -0400
commit7352f2c357619e23ed348bdadd48f38f9acd4d86 (patch)
tree39ac2440fb5d58866bc1ac9e57ff58424c235640
parente278a73bbe573b45f67794301746b08b8fa5c4b2 (diff)
compile time arrays and slices!
-rw-r--r--cgen.c29
-rw-r--r--eval.c59
-rw-r--r--main.c1
-rw-r--r--scope.c2
-rw-r--r--test.toc45
5 files changed, 87 insertions, 49 deletions
diff --git a/cgen.c b/cgen.c
index f8e35ff..ab2f370 100644
--- a/cgen.c
+++ b/cgen.c
@@ -1043,7 +1043,7 @@ static bool cgen_val_ptr_pre(CGenerator *g, void *v, Type *t, Location where) {
return false;
}
if (!cgen_type_pre(g, t->slice, where)) return false;
- cgen_write(g, "(d%p_[])", where.code); /* TODO: improve this somehow? */
+ cgen_write(g, "(d%p_[])", v); /* TODO: improve this somehow? */
if (!cgen_type_post(g, t->slice, where)) return false;
cgen_write(g, " = {");
for (U64 i = 0; i < s->n; i++) {
@@ -1051,11 +1051,12 @@ static bool cgen_val_ptr_pre(CGenerator *g, void *v, Type *t, Location where) {
if (!cgen_val_ptr(g, (char *)s->data + i * compiler_sizeof(t->slice), t->slice, where))
return false;
}
- cgen_write(g, "}");
+ cgen_write(g, "};");
+ cgen_nl(g);
} break;
case TYPE_ARR:
for (size_t i = 0; i < t->arr.n; i++) {
- if (!cgen_val_ptr_pre(g, (char *)v + i * compiler_sizeof(t->arr.of), t->arr.of, where))
+ if (!cgen_val_ptr_pre(g, (char *)*(void **)v + i * compiler_sizeof(t->arr.of), t->arr.of, where))
return false;
}
break;
@@ -1083,13 +1084,13 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) {
cgen_write(g, "{");
for (size_t i = 0; i < t->arr.n; i++) {
if (i) cgen_write(g, ", ");
- if (!cgen_val_ptr(g, (char *)v + i * compiler_sizeof(t->arr.of), t->arr.of, where))
+ if (!cgen_val_ptr(g, *(char **)v + i * compiler_sizeof(t->arr.of), t->arr.of, where))
return false;
}
cgen_write(g, "}");
break;
case TYPE_SLICE:
- cgen_write(g, "{d%p_, %lu}", where.code, ((Slice *)v)->n);
+ cgen_write(g, "{d%p_, %lu}", v, ((Slice *)v)->n);
break;
case TYPE_FN:
cgen_fn_name(g, *(FnExpr **)v);
@@ -1117,6 +1118,10 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) {
return true;
}
+static bool cgen_val_pre(CGenerator *g, Value *v, Type *t, Location where) {
+ return cgen_val_ptr_pre(g, v, t, where);
+}
+
/* generates a value fit for use as an initializer */
static bool cgen_val(CGenerator *g, Value *v, Type *t, Location where) {
/*
@@ -1126,6 +1131,7 @@ static bool cgen_val(CGenerator *g, Value *v, Type *t, Location where) {
return cgen_val_ptr(g, v, t, where);
}
+
static bool cgen_decl(CGenerator *g, Declaration *d) {
if (cgen_fn_is_direct(g, d)) {
if (!cgen_fn(g, &d->expr.fn, d->where))
@@ -1134,6 +1140,8 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
if (d->type.kind == TYPE_TUPLE) {
long idx = 0;
arr_foreach(d->idents, Identifier, i) {
+ if (!cgen_val_pre(g, &d->val.tuple[idx], &d->type.tuple[idx], d->where))
+ return false;
if (!cgen_type_pre(g, &d->type.tuple[idx], d->where)) return false;
cgen_write(g, " ");
cgen_ident(g, *i);
@@ -1142,20 +1150,17 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
if (!cgen_val(g, &d->val.tuple[idx], &d->type.tuple[idx], d->where))
return false;
idx++;
+ cgen_write(g, ";");
+ cgen_nl(g);
}
- cgen_write(g, ";");
- cgen_nl(g);
} else {
+ if (!cgen_val_pre(g, &d->val, &d->type, d->where))
+ return false;
if (!cgen_type_pre(g, &d->type, d->where)) return false;
cgen_write(g, " ");
cgen_ident(g, d->idents[0]);
if (!cgen_type_post(g, &d->type, d->where)) return false;
cgen_write(g, " = ");
- if (d->type.kind == TYPE_ARR) {
- I64 *nums = d->val.arr;
- printf("%ld\n",nums[0]);
- }
- return true;
if (!cgen_val(g, &d->val, &d->type, d->where))
return false;
cgen_write(g, ";");
diff --git a/eval.c b/eval.c
index 4c0402b..564d409 100644
--- a/eval.c
+++ b/eval.c
@@ -1,4 +1,4 @@
-static bool eval_block(Evaluator *ev, Block *b, Value *v);
+static bool eval_block(Evaluator *ev, Block *b, Type *t, Value *v);
static bool eval_expr(Evaluator *ev, Expression *e, Value *v);
static bool block_enter(Block *b, Statement *stmts, U32 flags);
static void block_exit(Block *b, Statement *stmts);
@@ -41,15 +41,15 @@ static size_t compiler_sizeof(Type *t) {
case TYPE_BUILTIN:
return compiler_sizeof_builtin(t->builtin);
case TYPE_FN:
- return sizeof t->fn;
+ return sizeof(FnExpr *);
case TYPE_PTR:
- return sizeof t->ptr;
+ return sizeof(void *);
case TYPE_ARR:
return t->arr.n * compiler_sizeof(t->arr.of);
case TYPE_TUPLE:
- return sizeof t->tuple;
+ return sizeof(Value *);
case TYPE_SLICE:
- return sizeof t->slice;
+ return sizeof(Slice);
case TYPE_VOID:
case TYPE_UNKNOWN:
return 0;
@@ -141,6 +141,29 @@ static void u64_to_val(Value *v, BuiltinType v_type, U64 x) {
i64_to_val(v, v_type, (I64)x);
}
+static void val_copy(Value *dest, Value *src, Type *t) {
+ switch (t->kind) {
+ case TYPE_BUILTIN:
+ case TYPE_FN:
+ case TYPE_PTR:
+ case TYPE_SLICE:
+ case TYPE_VOID:
+ case TYPE_UNKNOWN:
+ *dest = *src;
+ break;
+ case TYPE_ARR: {
+ size_t bytes = t->arr.n * compiler_sizeof(t->arr.of);
+ dest->arr = err_malloc(bytes);
+ memcpy(dest->arr, src->arr, bytes);
+ } break;
+ case TYPE_TUPLE: {
+ size_t bytes = arr_len(t->tuple) * sizeof(*dest->tuple);
+ dest->tuple = malloc(bytes);
+ memcpy(dest->tuple, src->tuple, bytes);
+ } break;
+ }
+}
+
#define builtin_casts_to_int(x) \
case BUILTIN_I8: \
vout->i8 = (I8)vin->x; break; \
@@ -477,8 +500,10 @@ static bool eval_set(Evaluator *ev, Expression *set, Value *to) {
case BINARY_AT_INDEX: {
void *ptr;
Type *type;
+ /* get pointer to x[i] */
if (!eval_expr_ptr_at_index(ev, set, &ptr, &type))
return false;
+ /* set it to to */
eval_deref_set(ptr, to, type);
} break;
default: break;
@@ -723,12 +748,12 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
Value cond;
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, &e->type, v)) return false;
} else if (i->next_elif) {
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, &e->type, v)) return false;
}
} break;
case EXPR_WHILE: {
@@ -740,11 +765,11 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
if (!val_truthiness(&cond, &w->cond->type))
break;
}
- if (!eval_block(ev, &w->body, v)) return false;
+ if (!eval_block(ev, &w->body, &e->type, v)) return false;
}
} break;
case EXPR_BLOCK:
- if (!eval_block(ev, &e->block, v)) return false;
+ if (!eval_block(ev, &e->block, &e->type, v)) return false;
break;
case EXPR_LITERAL_BOOL:
v->boolv = e->booll;
@@ -850,7 +875,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
}
}
arr_clear(&args);
- if (!eval_block(ev, &fn->body, v)) {
+ if (!eval_block(ev, &fn->body, &e->type, v)) {
fn_exit(fn);
return false;
}
@@ -921,12 +946,13 @@ static bool eval_decl(Evaluator *ev, Declaration *d) {
arr_foreach(d->idents, Identifier, i) {
IdentDecl *id = ident_decl(*i);
if (has_expr && d->expr.kind == EXPR_TUPLE) {
- id->val = val.tuple[index++];
+ val_copy(&id->val, &val.tuple[index], &d->type.tuple[index]);
+ index++;
} else if (!has_expr && d->type.kind == TYPE_ARR) {
/* "stack" array */
id->val.arr = err_calloc(d->type.arr.n, compiler_sizeof(d->type.arr.of));
} else {
- id->val = val;
+ val_copy(&id->val, &val, &d->type);
}
id->flags |= IDECL_FLAG_HAS_VAL;
}
@@ -952,17 +978,22 @@ static bool eval_stmt(Evaluator *ev, Statement *stmt) {
return true;
}
-static bool eval_block(Evaluator *ev, Block *b, Value *v) {
+/* t is the type of the block. */
+static bool eval_block(Evaluator *ev, Block *b, Type *t, Value *v) {
block_enter(b, b->stmts, 0);
arr_foreach(b->stmts, Statement, stmt) {
if (!eval_stmt(ev, stmt))
return false;
if (ev->returning) break;
}
+ Value *returning = ev->returning;
+ Value r;
if (!ev->returning && b->ret_expr) {
- if (!eval_expr(ev, b->ret_expr, v))
+ returning = &r;
+ if (!eval_expr(ev, b->ret_expr, returning))
return false;
}
+ if (returning) val_copy(v, returning, t);
block_exit(b, b->stmts);
return true;
diff --git a/main.c b/main.c
index a3321a9..1153983 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,7 @@
/*
TODO:
array/slice values
+fix leaking of constant stack arrays
make sure initializers for global variables are compile-time constants
structs
length of slice/arr with .len
diff --git a/scope.c b/scope.c
index 5afee76..e715cc3 100644
--- a/scope.c
+++ b/scope.c
@@ -26,6 +26,8 @@ static void remove_ident_decls(Block *b, Declaration *d) {
IdentDecl *last_decl = arr_last(*decls);
if (last_decl && last_decl->scope == b) {
if ((last_decl->flags & IDECL_FLAG_HAS_VAL)
+ /* don't free const arrays (there's only one per decl) */
+ && !(last_decl->decl->flags & DECL_FLAG_CONST)
&& last_decl->decl->type.kind == TYPE_ARR) {
/* free array on stack */
free(last_decl->val.arr);
diff --git a/test.toc b/test.toc
index a1b29af..15d782a 100644
--- a/test.toc
+++ b/test.toc
@@ -13,32 +13,31 @@ putf @= fn(x: float) {
");
};
-ptriple @= fn(m: int, n: int) (int, int, int) {
- m*m-n*n, 2*m*n, m*m+n*n
-};
-
-f @= fn() int {
- a, b, c : int;
- a, b, c = ptriple(3, 2);
- a + b + c
-};
-aSDF @= fn() [3]int {
- x: [3]int;
- x[0] = 1;
- x[1] = 2;
- x[2] = 3;
+N @= 50;
+pascal @= fn() [N][]int {
+ x: [N][]int;
+ i := 0;
+ while i < N {
+ x[i] = new(int, i+1);
+ i = i + 1;
+ }
+ i = 0;
+ while i < N {
+ x[i][0] = 1;
+ x[i][i] = 1;
+ j := 1;
+ while j < i {
+ x[i][j] = x[i-1][j-1] + x[i-1][j];
+ j = j + 1;
+ }
+ i = i + 1;
+ }
x
};
main @= fn() {
- puti(f());
- A : [f()]int;
- x @= f();
- dsafsad @= ptriple;
- foo @= aSDF();
- puti(foo[0]);
- puti(foo[1]);
- puti(foo[2]);
- // B : [aSDF()[0]]int;
+ ptriangle @= pascal();
+ puti(ptriangle[49][25]);
+
};