summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-11-06 11:05:16 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-11-06 11:05:16 -0500
commit15d0f9a50bcd19e4d1efdd3574bc48bc712d4471 (patch)
tree8fb0219247c8758ca426a6453d24ea8388190ffb
parentb3e5b99840d5ead250239565aedeb41443cc1102 (diff)
each by pointer
-rw-r--r--cgen.c47
-rw-r--r--eval.c28
-rw-r--r--main.c3
-rw-r--r--test.toc27
-rw-r--r--types.c27
5 files changed, 86 insertions, 46 deletions
diff --git a/cgen.c b/cgen.c
index 80e82ff..fa1aa3a 100644
--- a/cgen.c
+++ b/cgen.c
@@ -740,6 +740,8 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
cgen_write(g, " = 0");
}
cgen_write(g, "; ");
+ bool uses_ptr;
+ Type *of_type;
if (!(is_range && !ea->range.to)) { /* if it's finite */
if (is_range) {
if (ea->value)
@@ -755,12 +757,17 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
else
cgen_write(g, "i_");
cgen_write(g, " < ");
- switch (ea->of->type.kind) {
+ of_type = &ea->of->type;
+ uses_ptr = of_type->kind == TYPE_PTR;
+ if (uses_ptr) {
+ of_type = of_type->ptr;
+ }
+ switch (of_type->kind) {
case TYPE_ARR:
- cgen_write(g, "%lu", (unsigned long)ea->of->type.arr.n);
+ cgen_write(g, "%lu", (unsigned long)of_type->arr.n);
break;
case TYPE_SLICE:
- cgen_write(g, "of_.n");
+ cgen_write(g, "of_%sn", uses_ptr ? "->" : ".");
break;
default: assert(0); break;
}
@@ -795,22 +802,25 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
/* necessary for iterating over, e.g., an array of arrays */
if (!cgen_type_pre(g, &ea->type, e->where))
return false;
- cgen_write(g, "(*p_)");
+ if (uses_ptr)
+ cgen_write(g, "p_");
+ else
+ cgen_write(g, "(*p_)");
if (!cgen_type_post(g, &ea->type, e->where))
return false;
cgen_write(g, " = ");
- if (ea->of->type.kind == TYPE_SLICE) {
+ if (of_type->kind == TYPE_SLICE) {
cgen_write(g, "((");
if (!cgen_type_pre(g, &ea->type, e->where)) return false;
- cgen_write(g, "(*)");
+ if (!uses_ptr) cgen_write(g, "(*)");
if (!cgen_type_post(g, &ea->type, e->where)) return false;
- cgen_write(g, ")of_.data) + ");
+ cgen_write(g, ")of_%sdata) + ", uses_ptr ? "->" : ".");
if (ea->index)
cgen_ident(g, ea->index);
else
cgen_write(g, "i_");
} else {
- cgen_write(g, "&of_[");
+ cgen_write(g, "&%sof_%s[", uses_ptr ? "(*" : "", uses_ptr ? ")" : "");
if (ea->index)
cgen_ident(g, ea->index);
else
@@ -823,13 +833,20 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
cgen_ident(g, ea->value);
if (!cgen_type_post(g, &ea->type, e->where)) return false;
cgen_write(g, "; ");
- Expression set_expr;
- set_expr.kind = EXPR_IDENT;
- set_expr.ident = ea->value;
- set_expr.type = ea->type;
- set_expr.flags = EXPR_FLAG_FOUND_TYPE;
- if (!cgen_set(g, &set_expr, NULL, NULL, "(*p_)"))
- return false;
+ if (uses_ptr) {
+ cgen_ident(g, ea->value);
+ cgen_write(g, " = p_;");
+ cgen_nl(g);
+ } else {
+ Expression set_expr;
+ set_expr.kind = EXPR_IDENT;
+ set_expr.ident = ea->value;
+ set_expr.type = ea->type;
+ set_expr.flags = EXPR_FLAG_FOUND_TYPE;
+
+ if (!cgen_set(g, &set_expr, NULL, NULL, "(*p_)"))
+ return false;
+ }
}
}
if (!cgen_block(g, &ea->body, ret_name, CGEN_BLOCK_NOBRACES))
diff --git a/eval.c b/eval.c
index 3c44470..e2beb26 100644
--- a/eval.c
+++ b/eval.c
@@ -1251,28 +1251,42 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
} else {
value_val = &val;
}
- index_val->i64 = 0;
I64 len;
- switch (ea->of->type.kind) {
+ bool uses_ptr = false;
+ Type *of_type = &ea->of->type;
+ if (of_type->kind == TYPE_PTR) {
+ uses_ptr = true;
+ of_type = of_type->ptr;
+ }
+ switch (of_type->kind) {
case TYPE_ARR:
- len = (I64)ea->of->type.arr.n;
+ len = (I64)of_type->arr.n;
+ if (uses_ptr) {
+ of.arr = of.ptr;
+ }
+
break;
case TYPE_SLICE:
+ if (uses_ptr) {
+ of.slice = *(Slice *)of.ptr;
+ }
len = of.slice.n;
break;
default: assert(0); return false;
}
-
Type i64t;
i64t.flags = TYPE_FLAG_RESOLVED;
i64t.kind = TYPE_BUILTIN;
i64t.builtin = BUILTIN_I64;
-
+ index_val->i64 = 0;
while (index_val->i64 < len) {
void *ptr;
- if (!eval_val_ptr_at_index(ev, e->where, &of, (U64)index_val->i64, &ea->of->type, &i64t, &ptr, NULL))
+ if (!eval_val_ptr_at_index(ev, e->where, &of, (U64)index_val->i64, of_type, &i64t, &ptr, NULL))
return false;
- eval_deref(value_val, ptr, &ea->type);
+ if (uses_ptr)
+ value_val->ptr = ptr;
+ else
+ eval_deref(value_val, ptr, &ea->type);
if (!eval_block(ev, &ea->body, &e->type, v))
return false;
index_val->i64++;
diff --git a/main.c b/main.c
index 7250218..c3b544c 100644
--- a/main.c
+++ b/main.c
@@ -1,8 +1,5 @@
/*
TODO:
-allow just each arr { ... }
-each pointer
-compile-time each pointer
prevent each x := x
+=, -=, *=, /=
compile-time arguments
diff --git a/test.toc b/test.toc
index 2bd8e0f..347eb5a 100644
--- a/test.toc
+++ b/test.toc
@@ -45,22 +45,21 @@ putf @= fn(x: float) {
// };
g @= fn() int {
- foo : [10]int; // = new(int, 10);
+ foo : = new(int, 10);
total := 0;
- each foo { total = total + 1; }
-// each _, i := foo {
- // foo[i] = i;
- // };
- // total := 0;
- // each x := foo {
- // total = total + x;
- // }
- // total
-
- each i := 1..10 {
- total = total + i;
- total
+ // each foo { total = total + 1; }
+ each x, i := &foo {
+ *x = i;
+ };
+ each x, i := foo {
+ total = total + x * i;
}
+ total
+
+ // each i := 1..10 {
+ // total = total + i;
+ // total
+ // }
// total := 0;
// each i, j := 1..10 {
// total = total + i * j;
diff --git a/types.c b/types.c
index 02c32bc..19fa057 100644
--- a/types.c
+++ b/types.c
@@ -735,13 +735,19 @@ static bool types_expr(Typer *tr, Expression *e) {
} else {
if (!types_expr(tr, ea->of))
return false;
- Type *of_type = NULL;
- switch (ea->of->type.kind) {
+ Type *iter_type = &ea->of->type;
+
+ bool uses_ptr = false;
+ if (iter_type->kind == TYPE_PTR) {
+ uses_ptr = true;
+ iter_type = iter_type->ptr;
+ }
+ switch (iter_type->kind) {
case TYPE_SLICE:
- of_type = ea->of->type.slice;
+ iter_type = iter_type->slice;
break;
case TYPE_ARR:
- of_type = ea->of->type.arr.of;
+ iter_type = iter_type->arr.of;
break;
default: {
char *s = type_to_str(&ea->of->type);
@@ -750,15 +756,22 @@ static bool types_expr(Typer *tr, Expression *e) {
return false;
}
}
+ Type ptr_type;
+ if (uses_ptr) {
+ ptr_type.flags = TYPE_FLAG_RESOLVED;
+ ptr_type.kind = TYPE_PTR;
+ ptr_type.ptr = iter_type;
+ iter_type = &ptr_type;
+ }
if (ea->flags & EACH_ANNOTATED_TYPE) {
- if (!type_eq(of_type, &ea->type)) {
- char *exp = type_to_str(of_type);
+ if (!type_eq(iter_type, &ea->type)) {
+ char *exp = type_to_str(iter_type);
char *got = type_to_str(&ea->type);
err_print(e->where, "Expected to iterate over type %s, but it was annotated as iterating over type %s.");
free(exp); free(got);
return false;
}
- } else ea->type = *of_type;
+ } else ea->type = *iter_type;
}
if ((ea->flags & EACH_IS_RANGE) && ea->range.step) {
Value *stepval = typer_malloc(tr, sizeof *ea->range.stepval);