summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-10-24 23:21:19 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2019-10-24 23:21:19 -0400
commite278a73bbe573b45f67794301746b08b8fa5c4b2 (patch)
tree5913c44d58b787c4b70e6f352e9e20c7447335c6
parent737b1c8be8912cce40b1874a657a579e15d531ee (diff)
started getting compile time arrays and slices to work
-rw-r--r--cgen.c94
-rw-r--r--main.c2
-rw-r--r--test.toc15
3 files changed, 91 insertions, 20 deletions
diff --git a/cgen.c b/cgen.c
index b5b7ce8..f8e35ff 100644
--- a/cgen.c
+++ b/cgen.c
@@ -9,6 +9,7 @@ static bool cgen_type_pre(CGenerator *g, Type *t, Location where);
static bool cgen_type_post(CGenerator *g, Type *t, Location where);
static bool cgen_decl(CGenerator *g, Declaration *d);
static bool cgen_ret(CGenerator *g, Expression *ret);
+static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where);
static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *ev) {
g->outc = out;
@@ -1033,7 +1034,43 @@ static bool cgen_fn(CGenerator *g, FnExpr *f, Location where) {
return true;
}
-static bool cgen_val(CGenerator *g, Value *v, Type *t, Location where) {
+static bool cgen_val_ptr_pre(CGenerator *g, void *v, Type *t, Location where) {
+ switch (t->kind) {
+ case TYPE_SLICE: {
+ Slice *s = (Slice *)v;
+ for (U64 i = 0; i < s->n; i++) {
+ if (!cgen_val_ptr_pre(g, (char *)s->data + i * compiler_sizeof(t->slice), t->slice, where))
+ return false;
+ }
+ if (!cgen_type_pre(g, t->slice, where)) return false;
+ cgen_write(g, "(d%p_[])", where.code); /* 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++) {
+ if (i) cgen_write(g, ", ");
+ if (!cgen_val_ptr(g, (char *)s->data + i * compiler_sizeof(t->slice), t->slice, where))
+ return false;
+ }
+ cgen_write(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))
+ return false;
+ }
+ break;
+ case TYPE_FN:
+ case TYPE_UNKNOWN:
+ case TYPE_TUPLE:
+ case TYPE_VOID:
+ case TYPE_BUILTIN:
+ case TYPE_PTR:
+ break;
+ }
+ return true;
+}
+
+static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) {
switch (t->kind) {
case TYPE_TUPLE:
case TYPE_VOID:
@@ -1043,38 +1080,52 @@ static bool cgen_val(CGenerator *g, Value *v, Type *t, Location where) {
err_print(where, "Cannot determine type.");
return false;
case TYPE_ARR:
- err_print(where, "Not implemented yet."); /* TODO */
- return false;
+ 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))
+ return false;
+ }
+ cgen_write(g, "}");
+ break;
case TYPE_SLICE:
- err_print(where, "Not implemented yet."); /* TODO (similar to above) */
- return false;
+ cgen_write(g, "{d%p_, %lu}", where.code, ((Slice *)v)->n);
+ break;
case TYPE_FN:
- cgen_ident_id(g, v->fn->c.id);
+ cgen_fn_name(g, *(FnExpr **)v);
break;
case TYPE_PTR:
- /* TODO: maybe just gen the whole expression? */
err_print(where, "Cannot bring compile time pointer to runtime.");
return false;
case TYPE_BUILTIN:
switch (t->builtin) {
- case BUILTIN_I8: cgen_write(g, "%"PRId8, v->i8); break;
- case BUILTIN_U8: cgen_write(g, "%"PRIu8, v->u8); break;
- case BUILTIN_I16: cgen_write(g, "%"PRId16, v->i16); break;
- case BUILTIN_U16: cgen_write(g, "%"PRIu16, v->u16); break;
- case BUILTIN_I32: cgen_write(g, "%"PRId32, v->i32); break;
- case BUILTIN_U32: cgen_write(g, "%"PRIu32, v->u32); break;
- case BUILTIN_I64: cgen_write(g, "%"PRId64, v->i64); break;
- case BUILTIN_U64: cgen_write(g, "%"PRIu64, v->u64); break;
- case BUILTIN_F32: cgen_write(g, F32_FMT, v->f32); break;
- case BUILTIN_F64: cgen_write(g, F64_FMT, v->f64); break;
- case BUILTIN_CHAR: cgen_write(g, "\\x%02x", v->charv); break;
- case BUILTIN_BOOL: cgen_write(g, "%s", v->boolv ? "true" : "false"); break;
+ case BUILTIN_I8: cgen_write(g, "%"PRId8, *(I8 *)v); break;
+ case BUILTIN_U8: cgen_write(g, "%"PRIu8, *(U8 *)v); break;
+ case BUILTIN_I16: cgen_write(g, "%"PRId16, *(I16 *)v); break;
+ case BUILTIN_U16: cgen_write(g, "%"PRIu16, *(U16 *)v); break;
+ case BUILTIN_I32: cgen_write(g, "%"PRId32, *(I32 *)v); break;
+ case BUILTIN_U32: cgen_write(g, "%"PRIu32, *(U32 *)v); break;
+ case BUILTIN_I64: cgen_write(g, "%"PRId64, *(I64 *)v); break;
+ case BUILTIN_U64: cgen_write(g, "%"PRIu64, *(U64 *)v); break;
+ case BUILTIN_F32: cgen_write(g, F32_FMT, *(F32 *)v); break;
+ case BUILTIN_F64: cgen_write(g, F64_FMT, *(F64 *)v); break;
+ case BUILTIN_CHAR: cgen_write(g, "\\x%02x", *(char *)v); break;
+ case BUILTIN_BOOL: cgen_write(g, "%s", *(bool *)v ? "true" : "false"); break;
}
break;
}
return true;
}
+/* generates a value fit for use as an initializer */
+static bool cgen_val(CGenerator *g, Value *v, Type *t, Location where) {
+ /*
+ Because Value is a union, a pointer to v works as a pointer to any member.
+ As a result, this function is only needed for type checking.
+ */
+ 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))
@@ -1100,6 +1151,11 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
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/main.c b/main.c
index 638e72c..a3321a9 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,6 @@
/*
TODO:
-compile time arrays, slices
+array/slice values
make sure initializers for global variables are compile-time constants
structs
length of slice/arr with .len
diff --git a/test.toc b/test.toc
index 87e4e47..a1b29af 100644
--- a/test.toc
+++ b/test.toc
@@ -23,7 +23,22 @@ f @= fn() int {
a + b + c
};
+aSDF @= fn() [3]int {
+ x: [3]int;
+ x[0] = 1;
+ x[1] = 2;
+ x[2] = 3;
+ 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;
};