aboutsummaryrefslogtreecommitdiff
path: root/compiler/types.cup
blob: c2afdec02b9d0284d58f94bc541f04dd5d27d8d3 (plain) (blame)
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
import "std/common.cup"

enum BaseType {
    TYPE_VOID,
    TYPE_ANY,

    TYPE_PTR,
    TYPE_ARRAY,
    TYPE_STRUCT,
    TYPE_UNION,

    TYPE_INT,
    TYPE_CHAR,
};

struct Type {
    typ: int;
    ptr: Type*;
    struct_name: char*;
    size: int;
    array_size: int;
    fields: struct {
        names: char**;
        types: Type**;
        num_fields: int;
    };
};

fn size_for_base_type(type: int): int {
    if (type == TYPE_INT) return 8;
    if (type == TYPE_PTR) return 8;
    if (type == TYPE_CHAR) return 1;
    // Need to be initialized explicitly for compound types 
    return 0; 
}

fn size_for_type(typ: Type*): int {
    if (typ.typ == TYPE_INT) return 8;
    if (typ.typ == TYPE_PTR) return 8;
    if (typ.typ == TYPE_CHAR) return 1;
    if (typ.typ == TYPE_ARRAY) return typ.array_size * size_for_type(typ.ptr);
    if (typ.typ == TYPE_STRUCT) return typ.size;
    if (typ.typ == TYPE_UNION) return typ.size;
    if (typ.typ == TYPE_VOID) return 0;
    if (typ.typ == TYPE_ANY) return 8;
    die("Unknown type in size_for_type");
}

let _type_int: Type* = null;
let _type_char: Type* = null;
let _type_void: Type* = null;
let _type_any: Type* = null;

fn type_new(typ: int): Type* {
    if (_type_int == null) { _type_int = malloc(sizeof(Type)); _type_int.typ = TYPE_INT; _type_int.size = 8; }
    if (_type_char == null) { _type_char = malloc(sizeof(Type)); _type_char.typ = TYPE_CHAR; _type_char.size = 1; }
    if (_type_void == null) { _type_void = malloc(sizeof(Type)); _type_void.typ = TYPE_VOID; _type_void.size = 0; }
    if (_type_any == null) { _type_any = malloc(sizeof(Type)); _type_any.typ = TYPE_ANY; _type_any.size = 8; }
    
    if (typ == TYPE_INT) return _type_int;
    if (typ == TYPE_CHAR) return _type_char;
    if (typ == TYPE_VOID) return _type_void;
    if (typ == TYPE_ANY) return _type_any;

    putsln("Allocating Type*");

    let t: Type* = malloc(sizeof(Type));
    t.typ = typ;
    t.size = size_for_base_type(typ);
    return t;
}

fn type_new_ptr(typ: int): Type* {
    let ptr = type_new(TYPE_PTR);
    ptr.ptr = type_new(typ);
    return ptr;
}

// This is named differently because it performs an allocation
fn create_type_string(typ: Type *): char* {
    let buf: char* = malloc(32);
    while (typ.typ == TYPE_PTR || typ.typ == TYPE_ARRAY) {
        strcat(buf, typ.typ == TYPE_PTR ? "*" : "[]");
        typ = typ.ptr;
    }

         if (typ.typ == TYPE_INT) strcat(buf, "int");
    else if (typ.typ == TYPE_CHAR) strcat(buf, "char");
    else if (typ.typ == TYPE_VOID) strcat(buf, "void");
    else if (typ.typ == TYPE_ANY) strcat(buf, "any");
    else  die("type_to_string: unknown type");

    return buf;
}