Cthulhu  0.2.10
Cthulhu compiler collection
sema.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-3.0-only
2 
3 #include "ctu/sema/sema.h"
4 
7 #include "cthulhu/tree/tree.h"
8 #include "cthulhu/tree/query.h"
9 
10 #include "cthulhu/util/util.h"
11 
12 #include "memory/memory.h"
13 #include "std/vector.h"
14 
15 #include "base/panic.h"
16 
20 
22 {
23  CTASSERT(sema != NULL);
24  CTASSERT(block != NULL);
25 
26  ctu_sema_t it = {
27  .sema = sema,
28  .decl = decl,
29  .block = block
30  };
31 
32  return it;
33 }
34 
36 {
37  CTASSERT(parent != NULL);
38  CTASSERT(decl != NULL);
39  CTASSERT(block != NULL);
40 
41  ctu_sema_t it = {
42  .sema = sema,
43  .decl = decl,
44  .block = block,
45  .current_loop = parent->current_loop,
46  };
47 
48  return it;
49 }
50 
52 {
53  CTASSERT(sema != NULL);
54 
55  ctu_sema_t it = {
56  .sema = sema->sema,
57  .decl = sema->decl,
58  .block = sema->block,
59  .current_loop = sema->current_loop,
60  };
61 
62  return it;
63 }
64 
66 {
67  tree_t *it = sema->sema;
68  return it->reports;
69 }
70 
74 
75 tree_t *ctu_get_namespace(tree_t *sema, const char *name, bool *imported)
76 {
77  const size_t local[] = { eCtuTagModules };
78  search_t search_local = { local, sizeof(local) / sizeof(size_t) };
79  void *it = util_select_decl(sema, search_local, name);
80  if (it != NULL) { return it; }
81 
82  const size_t global[] = { eCtuTagImports };
83  search_t search_global = { global, sizeof(global) / sizeof(size_t) };
84  it = util_select_decl(sema, search_global, name);
85  if (it != NULL)
86  {
87  if (imported != NULL) { *imported = true; }
88  return it;
89  }
90 
91  return NULL;
92 }
93 
94 tree_t *ctu_get_import(tree_t *sema, const char *name)
95 {
96  const size_t tags[] = { eCtuTagImports };
97  search_t search = { tags, sizeof(tags) / sizeof(size_t) };
98  return util_select_decl(sema, search, name);
99 }
100 
101 tree_t *ctu_get_type(tree_t *sema, const char *name)
102 {
103  const size_t tags[] = { eCtuTagTypes };
104  search_t search = { tags, sizeof(tags) / sizeof(size_t) };
105  return util_select_decl(sema, search, name);
106 }
107 
108 ctu_attrib_t *ctu_get_attrib(tree_t *sema, const char *name)
109 {
110  const size_t tags[] = { eCtuTagAttribs };
111  search_t search = { tags, sizeof(tags) / sizeof(size_t) };
112  return util_select_decl(sema, search, name);
113 }
114 
115 tree_t *ctu_get_decl(tree_t *sema, const char *name)
116 {
117  const size_t tags[] = { eCtuTagValues, eCtuTagFunctions };
118  search_t search = { tags, sizeof(tags) / sizeof(size_t) };
119  return util_select_decl(sema, search, name);
120 }
121 
122 tree_t *ctu_get_loop(tree_t *sema, const char *name)
123 {
124  const size_t tags[] = { eCtuTagLabels };
125  search_t search = { tags, sizeof(tags) / sizeof(size_t) };
126  return util_select_decl(sema, search, name);
127 }
128 
129 void ctu_add_decl(tree_t *sema, ctu_tag_t tag, const char *name, tree_t *decl)
130 {
131  CTASSERT(name != NULL);
132  CTASSERT(decl != NULL);
133 
134  tree_t *old = tree_module_get(sema, tag, name);
135  if (old != NULL)
136  {
137  evt_symbol_shadowed(sema->reports, name, tree_get_node(old), tree_get_node(decl));
138  }
139  else
140  {
141  tree_module_set(sema, tag, name, decl);
142  }
143 }
144 
148 
150 {
151  CTASSERT(sema != NULL);
152 
153  return sema->current_loop;
154 }
155 
157 {
158  CTASSERT(sema != NULL);
159 
160  sema->current_loop = loop;
161 }
162 
166 
167 static tree_t *gIntTypes[eDigitTotal * eSignTotal] = { NULL };
168 static tree_t *gBoolType = NULL;
169 static tree_t *gVoidType = NULL;
170 static tree_t *gOpaqueType = NULL;
171 static tree_t *gStringType = NULL;
172 
173 static tree_t *gLetter = NULL;
174 
175 #define DIGIT_TYPE(DIGIT, SIGN) gIntTypes[(DIGIT) * eSignTotal + (SIGN)]
176 
177 static tree_t *make_int_type(const node_t *node, const char *name, digit_t digit, sign_t sign)
178 {
179  return (DIGIT_TYPE(digit, sign) = tree_type_digit(node, name, digit, sign));
180 }
181 
182 static tree_t *make_bool_type(const node_t *node, const char *name)
183 {
184  return (gBoolType = tree_type_bool(node, name));
185 }
186 
187 static tree_t *make_str_type(const node_t *node, const char *name)
188 {
189  return (gStringType = tree_type_pointer(node, name, gLetter, SIZE_MAX));
190 }
191 
192 static tree_t *make_void_type(const node_t *node, const char *name)
193 {
194  return (gVoidType = tree_type_unit(node, name));
195 }
196 
197 static tree_t *make_opaque_type(const node_t *node, const char *name)
198 {
199  return (gOpaqueType = tree_type_opaque(node, name));
200 }
201 
203 {
204  return DIGIT_TYPE(digit, sign);
205 }
206 
207 tree_t *ctu_get_char_type(void) { return gLetter; }
208 tree_t *ctu_get_bool_type(void) { return gBoolType; }
209 tree_t *ctu_get_void_type(void) { return gVoidType; }
210 
214 
215 typedef struct digit_info_t {
216  const char *name;
219 } digit_info_t;
220 
221 static const digit_info_t kDigitInfo[] = {
222  { "char", eDigitChar, eSignSigned },
223  { "uchar", eDigitChar, eSignUnsigned },
224 
225  { "short", eDigitShort, eSignSigned },
226  { "ushort", eDigitShort, eSignUnsigned },
227 
228  { "int", eDigitInt, eSignSigned },
229  { "uint", eDigitInt, eSignUnsigned },
230 
231  { "long", eDigitLong, eSignSigned },
232  { "ulong", eDigitLong, eSignUnsigned },
233 
234  { "isize", eDigitSize, eSignSigned },
235  { "usize", eDigitSize, eSignUnsigned },
236 
237  // TODO: better names for these
238  { "ptrdiff", eDigitPtr, eSignSigned },
239  { "uptrdiff", eDigitPtr, eSignUnsigned },
240 
241  { "int8", eDigit8, eSignSigned },
242  { "uint8", eDigit8, eSignUnsigned },
243 
244  { "int16", eDigit16, eSignSigned },
245  { "uint16", eDigit16, eSignUnsigned },
246 
247  { "int32", eDigit32, eSignSigned },
248  { "uint32", eDigit32, eSignUnsigned },
249 
250  { "int64", eDigit64, eSignSigned },
251  { "uint64", eDigit64, eSignUnsigned },
252 
253  { "intfast8", eDigitFast8, eSignSigned },
254  { "uintfast8", eDigitFast8, eSignUnsigned },
255 
256  { "intfast16", eDigitFast16, eSignSigned },
257  { "uintfast16", eDigitFast16, eSignUnsigned },
258 
259  { "intfast32", eDigitFast32, eSignSigned },
260  { "uintfast32", eDigitFast32, eSignUnsigned },
261 
262  { "intfast64", eDigitFast64, eSignSigned },
263  { "uintfast64", eDigitFast64, eSignUnsigned },
264 
265  { "intleast8", eDigitLeast8, eSignSigned },
266  { "uintleast8", eDigitLeast8, eSignUnsigned },
267 
268  { "intleast16", eDigitLeast16, eSignSigned },
269  { "uintleast16", eDigitLeast16, eSignUnsigned },
270 
271  { "intleast32", eDigitLeast32, eSignSigned },
272  { "uintleast32", eDigitLeast32, eSignUnsigned },
273 
274  { "intleast64", eDigitLeast64, eSignSigned },
275  { "uintleast64", eDigitLeast64, eSignUnsigned },
276 
277  { "float", eDigitFloat, eSignDefault },
278  { "double", eDigitDouble, eSignDefault },
279 };
280 
281 void ctu_rt_mod(language_runtime_t *runtime, tree_t *root)
282 {
283  arena_t *arena = runtime->arena;
284  const node_t *node = tree_get_node(root);
285 
286  gLetter = tree_type_digit(node, "letter", eDigitChar, eSignSigned);
287  tree_set_qualifiers(gLetter, eQualConst);
288 
289  for (size_t i = 0; i < sizeof(kDigitInfo) / sizeof(digit_info_t); i++)
290  {
291  const digit_info_t *info = &kDigitInfo[i];
292  tree_t *it = make_int_type(node, info->name, info->digit, info->sign);
293  ctu_add_decl(root, eCtuTagTypes, info->name, it);
294  }
295 
296  ctu_add_decl(root, eCtuTagTypes, "bool", make_bool_type(node, "bool"));
297  ctu_add_decl(root, eCtuTagTypes, "str", make_str_type(node, "str"));
298  ctu_add_decl(root, eCtuTagTypes, "void", make_void_type(node, "void"));
299  ctu_add_decl(root, eCtuTagTypes, "opaque", make_opaque_type(node, "opaque"));
300 
301  ctu_init_attribs(root, arena);
302 }
CT_PUREFN CT_TREE_API const node_t * tree_get_node(const tree_t *tree)
Definition: context.c:94
CT_TREE_API void tree_set_qualifiers(tree_t *tree, tree_quals_t qualifiers)
Definition: context.c:42
ctu_tag_t
Definition: sema.h:14
CT_EVENTS_API event_builder_t evt_symbol_shadowed(logger_t *logger, const char *name, const node_t *prev, const node_t *next)
signal that a declaration would shadow a previous declaration
Definition: events.c:47
#define CTASSERT(expr)
assert a condition, prints the condition as a message
Definition: panic.h:130
CT_UTIL_API void * util_select_decl(tree_t *sema, search_t search, const char *name)
search for a declaration by name in a set of tags
Definition: util.c:16
CT_TREE_API tree_t * tree_type_bool(const node_t *node, const char *name)
create a bool type, this is a type that has only two values, true and false
Definition: tree.c:128
CT_TREE_API tree_t * tree_type_pointer(const node_t *node, const char *name, const tree_t *pointer, size_t length)
create a pointer type
Definition: tree.c:165
CT_TREE_API tree_t * tree_type_opaque(const node_t *node, const char *name)
create an opaque pointer type
Definition: tree.c:133
sign_t
integer sign
Definition: ops.h:104
digit_t
digit width
Definition: ops.h:96
CT_TREE_API tree_t * tree_type_digit(const node_t *node, const char *name, digit_t digit, sign_t sign)
create a digit type
Definition: tree.c:138
CT_TREE_API tree_t * tree_type_unit(const node_t *node, const char *name)
create a unit type, this is a type that has only one value. equivilent to void
Definition: tree.c:123
void * tree_module_set(tree_t *self, size_t tag, const char *name, void *value)
set a declaration in the current module
Definition: sema.c:111
void * tree_module_get(tree_t *self, size_t tag, const char *name)
recursively search for a declaration in a module
Definition: sema.c:59
void ctu_init_attribs(tree_t *sema, arena_t *arena)
Definition: attrib.c:231
void ctu_rt_mod(language_runtime_t *runtime, tree_t *root)
Definition: sema.c:281
void ctu_add_decl(tree_t *sema, ctu_tag_t tag, const char *name, tree_t *decl)
Definition: sema.c:129
tree_t * ctu_get_int_type(digit_t digit, sign_t sign)
Definition: sema.c:202
ctu_attrib_t * ctu_get_attrib(tree_t *sema, const char *name)
Definition: sema.c:108
ctu_sema_t ctu_sema_nested(ctu_sema_t *parent, tree_t *sema, tree_t *decl, vector_t *block)
Definition: sema.c:35
tree_t * ctu_get_char_type(void)
Definition: sema.c:207
tree_t * ctu_get_loop(tree_t *sema, const char *name)
Definition: sema.c:122
ctu_sema_t ctu_sema_init(tree_t *sema, tree_t *decl, vector_t *block)
Definition: sema.c:21
tree_t * ctu_get_namespace(tree_t *sema, const char *name, bool *imported)
Definition: sema.c:75
tree_t * ctu_get_type(tree_t *sema, const char *name)
Definition: sema.c:101
void ctu_set_current_loop(ctu_sema_t *sema, tree_t *loop)
Definition: sema.c:156
tree_t * ctu_get_import(tree_t *sema, const char *name)
Definition: sema.c:94
ctu_sema_t ctu_sema_child(ctu_sema_t *sema)
Definition: sema.c:51
tree_t * ctu_get_decl(tree_t *sema, const char *name)
Definition: sema.c:115
#define DIGIT_TYPE(DIGIT, SIGN)
Definition: sema.c:175
tree_t * ctu_get_void_type(void)
Definition: sema.c:209
tree_t * ctu_get_bool_type(void)
Definition: sema.c:208
tree_t * ctu_current_loop(ctu_sema_t *sema)
Definition: sema.c:149
logger_t * ctu_sema_reports(ctu_sema_t *sema)
Definition: sema.c:65
@ eSignTotal
Definition: ops.h:107
@ eDigitTotal
Definition: ops.h:99
an allocator object
Definition: arena.h:86
vector_t * block
current statement block
Definition: sema.h:27
tree_t * decl
current decl
Definition: sema.h:26
tree_t * current_loop
current loop
Definition: sema.h:28
tree_t * sema
current scope
Definition: sema.h:25
const char * name
Definition: sema.c:216
sign_t sign
Definition: sema.c:218
digit_t digit
Definition: sema.c:217
arena_t * arena
default memory arena
Definition: broker.h:266
a logging sink
Definition: notify.c:14
a position in a source file
Definition: node.h:23
Definition: util.h:28
Definition: tree.h:67
logger_t * reports
Definition: tree.h:227
a generic vector of pointers
Definition: vector.c:16