1 // This file defines how to compile pointers and allocated memory
10 #include "../environment.h"
11 #include "../stdlib/text.h"
12 #include "../typecheck.h"
13 #include "compilation.h"
16 Text_t compile_to_pointer_depth(env_t *env, ast_t *ast, int64_t target_depth, bool needs_incref) {
17 Text_t val = compile(env, ast);
18 type_t *t = get_type(env, ast);
20 for (type_t *tt = t; tt->tag == PointerType; tt = Match(tt, PointerType)->pointed)
23 // Passing a literal value won't trigger an incref, because it's ephemeral,
24 // e.g. [10, 20].reversed()
25 if (t->tag != PointerType && needs_incref && !can_be_mutated(env, ast)) needs_incref = false;
27 while (depth != target_depth) {
28 if (depth < target_depth) {
29 if (ast->tag == Var && target_depth == 1) val = Texts("(&", val, ")");
30 else code_err(ast, "This should be a pointer, not ", type_to_text(get_type(env, ast)));
31 t = Type(PointerType, .pointed = t, .is_stack = true);
34 DeclareMatch(ptr, t, PointerType);
35 val = Texts("*(", val, ")");
41 while (t->tag == PointerType) {
42 DeclareMatch(ptr, t, PointerType);
46 if (needs_incref && t->tag == ListType) val = Texts("LIST_COPY(", val, ")");
47 else if (needs_incref && t->tag == TableType) val = Texts("TABLE_COPY(", val, ")");
53 Text_t compile_typed_allocation(env_t *env, ast_t *ast, type_t *pointer_type) {
54 // TODO: for constructors, do new(T, ...) instead of heap((T){...})
55 type_t *pointed = Match(pointer_type, PointerType)->pointed;
58 return Texts("heap(", compile_maybe_incref(env, Match(ast, HeapAllocate)->value, pointed), ")");
60 case StackReference: {
61 ast_t *subject = Match(ast, StackReference)->value;
62 if (can_be_mutated(env, subject) && type_eq(pointed, get_type(env, subject)))
63 return Texts("(&", compile_lvalue(env, subject), ")");
64 else return Texts("stack(", compile_maybe_incref(env, subject, pointed), ")");
66 default: code_err(ast, "Not an allocation!");