aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-02-25 13:04:35 -0500
committerBruce Hill <bruce@bruce-hill.com>2024-02-25 13:04:35 -0500
commitf7d403c35849758d68e3a0ca9a9777bfce7da0b7 (patch)
tree0e9fad4e8e8e447e1ba5d837233f985f98d14d69
parent394f720fb0bdcc9acfa3614a5ded650383ec8feb (diff)
WIP on stackrefs
-rw-r--r--builtins/array.h18
-rw-r--r--compile.c10
-rw-r--r--typecheck.c29
-rw-r--r--typecheck.h1
4 files changed, 43 insertions, 15 deletions
diff --git a/builtins/array.h b/builtins/array.h
index 9e74c41d..59245ffe 100644
--- a/builtins/array.h
+++ b/builtins/array.h
@@ -8,15 +8,15 @@
#include "types.h"
// Convert negative indices to back-indexed without branching: index0 = index + (index < 0)*(len+1)) - 1
-#define $Array_get(type, x, i, filename, start, end) ({ \
- const array_t *$arr = x; int64_t $index = (int64_t)(i); \
- int64_t $off = $index + ($index < 0) * ($arr->length + 1) - 1; \
- if (__builtin_expect($off < 0 || $off >= $arr->length, 0)) \
- fail_source(filename, start, end, "Invalid array index: %r (array has length %ld)\n", Int64__as_str(&$index, USE_COLOR, NULL), $arr->length); \
- *(type*)($arr->data + $arr->stride * $off);})
-#define $Array_get_unchecked(type, x, i) ({ const array_t *$arr = x; int64_t $index = (int64_t)(i); \
- int64_t $off = $index + ($index < 0) * ($arr->length + 1) - 1; \
- *(type*)($arr->data + $arr->stride * $off);})
+#define $Array_get(type, x, i, filename, start, end) *({ \
+ const array_t $arr = x; int64_t $index = (int64_t)(i); \
+ int64_t $off = $index + ($index < 0) * ($arr.length + 1) - 1; \
+ if (__builtin_expect($off < 0 || $off >= $arr.length, 0)) \
+ fail_source(filename, start, end, "Invalid array index: %r (array has length %ld)\n", Int64__as_str(&$index, USE_COLOR, NULL), $arr.length); \
+ (type*)($arr.data + $arr.stride * $off);})
+#define $Array_get_unchecked(type, x, i) *({ const array_t $arr = x; int64_t $index = (int64_t)(i); \
+ int64_t $off = $index + ($index < 0) * ($arr.length + 1) - 1; \
+ (type*)($arr.data + $arr.stride * $off);})
#define $is_atomic(x) _Generic(x, bool: true, int8_t: true, int16_t: true, int32_t: true, int64_t: true, float: true, double: true, default: false)
#define $Array(x, ...) ({ __typeof(x) $items[] = {x, __VA_ARGS__}; \
(array_t){.length=sizeof($items)/sizeof($items[0]), \
diff --git a/compile.c b/compile.c
index 455f13f4..4163a202 100644
--- a/compile.c
+++ b/compile.c
@@ -176,10 +176,10 @@ CORD compile(env_t *env, ast_t *ast)
case Negative: return CORD_asprintf("-(%r)", compile(env, Match(ast, Negative)->value));
case HeapAllocate: return CORD_asprintf("$heap(%r)", compile(env, Match(ast, HeapAllocate)->value));
case StackReference: {
- ast_t *value = Match(ast, StackReference)->value;
- if (value->tag == Var)
- return CORD_cat("&", compile(env, Match(ast, StackReference)->value));
- return CORD_all("$stack(", compile(env, Match(ast, StackReference)->value), ")");
+ ast_t *subject = Match(ast, StackReference)->value;
+ if (can_be_mutated(env, subject))
+ return CORD_cat("&", compile(env, subject));
+ return CORD_all("$stack(", compile(env, subject), ")");
}
case BinaryOp: {
auto binop = Match(ast, BinaryOp);
@@ -886,7 +886,7 @@ CORD compile(env_t *env, ast_t *ast)
if (index_t->tag != IntType)
code_err(indexing->index, "Arrays can only be indexed by integers, not %T", index_t);
type_t *item_type = Match(container_t, ArrayType)->item_type;
- CORD arr = compile_to_pointer_depth(env, indexing->indexed, 1, false);
+ CORD arr = compile_to_pointer_depth(env, indexing->indexed, 0, false);
CORD index = compile(env, indexing->index);
file_t *f = indexing->index->file;
if (indexing->unchecked)
diff --git a/typecheck.c b/typecheck.c
index ce3c9d08..a5153512 100644
--- a/typecheck.c
+++ b/typecheck.c
@@ -203,6 +203,7 @@ type_t *get_type(env_t *env, ast_t *ast)
ast_t *value = Match(ast, StackReference)->value;
type_t *pointed_t = get_type(env, Match(ast, StackReference)->value);
bool is_stack = true;
+ bool is_readonly = !can_be_mutated(env, value);
// References to heap members/indexes are heap pointers, e.g. v := @Vec{1,2}; &v.x
switch (value->tag) {
case FieldAccess: {
@@ -217,7 +218,7 @@ type_t *get_type(env_t *env, ast_t *ast)
}
default: break;
}
- return Type(PointerType, .pointed=pointed_t, .is_stack=is_stack);
+ return Type(PointerType, .pointed=pointed_t, .is_stack=is_stack, .is_readonly=is_readonly);
}
case StringJoin: case StringLiteral: {
return Type(StringType);
@@ -711,4 +712,30 @@ type_t *get_arg_type(env_t *env, arg_t *arg)
return get_type(env, arg->default_val);
}
+bool can_be_mutated(env_t *env, ast_t *ast)
+{
+ switch (ast->tag) {
+ case Var: return true;
+ case FieldAccess: {
+ auto access = Match(ast, FieldAccess);
+ type_t *fielded_type = get_type(env, access->fielded);
+ if (fielded_type->tag == PointerType) {
+ auto ptr = Match(fielded_type, PointerType);
+ return !ptr->is_readonly;
+ }
+ return can_be_mutated(env, access->fielded);
+ }
+ case Index: {
+ auto index = Match(ast, Index);
+ type_t *indexed_type = get_type(env, index->indexed);
+ if (indexed_type->tag == PointerType) {
+ auto ptr = Match(indexed_type, PointerType);
+ return !ptr->is_readonly;
+ }
+ return false;
+ }
+ default: return false;
+ }
+}
+
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/typecheck.h b/typecheck.h
index a44e658b..bb6ed397 100644
--- a/typecheck.h
+++ b/typecheck.h
@@ -17,5 +17,6 @@ type_t *get_file_type(env_t *env, const char *path);
type_t *get_function_def_type(env_t *env, ast_t *ast);
type_t *get_arg_type(env_t *env, arg_t *arg);
type_t *get_arg_ast_type(env_t *env, arg_ast_t *arg);
+bool can_be_mutated(env_t *env, ast_t *ast);
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0