Cthulhu  0.2.10
Cthulhu compiler collection
type.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-3.0-only
2 
3 #include "ctu/sema/type.h"
4 #include "arena/arena.h"
6 #include "cthulhu/tree/tree.h"
7 #include "ctu/sema/sema.h"
8 #include "ctu/sema/expr.h"
9 #include "ctu/ast.h"
10 
11 #include "cthulhu/util/util.h"
12 
13 #include "cthulhu/tree/query.h"
14 
15 #include "memory/memory.h"
16 #include "std/vector.h"
17 #include "std/str.h"
18 
19 #include "base/panic.h"
20 
24 
25 static const size_t kModuleTags[] = { eCtuTagModules, eCtuTagImports };
26 static const size_t kDeclTags[] = { eCtuTagTypes };
27 
28 static const decl_search_t kSearchType = {
29  .module_tags = kModuleTags,
30  .module_count = sizeof(kModuleTags) / sizeof(size_t),
31 
32  .decl_tags = kDeclTags,
33  .decl_count = sizeof(kDeclTags) / sizeof(size_t)
34 };
35 
36 static tree_t *sema_type_name(tree_t *sema, const ctu_t *type)
37 {
38  return util_search_path(sema, &kSearchType, type->node, type->type_name);
39 }
40 
41 static tree_t *ctu_sema_type_pointer(ctu_sema_t *sema, const ctu_t *type)
42 {
43  tree_t *pointee = ctu_sema_type(sema, type->pointer);
44  arena_t *arena = get_global_arena();
45  return tree_type_pointer(type->node, str_format(arena, "*%s", tree_get_name(pointee)), pointee, 1);
46 }
47 
48 static tree_t *sema_type_function(ctu_sema_t *sema, const ctu_t *type)
49 {
50  tree_t *result = ctu_sema_type(sema, type->return_type);
51 
52  arena_t *arena = get_global_arena();
53  size_t len = vector_len(type->params);
54  vector_t *params = vector_of(len, arena);
55  for (size_t i = 0; i < len; i++)
56  {
57  const ctu_t *param = vector_get(type->params, i);
58  tree_t *ty = ctu_sema_type(sema, param);
59  if (tree_is(ty, eTreeTypeUnit))
60  {
61  msg_notify(ctu_sema_reports(sema), &kEvent_InvalidFunctionSignature, param->node, "void type is not allowed in function parameters");
62  }
63 
64  tree_t *it = tree_decl_param(param->node, "", ty);
65  vector_set(params, i, it);
66  }
67 
68  return tree_type_closure(type->node, "", result, params, eArityFixed);
69 }
70 
71 static tree_t *sema_type_array(ctu_sema_t *sema, const ctu_t *type)
72 {
73  tree_t *inner = ctu_sema_type(sema, type->array_type);
74  tree_t *length = ctu_sema_rvalue(sema, type->array_length, ctu_get_int_type(eDigitSize, eSignUnsigned));
75 
76  mpz_t value;
77  mpz_init(value);
78  if (!util_eval_digit(value, length))
79  {
80  msg_notify(ctu_sema_reports(sema), &kEvent_InvalidArraySize, type->node, "array length must be a constant integer");
81  }
82 
83  size_t v = mpz_get_ui(value);
84 
85  return tree_type_array(type->node, "", inner, v);
86 }
87 
88 static tree_t *sema_type_const(ctu_sema_t *sema, const ctu_t *type)
89 {
90  tree_t *inner = ctu_sema_type(sema, type->type);
91 
92  tree_t *result = arena_memdup(inner, sizeof(tree_t), get_global_arena());
93  result->quals |= eQualConst;
94 
95  return result;
96 }
97 
98 static tree_t *sema_type_inner(ctu_sema_t *sema, const ctu_t *type)
99 {
100  CTASSERT(type != NULL);
101 
102  switch (type->kind)
103  {
104  case eCtuTypePointer: return ctu_sema_type_pointer(sema, type);
105  case eCtuTypeName: return sema_type_name(sema->sema, type);
106  case eCtuTypeFunction: return sema_type_function(sema, type);
107  case eCtuTypeArray: return sema_type_array(sema, type);
108  case eCtuTypeConst: return sema_type_const(sema, type);
109 
110  default: CT_NEVER("invalid type kind %d", type->kind);
111  }
112 }
113 
114 tree_t *ctu_sema_type(ctu_sema_t *sema, const ctu_t *type)
115 {
116  tree_t *result = sema_type_inner(sema, type);
117  return tree_resolve_type(tree_get_cookie(sema->sema), result);
118 }
CT_PUREFN CT_TREE_API const char * tree_get_name(const tree_t *tree)
Definition: context.c:102
CT_PUREFN CT_TREE_API bool tree_is(const tree_t *self, tree_kind_t kind)
Definition: query.c:91
@ eCtuTypeArray
Definition: ast.h:61
@ eCtuTypePointer
Definition: ast.h:59
@ eCtuTypeConst
Definition: ast.h:62
@ eCtuTypeName
Definition: ast.h:58
@ eCtuTypeFunction
Definition: ast.h:60
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_get_int_type(digit_t digit, sign_t sign)
Definition: sema.c:202
logger_t * ctu_sema_reports(ctu_sema_t *sema)
Definition: sema.c:65
CT_MEMORY_API arena_t * get_global_arena(void)
get the global memory arena
Definition: memory.c:16
CT_NODISCARD CT_ARENA_API void * arena_memdup(STA_READS(size) const void *ptr, size_t size, arena_t *arena)
duplicate a memory region from a custom allocator duplicate a region of memory and return a pointer t...
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
CT_UTIL_API bool util_eval_digit(mpz_t value, const tree_t *expr)
evaluate a digit expression
Definition: util.c:293
CT_UTIL_API tree_t * util_search_path(tree_t *sema, const decl_search_t *search, const node_t *node, vector_t *path)
search for a decl given a path
Definition: query.c:92
CT_TREE_API tree_t * tree_type_closure(const node_t *node, const char *name, const tree_t *result, const vector_t *params, tree_arity_t arity)
create a function pointer type
Definition: tree.c:146
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_decl_param(const node_t *node, const char *name, const tree_t *type)
Definition: decl.c:188
CT_TREE_API tree_t * tree_resolve_type(tree_cookie_t *cookie, const tree_t *decl)
Definition: decl.c:102
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_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_of(size_t len, arena_t *arena)
create a new vector with a specified length
Definition: vector.c:71
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_sema_type(ctu_sema_t *sema, const ctu_t *type)
Definition: type.c:114
STA_DECL char * str_format(arena_t *arena, const char *fmt,...)
Definition: str.c:97
an allocator object
Definition: arena.h:86
tree_t * sema
current scope
Definition: sema.h:25
Definition: ast.h:86
ctu_t * array_type
Definition: ast.h:232
ctu_kind_t kind
Definition: ast.h:87
const vector_t * params
Definition: ast.h:116
vector_t * type_name
Definition: ast.h:222
ctu_t * return_type
Definition: ast.h:118
const node_t * node
Definition: ast.h:88
ctu_t * array_length
Definition: ast.h:233
ctu_t * type
Definition: ast.h:109
ctu_t * pointer
Definition: ast.h:226
const size_t * module_tags
Definition: util.h:43
Definition: tree.h:67
tree_quals_t quals
Definition: tree.h:166
a generic vector of pointers
Definition: vector.c:16