summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-04-25 17:43:13 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-04-25 17:43:13 -0400
commit1cceedc5ca053b018bc98e96a7dd77d17dde1ada (patch)
tree8295bb9dce0f70e533e8a98bc978490b6c2fa742
parenta161b75a01eee7249f989c3a85d92b69c1818370 (diff)
consistently handling indexing pointer to array/slice
-rw-r--r--cgen.c9
-rw-r--r--eval.c40
-rw-r--r--main.c2
-rw-r--r--test.toc30
-rw-r--r--tests/arrs_slices.toc47
-rw-r--r--tests/arrs_slices_expected2
-rwxr-xr-xtests/test.sh1
-rw-r--r--types.c2
8 files changed, 95 insertions, 38 deletions
diff --git a/cgen.c b/cgen.c
index 56ceb20..c6e5c6f 100644
--- a/cgen.c
+++ b/cgen.c
@@ -1321,10 +1321,17 @@ static void cgen_expr(CGenerator *g, Expression *e) {
s = "%="; break;
case BINARY_AT_INDEX: {
Type *lhs_type = &lhs->type;
+ bool uses_ptr = false;
+ if (lhs_type->kind == TYPE_PTR) {
+ uses_ptr = true;
+ lhs_type = lhs_type->ptr;
+ }
cgen_write(g, "(");
switch (lhs_type->kind) {
case TYPE_ARR:
+ if (uses_ptr) cgen_write(g, "(*");
cgen_expr(g, lhs);
+ if (uses_ptr) cgen_write(g, ")");
cgen_write(g, "[");
cgen_expr(g, rhs);
cgen_write(g, "]");
@@ -1336,7 +1343,7 @@ static void cgen_expr(CGenerator *g, Expression *e) {
cgen_type_post(g, &e->type);
cgen_write(g, ")(");
cgen_expr(g, lhs);
- cgen_write(g, ".data))[");
+ cgen_write(g, "%sdata))[", uses_ptr ? "->" : ".");
cgen_expr(g, rhs);
cgen_write(g, "]");
break;
diff --git a/eval.c b/eval.c
index 9a65ff9..0ade240 100644
--- a/eval.c
+++ b/eval.c
@@ -596,6 +596,13 @@ static void eval_deref_set(void *set, Value *to, Type *type) {
}
static Status eval_val_ptr_at_index(Location where, Value *arr, U64 i, Type *arr_type, void **ptr, Type **type) {
+ void *arr_ptr = NULL;
+ if (arr_type->kind == TYPE_PTR) {
+ arr_ptr = arr->ptr;
+ arr_type = arr_type->ptr;
+ } else {
+ arr_ptr = val_get_ptr(arr, arr_type);
+ }
switch (arr_type->kind) {
case TYPE_ARR: {
U64 arr_sz = (U64)arr_type->arr.n;
@@ -603,33 +610,36 @@ static Status eval_val_ptr_at_index(Location where, Value *arr, U64 i, Type *arr
err_print(where, "Array out of bounds (index = %lu, array size = %lu)\n", (unsigned long)i, (unsigned long)arr_sz);
return false;
}
- *ptr = (char *)arr->arr + compiler_sizeof(arr_type->arr.of) * i;
+ *ptr = (char *)arr_ptr + compiler_sizeof(arr_type->arr.of) * i;
if (type) *type = arr_type->arr.of;
} break;
case TYPE_SLICE: {
- U64 slice_sz = (U64)arr->slice.len;
+ Slice slice = *(Slice *)arr_ptr;
+ U64 slice_sz = (U64)slice.len;
if (i >= slice_sz) {
err_print(where, "Slice out of bounds (index = %lu, slice size = %lu)\n", (unsigned long)i, (unsigned long)slice_sz);
return false;
}
- if (!arr->slice.data) {
+ if (!slice.data) {
err_print(where, "Indexing null slice.");
return false;
}
- *ptr = (char *)arr->slice.data + compiler_sizeof(arr_type->slice) * i;
+ *ptr = (char *)slice.data + compiler_sizeof(arr_type->slice) * i;
if (type) *type = arr_type->slice;
} break;
- case TYPE_BUILTIN:
+ case TYPE_BUILTIN: {
+ VarArg *varargs = *(VarArg **)arr_ptr;
if (arr_type->builtin == BUILTIN_VARARGS) {
- if (i >= (U64)arr_len(arr->varargs)) {
+ if (i >= (U64)arr_len(varargs)) {
err_print(where, "Varargs out of bounds (index = %lu, varargs size = %lu)\n", (unsigned long)i, (unsigned long)arr_len(arr->varargs));
return false;
}
- VarArg *vararg = &arr->varargs[i];
+ VarArg *vararg = &varargs[i];
*ptr = &vararg->val;
*type = vararg->type;
break;
}
+ }
/* fallthrough */
default: assert(0); break;
}
@@ -687,6 +697,7 @@ static Value *ident_val(Evaluator *ev, Identifier i, Location where) {
return &decl->val;
}
} else if (decl->flags & DECL_IS_CONST) {
+ assert(decl->flags & DECL_FOUND_VAL);
return decl_val_at_index(decl, idx);
} else if (decl->val_stack) {
Value *valp = arr_last(decl->val_stack);
@@ -762,9 +773,18 @@ static Status eval_address_of(Evaluator *ev, Expression *e, void **ptr) {
*ptr = v.ptr;
} break;
case UNARY_LEN: {
- Value slice;
- if (!eval_expr(ev, e, &slice)) return false;
- *ptr = &slice.slice.len;
+ Type *of_type = &e->unary.of->type;
+ Slice *slice;
+ Value of_val;
+ if (!eval_expr(ev, e, &of_val)) return false;
+ if (of_type->kind == TYPE_PTR) {
+ assert(of_type->ptr->kind == TYPE_SLICE);
+ slice = of_val.ptr;
+ } else {
+ assert(of_type->kind == TYPE_SLICE);
+ slice = &of_val.slice;
+ }
+ *ptr = &slice->len;
} break;
default: assert(0); return false;
}
diff --git a/main.c b/main.c
index 0ac2443..4fc4bd3 100644
--- a/main.c
+++ b/main.c
@@ -8,8 +8,6 @@
/*
@TODO:
-make sure you can do a[i] where a is &[5]int or &[]char or something
-do we consistently handle x := &some_array_or_slice; x.len
use
- use with struct members (e.g. SuperPoint ::= struct { use p: Point; })
compile to a temp file, then move it if compilation succeeds
diff --git a/test.toc b/test.toc
index 790a115..644f701 100644
--- a/test.toc
+++ b/test.toc
@@ -1,27 +1,9 @@
-#include "std/mem.toc", mem;
-#include "std/io.toc", io;
-
-calculation ::= fn() int {
- total := 0;
- i := mem.new(int);
- *i = 3;
- ns := mem.news(int, 10);
- for n, i := &ns {
- if i % 2 == 0 {
- *n = i;
- }
- }
- for n := ns {
- total += n;
- }
- total += *i;
- mem.del(i);
- mem.dels(ns);
- total
-}
+#include "std/io.toc";
main ::= fn() {
- io.puti(calculation());
- x ::= calculation();
- io.puti(x);
+ x:[]int;
+ p:=&x;
+ p.len = 12;
+ puti(p.len);
}
+main();
diff --git a/tests/arrs_slices.toc b/tests/arrs_slices.toc
new file mode 100644
index 0000000..dc7526d
--- /dev/null
+++ b/tests/arrs_slices.toc
@@ -0,0 +1,47 @@
+#include "std/mem.toc", mem;
+#include "std/io.toc", io;
+use mem;
+
+fill_array ::= fn(n ::=, a : &[n]int) {
+ for i := 0..n-1 {
+ a[i] = i*i;
+ }
+ a[0] = 17;
+}
+
+sum_array ::= fn(n ::=, a : &[n]int) total := 0 {
+ for i := 0..n-1 {
+ total += a[i];
+ }
+}
+
+fill_slice ::= fn(a: &[]int) {
+ *a = mem.news(int, 3);
+ a[0] = 1;
+ a[1] = 48;
+ a[2] = 136;
+}
+
+sum_slice ::= fn(a : &[]int) total := 0 {
+ for i := 0..a.len-1 {
+ total += a[i];
+ }
+}
+
+thing ::= fn() int {
+ foo : [5]int;
+ fill_array(&foo);
+ a := sum_array(&foo);
+ bar : []int;
+ defer dels(bar);
+ fill_slice(&bar);
+ b := sum_slice(&bar);
+ a+b
+}
+
+main ::= fn() {
+ a := thing();
+ b ::= thing();
+ io.puti(a);
+ io.puti(b);
+}
diff --git a/tests/arrs_slices_expected b/tests/arrs_slices_expected
new file mode 100644
index 0000000..d41c8a7
--- /dev/null
+++ b/tests/arrs_slices_expected
@@ -0,0 +1,2 @@
+232
+232
diff --git a/tests/test.sh b/tests/test.sh
index 1168e5b..75697ef 100755
--- a/tests/test.sh
+++ b/tests/test.sh
@@ -3,6 +3,7 @@
tests='bf
control_flow
types
+arrs_slices
defer
sizeof
new
diff --git a/types.c b/types.c
index e111148..056b800 100644
--- a/types.c
+++ b/types.c
@@ -412,7 +412,7 @@ static Status expr_must_lval(Expression *e, char const *purpose) {
return of_type->kind == TYPE_SLICE
|| (of_type->kind == TYPE_PTR
- && of_type->kind == TYPE_SLICE);
+ && of_type->ptr->kind == TYPE_SLICE);
}
err_print(e->where, "Cannot %s operator %s.", purpose, unary_op_to_str(e->unary.op));
return false;