Cthulhu  0.2.10
Cthulhu compiler collection
query.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: LGPL-3.0-only
2 
3 #include "arena/arena.h"
4 #include "base/util.h"
5 #include "common.h"
6 
7 #include "cthulhu/tree/query.h"
8 
9 #include "memory/memory.h"
10 #include "std/vector.h"
11 #include "std/str.h"
12 
13 #include "base/panic.h"
14 
15 #include <stdint.h>
16 #include <stdio.h>
17 
18 static bool has_name(tree_kind_t kind)
19 {
20  return kind_has_tag(kind, eTagName);
21 }
22 
24 {
25  switch (kind)
26  {
27 #define TREE_KIND(ID, NAME, TAGS) case ID: return NAME;
28 #include "cthulhu/tree/tree.inc"
29 
30  default: CT_NEVER("invalid tree kind %d", kind);
31  }
32 }
33 
34 static const char *length_name(size_t length, arena_t *arena)
35 {
36  if (length == SIZE_MAX) return "unbounded";
37  return str_format(arena, "%zu", length);
38 }
39 
40 const char *tree_to_string(const tree_t *self)
41 {
42  arena_t *arena = get_global_arena();
43  return tree_to_string_arena(self, arena);
44 }
45 
46 char *tree_to_string_arena(const tree_t *self, arena_t *arena)
47 {
48  CTASSERT(arena != NULL);
49 
50  if (self == NULL) { return arena_strdup("nil", arena); }
51 
52  tree_kind_t kind = tree_get_kind(self);
53  switch (kind)
54  {
55  case eTreeError:
56  return str_format(arena, "{ error: %s }", self->message);
57 
58  case eTreeTypeArray:
59  return str_format(arena, "{ array %s { element: %s, length: %zu } }", tree_get_name(self), tree_to_string(self->ptr), self->length);
60 
61  case eTreeTypePointer:
62  return str_format(arena, "{ pointer %s { to: %s, length: %s } }", tree_get_name(self), tree_to_string(self->ptr), length_name(self->length, arena));
63 
64  case eTreeTypeReference:
65  return str_format(arena, "{ reference %s { to: %s } }", tree_get_name(self), tree_to_string(self->ptr));
66 
67  case eTreeTypeAlias:
68  return str_format(arena, "{ alias %s { to: %s } }", tree_get_name(self), tree_to_string_arena(tree_get_type(self), arena));
69 
70  default:
71  break;
72  }
73 
74  if (has_name(self->kind))
75  {
76  return str_format(arena, "{ %s: %s }", tree_kind_to_string(self->kind), tree_get_name(self));
77  }
78 
79  const char *it = tree_kind_to_string(self->kind);
80  return arena_strdup(it, arena);
81 }
82 
84 {
85  CTASSERT(self != NULL);
86  CTASSERT(self->attrib != NULL);
87 
88  return self->attrib;
89 }
90 
91 bool tree_is(const tree_t *self, tree_kind_t kind)
92 {
93  CTASSERT(self != NULL);
94 
95  return self->kind == kind;
96 }
97 
98 bool tree_has_vis(const tree_t *self, tree_visibility_t visibility)
99 {
100  const tree_attribs_t *attrib = tree_get_attrib(self);
101  return attrib->visibility == visibility;
102 }
103 
107 
108 #if CTU_DEBUG
109 # define EXPECT_STORAGE_DECL(SELF) CTASSERTF(tree_has_storage(SELF), "only globals and locals can have storage, got %s", tree_to_string(SELF))
110 #else
111 # define EXPECT_STORAGE_DECL(SELF) (void)0
112 #endif
113 
114 bool tree_has_storage(const tree_t *self)
115 {
116  return tree_is(self, eTreeDeclGlobal) || tree_is(self, eTreeDeclLocal);
117 }
118 
120 {
121  EXPECT_STORAGE_DECL(self);
122 
123  return self->storage;
124 }
125 
127 {
128  tree_storage_t storage = get_storage(self);
129 
130  tree_quals_t quals = storage.quals;
131  CTASSERTF((quals & (eQualConst | eQualMutable)) != (eQualConst | eQualMutable), "global %s has both const and mutable quals", tree_to_string(self));
132  CTASSERTF(quals != eQualNone, "global %s has no quals", tree_to_string(self));
133  return quals;
134 }
135 
137 {
138  tree_storage_t storage = get_storage(self);
139 
140  CTASSERTF(storage.storage != NULL, "global %s has no storage type", tree_to_string(self));
141  return storage.storage;
142 }
143 
144 size_t tree_get_storage_size(const tree_t *self)
145 {
146  tree_storage_t storage = get_storage(self);
147 
148  CTASSERTF(storage.length != SIZE_MAX, "global %s has no storage length", tree_to_string(self));
149  return storage.length;
150 }
151 
155 
157 {
158  TREE_EXPECT(self, eTreeTypeEnum);
159 
160  return self->cases;
161 }
162 
166 
167 const tree_t *tree_fn_get_return(const tree_t *self)
168 {
169  switch (tree_get_kind(self))
170  {
171  case eTreeTypeReference: return tree_fn_get_return(self->ptr);
172  case eTreeTypeClosure: return self->return_type;
173  case eTreeDeclFunction: return tree_fn_get_return(tree_get_type(self));
174 
175  default: CT_NEVER("invalid function kind %s", tree_to_string(self));
176  }
177 }
178 
179 const vector_t *tree_fn_get_params(const tree_t *self)
180 {
181  switch (tree_get_kind(self))
182  {
183  case eTreeTypeReference: return tree_fn_get_params(self->ptr);
184  case eTreeTypeClosure: return self->params;
185  case eTreeDeclFunction: return tree_fn_get_params(tree_get_type(self));
186 
187  default: CT_NEVER("invalid function kind %s", tree_to_string(self));
188  }
189 }
190 
192 {
193  switch (tree_get_kind(self))
194  {
195  case eTreeTypeClosure: return self->arity;
196  case eTreeDeclFunction: {
197  const tree_t *type = tree_get_type(self);
198  return type->arity;
199  }
200 
201  default: CT_NEVER("invalid function kind %s", tree_to_string(self));
202  }
203 }
204 
208 
209 static tree_t *find_field(vector_t *fields, const char *name)
210 {
211  size_t len = vector_len(fields);
212  for (size_t i = 0; i < len; i++)
213  {
214  tree_t *field = vector_get(fields, i);
215  if (str_equal(tree_get_name(field), name))
216  {
217  return field;
218  }
219  }
220 
221  return NULL;
222 }
223 
224 tree_t *tree_ty_get_field(const tree_t *self, const char *name)
225 {
226  TREE_EXPECT(self, eTreeTypeStruct);
227 
228  return find_field(self->fields, name);
229 }
230 
231 tree_t *tree_ty_get_case(const tree_t *self, const char *name)
232 {
233  TREE_EXPECT(self, eTreeTypeEnum);
234 
235  return find_field(self->cases, name);
236 }
237 
238 bool tree_ty_is_address(const tree_t *type)
239 {
240  switch (tree_get_kind(type))
241  {
242  case eTreeTypePointer:
243  case eTreeTypeReference:
244  return true;
245 
246  default:
247  return false;
248  }
249 }
250 
251 static tree_quals_t get_quals(const tree_t *self)
252 {
253  CTASSERT(self != NULL);
254  return self->quals;
255 }
256 
258 {
259  tree_quals_t quals = get_quals(self);
260 
261  // make sure we dont have both eQualConst and eQualMutable bits set
262  CTASSERTF((quals & (eQualConst | eQualMutable)) != (eQualConst | eQualMutable), "type %s has both const and mutable quals", tree_to_string(self));
263 
264  return quals;
265 }
266 
267 const tree_t *tree_ty_load_type(const tree_t *self)
268 {
269  switch (tree_get_kind(self))
270  {
271  case eTreeTypeArray:
272  case eTreeTypePointer:
273  case eTreeTypeReference:
274  return self->ptr;
275 
276  default:
277  return self;
278  }
279 }
CT_PUREFN CT_TREE_API tree_kind_t tree_get_kind(const tree_t *tree)
Definition: context.c:143
CT_PUREFN CT_TREE_API const char * tree_get_name(const tree_t *tree)
Definition: context.c:102
CT_PUREFN CT_TREE_API const tree_t * tree_get_type(const tree_t *tree)
Definition: context.c:132
CT_CONSTFN CT_LOCAL bool kind_has_tag(tree_kind_t kind, tree_tags_t tags)
Definition: context.c:17
#define TREE_EXPECT(SELF, KIND)
Definition: common.h:22
vector_t * tree_enum_get_cases(const tree_t *self)
Definition: query.c:156
tree_storage_t get_storage(const tree_t *self)
Definition: query.c:119
bool tree_has_vis(const tree_t *self, tree_visibility_t visibility)
Definition: query.c:98
const tree_t * tree_ty_load_type(const tree_t *self)
get the type of a type after it has been loaded
Definition: query.c:267
const tree_attribs_t * tree_get_attrib(const tree_t *self)
Definition: query.c:83
tree_quals_t tree_ty_get_quals(const tree_t *self)
Definition: query.c:257
tree_t * tree_ty_get_field(const tree_t *self, const char *name)
Definition: query.c:224
bool tree_is(const tree_t *self, tree_kind_t kind)
Definition: query.c:91
const char * tree_to_string(const tree_t *self)
Definition: query.c:40
const vector_t * tree_fn_get_params(const tree_t *self)
Definition: query.c:179
const tree_t * tree_get_storage_type(const tree_t *self)
Definition: query.c:136
const char * tree_kind_to_string(tree_kind_t kind)
Definition: query.c:23
tree_t * tree_ty_get_case(const tree_t *self, const char *name)
Definition: query.c:231
bool tree_has_storage(const tree_t *self)
Definition: query.c:114
bool tree_ty_is_address(const tree_t *type)
Definition: query.c:238
tree_quals_t tree_get_storage_quals(const tree_t *self)
Definition: query.c:126
char * tree_to_string_arena(const tree_t *self, arena_t *arena)
Definition: query.c:46
#define EXPECT_STORAGE_DECL(SELF)
Definition: query.c:111
tree_arity_t tree_fn_get_arity(const tree_t *self)
Definition: query.c:191
size_t tree_get_storage_size(const tree_t *self)
Definition: query.c:144
const tree_t * tree_fn_get_return(const tree_t *self)
Definition: query.c:167
CT_NODISCARD CT_PUREFN CT_BASE_API bool str_equal(const char *lhs, const char *rhs)
compare strings equality
Definition: util.c:76
CT_MEMORY_API arena_t * get_global_arena(void)
get the global memory arena
Definition: memory.c:16
CT_NODISCARD CT_ARENA_API char * arena_strdup(const char *str, arena_t *arena)
allocate a copy of a string from a custom allocator
Definition: arena.c:95
#define CT_NEVER(...)
assert that a code path is never reached
Definition: panic.h:136
#define CTASSERT(expr)
assert a condition, prints the condition as a message
Definition: panic.h:130
#define CTASSERTF(expr,...)
assert a condition with a message and optional format arguments
Definition: panic.h:116
tree_arity_t
all arities
Definition: ops.h:64
tree_quals_t
all type qualifiers
Definition: ops.h:25
tree_visibility_t
symbol visibility
Definition: ops.h:88
tree_kind_t
all tree node types
Definition: ops.h:17
CT_NODISCARD CT_PUREFN CT_STD_API void * vector_get(const vector_t *vector, size_t index)
get a value from a vector
Definition: vector.c:134
CT_NODISCARD CT_PUREFN CT_STD_API size_t vector_len(const vector_t *vector)
get the length of a vector
Definition: vector.c:152
STA_DECL char * str_format(arena_t *arena, const char *fmt,...)
Definition: str.c:97
an allocator object
Definition: arena.h:86
tree_visibility_t visibility
the visibility of the declaration
Definition: tree.h:52
storage for a value
Definition: context.h:23
tree_quals_t quals
the qualifiers for the storage
Definition: context.h:31
size_t length
the count of elements
Definition: context.h:28
const tree_t * storage
the underlying storage type
Definition: context.h:25
Definition: tree.h:67
tree_arity_t arity
Definition: tree.h:209
const tree_t * ptr
Definition: tree.h:172
a generic vector of pointers
Definition: vector.c:16