commit dfc768c822f78bd45cf20fbbf1a3a0dbf22a1561
parent aaf6db9c248719033e623dd0e8a1c5e7f9ed4286
Author: Bor Grošelj Simić <bor.groseljsimic@telemach.net>
Date: Wed, 18 Aug 2021 17:24:44 +0200
eval: only allow taking address of globals
Signed-off-by: Bor Grošelj Simić <bor.groseljsimic@telemach.net>
Diffstat:
2 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/src/eval.c b/src/eval.c
@@ -16,13 +16,9 @@ eval_access(struct context *ctx, struct expression *in, struct expression *out)
out->type = EXPR_CONSTANT;
out->result = in->result;
- // TODO: Probably have not considered all of the edge cases here
switch (in->access.type) {
case ACCESS_IDENTIFIER:
- out->constant.object = in->access.object;
- out->constant.ival = 0;
- assert(in->access.object->otype == O_DECL); // TODO: Bubble this up
- break;
+ return EVAL_INVALID; // &ident handled in eval_unarithm
case ACCESS_INDEX:
assert(0); // TODO
case ACCESS_FIELD:
@@ -638,22 +634,32 @@ eval_tuple(struct context *ctx, struct expression *in, struct expression *out)
static enum eval_result
eval_unarithm(struct context *ctx, struct expression *in, struct expression *out)
{
+ out->type = EXPR_CONSTANT;
+
+ if (in->unarithm.op == UN_ADDRESS) {
+ assert(in->unarithm.operand->type == EXPR_ACCESS);
+ // TODO other access types
+ assert(in->unarithm.operand->access.type == ACCESS_IDENTIFIER);
+ if (in->unarithm.operand->access.object->otype != O_DECL) {
+ return EVAL_INVALID;
+ }
+ out->result = type_store_lookup_pointer(
+ ctx->store, in->unarithm.operand->result, 0);
+ out->constant.object = in->unarithm.operand->access.object;
+ out->constant.ival = 0;
+ return EVAL_OK;
+ }
+
struct expression lvalue = {0};
enum eval_result r = eval_expr(ctx, in->unarithm.operand, &lvalue);
if (r != EVAL_OK) {
return r;
}
- out->type = EXPR_CONSTANT;
out->result = lvalue.result;
switch (in->unarithm.op) {
case UN_ADDRESS:
- assert(lvalue.type == EXPR_CONSTANT);
- assert(lvalue.constant.object);
- out->result = type_store_lookup_pointer(
- ctx->store, lvalue.result, 0);
- out->constant = lvalue.constant;
- break;
+ assert(0); // handled above
case UN_BNOT:
out->constant.uval = ~lvalue.constant.uval;
break;
diff --git a/tests/11-globals.ha b/tests/11-globals.ha
@@ -43,6 +43,7 @@ fn storage() void = {
fn invariants() void = {
assert(rt::compile("fn test() int; let x: int = test();") != 0);
+ assert(rt::compile("const a: u8 = 2; const b: u8 = a + 5;") != 0);
};
fn counter() int = {
@@ -57,6 +58,16 @@ fn static_binding() void = {
assert(counter() == 3);
};
+const val: u32 = 42;
+const tup: (u8, str) = (2, "asdf");
+const ptr: *u32 = &val;
+const ptr_tup: *(u8, str) = &tup;
+// TODO const ptr_memb: *str = &tup.1;
+
+fn pointers() void = {
+ assert(ptr == &val && *ptr == val);
+};
+
export fn main() void = {
// TODO: Expand this test:
// - Declare & validate globals of more types
@@ -65,4 +76,5 @@ export fn main() void = {
storage();
invariants();
static_binding();
+ pointers();
};