Cthulhu  0.2.10
Cthulhu compiler collection
expr.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-3.0-only
2 
3 #include "ctu/sema/expr.h"
5 #include "cthulhu/tree/builtin.h"
6 #include "cthulhu/tree/ops.h"
7 #include "cthulhu/tree/tree.h"
9 #include "ctu/sema/default.h"
10 #include "ctu/sema/type.h"
11 #include "ctu/driver.h"
12 #include "ctu/ast.h"
13 
14 #include "cthulhu/util/types.h"
15 #include "cthulhu/util/util.h"
16 
17 #include "cthulhu/tree/query.h"
18 
19 #include "memory/memory.h"
20 #include "std/set.h"
21 #include "std/str.h"
22 #include "std/vector.h"
23 
24 #include "base/panic.h"
25 
26 #include "core/macros.h"
27 #include <stdio.h>
28 
32 
33 static const size_t kImportTags[] = {eCtuTagImports, eCtuTagTypes};
34 static const size_t kDeclTags[] = {eCtuTagValues, eCtuTagFunctions};
35 
36 static const search_t kSearchImports = {
37  .tags = kImportTags,
38  .count = sizeof(kImportTags) / sizeof(size_t),
39 };
40 
41 static const search_t kSearchDecl = {
42  .tags = kDeclTags,
43  .count = sizeof(kDeclTags) / sizeof(size_t),
44 };
45 
46 static bool is_public(const tree_t *decl)
47 {
48  const tree_attribs_t *attrib = tree_get_attrib(decl);
49  return attrib->visibility == eVisiblePublic;
50 }
51 
52 // TODO: needs_load is awful
53 static tree_t *sema_decl_name(tree_t *sema, const node_t *node, const vector_t *path, bool *needs_load)
54 {
55  bool is_imported = false;
56  tree_t *ns = util_search_namespace(sema, kSearchImports, node, path, &is_imported);
57  if (tree_is(ns, eTreeError))
58  {
59  return ns;
60  }
61 
62  const char *name = vector_tail(path);
63  if (tree_is(ns, eTreeTypeEnum))
64  {
65  tree_t *resolve = tree_resolve(tree_get_cookie(sema), ns);
66  const tree_t *it = tree_ty_get_case(resolve, name);
67  if (it != NULL)
68  {
69  *needs_load = false;
70  // TODO: we always treat this as const
71  // just need to slap const on everything in this file
72  return (tree_t*)it;
73  }
74 
75  return tree_raise(node, sema->reports, &kEvent_SymbolNotFound,
76  "enum case `%s` not found in `%s`", name, tree_to_string(ns));
77  }
78 
79  if (tree_is(ns, eTreeDeclModule))
80  {
81  tree_t *decl = util_select_decl(ns, kSearchDecl, name);
82  if (decl == NULL)
83  {
84  return tree_raise(node, sema->reports, &kEvent_SymbolNotFound,
85  "declaration `%s` not found in `%s`", name, tree_to_string(ns));
86  }
87 
88  if (is_imported && !is_public(decl))
89  {
90  msg_notify(sema->reports, &kEvent_SymbolNotVisible, node,
91  "cannot access non-public declaration `%s`", name);
92  }
93 
94  if (tree_is(decl, eTreeDeclFunction) || tree_is(decl, eTreeDeclParam))
95  {
96  *needs_load = false;
97  return decl;
98  }
99 
100  return tree_resolve(tree_get_cookie(sema), decl);
101  }
102 
103  CT_NEVER("invalid namespace type %s", tree_to_string(ns));
104 }
105 
109 
110 static tree_t *verify_expr_type(tree_t *sema, tree_kind_t kind, const tree_t *type,
111  const char *expr_kind, tree_t *expr)
112 {
113  CT_UNUSED(kind);
114  CT_UNUSED(expr_kind);
115 
116  if (type == NULL)
117  {
118  return expr;
119  }
120 
121  tree_t *result = util_type_cast(type, expr);
122  if (tree_is(result, eTreeError))
123  {
124  tree_report(sema->reports, result);
125  }
126  return result;
127 }
128 
129 static tree_t *sema_bool(tree_t *sema, const ctu_t *expr, const tree_t *implicit_type)
130 {
131  const tree_t *type = implicit_type ? implicit_type : ctu_get_bool_type();
132  if (!tree_is(type, eTreeTypeBool))
133  {
134  return tree_raise(expr->node, sema->reports, &kEvent_InvalidLiteralType, "invalid type `%s` for boolean literal",
135  tree_to_string(type));
136  }
137 
138  tree_t *it = tree_expr_bool(expr->node, type, expr->bool_value);
139 
140  return verify_expr_type(sema, eTreeTypeBool, type, "boolean literal", it);
141 }
142 
143 static tree_t *sema_int(tree_t *sema, const ctu_t *expr, const tree_t *implicit_type)
144 {
145  // TODO: validate implicit type if theres a suffix set
146  ctu_integer_t value = expr->integer;
147  const tree_t *type = implicit_type
148  ? implicit_type
149  : ctu_get_int_type(value.digit, value.sign);
150 
151  if (!tree_is(type, eTreeTypeDigit))
152  {
153  return tree_raise(expr->node, sema->reports, &kEvent_InvalidLiteralType, "invalid type `%s` for integer literal",
154  tree_to_string(type));
155  }
156 
157  tree_t *it = tree_expr_digit(expr->node, type, value.value);
158 
159  return verify_expr_type(sema, eTreeTypeDigit, type, "integer literal", it);
160 }
161 
162 static tree_t *sema_cast(ctu_sema_t *sema, const ctu_t *expr)
163 {
164  const tree_t *ty = ctu_sema_type(sema, expr->cast);
165  tree_t *inner = ctu_sema_rvalue(sema, expr->expr, NULL);
166  tree_t *cast = util_type_cast(ty, inner);
167  if (tree_is(cast, eTreeError))
168  {
169  tree_report(ctu_sema_reports(sema), cast);
170  }
171 
172  return cast;
173 }
174 
175 static tree_t *sema_string(tree_t *sema, const ctu_t *expr, const tree_t *implicit_type)
176 {
177  // +1 length for the nul terminator
178  tree_t *type = tree_type_array(expr->node, "str", ctu_get_char_type(), expr->length + 1);
179  tree_t *str = tree_expr_string(expr->node, type, expr->text, expr->length);
180  if (implicit_type != NULL)
181  {
182  return ctu_cast_type(sema, str, implicit_type);
183  }
184 
185  return str;
186 }
187 
188 static tree_t *sema_char(tree_t *sema, const ctu_t *expr, const tree_t *implicit_type)
189 {
190  const tree_t *type = implicit_type ? implicit_type : ctu_get_char_type();
191  if (!tree_is(type, eTreeTypeDigit))
192  {
193  return tree_raise(expr->node, sema->reports, &kEvent_InvalidLiteralType, "invalid type `%s` for char literal",
194  tree_to_string(type));
195  }
196 
197  if (expr->length < 1)
198  {
199  return tree_raise(expr->node, sema->reports, &kEvent_InvalidLiteralType, "char literal must contain at least 1 code point");
200  }
201 
202  mpz_t value;
203  mpz_init_set_ui(value, expr->text[0]);
204  tree_t *it = tree_expr_digit(expr->node, type, value);
205 
206  return verify_expr_type(sema, eTreeTypeDigit, type, "char literal", it);
207 }
208 
209 static tree_t *sema_name(tree_t *sema, const ctu_t *expr)
210 {
211  bool needs_load = false;
212  return sema_decl_name(sema, expr->node, expr->path, &needs_load);
213 }
214 
215 static tree_t *sema_load(tree_t *sema, const ctu_t *expr, const tree_t *implicit_type)
216 {
217  bool needs_load = true;
218 
219  tree_t *name = sema_decl_name(sema, expr->node, expr->path, &needs_load);
220 
221  if (!tree_is(name, eTreeDeclFunction))
222  {
223  if (tree_is(tree_get_type(name), eTreeTypeArray))
224  {
225  needs_load = false;
226  }
227  }
228 
229  if (needs_load)
230  {
231  name = tree_expr_load(expr->node, name);
232  }
233 
234  if (implicit_type != NULL)
235  {
236  tree_t *inner = tree_resolve_type(tree_get_cookie(sema), name);
237  return ctu_cast_type(sema, inner, implicit_type);
238  }
239 
240  return name;
241 }
242 
243 static tree_t *sema_compare(ctu_sema_t *sema, const ctu_t *expr)
244 {
245  tree_t *left = ctu_sema_rvalue(sema, expr->lhs, NULL);
246  tree_t *right = ctu_sema_rvalue(sema, expr->rhs, NULL);
247 
249  {
250  return tree_raise(expr->node, ctu_sema_reports(sema), &kEvent_InvalidBinaryOperation, "cannot compare `%s` to `%s`",
252  tree_to_string(tree_get_type(right)));
253  }
254 
255  return tree_expr_compare(expr->node, ctu_get_bool_type(), expr->compare, left, right);
256 }
257 
258 static tree_t *sema_binary(ctu_sema_t *sema, const ctu_t *expr, const tree_t *implicit_type)
259 {
260  tree_t *left = ctu_sema_rvalue(sema, expr->lhs, implicit_type);
261  tree_t *right = ctu_sema_rvalue(sema, expr->rhs, implicit_type);
262 
263  if (tree_is(left, eTreeError) || tree_is(right, eTreeError))
264  {
265  return tree_error(expr->node, &kEvent_InvalidBinaryOperation, "invalid binary");
266  }
267 
268  // TODO: calculate proper type to use
269  const tree_t *common_type = implicit_type == NULL ? tree_get_type(left) : implicit_type;
270 
271  const tree_t *lhs = ctu_cast_type(sema->sema, left, common_type);
272  const tree_t *rhs = ctu_cast_type(sema->sema, right, common_type);
273 
274  return tree_expr_binary(expr->node, common_type, expr->binary, lhs, rhs);
275 }
276 
277 static tree_t *sema_unary(ctu_sema_t *sema, const ctu_t *expr, const tree_t *implicit_type)
278 {
279  tree_t *inner = ctu_sema_rvalue(sema, expr->expr, implicit_type);
280 
281  if (tree_is(inner, eTreeError))
282  {
283  return tree_error(expr->node, &kEvent_InvalidUnaryOperation, "invalid unary");
284  }
285 
286  switch (expr->unary)
287  {
288  case eUnaryAbs:
289  case eUnaryNeg:
290  case eUnaryFlip:
291  if (!tree_is(tree_get_type(inner), eTreeTypeDigit))
292  {
293  return tree_raise(expr->node, ctu_sema_reports(sema), &kEvent_InvalidUnaryOperation,
294  "cannot apply unary `%s` to non-digit type `%s`",
295  unary_name(expr->unary), tree_to_string(tree_get_type(inner)));
296  }
297  break;
298 
299  case eUnaryNot:
300  if (!tree_is(tree_get_type(inner), eTreeTypeBool))
301  {
302  return tree_raise(expr->node, ctu_sema_reports(sema), &kEvent_InvalidUnaryOperation,
303  "cannot apply unary `%s` to non-bool type `%s`",
304  unary_name(expr->unary), tree_to_string(tree_get_type(inner)));
305  }
306  break;
307 
308  default: CT_NEVER("invalid unary %d", expr->unary);
309  }
310 
311  return tree_expr_unary(expr->node, expr->unary, inner);
312 }
313 
314 static const tree_t *get_param_checked(const vector_t *params, size_t i)
315 {
316  if (i >= vector_len(params))
317  {
318  return NULL;
319  }
320 
321  const tree_t *param = vector_get(params, i);
322  return tree_get_type(param);
323 }
324 
325 static tree_t *sema_call(ctu_sema_t *sema, const ctu_t *expr)
326 {
327  tree_t *callee = ctu_sema_lvalue(sema, expr->callee);
328  if (tree_is(callee, eTreeError))
329  {
330  return callee;
331  }
332 
333  const tree_t *type = tree_get_type(tree_resolve_type(tree_get_cookie(sema->sema), callee));
334  if (tree_is(type, eTreeTypeReference))
335  {
336  callee = tree_expr_load(expr->node, callee);
337  }
338 
339  const vector_t *params = tree_fn_get_params(type);
340 
341  arena_t *arena = get_global_arena();
342  size_t len = vector_len(expr->args);
343  vector_t *result = vector_of(len, arena);
344  for (size_t i = 0; i < len; i++)
345  {
346  const tree_t *ty = get_param_checked(params, i);
347 
348  ctu_t *it = vector_get(expr->args, i);
349  tree_t *arg = ctu_sema_rvalue(sema, it, ty);
350  vector_set(result, i, arg);
351  }
352 
353  return tree_expr_call(expr->node, callee, result);
354 }
355 
356 static const tree_t *get_ptr_type(const tree_t *ty)
357 {
358  if (tree_is(ty, eTreeTypeReference))
359  {
360  return ty->ptr;
361  }
362 
363  return ty;
364 }
365 
366 static tree_t *sema_deref_lvalue(ctu_sema_t *sema, const ctu_t *expr)
367 {
368  tree_t *inner = ctu_sema_rvalue(sema, expr->expr, NULL);
369  if (tree_is(inner, eTreeError))
370  {
371  return inner;
372  }
373 
374  mpz_t zero;
375  mpz_init_set_ui(zero, 0);
376  tree_t *index = tree_expr_digit(expr->node, ctu_get_int_type(eDigitSize, eSignUnsigned), zero);
377 
378  const tree_t *type = tree_get_type(inner);
379  const tree_t *ty = get_ptr_type(type);
380  if (!tree_is(ty, eTreeTypePointer))
381  {
382  return tree_raise(expr->node, ctu_sema_reports(sema), &kEvent_InvalidDereference,
383  "cannot dereference non-pointer type `%s` inside lvalue", tree_to_string(ty));
384  }
385 
386  tree_t *ref = tree_type_reference(expr->node, tree_get_name(type), ty->ptr);
387  return tree_expr_offset(expr->node, ref, inner, index);
388 }
389 
390 static tree_t *sema_deref_rvalue(ctu_sema_t *sema, const ctu_t *expr)
391 {
392  tree_t *inner = ctu_sema_rvalue(sema, expr->expr, NULL);
393  if (tree_is(inner, eTreeError))
394  {
395  return inner;
396  }
397 
398  return tree_expr_load(expr->node, inner);
399 }
400 
401 static tree_t *sema_ref(ctu_sema_t *sema, const ctu_t *expr)
402 {
403  tree_t *inner = ctu_sema_lvalue(sema, expr->expr);
404  if (tree_is(inner, eTreeError))
405  {
406  return inner;
407  }
408 
409  if (tree_is(inner, eTreeDeclLocal))
410  {
411  // TODO: do we need a way to get a pointer to a local?
412  const tree_t *type = tree_get_storage_type(inner);
413  const tree_t *ptr = tree_type_pointer(expr->node, "", type, 1);
414  return tree_expr_cast(expr->node, ptr, inner, eCastBit); // TODO: is this cast right
415  }
416 
417  const tree_t *type = tree_get_type(inner);
418  if (tree_is(type, eTreeTypeReference))
419  {
420  tree_t *ptr = tree_type_pointer(expr->node, "", type->ptr, 1);
421  return tree_expr_cast(expr->node, ptr, inner, eCastBit);
422  }
423 
424  return tree_expr_address(expr->node, inner);
425 }
426 
427 static bool can_index_type(const tree_t *ty)
428 {
429  switch (tree_get_kind(ty))
430  {
431  case eTreeTypePointer:
432  case eTreeTypeArray: return true;
433 
434  default: return false;
435  }
436 }
437 
438 typedef struct index_pair_t {
441  const tree_t *type;
442 } index_pair_t;
443 
444 static index_pair_t sema_index_inner(ctu_sema_t *sema, const ctu_t *expr)
445 {
446  tree_t *index = ctu_sema_rvalue(sema, expr->index, ctu_get_int_type(eDigitSize, eSignUnsigned));
447  tree_t *object = ctu_sema_rvalue(sema, expr->expr, NULL);
448 
449  const tree_t *ty = get_ptr_type(tree_get_type(object));
450  if (!can_index_type(ty))
451  {
452  tree_t *error = tree_raise(expr->node, ctu_sema_reports(sema), &kEvent_InvalidIndex,
453  "cannot index non-pointer type `%s`", tree_to_string(ty));
454  index_pair_t pair = {
455  .object = error,
456  .index = NULL,
457  .type = NULL,
458  };
459  return pair;
460  }
461 
462  index_pair_t pair = {
463  .object = object,
464  .index = index,
465  .type = ty,
466  };
467 
468  return pair;
469 }
470 
471 static tree_t *sema_index_rvalue(ctu_sema_t *sema, const ctu_t *expr)
472 {
473  index_pair_t pair = sema_index_inner(sema, expr);
474  if (tree_is(pair.object, eTreeError))
475  {
476  return pair.object;
477  }
478 
479  tree_t *offset = tree_expr_offset(expr->node, pair.type, pair.object, pair.index);
480  return tree_expr_load(expr->node, offset);
481 }
482 
483 static tree_t *sema_index_lvalue(ctu_sema_t *sema, const ctu_t *expr)
484 {
485  index_pair_t pair = sema_index_inner(sema, expr);
486  if (tree_is(pair.object, eTreeError))
487  {
488  return pair.object;
489  }
490 
491  const tree_t *ty = pair.type;
492  tree_t *ref = tree_type_reference(expr->node, "", ty->ptr);
493  return tree_expr_offset(expr->node, ref, pair.object, pair.index);
494 }
495 
500 
501 static tree_t *sema_field_common(ctu_sema_t *sema, const ctu_t *expr, tree_t **object, tree_t **field)
502 {
503  CTASSERT(object != NULL);
504  CTASSERT(field != NULL);
505 
506  tree_t *object_tmp = ctu_sema_lvalue(sema, expr->expr);
507  const tree_t *ty = get_ptr_type(tree_get_type(object_tmp));
508  if (!tree_is(ty, eTreeTypeStruct))
509  {
510  return tree_raise(expr->node, ctu_sema_reports(sema), &kEvent_InvalidIndirection,
511  "cannot access field of non-struct type `%s`", tree_to_string(ty));
512  }
513 
514  tree_t *field_tmp = tree_ty_get_field(ty, expr->field);
515  if (field_tmp == NULL)
516  {
517  return tree_raise(expr->node, ctu_sema_reports(sema), &kEvent_SymbolNotFound,
518  "field `%s` not found in struct `%s`", expr->field, tree_to_string(ty));
519  }
520 
521  *object = object_tmp;
522  *field = field_tmp;
523 
524  return tree_type_reference(expr->node, "", tree_get_type(field_tmp));
525 }
526 
527 static tree_t *sema_field_lvalue(ctu_sema_t *sema, const ctu_t *expr)
528 {
529  tree_t *object = NULL;
530  tree_t *field = NULL;
531  tree_t *type = sema_field_common(sema, expr, &object, &field);
532  if (tree_is(type, eTreeError))
533  {
534  return type;
535  }
536 
537  return tree_expr_field(expr->node, type, object, field);
538 }
539 
540 static tree_t *sema_field_rvalue(ctu_sema_t *sema, const ctu_t *expr)
541 {
542  tree_t *object = NULL;
543  tree_t *field = NULL;
544  tree_t *type = sema_field_common(sema, expr, &object, &field);
545  if (tree_is(type, eTreeError))
546  {
547  return type;
548  }
549 
550  tree_t *access = tree_expr_field(expr->node, type, object, field);
551  return tree_expr_load(expr->node, access);
552 }
553 
554 static tree_t *sema_field_indirect_lvalue(ctu_sema_t *sema, const ctu_t *expr)
555 {
556  tree_t *object = ctu_sema_lvalue(sema, expr->expr);
557  const tree_t *ptr = get_ptr_type(tree_get_type(object));
558  if (!tree_is(ptr, eTreeTypePointer) || !util_type_is_aggregate(ptr->ptr))
559  {
560  return tree_raise(expr->node, ctu_sema_reports(sema), &kEvent_InvalidIndirection,
561  "cannot indirectly access field of non-pointer-to-struct type `%s`",
562  tree_to_string(ptr));
563  }
564 
565  const tree_t *ty = ptr->ptr;
566  tree_t *field = tree_ty_get_field(ty, expr->field);
567  if (field == NULL)
568  {
569  return tree_raise(expr->node, ctu_sema_reports(sema), &kEvent_FieldNotFound,
570  "field `%s` not found in struct `%s`", expr->field, tree_to_string(ty));
571  }
572 
573  tree_t *ref = tree_type_reference(expr->node, "", tree_get_type(field));
574  return tree_expr_field(expr->node, ref, object, field);
575 }
576 
577 static tree_t *sema_field_indirect_rvalue(ctu_sema_t *sema, const ctu_t *expr)
578 {
579  tree_t *object = ctu_sema_lvalue(sema, expr->expr);
580  const tree_t *ptr = get_ptr_type(tree_get_type(object));
581  if (!tree_is(ptr, eTreeTypePointer) || !util_type_is_aggregate(ptr->ptr))
582  {
583  return tree_raise(expr->node, ctu_sema_reports(sema), &kEvent_InvalidIndirection,
584  "cannot indirectly access field of non-pointer-to-struct type `%s`",
585  tree_to_string(ptr));
586  }
587 
588  const tree_t *ty = ptr->ptr;
589  tree_t *field = tree_ty_get_field(ty, expr->field);
590  if (field == NULL)
591  {
592  return tree_raise(expr->node, ctu_sema_reports(sema), &kEvent_FieldNotFound,
593  "field `%s` not found in struct `%s`", expr->field, tree_to_string(ty));
594  }
595 
596  tree_t *ref = tree_type_reference(expr->node, "", tree_get_type(field));
597  tree_t *access = tree_expr_field(expr->node, ref, object, field);
598  return tree_expr_load(expr->node, access);
599 }
600 
601 static tree_t *sema_init(ctu_sema_t *sema, const ctu_t *expr, const tree_t *implicit_type)
602 {
603  logger_t *reports = ctu_sema_reports(sema);
604  if (implicit_type == NULL)
605  {
606  return tree_raise(expr->node, reports, &kEvent_InvalidInitializer, "cannot infer type of initializer");
607  }
608 
609  if (!tree_is(implicit_type, eTreeTypeStruct))
610  {
611  return tree_raise(expr->node, reports, &kEvent_InvalidInitializer, "cannot initialize non-struct type `%s`",
612  tree_to_string(implicit_type));
613  }
614 
615  const tree_t *ref = ctu_resolve_decl_type(implicit_type);
616 
617  tree_storage_t storage = {
618  .storage = implicit_type,
619  .length = 1,
620  .quals = eQualMutable
621  };
622  tree_t *local = tree_decl_local(expr->node, NULL, storage, ref);
623  tree_add_local(sema->decl, local);
624 
625  size_t field_count = vector_len(implicit_type->fields);
626  set_t *fields = set_new(field_count, kTypeInfoPtr, get_global_arena());
627 
628  size_t len = vector_len(expr->inits);
629  for (size_t i = 0; i < len; i++)
630  {
631  ctu_t *element = vector_get(expr->inits, i);
632  CTASSERTF(element->kind == eCtuFieldInit, "invalid init kind %d", element->kind);
633 
634  tree_t *field = tree_ty_get_field(implicit_type, element->field);
635  if (field == NULL)
636  {
637  msg_notify(reports, &kEvent_FieldNotFound, element->node,
638  "field `%s` not found in struct `%s`", element->field,
639  tree_to_string(implicit_type));
640  continue;
641  }
642 
643  const tree_t *field_type = tree_get_type(field);
644 
645  tree_t *value = ctu_sema_rvalue(sema, element->expr, field_type);
646  tree_t *ref_type = tree_type_reference(element->node, "", field_type);
647  tree_t *dst = tree_expr_field(element->node, ref_type, local, field);
648  tree_t *assign = tree_stmt_assign(element->node, dst, value);
649 
650  vector_push(&sema->block, assign);
651  set_add(fields, field);
652  }
653 
654  for (size_t i = 0; i < field_count; i++)
655  {
656  tree_t *field = vector_get(implicit_type->fields, i);
657  if (!set_contains(fields, field))
658  {
659  // default init field
660  const tree_t *value = ctu_get_default_value(expr->node, tree_get_type(field));
661  tree_t *ref_type = tree_type_reference(expr->node, "", tree_get_type(field));
662  tree_t *dst = tree_expr_field(expr->node, ref_type, local, field);
663  tree_t *assign = tree_stmt_assign(expr->node, dst, value);
664 
665  vector_push(&sema->block, assign);
666  }
667  }
668 
669  return tree_expr_load(expr->node, local);
670 }
671 
672 static tree_t *sema_sizeof(ctu_sema_t *sema, const ctu_t *expr)
673 {
674  const tree_t *ty = ctu_sema_type(sema, expr->type);
675  return tree_builtin_sizeof(expr->node, ty, ctu_get_int_type(eDigitSize, eSignUnsigned));
676 }
677 
678 static tree_t *sema_alignof(ctu_sema_t *sema, const ctu_t *expr)
679 {
680  const tree_t *ty = ctu_sema_type(sema, expr->type);
681  return tree_builtin_alignof(expr->node, ty, ctu_get_int_type(eDigitSize, eSignUnsigned));
682 }
683 
684 static tree_t *sema_offsetof(ctu_sema_t *sema, const ctu_t *expr)
685 {
686  const tree_t *ty = ctu_sema_type(sema, expr->expr);
687  if (!util_type_is_aggregate(ty))
688  {
689  return tree_raise(
690  expr->node, ctu_sema_reports(sema), &kEvent_NotAnAggregate,
691  "cannot get offset of non-aggregate type `%s`", tree_to_string(ty)
692  );
693  }
694 
695  const tree_t *field = tree_ty_get_field(ty, expr->field);
696  if (field == NULL)
697  {
698  return tree_raise(
699  expr->node, ctu_sema_reports(sema), &kEvent_FieldNotFound,
700  "field `%s` not found in struct `%s`", expr->expr, tree_to_string(ty)
701  );
702  }
703 
704  return tree_builtin_offsetof(expr->node, ty, field, ctu_get_int_type(eDigitSize, eSignUnsigned));
705 }
706 
708 {
709  CTASSERT(expr != NULL);
710 
711  switch (expr->kind)
712  {
713  case eCtuExprName: return sema_name(sema->sema, expr);
714  case eCtuExprDeref: return sema_deref_lvalue(sema, expr);
715  case eCtuExprIndex: return sema_index_lvalue(sema, expr);
716  case eCtuExprField: return sema_field_lvalue(sema, expr);
717  case eCtuExprFieldIndirect: return sema_field_indirect_lvalue(sema, expr);
718 
719  default: CT_NEVER("invalid lvalue-expr kind %d", expr->kind);
720  }
721 }
722 
723 tree_t *ctu_sema_rvalue(ctu_sema_t *sema, const ctu_t *expr, const tree_t *implicit_type)
724 {
725  CTASSERT(expr != NULL);
726 
727  const tree_t *inner = implicit_type == NULL
728  ? NULL
729  : tree_resolve(tree_get_cookie(sema->sema), implicit_type);
730 
731  inner = tree_follow_type(inner);
732 
733  switch (expr->kind)
734  {
735  case eCtuExprBool: return sema_bool(sema->sema, expr, inner);
736  case eCtuExprInt: return sema_int(sema->sema, expr, inner);
737  case eCtuExprString: return sema_string(sema->sema, expr, inner);
738  case eCtuExprChar: return sema_char(sema->sema, expr, inner);
739  case eCtuExprCast: return sema_cast(sema, expr);
740  case eCtuExprInit: return sema_init(sema, expr, inner);
741 
742  case eCtuExprName: return sema_load(sema->sema, expr, inner);
743  case eCtuExprCall: return sema_call(sema, expr);
744 
745  case eCtuExprRef: return sema_ref(sema, expr);
746  case eCtuExprDeref: return sema_deref_rvalue(sema, expr);
747  case eCtuExprIndex: return sema_index_rvalue(sema, expr);
748  case eCtuExprField: return sema_field_rvalue(sema, expr);
749  case eCtuExprFieldIndirect: return sema_field_indirect_rvalue(sema, expr);
750 
751  case eCtuExprCompare: return sema_compare(sema, expr);
752  case eCtuExprBinary: return sema_binary(sema, expr, inner);
753  case eCtuExprUnary: return sema_unary(sema, expr, inner);
754  case eCtuExprSizeOf: return sema_sizeof(sema, expr);
755  case eCtuExprAlignOf: return sema_alignof(sema, expr);
756  case eCtuExprOffsetOf: return sema_offsetof(sema, expr);
757 
758  default: CT_NEVER("invalid rvalue-expr kind %d", expr->kind);
759  }
760 }
761 
762 static tree_t *sema_local(ctu_sema_t *sema, const ctu_t *stmt)
763 {
764  tree_t *type = stmt->type == NULL ? NULL : ctu_sema_type(sema, stmt->type);
765  tree_t *value = stmt->value == NULL ? NULL : ctu_sema_rvalue(sema, stmt->value, type);
766 
767  CTASSERT(value != NULL || type != NULL);
768 
769  const tree_t *actual_type = type != NULL
770  ? tree_resolve(tree_get_cookie(sema->sema), type)
771  : tree_get_type(value);
772 
773  const tree_t *ref = tree_type_reference(stmt->node, stmt->name, actual_type);
774  tree_storage_t storage = {
775  .storage = actual_type,
776  .length = 1,
777  .quals = stmt->mut ? eQualMutable : eQualConst,
778  };
779  tree_t *self = tree_decl_local(stmt->node, stmt->name, storage, ref);
780  tree_add_local(sema->decl, self);
781  ctu_add_decl(sema->sema, eCtuTagValues, stmt->name, self);
782 
783  if (value != NULL)
784  {
785  return tree_stmt_init(stmt->node, self, value);
786  }
787 
788  // TODO: maybe a nop node would be better
789  return tree_stmt_block(stmt->node, &kEmptyVector);
790 }
791 
792 static tree_t *sema_stmts(ctu_sema_t *sema, const ctu_t *stmt)
793 {
794  tree_t *decl = sema->decl;
795  size_t len = vector_len(stmt->stmts);
796 
797  size_t sizes[eCtuTagTotal] = {
798  [eCtuTagTypes] = 4,
799  [eCtuTagValues] = 4,
800  [eCtuTagFunctions] = 4,
801  };
802 
803  tree_t *ctx = tree_module(sema->sema, stmt->node, decl->name, eCtuTagTotal, sizes);
804  arena_t *arena = get_global_arena();
805  ctu_sema_t inner = ctu_sema_nested(sema, ctx, sema->decl, vector_new(len, arena));
806  for (size_t i = 0; i < len; i++)
807  {
808  ctu_t *it = vector_get(stmt->stmts, i);
809  tree_t *step = ctu_sema_stmt(&inner, it);
810  vector_push(&inner.block, step);
811  }
812 
813  return tree_stmt_block(stmt->node, inner.block);
814 }
815 
816 static tree_t *sema_return(ctu_sema_t *sema, const ctu_t *stmt)
817 {
818  const tree_t *result = tree_fn_get_return(sema->decl);
819 
820  if (stmt->result == NULL)
821  {
822  return tree_stmt_return(stmt->node, tree_expr_unit(stmt->node, result));
823  }
824 
825  tree_t *value = ctu_sema_rvalue(sema, stmt->result, result);
826 
827  return tree_stmt_return(stmt->node, value);
828 }
829 
830 static tree_t *sema_while(ctu_sema_t *sema, const ctu_t *stmt)
831 {
832  tree_t *save = ctu_current_loop(sema);
833 
834  tree_t *cond = ctu_sema_rvalue(sema, stmt->cond, ctu_get_bool_type());
835  tree_t *loop = tree_stmt_loop(stmt->node, cond, tree_stmt_block(stmt->node, &kEmptyVector),
836  NULL);
837 
838  if (stmt->name != NULL)
839  {
840  ctu_add_decl(sema->sema, eCtuTagLabels, stmt->name, loop);
841  }
842 
843  ctu_set_current_loop(sema, loop);
844 
845  loop->then = ctu_sema_stmt(sema, stmt->then);
846  ctu_set_current_loop(sema, save);
847 
848  loop->other = stmt->other == NULL ? NULL : ctu_sema_stmt(sema, stmt->other);
849 
850  return loop;
851 }
852 
853 static tree_t *sema_assign(ctu_sema_t *sema, const ctu_t *stmt)
854 {
855  tree_t *dst = ctu_sema_lvalue(sema, stmt->dst);
856  const tree_t *ty = tree_get_type(dst);
857 
858  tree_t *src = ctu_sema_rvalue(sema, stmt->src, tree_ty_load_type(ty));
859 
860  return tree_stmt_assign(stmt->node, dst, src);
861 }
862 
863 static tree_t *sema_branch(ctu_sema_t *sema, const ctu_t *stmt)
864 {
865  tree_t *cond = ctu_sema_rvalue(sema, stmt->cond, ctu_get_bool_type());
866  tree_t *then = ctu_sema_stmt(sema, stmt->then);
867  tree_t *other = stmt->other == NULL ? NULL : ctu_sema_stmt(sema, stmt->other);
868 
869  return tree_stmt_branch(stmt->node, cond, then, other);
870 }
871 
872 static tree_t *get_label_loop(ctu_sema_t *sema, const ctu_t *stmt)
873 {
874  tree_t *ctx = sema->sema;
875  if (stmt->label == NULL)
876  {
877  tree_t *loop = ctu_current_loop(sema);
878  if (loop != NULL)
879  {
880  return loop;
881  }
882 
883  return tree_raise(stmt->node, ctx->reports, &kEvent_InvalidControlFlow, "loop control statement not within a loop");
884  }
885 
886  tree_t *decl = ctu_get_loop(ctx, stmt->label);
887  if (decl != NULL)
888  {
889  return decl;
890  }
891 
892  return tree_raise(stmt->node, ctx->reports, &kEvent_SymbolNotFound, "label `%s` not found",
893  stmt->label);
894 }
895 
896 static tree_t *sema_break(ctu_sema_t *sema, const ctu_t *stmt)
897 {
898  tree_t *loop = get_label_loop(sema, stmt);
899  return tree_stmt_jump(stmt->node, loop, eJumpBreak);
900 }
901 
902 static tree_t *sema_continue(ctu_sema_t *sema, const ctu_t *stmt)
903 {
904  tree_t *loop = get_label_loop(sema, stmt);
905  return tree_stmt_jump(stmt->node, loop, eJumpContinue);
906 }
907 
908 tree_t *ctu_sema_stmt(ctu_sema_t *sema, const ctu_t *stmt)
909 {
910  CTASSERT(sema->sema != NULL);
911  CTASSERT(sema->decl != NULL);
912  CTASSERT(sema->block != NULL);
913 
914  CTASSERT(stmt != NULL);
915 
916  switch (stmt->kind)
917  {
918  case eCtuStmtLocal: return sema_local(sema, stmt);
919  case eCtuStmtList: return sema_stmts(sema, stmt);
920  case eCtuStmtReturn: return sema_return(sema, stmt);
921  case eCtuStmtWhile: return sema_while(sema, stmt);
922  case eCtuStmtAssign: return sema_assign(sema, stmt);
923  case eCtuStmtBranch: return sema_branch(sema, stmt);
924 
925  case eCtuStmtBreak: return sema_break(sema, stmt);
926  case eCtuStmtContinue: return sema_continue(sema, stmt);
927 
928  case eCtuExprCompare:
929  case eCtuExprBinary:
930  case eCtuExprUnary:
931  case eCtuExprName:
932  msg_notify(ctu_sema_reports(sema), &kEvent_ExpressionHasNoEffect, stmt->node,
933  "expression statement may have no effect");
934  /* fallthrough */
935 
936  case eCtuExprCall: return ctu_sema_rvalue(sema, stmt, NULL);
937 
938  default: CT_NEVER("invalid stmt kind %d", stmt->kind);
939  }
940 }
941 
943 {
944  switch (tree_get_kind(type))
945  {
946  case eTreeTypePointer:
947  case eTreeTypeArray:
948  CTASSERTF(type->length != SIZE_MAX, "type %s has no length", tree_to_string(type));
949  return ctu_resolve_storage_length(type->ptr) * type->length;
950 
951  default: return 1;
952  }
953 }
954 
956 {
957  switch (tree_get_kind(type))
958  {
959  case eTreeTypeArray: return ctu_resolve_storage_type(type->ptr);
960  case eTreeTypePointer: return type->ptr;
961  case eTreeTypeReference: CT_NEVER("cannot resolve storage type of reference");
962 
963  default: return type;
964  }
965 }
966 
968 {
969  switch (tree_get_kind(type))
970  {
971  case eTreeTypeArray:
972  case eTreeTypePointer: return type;
973 
974  case eTreeTypeReference: CT_NEVER("cannot resolve decl type of reference");
975 
976  default: return tree_type_reference(tree_get_node(type), tree_get_name(type), type);
977  }
978 }
CT_TREE_API tree_t * tree_builtin_alignof(const node_t *node, const tree_t *type, const tree_t *align_type)
Definition: builtin.c:13
CT_TREE_API tree_t * tree_builtin_offsetof(const node_t *node, const tree_t *type, const tree_t *field, const tree_t *offset_type)
Definition: builtin.c:20
CT_BEGIN_API CT_TREE_API tree_t * tree_builtin_sizeof(const node_t *node, const tree_t *type, const tree_t *size_type)
Definition: builtin.c:6
CT_PUREFN CT_TREE_API const node_t * tree_get_node(const tree_t *tree)
Definition: context.c:94
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_PUREFN CT_TREE_API bool tree_is(const tree_t *self, tree_kind_t kind)
Definition: query.c:91
CT_TREE_API const char * tree_to_string(const tree_t *self)
Definition: query.c:40
CT_PUREFN CT_TREE_API tree_t * tree_ty_get_case(const tree_t *self, const char *name)
Definition: query.c:231
CT_PUREFN CT_TREE_API const tree_t * tree_fn_get_return(const tree_t *self)
Definition: query.c:167
CT_TREE_API const tree_t * tree_get_storage_type(const tree_t *self)
Definition: query.c:136
CT_PUREFN CT_TREE_API tree_t * tree_ty_get_field(const tree_t *self, const char *name)
Definition: query.c:224
CT_TREE_API const tree_attribs_t * tree_get_attrib(const tree_t *self)
Definition: query.c:83
CT_PUREFN CT_TREE_API const vector_t * tree_fn_get_params(const tree_t *self)
Definition: query.c:179
CT_PUREFN CT_TREE_API 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
@ eCtuExprField
Definition: ast.h:36
@ eCtuExprAlignOf
Definition: ast.h:44
@ eCtuStmtBranch
Definition: ast.h:55
@ eCtuStmtWhile
Definition: ast.h:51
@ eCtuStmtContinue
Definition: ast.h:54
@ eCtuExprBinary
Definition: ast.h:32
@ eCtuStmtAssign
Definition: ast.h:52
@ eCtuExprChar
Definition: ast.h:26
@ eCtuExprFieldIndirect
Definition: ast.h:37
@ eCtuExprName
Definition: ast.h:27
@ eCtuExprCast
Definition: ast.h:28
@ eCtuExprDeref
Definition: ast.h:40
@ eCtuStmtBreak
Definition: ast.h:53
@ eCtuExprCompare
Definition: ast.h:31
@ eCtuExprSizeOf
Definition: ast.h:43
@ eCtuStmtList
Definition: ast.h:48
@ eCtuStmtLocal
Definition: ast.h:49
@ eCtuStmtReturn
Definition: ast.h:50
@ eCtuExprCall
Definition: ast.h:34
@ eCtuExprInt
Definition: ast.h:23
@ eCtuExprString
Definition: ast.h:25
@ eCtuExprOffsetOf
Definition: ast.h:45
@ eCtuExprInit
Definition: ast.h:29
@ eCtuExprBool
Definition: ast.h:24
@ eCtuFieldInit
Definition: ast.h:78
@ eCtuExprRef
Definition: ast.h:39
@ eCtuExprUnary
Definition: ast.h:33
@ eCtuExprIndex
Definition: ast.h:35
@ eCtuTagTotal
Definition: sema.h:17
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_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
void ctu_set_current_loop(ctu_sema_t *sema, tree_t *loop)
Definition: sema.c:156
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
tree_t * ctu_sema_type(ctu_sema_t *sema, const ctu_t *type)
Definition: type.c:114
tree_t * ctu_sema_lvalue(ctu_sema_t *sema, const ctu_t *expr)
Definition: expr.c:707
const tree_t * ctu_resolve_storage_type(const tree_t *type)
Definition: expr.c:955
size_t ctu_resolve_storage_length(const tree_t *type)
Definition: expr.c:942
tree_t * ctu_sema_rvalue(ctu_sema_t *sema, const ctu_t *expr, const tree_t *implicit_type)
Definition: expr.c:723
tree_t * ctu_sema_stmt(ctu_sema_t *sema, const ctu_t *stmt)
Definition: expr.c:908
const tree_t * ctu_resolve_decl_type(const tree_t *type)
Definition: expr.c:967
const tree_t * ctu_get_default_value(const node_t *node, const tree_t *type)
Definition: default.c:23
CT_MEMORY_API arena_t * get_global_arena(void)
get the global memory arena
Definition: memory.c:16
CT_NODISCARD CT_STD_API set_t * set_new(size_t size, hash_info_t info, arena_t *arena)
create a new set
Definition: set.c:51
CT_STD_API const void * set_add(set_t *set, const void *key)
add a key to a set
Definition: set.c:85
CT_NODISCARD CT_PUREFN CT_STD_API bool set_contains(const set_t *set, const void *key)
check if a set contains a key
Definition: set.c:118
#define CT_UNUSED(x)
mark a variable as unused
Definition: macros.h:46
CT_NOTIFY_API event_builder_t msg_notify(INOUT_NOTNULL logger_t *logs, const diagnostic_t *diagnostic, const node_t *node, STA_FORMAT_STRING const char *fmt,...)
notify the logger of a new message
#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
CT_UTIL_API bool util_type_is_aggregate(const tree_t *type)
Definition: util.c:323
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_UTIL_API tree_t * util_search_namespace(tree_t *sema, search_t search, const node_t *node, const vector_t *path, bool *is_imported)
search for a namespace given a path, ignoring the last element in the path
Definition: query.c:66
CT_UTIL_API tree_t * util_type_cast(const tree_t *dst, tree_t *expr)
attempt to cast an expression to a type
Definition: util.c:212
CT_UTIL_API bool util_types_comparable(tree_cookie_t *cookie, const tree_t *lhs, const tree_t *rhs)
query two types for comparability in binary logic operations
Definition: util.c:69
CT_TREE_API tree_t * tree_expr_unit(const node_t *node, const tree_t *type)
Definition: tree.c:203
CT_TREE_API tree_t * tree_stmt_jump(const node_t *node, tree_t *label, tree_jump_t jump)
Definition: tree.c:425
CT_TREE_API tree_t * tree_type_reference(const node_t *node, const char *name, const tree_t *reference)
create a reference type
Definition: tree.c:185
CT_TREE_API void tree_report(logger_t *reports, const tree_t *error)
Definition: tree.c:49
CT_TREE_API tree_t * tree_expr_field(const node_t *node, const tree_t *type, tree_t *object, tree_t *field)
Definition: tree.c:319
CT_TREE_API tree_t * tree_stmt_loop(const node_t *node, tree_t *cond, tree_t *body, tree_t *other)
Definition: tree.c:401
CT_TREE_API tree_t * tree_expr_offset(const node_t *node, const tree_t *type, tree_t *object, tree_t *offset)
Definition: tree.c:333
CT_TREE_API tree_t * tree_expr_digit(const node_t *node, const tree_t *type, const mpz_t value)
Definition: tree.c:217
CT_TREE_API tree_t * tree_expr_cast(const node_t *node, const tree_t *type, const tree_t *expr, tree_cast_t cast)
create a cast expression
Definition: tree.c:251
CT_TREE_API tree_t * tree_module(tree_t *parent, const node_t *node, const char *name, size_t decls, const size_t *sizes)
create a new module
Definition: sema.c:52
CT_TREE_API tree_t * tree_expr_unary(const node_t *node, unary_t unary, tree_t *expr)
Definition: tree.c:290
CT_TREE_API tree_t * tree_stmt_init(const node_t *node, tree_t *dst, tree_t *src)
Definition: tree.c:396
CT_TREE_API tree_t * tree_stmt_return(const node_t *node, const tree_t *value)
create a return statement
Definition: tree.c:368
CT_TREE_API tree_t * tree_error(const node_t *node, const diagnostic_t *diagnostic, const char *message,...)
Definition: tree.c:67
CT_TREE_API tree_t * tree_expr_compare(const node_t *node, const tree_t *type, compare_t compare, const tree_t *lhs, const tree_t *rhs)
Definition: tree.c:307
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_cookie_t * tree_get_cookie(tree_t *sema)
return a resolution cookie
Definition: sema.c:136
CT_TREE_API tree_t * tree_raise(const node_t *node, logger_t *reports, const diagnostic_t *diagnostic, const char *message,...)
Definition: tree.c:76
CT_TREE_API tree_t * tree_expr_call(const node_t *node, const tree_t *callee, const vector_t *args)
Definition: tree.c:344
CT_TREE_API tree_t * tree_expr_string(const node_t *node, const tree_t *type, const char *value, size_t length)
create a string expression
Definition: tree.c:235
CT_TREE_API tree_t * tree_expr_bool(const node_t *node, const tree_t *type, bool value)
Definition: tree.c:208
CT_TREE_API tree_t * tree_expr_binary(const node_t *node, const tree_t *type, binary_t binary, const tree_t *lhs, const tree_t *rhs)
Definition: tree.c:298
CT_TREE_API tree_t * tree_expr_load(const node_t *node, tree_t *expr)
load a value from a pointer or storage
Definition: tree.c:261
CT_TREE_API tree_t * tree_resolve_type(tree_cookie_t *cookie, const tree_t *decl)
Definition: decl.c:102
tree_kind_t
all tree node types
Definition: ops.h:17
CT_TREE_API tree_t * tree_expr_address(const node_t *node, tree_t *expr)
create a reference to an object
Definition: tree.c:281
CT_TREE_API const tree_t * tree_follow_type(const tree_t *type)
Definition: decl.c:274
CT_TREE_API tree_t * tree_stmt_assign(const node_t *node, tree_t *dst, const tree_t *src)
Definition: tree.c:391
CT_TREE_API tree_t * tree_stmt_block(const node_t *node, const vector_t *stmts)
create a block statement
Definition: tree.c:359
CT_TREE_API void tree_add_local(tree_t *self, tree_t *decl)
Definition: decl.c:243
CT_TREE_API const char * unary_name(unary_t op)
get the pretty name of a unary operator
Definition: ops.c:18
CT_TREE_API tree_t * tree_resolve(tree_cookie_t *cookie, const tree_t *decl)
Definition: decl.c:47
CT_TREE_API tree_t * tree_stmt_branch(const node_t *node, tree_t *cond, tree_t *then, tree_t *other)
Definition: tree.c:413
CT_TREE_API tree_t * tree_decl_local(const node_t *node, const char *name, tree_storage_t storage, const tree_t *type)
Definition: decl.c:198
CT_TREE_API tree_t * tree_type_array(const node_t *node, const char *name, const tree_t *array, size_t length)
create a new array type
Definition: tree.c:175
CT_STD_API const hash_info_t kTypeInfoPtr
type information for a generic pointer this operates on the pointer itself and not the data it points...
Definition: typeinfo.c:41
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_STD_API vector_t * vector_new(size_t size, arena_t *arena)
create a new vector with an initial capacity
Definition: vector.c:63
CT_NODISCARD CT_STD_API vector_t * vector_of(size_t len, arena_t *arena)
create a new vector with a specified length
Definition: vector.c:71
CT_STD_API const vector_t kEmptyVector
a global empty vector used to avoid allocating alot of empty vectors
Definition: vector.c:25
CT_STD_API void vector_push(vector_t **vector, void *value)
push a value onto the end of a vector
Definition: vector.c:108
CT_NODISCARD CT_PUREFN CT_STD_API void * vector_tail(const vector_t *vector)
get the last element of a vector
Definition: vector.c:143
CT_STD_API void vector_set(vector_t *vector, size_t index, void *value)
set a value in a vector
Definition: vector.c:125
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
tree_t * ctu_cast_type(tree_t *sema, tree_t *expr, const tree_t *type)
Definition: resolve.c:38
an allocator object
Definition: arena.h:86
digit_t digit
Definition: ast.h:17
sign_t sign
Definition: ast.h:18
mpz_t value
Definition: ast.h:16
vector_t * block
current statement block
Definition: sema.h:27
tree_t * decl
current decl
Definition: sema.h:26
tree_t * sema
current scope
Definition: sema.h:25
Definition: ast.h:86
ctu_t * then
Definition: ast.h:103
ctu_t * cond
Definition: ast.h:102
ctu_t * other
Definition: ast.h:104
ctu_kind_t kind
Definition: ast.h:87
binary_t binary
Definition: ast.h:172
ctu_t * callee
Definition: ast.h:202
size_t length
Definition: ast.h:160
ctu_t * index
Definition: ast.h:185
compare_t compare
Definition: ast.h:175
ctu_t * value
Definition: ast.h:110
const vector_t * inits
Definition: ast.h:164
char * field
Definition: ast.h:191
char * text
Definition: ast.h:159
char * label
Definition: ast.h:219
ctu_integer_t integer
Definition: ast.h:152
bool mut
Definition: ast.h:111
const vector_t * args
Definition: ast.h:203
ctu_t * src
Definition: ast.h:215
ctu_t * rhs
Definition: ast.h:179
const node_t * node
Definition: ast.h:88
ctu_t * lhs
Definition: ast.h:178
ctu_t * cast
Definition: ast.h:194
const vector_t * stmts
Definition: ast.h:207
ctu_t * type
Definition: ast.h:109
ctu_t * expr
Definition: ast.h:197
ctu_t * result
Definition: ast.h:210
const vector_t * path
Definition: ast.h:167
unary_t unary
Definition: ast.h:188
bool bool_value
Definition: ast.h:155
char * name
Definition: ast.h:92
ctu_t * dst
Definition: ast.h:214
const tree_t * type
Definition: expr.c:441
tree_t * object
Definition: expr.c:439
tree_t * index
Definition: expr.c:440
a logging sink
Definition: notify.c:14
a position in a source file
Definition: node.h:23
Definition: util.h:28
const size_t * tags
Definition: util.h:29
an unordered hash set
Definition: set.c:19
tree_visibility_t visibility
the visibility of the declaration
Definition: tree.h:52
storage for a value
Definition: context.h:23
const tree_t * storage
the underlying storage type
Definition: context.h:25
Definition: tree.h:67
tree_t * other
Definition: tree.h:140
logger_t * reports
Definition: tree.h:227
vector_t * fields
Definition: tree.h:184
size_t length
Definition: tree.h:174
const char * name
the name of the declaration
Definition: tree.h:163
const tree_t * type
Definition: tree.h:70
const tree_t * ptr
Definition: tree.h:172
tree_t * then
Definition: tree.h:139
a generic vector of pointers
Definition: vector.c:16