harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Msrc/eval.c | 30++++++++++++++++++------------
Mtests/11-globals.ha | 12++++++++++++
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(); };