diff options
-rw-r--r-- | cgen.c | 9 | ||||
-rw-r--r-- | eval.c | 40 | ||||
-rw-r--r-- | main.c | 2 | ||||
-rw-r--r-- | test.toc | 30 | ||||
-rw-r--r-- | tests/arrs_slices.toc | 47 | ||||
-rw-r--r-- | tests/arrs_slices_expected | 2 | ||||
-rwxr-xr-x | tests/test.sh | 1 | ||||
-rw-r--r-- | types.c | 2 |
8 files changed, 95 insertions, 38 deletions
@@ -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; @@ -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; } @@ -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 @@ -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 @@ -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; |