aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/outdecl.c
blob: d23663e8475d076b38e87cac9dc3ecaeb89fd6d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

/*
 * Outputs C declarations for types and functions.
 *
 * Copyright © 2020-2025 Samuel Lidén Borell <samuel@kodafritt.se>
 *
 * SPDX-License-Identifier: EUPL-1.2+
 */
#include <assert.h>
#include "compiler.h"
#include "out.h"

static void emit_func_ident(struct Func *func)
{
    struct Type *class_ = func->class_;
    if (class_) {
        if (class_->outer) {
            assert(class_->outer->outer == NULL);
            emit_ident(&class_->outer->ident);
            outc('_');
        }
        emit_ident(&class_->ident);
        outc('_');
    }
    emit_ident(&func->ident);
}

/** Emits a list of field or variable declarations */
static void emit_datadef_list(struct Var *var_list)
{
    struct Var *var;
    for (var = var_list; var; var = var->next) {
        indent();
        emit_typeref_prefix(var->typeref);
        emit_ident(&var->ident);
        emit_typeref_suffix(var->typeref);
        outf(";\n");
    }
}

static void emit_param_list(struct Var *var_list)
{
    struct Var *var;
    for (var = var_list; var; var = var->next) {
        emit_typeref_prefix(var->typeref);
        emit_ident(&var->ident);
        emit_typeref_suffix(var->typeref);
        if (var->next) {
            outf(", ");
        }
    }
}

static void emit_func_decl(struct Func *func, bool is_pre_decl)
{
    if (func->num_returns >= 2) {
        /* XXX perhaps the return types should be named by their contents,
               and de-duplicated with #ifdefs?
               (note: for generic types, there are two cases for parameters:
                bound and unbound) */
        if (is_pre_decl) {
            beginf("struct ");
            emit_func_ident(func);
            outf("__Return {\n");
            emit_datadef_list(func->returns);
            endf("};\n");
        }
        outf("struct ");
        emit_func_ident(func);
        outf("__Return ");
        emit_func_ident(func);
    } else if (func->num_returns == 1) {
        emit_typeref_prefix(func->returns[0].typeref);
        emit_func_ident(func);
        emit_typeref_suffix(func->returns[0].typeref);
    } else {
        assert(func->num_returns == 0);
        outf("void ");
        emit_func_ident(func);
    }
    outc('(');
    if (func->num_params == 0) {
        outf("void");
    } else {
        emit_param_list(func->params);
    }
    outc(')');
}

void predeclare_type(struct Type *type)
{
    emit_type(type);
    outf(";\n");
}

void define_type(struct Type *type)
{
    outc('\n');
    emit_type(type);
    outf(" {\n");
    indentlevel++;
    /* TODO for each field
        emit_typeref_prefix(field->typeref);
        emit_ident(&field->ident);
        emit_typeref_suffix(field->typeref);
    */
    endf("};\n");
}

void predeclare_funcs(struct Func *funcs_list)
{
    struct Func *func;
    for (func = funcs_list; func; func = func->next) {
        emit_func_decl(func, true);
        outf(";\n");
    }
}

void define_funcs(struct Func *funcs_list)
{
    struct Func *func;
    for (func = funcs_list; func; func = func->next) {
        outc('\n');
        emit_func_decl(func, false);
        beginf("\n{\n");
        emit_datadef_list(func->vardecls);
        /* TODO for multiple return values: define variable of __Return type */
        emit_statements_inside(func->code);
        endf("}\n");
    }
}