aboutsummaryrefslogtreecommitdiff
path: root/compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c63
1 files changed, 31 insertions, 32 deletions
diff --git a/compile.c b/compile.c
index b02e2ffe..cde052c6 100644
--- a/compile.c
+++ b/compile.c
@@ -280,9 +280,20 @@ CORD compile_type(type_t *t)
static CORD compile_lvalue(env_t *env, ast_t *ast)
{
if (!can_be_mutated(env, ast)) {
- if (ast->tag == Index || ast->tag == FieldAccess) {
- ast_t *subject = ast->tag == Index ? Match(ast, Index)->indexed : Match(ast, FieldAccess)->fielded;
- code_err(subject, "This is an immutable value, you can't assign to it");
+ if (ast->tag == Index) {
+ ast_t *subject = Match(ast, Index)->indexed;
+ type_t *t = get_type(env, subject);
+ if (t->tag == PointerType && Match(t, PointerType)->is_view)
+ code_err(ast, "This is a read-only view and you can't mutate its contents");
+ else
+ code_err(subject, "This is an immutable value, you can't mutate its contents");
+ } else if (ast->tag == FieldAccess) {
+ ast_t *subject = Match(ast, FieldAccess)->fielded;
+ type_t *t = get_type(env, subject);
+ if (t->tag == PointerType && Match(t, PointerType)->is_view)
+ code_err(subject, "This is a read-only view and you can't mutate its fields");
+ else
+ code_err(subject, "This is an immutable value, you can't assign to its fields");
} else {
code_err(ast, "This is a value of type %T and can't be used as an assignment target", get_type(env, ast));
}
@@ -508,8 +519,6 @@ CORD compile_statement(env_t *env, ast_t *ast)
if (!assign->targets->next && assign->targets->ast->tag == Var && is_idempotent(assign->targets->ast)) {
// Common case: assigning to one variable:
type_t *lhs_t = get_type(env, assign->targets->ast);
- if (lhs_t->tag == PointerType && Match(lhs_t, PointerType)->is_stack)
- code_err(test->expr, "Stack references cannot be assigned to local variables because the variable may outlive the stack memory.");
env_t *val_scope = with_enum_scope(env, lhs_t);
type_t *rhs_t = get_type(val_scope, assign->values->ast);
CORD value;
@@ -537,8 +546,6 @@ CORD compile_statement(env_t *env, ast_t *ast)
int64_t i = 1;
for (ast_list_t *target = assign->targets, *value = assign->values; target && value; target = target->next, value = value->next) {
type_t *target_type = get_type(env, target->ast);
- if (target_type->tag == PointerType && Match(target_type, PointerType)->is_stack)
- code_err(ast, "Stack references cannot be assigned to local variables because the variable may outlive the stack memory.");
env_t *val_scope = with_enum_scope(env, target_type);
type_t *value_type = get_type(val_scope, value->ast);
CORD val_code;
@@ -611,8 +618,6 @@ CORD compile_statement(env_t *env, ast_t *ast)
// Single assignment, no temp vars needed:
if (assign->targets && !assign->targets->next && is_idempotent(assign->targets->ast)) {
type_t *lhs_t = get_type(env, assign->targets->ast);
- if (lhs_t->tag == PointerType && Match(lhs_t, PointerType)->is_stack)
- code_err(ast, "Stack references cannot be assigned to local variables because the variable may outlive the stack memory.");
env_t *val_env = with_enum_scope(env, lhs_t);
type_t *rhs_t = get_type(val_env, assign->values->ast);
CORD val;
@@ -630,8 +635,6 @@ CORD compile_statement(env_t *env, ast_t *ast)
int64_t i = 1;
for (ast_list_t *value = assign->values, *target = assign->targets; value && target; value = value->next, target = target->next) {
type_t *lhs_t = get_type(env, target->ast);
- if (lhs_t->tag == PointerType && Match(lhs_t, PointerType)->is_stack)
- code_err(ast, "Stack references cannot be assigned to local variables because the variable may outlive the stack memory.");
env_t *val_env = with_enum_scope(env, lhs_t);
type_t *rhs_t = get_type(val_env, value->ast);
CORD val;
@@ -1520,7 +1523,7 @@ CORD compile_to_pointer_depth(env_t *env, ast_t *ast, int64_t target_depth, bool
val = CORD_all("(&", val, ")");
else
code_err(ast, "This should be a pointer, not %T", get_type(env, ast));
- t = Type(PointerType, .pointed=t, .is_stack=true);
+ t = Type(PointerType, .pointed=t, .is_view=true);
++depth;
} else {
auto ptr = Match(t, PointerType);
@@ -1980,13 +1983,6 @@ CORD compile(env_t *env, ast_t *ast)
}
// TODO: for constructors, do new(T, ...) instead of heap((T){...})
case HeapAllocate: return heap_strf("heap(%r)", compile(env, Match(ast, HeapAllocate)->value));
- case StackReference: {
- ast_t *subject = Match(ast, StackReference)->value;
- if (can_be_mutated(env, subject))
- return CORD_all("(&", compile_lvalue(env, subject), ")");
- else
- code_err(subject, "This subject can't be mutated!");
- }
case Optional: {
ast_t *value = Match(ast, Optional)->value;
CORD value_code = compile(env, value);
@@ -2354,7 +2350,7 @@ CORD compile(env_t *env, ast_t *ast)
static int64_t comp_num = 1;
const char *comprehension_name = heap_strf("arr$%ld", comp_num++);
ast_t *comprehension_var = FakeAST(InlineCCode, .code=Text$format("&%s", comprehension_name),
- .type=Type(PointerType, .pointed=array_type, .is_stack=true));
+ .type=Type(PointerType, .pointed=array_type, .is_view=true));
Closure_t comp_action = {.fn=add_to_array_comprehension, .userdata=comprehension_var};
scope->comprehension_action = &comp_action;
CORD code = CORD_all("({ Array_t ", comprehension_name, " = {};");
@@ -2433,7 +2429,7 @@ CORD compile(env_t *env, ast_t *ast)
env_t *scope = fresh_scope(env);
const char *comprehension_name = heap_strf("table$%ld", comp_num++);
ast_t *comprehension_var = FakeAST(InlineCCode, .code=Text$format("&%s", comprehension_name),
- .type=Type(PointerType, .pointed=table_type, .is_stack=true));
+ .type=Type(PointerType, .pointed=table_type, .is_view=true));
CORD code = CORD_all("({ Table_t ", comprehension_name, " = {");
if (table->fallback)
@@ -2487,7 +2483,7 @@ CORD compile(env_t *env, ast_t *ast)
env_t *scope = item_type->tag == EnumType ? with_enum_scope(env, item_type) : fresh_scope(env);
const char *comprehension_name = heap_strf("set$%ld", comp_num++);
ast_t *comprehension_var = FakeAST(InlineCCode, .code=Text$format("&%s", comprehension_name),
- .type=Type(PointerType, .pointed=set_type, .is_stack=true));
+ .type=Type(PointerType, .pointed=set_type, .is_view=true));
CORD code = CORD_all("({ Table_t ", comprehension_name, " = {};");
Closure_t comp_action = {.fn=add_to_set_comprehension, .userdata=comprehension_var};
scope->comprehension_action = &comp_action;
@@ -2671,10 +2667,13 @@ CORD compile(env_t *env, ast_t *ast)
(void)compile_arguments(env, ast, NULL, call->args);
return CORD_all("Array$shuffled(", self, ", ", padded_item_size, ")");
} else if (streq(call->name, "sort") || streq(call->name, "sorted")) {
- CORD self = compile_to_pointer_depth(env, call->self, streq(call->name, "sort") ? 1 : 0, false);
+ CORD self = streq(call->name, "sort")
+ ? compile_to_pointer_depth(env, call->self, 1, false)
+ // No need to do an ARRAY_COPY() here because it happens inside Array$sorted():
+ : compile_to_pointer_depth(env, call->self, 0, false);
CORD comparison;
if (call->args) {
- type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true);
+ type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_view=true);
type_t *fn_t = Type(FunctionType, .args=new(arg_t, .name="x", .type=item_ptr, .next=new(arg_t, .name="y", .type=item_ptr)),
.ret=Type(IntType, .bits=TYPE_IBITS32));
arg_t *arg_spec = new(arg_t, .name="by", .type=Type(ClosureType, .fn=fn_t));
@@ -2687,7 +2686,7 @@ CORD compile(env_t *env, ast_t *ast)
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
CORD comparison;
if (call->args) {
- type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true);
+ type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_view=true);
type_t *fn_t = Type(FunctionType, .args=new(arg_t, .name="x", .type=item_ptr, .next=new(arg_t, .name="y", .type=item_ptr)),
.ret=Type(IntType, .bits=TYPE_IBITS32));
arg_t *arg_spec = new(arg_t, .name="by", .type=Type(ClosureType, .fn=fn_t));
@@ -2698,7 +2697,7 @@ CORD compile(env_t *env, ast_t *ast)
return CORD_all("Array$heapify(", self, ", ", comparison, ", ", padded_item_size, ")");
} else if (streq(call->name, "heap_push")) {
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
- type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true);
+ type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_view=true);
type_t *fn_t = Type(FunctionType, .args=new(arg_t, .name="x", .type=item_ptr, .next=new(arg_t, .name="y", .type=item_ptr)),
.ret=Type(IntType, .bits=TYPE_IBITS32));
ast_t *default_cmp = FakeAST(InlineCCode,
@@ -2711,7 +2710,7 @@ CORD compile(env_t *env, ast_t *ast)
return CORD_all("Array$heap_push_value(", self, ", ", arg_code, ", ", padded_item_size, ")");
} else if (streq(call->name, "heap_pop")) {
CORD self = compile_to_pointer_depth(env, call->self, 1, false);
- type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true);
+ type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_view=true);
type_t *fn_t = Type(FunctionType, .args=new(arg_t, .name="x", .type=item_ptr, .next=new(arg_t, .name="y", .type=item_ptr)),
.ret=Type(IntType, .bits=TYPE_IBITS32));
ast_t *default_cmp = FakeAST(InlineCCode,
@@ -2722,8 +2721,8 @@ CORD compile(env_t *env, ast_t *ast)
CORD arg_code = compile_arguments(env, ast, arg_spec, call->args);
return CORD_all("Array$heap_pop_value(", self, ", ", arg_code, ", ", padded_item_size, ", ", compile_type(item_t), ")");
} else if (streq(call->name, "binary_search")) {
- CORD self = compile_to_pointer_depth(env, call->self, 0, false);
- type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true);
+ CORD self = compile_to_pointer_depth(env, call->self, 0, call->args != NULL);
+ type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_view=true);
type_t *fn_t = Type(FunctionType, .args=new(arg_t, .name="x", .type=item_ptr, .next=new(arg_t, .name="y", .type=item_ptr)),
.ret=Type(IntType, .bits=TYPE_IBITS32));
ast_t *default_cmp = FakeAST(InlineCCode,
@@ -2744,8 +2743,8 @@ CORD compile(env_t *env, ast_t *ast)
return CORD_all("Array$find_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args),
", ", compile_type_info(env, self_value_t), ")");
} else if (streq(call->name, "first")) {
- CORD self = compile_to_pointer_depth(env, call->self, 0, false);
- type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_stack=true);
+ CORD self = compile_to_pointer_depth(env, call->self, 0, call->args != NULL);
+ type_t *item_ptr = Type(PointerType, .pointed=item_t, .is_view=true);
type_t *predicate_type = Type(
ClosureType, .fn=Type(FunctionType, .args=new(arg_t, .name="item", .type=item_ptr), .ret=Type(BoolType)));
arg_t *arg_spec = new(arg_t, .name="predicate", .type=predicate_type);
@@ -3490,7 +3489,7 @@ CORD compile_type_info(env_t *env, type_t *t)
}
case PointerType: {
auto ptr = Match(t, PointerType);
- CORD sigil = ptr->is_stack ? "&" : "@";
+ CORD sigil = ptr->is_view ? "&" : "@";
return heap_strf("Pointer$info(%r, %r)",
CORD_quoted(sigil),
compile_type_info(env, ptr->pointed));