diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-10-28 13:53:15 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-10-28 13:53:15 -0400 |
| commit | 9c302fdc34403f46572d9524309617888ba816bb (patch) | |
| tree | 58ea7faf390536503de114cf2889ed85ba60df7b /typecheck.c | |
| parent | c632a72486d347e7ef30c0b7890e2045ed42b903 (diff) | |
| parent | ce2aebe91085f987aab31bd2a49820fb605cf386 (diff) | |
Merge branch 'main' into internal-textsinternal-texts
Diffstat (limited to 'typecheck.c')
| -rw-r--r-- | typecheck.c | 61 |
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; |
