-
Notifications
You must be signed in to change notification settings - Fork 43
/
type.c
175 lines (156 loc) · 5.54 KB
/
type.c
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include "gwion_util.h"
#include "gwion_ast.h"
#include "gwion_env.h"
#include "vm.h"
#include "traverse.h"
#include "parse.h"
#include "gwion.h"
#include "clean.h"
#include "object.h"
#include "instr.h"
#include "operator.h"
#include "import.h"
ANN static inline bool freeable(const Type a) {
return tflag(a, tflag_tmpl) || GET_FLAG(a, global);
}
ANN void free_type(const Type a, struct Gwion_ *const gwion) {
if (freeable(a)) {
if (tflag(a, tflag_udef))
free_union_def(gwion->mp, a->info->udef);
else if (tflag(a, tflag_cdef))
class_def_cleaner(gwion, a->info->cdef);
}
// if (tflag(a, tflag_cdef) && a->info->parent)
// type_remref(a->info->parent, gwion);
if (a->nspc) nspc_remref(a->nspc, gwion);
if (a->info->tuple) free_tupleform(a->info->tuple, gwion);
mp_free(gwion->mp, TypeInfo, a->info);
mp_free(gwion->mp, Type, a);
}
Type new_type(MemPool p, const m_str name, const Type parent) {
const Type type = mp_calloc(p, Type);
type->name = name;
type->info = mp_calloc(p, TypeInfo);
type->info->parent = parent;
if (parent) type->size = parent->size;
type->ref = 1;
return type;
}
ANN Type type_copy(MemPool p, const Type type) {
const Type a = new_type(p, type->name, type->info->parent);
a->size = type->size;
a->array_depth = type->array_depth;
a->info->gack = type->info->gack;
return a;
}
ANN bool isa(const restrict Type var, const restrict Type parent) {
return (var == parent) ? true
: var->info->parent ? isa(var->info->parent, parent)
: false;
}
ANN Type find_common_anc(const restrict Type lhs, const restrict Type rhs) {
return isa(lhs, rhs) ? rhs : isa(rhs, lhs) ? lhs : NULL;
}
#define describe_find(name, t) \
ANN t find_##name(const Type type, const Symbol xid) { \
if (type->nspc) { \
const t val = nspc_lookup_##name##2(type->nspc, xid); \
if (val) return val; \
} \
return type->info->parent ? find_##name(type->info->parent, xid) : NULL; \
}
describe_find(value, Value)
// describe_find(func, Func)
ANN Type array_base(Type type) {
const Type t = typedef_base(type);
return t->array_depth ? array_base(t->info->base_type) : t;
}
ANN /*static */ Symbol array_sym(const Env env, const Type src,
const m_uint depth) {
if (src->array_depth == depth) return insert_symbol(src->name);
const m_uint total_depth = src->array_depth + depth;
const Type t = array_base_simple(src);
size_t len = strlen(t->name);
char name[len + 2 * total_depth + 1];
strcpy(name, t->name);
m_uint i = total_depth + 1;
while (--i) {
strcpy(name + len, "[]");
len += 2;
}
return insert_symbol(name);
}
ANN Type array_type(const Env env, const Type src, const m_uint depth, const loc_t loc) {
if(!depth) return src;
const Symbol sym = array_sym(env, src, depth);
const Type type = nspc_lookup_type1(src->info->value->from->owner, sym);
if (type) return type;
const size_t tdepth = depth + src->array_depth;
const Type base = tdepth > 1 ? array_type(env, src, tdepth - 1, loc) : src;
const Type_Decl td = { .tag = MK_TAG(insert_symbol(src->name), loc) };
struct TemplateScan ts = {.t = base, .td=&td };
struct Op_Import opi = {.op = insert_symbol("class"),
.lhs = env->gwion->type[et_array],
.data = (uintptr_t)&ts};
return op_check(env, &opi);
}
ANN bool type_ref(Type t) {
do {
if (tflag(t, tflag_empty)) return true;
if (tflag(t, tflag_typedef) && tflag(t, tflag_cdef)) {
if (t->info->cdef->base.ext && t->info->cdef->base.ext->array) {
if (!t->info->cdef->base.ext->array->exp)
return true;
else {
const Type type = t->info->parent->info->base_type;
if (tflag(type, tflag_empty)) return true;
}
}
}
} while ((t = t->info->parent));
return false;
}
ANN m_uint get_depth(const Type type) {
m_uint depth = 0;
Type t = type;
do {
if (t->array_depth) {
depth += t->array_depth;
t = t->info->base_type;
} else
t = t->info->parent;
} while (t);
return depth;
}
ANN bool is_func(const struct Gwion_ *gwion, const Type t) {
return isa(actual_type(gwion, t), gwion->type[et_function]);
}
ANN bool is_object(const struct Gwion_ *gwion, const Type t) {
return isa(t, gwion->type[et_object]);
}
ANN inline bool is_class(const struct Gwion_ *gwion, const Type t) {
// return isa(t, gwion->type[et_class]);
return t->info->parent == gwion->type[et_class];
}
ANN Type actual_type(const struct Gwion_ *gwion, const Type t) {
return is_class(gwion, t) ? t->info->base_type : t;
}
ANN void inherit(const Type t) {
const Nspc nspc = t->nspc, parent = t->info->parent->nspc;
if (nspc) nspc->offset = parent->offset;
if (parent && parent->vtable.ptr) vector_copy2(&parent->vtable, &nspc->vtable);
}
ANN bool from_global_nspc(const Env env, const Nspc nspc) {
Nspc global = env->global_nspc;
while(global) {
if (nspc == global)
return true;
global = global->parent;
}
return false;
}
ANN bool type_global(const Env env, Type t) {
do if(from_global_nspc(env, t->info->value->from->owner)) return true;
while((t = t->info->value->from->owner_class));
return false;
}