aboutsummaryrefslogtreecommitdiff
path: root/typecheck.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-10-28 13:53:15 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-10-28 13:53:15 -0400
commit9c302fdc34403f46572d9524309617888ba816bb (patch)
tree58ea7faf390536503de114cf2889ed85ba60df7b /typecheck.c
parentc632a72486d347e7ef30c0b7890e2045ed42b903 (diff)
parentce2aebe91085f987aab31bd2a49820fb605cf386 (diff)
Merge branch 'main' into internal-textsinternal-texts
Diffstat (limited to 'typecheck.c')
-rw-r--r--typecheck.c61
1 files changed, 13 insertions, 48 deletions
diff --git a/typecheck.c b/typecheck.c
index 6d01359f..43dec880 100644
--- a/typecheck.c
+++ b/typecheck.c
@@ -46,13 +46,13 @@ type_t *parse_type_ast(env_t *env, type_ast_t *ast)
type_t *pointed_t = parse_type_ast(env, ptr->pointed);
if (pointed_t->tag == VoidType)
code_err(ast, "Void pointers are not supported. You probably meant 'Memory' instead of 'Void'");
- return Type(PointerType, .pointed=pointed_t, .is_stack=ptr->is_stack);
+ return Type(PointerType, .pointed=pointed_t, .is_view=ptr->is_view);
}
case ArrayTypeAST: {
type_ast_t *item_type = Match(ast, ArrayTypeAST)->item;
type_t *item_t = parse_type_ast(env, item_type);
if (!item_t) code_err(item_type, "I can't figure out what this type is.");
- if (has_stack_memory(item_t))
+ if (has_view_memory(item_t))
code_err(item_type, "Arrays can't have stack references because the array may outlive the stack frame.");
if (type_size(item_t) > ARRAY_MAX_STRIDE)
code_err(ast, "This array holds items that take up %ld bytes, but the maximum supported size is %ld bytes. Consider using an array of pointers instead.",
@@ -63,7 +63,7 @@ type_t *parse_type_ast(env_t *env, type_ast_t *ast)
type_ast_t *item_type = Match(ast, SetTypeAST)->item;
type_t *item_t = parse_type_ast(env, item_type);
if (!item_t) code_err(item_type, "I can't figure out what this type is.");
- if (has_stack_memory(item_t))
+ if (has_view_memory(item_t))
code_err(item_type, "Sets can't have stack references because the array may outlive the stack frame.");
if (type_size(item_t) > ARRAY_MAX_STRIDE)
code_err(ast, "This set holds items that take up %ld bytes, but the maximum supported size is %ld bytes. Consider using an set of pointers instead.",
@@ -85,19 +85,19 @@ type_t *parse_type_ast(env_t *env, type_ast_t *ast)
type_ast_t *key_type_ast = Match(ast, TableTypeAST)->key;
type_t *key_type = parse_type_ast(env, key_type_ast);
if (!key_type) code_err(key_type_ast, "I can't figure out what type this is.");
- if (has_stack_memory(key_type))
+ if (has_view_memory(key_type))
code_err(key_type_ast, "Tables can't have stack references because the array may outlive the stack frame.");
type_ast_t *val_type_ast = Match(ast, TableTypeAST)->value;
type_t *val_type = parse_type_ast(env, val_type_ast);
if (!val_type) code_err(val_type_ast, "I can't figure out what type this is.");
- if (has_stack_memory(val_type))
+ if (has_view_memory(val_type))
code_err(val_type_ast, "Tables can't have stack references because the array may outlive the stack frame.");
return Type(TableType, .key_type=key_type, .value_type=val_type);
}
case FunctionTypeAST: {
auto fn = Match(ast, FunctionTypeAST);
type_t *ret_t = fn->ret ? parse_type_ast(env, fn->ret) : Type(VoidType);
- if (has_stack_memory(ret_t))
+ if (has_view_memory(ret_t))
code_err(fn->ret, "Functions are not allowed to return stack references, because the reference may no longer exist on the stack.");
arg_t *type_args = NULL;
for (arg_ast_t *arg = fn->args; arg; arg = arg->next) {
@@ -421,7 +421,7 @@ type_t *get_function_def_type(env_t *env, ast_t *ast)
REVERSE_LIST(args);
type_t *ret = fn->ret_type ? parse_type_ast(scope, fn->ret_type) : Type(VoidType);
- if (has_stack_memory(ret))
+ if (has_view_memory(ret))
code_err(ast, "Functions can't return stack references because the reference may outlive its stack frame.");
return Type(FunctionType, .args=args, .ret=ret);
}
@@ -510,45 +510,10 @@ type_t *get_type(env_t *env, ast_t *ast)
}
case HeapAllocate: {
type_t *pointed = get_type(env, Match(ast, HeapAllocate)->value);
- if (has_stack_memory(pointed))
+ if (has_view_memory(pointed))
code_err(ast, "Stack references cannot be moved to the heap because they may outlive the stack frame they were created in.");
return Type(PointerType, .pointed=pointed);
}
- case StackReference: {
- // Supported:
- // &variable
- // &struct_variable.field.(...)
- // &struct_ptr.field.(...)
- // Not supported:
- // &ptr[]
- // &list[index]
- // &table[key]
- // &(expression).field
- // &(expression)
- // &optional_struct_ptr.field
- ast_t *value = Match(ast, StackReference)->value;
- if (value->tag == Var)
- return Type(PointerType, .pointed=get_type(env, value), .is_stack=true);
-
- if (value->tag == FieldAccess) {
- ast_t *base = value;
- while (base->tag == FieldAccess)
- base = Match(base, FieldAccess)->fielded;
-
- type_t *ref_type = get_type(env, value);
- type_t *base_type = get_type(env, base);
- if (base_type->tag == OptionalType) {
- code_err(base, "This value might be null, so it can't be safely dereferenced");
- } else if (base_type->tag == PointerType) {
- auto ptr = Match(base_type, PointerType);
- return Type(PointerType, .pointed=ref_type, .is_stack=ptr->is_stack);
- } else if (base->tag == Var) {
- return Type(PointerType, .pointed=ref_type, .is_stack=true);
- }
- }
-
- code_err(ast, "'&' stack references can only be used on variables or fields of variables");
- }
case Optional: {
ast_t *value = Match(ast, Optional)->value;
type_t *t = get_type(env, value);
@@ -607,7 +572,7 @@ type_t *get_type(env_t *env, ast_t *ast)
} else {
code_err(ast, "I can't figure out what type this array has because it has no members or explicit type");
}
- if (has_stack_memory(item_type))
+ if (has_view_memory(item_type))
code_err(ast, "Arrays cannot hold stack references, because the array may outlive the stack frame the reference was created in.");
return Type(ArrayType, .item_type=item_type);
}
@@ -636,7 +601,7 @@ type_t *get_type(env_t *env, ast_t *ast)
item_type = item_merged;
}
}
- if (has_stack_memory(item_type))
+ if (has_view_memory(item_type))
code_err(ast, "Sets cannot hold stack references because the set may outlive the reference's stack frame.");
return Type(SetType, .item_type=item_type);
}
@@ -681,7 +646,7 @@ type_t *get_type(env_t *env, ast_t *ast)
value_type = val_merged;
}
}
- if (has_stack_memory(key_type) || has_stack_memory(value_type))
+ if (has_view_memory(key_type) || has_view_memory(value_type))
code_err(ast, "Tables cannot hold stack references because the table may outlive the reference's stack frame.");
return Type(TableType, .key_type=key_type, .value_type=value_type);
}
@@ -1143,7 +1108,7 @@ type_t *get_type(env_t *env, ast_t *ast)
declared, ret);
}
- if (has_stack_memory(ret))
+ if (has_view_memory(ret))
code_err(ast, "Functions can't return stack references because the reference may outlive its stack frame.");
return Type(ClosureType, Type(FunctionType, .args=args, .ret=ret));
}
@@ -1328,7 +1293,7 @@ PUREFUNC bool can_be_mutated(env_t *env, ast_t *ast)
auto index = Match(ast, Index);
type_t *indexed_type = get_type(env, index->indexed);
if (indexed_type->tag == PointerType)
- return true;
+ return !Match(indexed_type, PointerType)->is_view;
return can_be_mutated(env, index->indexed);
}
default: return false;