Cthulhu  0.2.10
Cthulhu compiler collection
ast.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-3.0-only
2 
3 #include "oberon/ast.h"
4 #include "oberon/driver.h"
5 
6 #include "cthulhu/broker/scan.h"
7 
8 #include "notify/notify.h"
9 
10 #include "scan/node.h"
11 #include "std/str.h"
12 #include "std/vector.h"
13 
14 #include "arena/arena.h"
15 
16 #include "base/util.h"
17 #include "base/panic.h"
18 #include "memory/memory.h"
19 
20 static void ensure_block_names_match(scan_t *scan, const node_t *node, const char *type,
21  const char *name, const char *end)
22 {
23  CTASSERTF(type != NULL && name != NULL, "(type=%s, name=%s)", type, name);
24 
25  if (end == NULL)
26  {
27  return;
28  }
29 
30  if (!str_equal(name, end))
31  {
32  logger_t *logger = ctx_get_logger(scan);
33  event_builder_t id = msg_notify(logger, &kEvent_BlockMismatchEnds, node,
34  "mismatching %s block BEGIN and END names", type);
35  msg_note(id, "BEGIN name `%s` does not match END name `%s`", name, end);
36  }
37 }
38 
39 static obr_t *obr_new(scan_t *scan, where_t where, obr_kind_t kind)
40 {
41  arena_t *arena = ctx_get_ast_arena(scan);
42 
43  obr_t *self = ARENA_MALLOC(sizeof(obr_t), "obr", scan, arena);
44  self->kind = kind;
45  self->node = node_new(scan, where);
46 
47  ARENA_IDENTIFY(self->node, "node", self, arena);
48 
49  return self;
50 }
51 
52 static obr_t *obr_decl(scan_t *scan, where_t where, obr_kind_t kind, char *name,
53  obr_visibility_t vis)
54 {
55  obr_t *self = obr_new(scan, where, kind);
56  self->name = name;
57  self->visibility = vis;
58  return self;
59 }
60 
61 static obr_t *obr_decl_from_symbol(scan_t *scan, where_t where, obr_kind_t kind,
62  const obr_symbol_t *symbol)
63 {
64  return obr_decl(scan, where, kind, symbol->name, symbol->visibility);
65 }
66 
67 static obr_t *obr_decl_symbol_location(const obr_symbol_t *symbol, obr_kind_t kind)
68 {
69  return obr_decl(symbol->scan, symbol->where, kind, symbol->name, symbol->visibility);
70 }
71 
72 obr_t *obr_module(scan_t *scan, where_t where, char *name, char *end, const vector_t *imports,
73  vector_t *decls, vector_t *init)
74 {
75  obr_t *self = obr_decl(scan, where, eObrModule, name, eObrVisPublic);
76  self->imports = imports;
77  self->decls = decls;
78  self->init = init;
79 
80  ensure_block_names_match(scan, self->node, "MODULE", name, end);
81 
82  return self;
83 }
84 
85 obr_t *obr_import(scan_t *scan, where_t where, char *name, char *symbol)
86 {
87  obr_t *self = obr_decl(scan, where, eObrImport, name, eObrVisPrivate);
88  self->symbol = symbol;
89  return self;
90 }
91 
92 /* decls */
93 
94 obr_t *obr_decl_type(scan_t *scan, where_t where, obr_symbol_t *symbol, obr_t *type)
95 {
96  obr_t *self = obr_decl_from_symbol(scan, where, eObrDeclType, symbol);
97  self->type = type;
98  return self;
99 }
100 
102 {
103  obr_t *self = obr_decl_symbol_location(symbol, eObrDeclVar);
104  self->type = type;
105  return self;
106 }
107 
108 obr_t *obr_decl_const(scan_t *scan, where_t where, obr_symbol_t *symbol, obr_t *value)
109 {
110  obr_t *self = obr_decl_from_symbol(scan, where, eObrDeclConst, symbol);
111  self->value = value;
112  return self;
113 }
114 
115 obr_t *obr_decl_procedure(scan_t *scan, where_t where, obr_symbol_t *symbol, obr_t *receiver,
116  const vector_t *params, obr_t *result, vector_t *locals, vector_t *body,
117  char *end)
118 {
119  obr_t *self = obr_decl_from_symbol(scan, where, eObrDeclProcedure, symbol);
120 
121  // only check if this is a procedure, not a forward decl
122  if (body != NULL)
123  {
124  ensure_block_names_match(scan, self->node, "PROCEDURE", symbol->name, end);
125  }
126 
127  self->receiver = receiver;
128  self->params = params;
129  self->result = result;
130  self->locals = locals;
131  self->body = body;
132  return self;
133 }
134 
135 /* exprs */
136 
137 obr_t *obr_expr_name(scan_t *scan, where_t where, char *name)
138 {
139  obr_t *self = obr_new(scan, where, eObrExprName);
140  self->object = name;
141  return self;
142 }
143 
144 obr_t *obr_expr_field(scan_t *scan, where_t where, obr_t *expr, char *field)
145 {
146  obr_t *self = obr_new(scan, where, eObrExprField);
147  self->expr = expr;
148  self->field = field;
149  return self;
150 }
151 
152 obr_t *obr_expr_cast(scan_t *scan, where_t where, obr_t *expr, obr_t *cast)
153 {
154  obr_t *self = obr_new(scan, where, eObrExprCast);
155  self->expr = expr;
156  self->cast = cast;
157  return self;
158 }
159 
160 obr_t *obr_expr_call(scan_t *scan, where_t where, obr_t *expr, const vector_t *args)
161 {
162  obr_t *self = obr_new(scan, where, eObrExprCall);
163  self->expr = expr;
164  self->args = args;
165  return self;
166 }
167 
168 obr_t *obr_expr_is(scan_t *scan, where_t where, obr_t *lhs, obr_t *rhs)
169 {
170  obr_t *self = obr_new(scan, where, eObrExprIs);
171  self->lhs = lhs;
172  self->rhs = rhs;
173  return self;
174 }
175 
176 obr_t *obr_expr_in(scan_t *scan, where_t where, obr_t *lhs, obr_t *rhs)
177 {
178  obr_t *self = obr_new(scan, where, eObrExprIn);
179  self->lhs = lhs;
180  self->rhs = rhs;
181  return self;
182 }
183 
184 obr_t *obr_expr_compare(scan_t *scan, where_t where, compare_t op, obr_t *lhs, obr_t *rhs)
185 {
186  obr_t *self = obr_new(scan, where, eObrExprCompare);
187  self->compare = op;
188  self->lhs = lhs;
189  self->rhs = rhs;
190  return self;
191 }
192 
193 obr_t *obr_expr_binary(scan_t *scan, where_t where, binary_t op, obr_t *lhs, obr_t *rhs)
194 {
195  obr_t *self = obr_new(scan, where, eObrExprBinary);
196  self->binary = op;
197  self->lhs = lhs;
198  self->rhs = rhs;
199  return self;
200 }
201 
202 obr_t *obr_expr_unary(scan_t *scan, where_t where, unary_t op, obr_t *expr)
203 {
204  obr_t *self = obr_new(scan, where, eObrExprUnary);
205  self->unary = op;
206  self->expr = expr;
207  return self;
208 }
209 
210 obr_t *obr_expr_digit(scan_t *scan, where_t where, const mpz_t digit)
211 {
212  obr_t *self = obr_new(scan, where, eObrExprDigit);
213  mpz_init_set(self->digit, digit);
214  return self;
215 }
216 
217 obr_t *obr_expr_string(scan_t *scan, where_t where, char *text, size_t length)
218 {
219  obr_t *self = obr_new(scan, where, eObrExprString);
220  self->text = text;
221  self->length = length;
222  return self;
223 }
224 
225 /* stmts */
226 
227 obr_t *obr_stmt_return(scan_t *scan, where_t where, obr_t *expr)
228 {
229  obr_t *self = obr_new(scan, where, eObrStmtReturn);
230  self->expr = expr;
231  return self;
232 }
233 
234 obr_t *obr_stmt_while(scan_t *scan, where_t where, obr_t *cond, vector_t *then)
235 {
236  obr_t *self = obr_new(scan, where, eObrStmtWhile);
237  self->cond = cond;
238  self->then = then;
239  return self;
240 }
241 
243 {
244  obr_t *self = obr_new(scan, where, eObrStmtLoop);
245  self->loop = loop;
246  return self;
247 }
248 
250 {
251  return obr_new(scan, where, eObrStmtBreak);
252 }
253 
254 obr_t *obr_stmt_repeat(scan_t *scan, where_t where, vector_t *repeat, obr_t *until)
255 {
256  obr_t *self = obr_new(scan, where, eObrStmtRepeat);
257  self->repeat = repeat;
258  self->until = until;
259  return self;
260 }
261 
262 obr_t *obr_stmt_assign(scan_t *scan, where_t where, obr_t *dst, obr_t *src)
263 {
264  obr_t *self = obr_new(scan, where, eObrStmtAssign);
265  self->dst = dst;
266  self->src = src;
267  return self;
268 }
269 
271 {
272  obr_t *self = obr_new(scan, where, eObrStmtBlock);
273  self->stmts = stmts;
274  return self;
275 }
276 
277 obr_t *obr_stmt_branch(scan_t *scan, where_t where, obr_t *cond, vector_t *then, obr_t *other)
278 {
279  obr_t *self = obr_new(scan, where, eObrStmtBranch);
280  self->branch = cond;
281  self->branch_body = then;
282  self->branch_else = other;
283  return self;
284 }
285 
286 /* types */
287 
288 obr_t *obr_type_name(scan_t *scan, where_t where, char *name)
289 {
290  obr_t *self = obr_new(scan, where, eObrTypeName);
291  self->name = name;
292  return self;
293 }
294 
295 obr_t *obr_type_qual(scan_t *scan, where_t where, char *name, char *symbol)
296 {
297  obr_t *self = obr_decl(scan, where, eObrTypeQual, name,
298  eObrVisPrivate); // TODO: should types need this data?
299  self->symbol = symbol;
300  return self;
301 }
302 
304 {
305  obr_t *self = obr_new(scan, where, eObrTypePointer);
306  self->pointer = type;
307  return self;
308 }
309 
310 obr_t *obr_type_array(scan_t *scan, where_t where, const vector_t *sizes, obr_t *type)
311 {
312  obr_t *self = obr_new(scan, where, eObrTypeArray);
313  self->sizes = sizes;
314  self->array_element = type;
315  return self;
316 }
317 
318 obr_t *obr_type_record(scan_t *scan, where_t where, vector_t *fields)
319 {
320  obr_t *self = obr_new(scan, where, eObrTypeRecord);
321  self->fields = fields;
322  return self;
323 }
324 
325 /* extra */
326 
328 {
329  obr_t *self = obr_decl_symbol_location(symbol, eObrField);
330  self->type = type;
331  return self;
332 }
333 
334 obr_t *obr_param(obr_symbol_t *symbol, obr_t *type, bool mut)
335 {
336  obr_t *self = obr_decl_symbol_location(symbol, eObrParam);
337  self->mut = mut;
338  self->type = type;
339  return self;
340 }
341 
342 obr_t *obr_receiver(scan_t *scan, where_t where, bool mut, char *name, char *type)
343 {
344  obr_t *self = obr_decl(scan, where, eObrReceiver, name, eObrVisPrivate);
345  self->mut = mut;
346  self->type = obr_type_name(scan, where, type);
347  return self;
348 }
349 
350 /* symbols */
351 
352 obr_symbol_t *obr_symbol(scan_t *scan, where_t where, char *name, obr_visibility_t visibility)
353 {
354  scan_context_t *ctx = scan_get_context(scan);
355  obr_symbol_t *self = ARENA_MALLOC(sizeof(obr_symbol_t), "obr_symbol", scan, ctx->arena);
356  self->scan = scan;
357  self->where = where;
358  self->name = name;
359  self->visibility = visibility;
360  return self;
361 }
362 
363 #define EXPAND_INNER(fn, scan, ...) \
364  do \
365  { \
366  scan_context_t *ctx = scan_get_context(scan); \
367  arena_t *arena = ctx->arena; \
368  size_t len = vector_len(symbols); \
369  vector_t *result = vector_of(len, arena); \
370  for (size_t i = 0; i < len; i++) \
371  { \
372  obr_symbol_t *symbol = vector_get(symbols, i); \
373  obr_t *decl = fn(symbol, __VA_ARGS__); \
374  vector_set(result, i, decl); \
375  } \
376  return result; \
377  } while (0)
378 
379 vector_t *obr_expand_vars(scan_t *scan, vector_t *symbols, obr_t *type)
380 {
381  EXPAND_INNER(obr_decl_var, scan, type);
382 }
383 
385 {
386  EXPAND_INNER(obr_field, scan, type);
387 }
388 
389 vector_t *obr_expand_params(scan_t *scan, vector_t *symbols, obr_t *type, bool mut)
390 {
391  EXPAND_INNER(obr_param, scan, type, mut);
392 }
CT_NODISCARD CT_PUREFN CT_SCAN_API void * scan_get_context(const scan_t *scan)
get the context of a scanner
Definition: scan.c:88
CT_BROKER_API logger_t * ctx_get_logger(const scan_t *scan)
Definition: context.c:14
CT_BROKER_API arena_t * ctx_get_ast_arena(const scan_t *scan)
Definition: context.c:32
CT_NODISCARD CT_PUREFN CT_BASE_API bool str_equal(const char *lhs, const char *rhs)
compare strings equality
Definition: util.c:76
CT_NODISCARD CT_SCAN_API node_t * node_new(const scan_t *scan, where_t where)
create a new node on the heap
Definition: node.c:40
#define ARENA_IDENTIFY(ptr, name, parent, arena)
rename and reparent a pointer in a custom allocator
Definition: arena.h:409
#define ARENA_MALLOC(size, name, parent, arena)
allocate memory from a custom allocator
Definition: arena.h:392
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
CT_NOTIFY_API void msg_note(event_builder_t builder, STA_FORMAT_STRING const char *fmt,...)
add a note to an existing message
#define CTASSERTF(expr,...)
assert a condition with a message and optional format arguments
Definition: panic.h:116
binary_t
all binary operators
Definition: ops.h:32
unary_t
all unary operators
Definition: ops.h:48
compare_t
all comparison operators
Definition: ops.h:40
obr_t * obr_param(obr_symbol_t *symbol, obr_t *type, bool mut)
Definition: ast.c:334
obr_t * obr_expr_digit(scan_t *scan, where_t where, const mpz_t digit)
Definition: ast.c:210
obr_t * obr_import(scan_t *scan, where_t where, char *name, char *symbol)
Definition: ast.c:85
obr_t * obr_expr_cast(scan_t *scan, where_t where, obr_t *expr, obr_t *cast)
Definition: ast.c:152
obr_t * obr_expr_name(scan_t *scan, where_t where, char *name)
Definition: ast.c:137
obr_symbol_t * obr_symbol(scan_t *scan, where_t where, char *name, obr_visibility_t visibility)
Definition: ast.c:352
obr_t * obr_stmt_block(scan_t *scan, where_t where, vector_t *stmts)
Definition: ast.c:270
obr_t * obr_decl_type(scan_t *scan, where_t where, obr_symbol_t *symbol, obr_t *type)
Definition: ast.c:94
obr_t * obr_expr_string(scan_t *scan, where_t where, char *text, size_t length)
Definition: ast.c:217
vector_t * obr_expand_fields(scan_t *scan, vector_t *symbols, obr_t *type)
Definition: ast.c:384
obr_t * obr_decl_const(scan_t *scan, where_t where, obr_symbol_t *symbol, obr_t *value)
Definition: ast.c:108
obr_t * obr_type_qual(scan_t *scan, where_t where, char *name, char *symbol)
Definition: ast.c:295
obr_t * obr_field(obr_symbol_t *symbol, obr_t *type)
Definition: ast.c:327
obr_t * obr_stmt_loop(scan_t *scan, where_t where, vector_t *loop)
Definition: ast.c:242
obr_t * obr_stmt_return(scan_t *scan, where_t where, obr_t *expr)
Definition: ast.c:227
obr_t * obr_type_record(scan_t *scan, where_t where, vector_t *fields)
Definition: ast.c:318
obr_t * obr_stmt_repeat(scan_t *scan, where_t where, vector_t *repeat, obr_t *until)
Definition: ast.c:254
obr_t * obr_stmt_assign(scan_t *scan, where_t where, obr_t *dst, obr_t *src)
Definition: ast.c:262
obr_t * obr_expr_call(scan_t *scan, where_t where, obr_t *expr, const vector_t *args)
Definition: ast.c:160
obr_t * obr_expr_is(scan_t *scan, where_t where, obr_t *lhs, obr_t *rhs)
Definition: ast.c:168
obr_t * obr_type_array(scan_t *scan, where_t where, const vector_t *sizes, obr_t *type)
Definition: ast.c:310
obr_t * obr_type_name(scan_t *scan, where_t where, char *name)
Definition: ast.c:288
obr_t * obr_expr_compare(scan_t *scan, where_t where, compare_t op, obr_t *lhs, obr_t *rhs)
Definition: ast.c:184
obr_t * obr_expr_unary(scan_t *scan, where_t where, unary_t op, obr_t *expr)
Definition: ast.c:202
obr_t * obr_expr_in(scan_t *scan, where_t where, obr_t *lhs, obr_t *rhs)
Definition: ast.c:176
obr_t * obr_expr_field(scan_t *scan, where_t where, obr_t *expr, char *field)
Definition: ast.c:144
vector_t * obr_expand_vars(scan_t *scan, vector_t *symbols, obr_t *type)
Definition: ast.c:379
#define EXPAND_INNER(fn, scan,...)
Definition: ast.c:363
obr_t * obr_decl_procedure(scan_t *scan, where_t where, obr_symbol_t *symbol, obr_t *receiver, const vector_t *params, obr_t *result, vector_t *locals, vector_t *body, char *end)
Definition: ast.c:115
obr_t * obr_stmt_while(scan_t *scan, where_t where, obr_t *cond, vector_t *then)
Definition: ast.c:234
obr_t * obr_decl_var(obr_symbol_t *symbol, obr_t *type)
Definition: ast.c:101
obr_t * obr_expr_binary(scan_t *scan, where_t where, binary_t op, obr_t *lhs, obr_t *rhs)
Definition: ast.c:193
obr_t * obr_stmt_break(scan_t *scan, where_t where)
Definition: ast.c:249
obr_t * obr_type_pointer(scan_t *scan, where_t where, obr_t *type)
Definition: ast.c:303
vector_t * obr_expand_params(scan_t *scan, vector_t *symbols, obr_t *type, bool mut)
Definition: ast.c:389
obr_t * obr_stmt_branch(scan_t *scan, where_t where, obr_t *cond, vector_t *then, obr_t *other)
Definition: ast.c:277
obr_t * obr_receiver(scan_t *scan, where_t where, bool mut, char *name, char *type)
Definition: ast.c:342
obr_t * obr_module(scan_t *scan, where_t where, char *name, char *end, const vector_t *imports, vector_t *decls, vector_t *init)
Definition: ast.c:72
obr_visibility_t
Definition: ast.h:23
obr_kind_t
Definition: ast.h:42
@ eObrExprCall
Definition: ast.h:57
@ eObrStmtLoop
Definition: ast.h:69
@ eObrExprIn
Definition: ast.h:63
@ eObrExprDigit
Definition: ast.h:52
@ eObrTypeQual
Definition: ast.h:45
@ eObrTypeArray
Definition: ast.h:47
@ eObrStmtBlock
Definition: ast.h:72
@ eObrExprCast
Definition: ast.h:64
@ eObrExprBinary
Definition: ast.h:60
@ eObrExprCompare
Definition: ast.h:61
@ eObrExprField
Definition: ast.h:56
@ eObrExprName
Definition: ast.h:55
@ eObrTypeRecord
Definition: ast.h:48
@ eObrDeclVar
Definition: ast.h:77
@ eObrExprUnary
Definition: ast.h:59
@ eObrTypePointer
Definition: ast.h:46
@ eObrReceiver
Definition: ast.h:85
@ eObrImport
Definition: ast.h:89
@ eObrDeclConst
Definition: ast.h:78
@ eObrStmtWhile
Definition: ast.h:68
@ eObrDeclProcedure
Definition: ast.h:80
@ eObrDeclType
Definition: ast.h:79
@ eObrStmtBranch
Definition: ast.h:73
@ eObrExprString
Definition: ast.h:53
@ eObrExprIs
Definition: ast.h:62
@ eObrStmtBreak
Definition: ast.h:74
@ eObrModule
Definition: ast.h:88
@ eObrParam
Definition: ast.h:84
@ eObrStmtAssign
Definition: ast.h:71
@ eObrStmtRepeat
Definition: ast.h:70
@ eObrStmtReturn
Definition: ast.h:67
@ eObrField
Definition: ast.h:83
@ eObrTypeName
Definition: ast.h:44
an allocator object
Definition: arena.h:86
an event builder handles adding additional information to an event
Definition: notify.h:68
a logging sink
Definition: notify.c:14
a position in a source file
Definition: node.h:23
where_t where
Definition: ast.h:31
obr_visibility_t visibility
Definition: ast.h:33
scan_t * scan
Definition: ast.h:30
char * name
Definition: ast.h:34
Definition: ast.h:93
vector_t * then
Definition: ast.h:120
const vector_t * args
Definition: ast.h:110
const vector_t * params
Definition: ast.h:207
vector_t * branch_body
Definition: ast.h:155
obr_t * src
Definition: ast.h:146
vector_t * locals
Definition: ast.h:210
obr_t * cast
Definition: ast.h:107
char * field
Definition: ast.h:101
obr_t * rhs
Definition: ast.h:140
arena_t * arena
Definition: scan.h:22
a source file scanner
Definition: scan.h:24
a generic vector of pointers
Definition: vector.c:16
a location inside a scanner locations are inclusive and 0-based
Definition: where.h:23