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 "pl0/sema.h"
4 #include "core/macros.h"
7 #include "memory/memory.h"
8 #include "pl0/ast.h"
9 
10 #include "cthulhu/util/util.h"
11 
12 #include "base/panic.h"
13 
14 #include "std/str.h"
15 #include "std/map.h"
16 #include "std/vector.h"
17 
18 #include "cthulhu/tree/tree.h"
19 #include "cthulhu/tree/query.h"
20 
21 static const tree_t *gIntType = NULL;
22 static const tree_t *gCharType = NULL;
23 static const tree_t *gBoolType = NULL;
24 static const tree_t *gVoidType = NULL;
25 
26 static const tree_t *gIntRef = NULL;
27 
28 static tree_t *gPrint = NULL; // pl0_print
29 static tree_t *gRuntimePrint = NULL; // printf
30 
31 static const tree_attribs_t kPrintAttrib = {
32  .link = eLinkImport,
33  .visibility = eVisiblePrivate,
34  .mangle = "printf"
35 };
36 
37 static const tree_attribs_t kExportAttrib = {
38  .link = eLinkExport,
39  .visibility = eVisiblePublic
40 };
41 
42 static const tree_attribs_t kEntryAttrib = {
43  .link = eLinkEntryCli,
44  .visibility = eVisiblePrivate
45 };
46 
47 static char *pl0_normalize(const char *name)
48 {
49  arena_t *arena = get_global_arena();
50  return str_lower(name, arena);
51 }
52 
53 static void report_pl0_shadowing(logger_t *reports, const char *name, const node_t *prev, const node_t *next)
54 {
55  event_builder_t id = evt_symbol_shadowed(reports, name, prev, next);
56  msg_note(id, "PL/0 is case insensitive");
57 }
58 
59 static tree_t *get_decl(tree_t *sema, const char *name, const pl0_tag_t *tags, size_t len)
60 {
61  char *id = pl0_normalize(name);
62  for (size_t i = 0; i < len; i++)
63  {
64  pl0_tag_t tag = tags[i];
65  tree_t *decl = tree_module_get(sema, tag, id);
66  if (decl != NULL) { return decl; }
67  }
68 
69  return NULL;
70 }
71 
72 static const pl0_tag_t kVarTags[] = { ePl0TagValues, ePl0TagImportedValues };
73 
74 static tree_t *get_var(tree_t *sema, const char *name)
75 {
76  return get_decl(sema, name, kVarTags, sizeof(kVarTags) / sizeof(pl0_tag_t));
77 }
78 
79 static const pl0_tag_t kProcTags[] = { ePl0TagProcs, ePl0TagImportedProcs };
80 
81 static tree_t *get_proc(tree_t *sema, const char *name)
82 {
83  return get_decl(sema, name, kProcTags, sizeof(kProcTags) / sizeof(pl0_tag_t));
84 }
85 
86 static void set_decl(tree_t *sema, pl0_tag_t tag, const char *name, tree_t *decl)
87 {
88  char *id = pl0_normalize(name);
89  tree_module_set(sema, tag, id, decl);
90 }
91 
92 static void set_proc(tree_t *sema, pl0_tag_t tag, const char *name, tree_t *proc)
93 {
94  tree_t *other = get_proc(sema, name);
95  if (other != NULL && other != proc)
96  {
97  const node_t *node = tree_get_node(proc);
98  const node_t *other_node = tree_get_node(other);
99  report_pl0_shadowing(sema->reports, name, other_node, node);
100  return;
101  }
102 
103  set_decl(sema, tag, name, proc);
104 }
105 
106 static void set_var(tree_t *sema, pl0_tag_t tag, const char *name, tree_t *tree)
107 {
108  tree_t *other = get_var(sema, name);
109  if (other != NULL && other != tree)
110  {
111  const node_t *node = tree_get_node(tree);
112  const node_t *other_node = tree_get_node(other);
113 
114  report_pl0_shadowing(sema->reports, name, other_node, node);
115  return;
116  }
117 
118  set_decl(sema, tag, name, tree);
119 }
120 
121 static tree_t *get_string_type(const node_t *node, size_t size)
122 {
123  return tree_type_pointer(node, "string", gCharType, size);
124 }
125 
126 static tree_t *get_bool_type(const node_t *node)
127 {
128  return tree_type_bool(node, "boolean");
129 }
130 
131 static tree_storage_t get_const_storage(const tree_t *type)
132 {
133  tree_storage_t storage = {
134  .storage = type,
135  .length = 1,
136  .quals = eQualConst
137  };
138 
139  return storage;
140 }
141 
142 static tree_storage_t get_mutable_storage(const tree_t *type)
143 {
144  tree_storage_t storage = {
145  .storage = type,
146  .length = 1,
147  .quals = eQualMutable
148  };
149 
150  return storage;
151 }
152 
153 void pl0_init(language_runtime_t *runtime, tree_t *root)
154 {
155  const node_t *node = tree_get_node(root);
156  arena_t *arena = runtime->arena;
157 
158  tree_t *character = tree_type_digit(node, "char", eDigitChar, eSignSigned);
159  tree_set_qualifiers(character, eQualConst);
160 
161  gIntType = tree_type_digit(node, "integer", eDigitInt, eSignSigned);
162  gCharType = character;
163  gBoolType = get_bool_type(node);
164 
165  gVoidType = tree_type_unit(node, "void");
166 
167  gIntRef = tree_type_reference(node, "ref", gIntType);
168 
169  tree_t *string_type = get_string_type(node, 4);
170 
171  vector_t *params = vector_of(1, arena);
172  vector_set(params, 0, tree_decl_param(node, "fmt", string_type));
173 
174  tree_t *signature = tree_type_closure(node, "printf", gIntType, params, eArityVariable);
175  gRuntimePrint = tree_decl_function(node, "printf", signature, params, &gEmptyVector, NULL);
176  tree_set_attrib(gRuntimePrint, &kPrintAttrib);
177 
178  tree_t *param = tree_decl_param(node, "number", gIntType);
179  vector_t *rt_print_params = vector_init(param, arena);
180 
181  vector_t *args = vector_of(2, arena);
182  vector_set(args, 0, tree_expr_string(node, string_type, "%d\n", 4));
183  vector_set(args, 1, param);
184  tree_t *call = tree_expr_call(node, gRuntimePrint, args);
185 
186  tree_t *putd_signature = tree_type_closure(node, "__builtin_pl0_print", gVoidType, rt_print_params, eArityFixed);
187  gPrint = tree_decl_function(node, "__builtin_pl0_print", putd_signature, rt_print_params, &gEmptyVector, call);
188  tree_set_attrib(gPrint, &kExportAttrib);
189 
190  // populate builtins
191  set_proc(root, ePl0TagProcs, "__builtin_pl0_print", gPrint);
192  set_proc(root, ePl0TagProcs, "printf", gRuntimePrint);
193 }
194 
195 static void report_pl0_unresolved(logger_t *reports, const node_t *node, const char *name)
196 {
197  event_builder_t id = msg_notify(reports, &kEvent_SymbolNotFound, node, "unresolved reference to `%s`", name);
198  msg_note(id, "symbol resolution is case sensitive");
199 }
200 
204 
205 static tree_t *sema_expr(tree_t *sema, pl0_t *node);
206 static tree_t *sema_compare(tree_t *sema, pl0_t *node);
207 static tree_t *sema_stmt(tree_t *sema, pl0_t *node);
208 
209 static tree_t *sema_digit(pl0_t *node)
210 {
211  return tree_expr_digit(node->node, gIntType, node->digit);
212 }
213 
214 static tree_t *sema_ident(tree_t *sema, pl0_t *node)
215 {
216  tree_t *var = get_var(sema, node->ident);
217  if (var == NULL)
218  {
219  report_pl0_unresolved(sema->reports, node->node, node->ident);
220  return tree_error(node->node, &kEvent_SymbolNotFound, "unresolved identifier `%s`", node->ident);
221  }
222 
223  return tree_resolve(tree_get_cookie(sema), var);
224 }
225 
226 static tree_t *sema_binary(tree_t *sema, pl0_t *node)
227 {
228  tree_t *lhs = sema_expr(sema, node->lhs);
229  tree_t *rhs = sema_expr(sema, node->rhs);
230  return tree_expr_binary(node->node, gIntType, node->binary, lhs, rhs);
231 }
232 
233 static tree_t *sema_unary(tree_t *sema, pl0_t *node)
234 {
235  tree_t *operand = sema_expr(sema, node->operand);
236  return tree_expr_unary(node->node, node->unary, operand);
237 }
238 
239 static tree_t *sema_expr(tree_t *sema, pl0_t *node)
240 {
241  switch (node->type)
242  {
243  case ePl0Digit:
244  return sema_digit(node);
245  case ePl0Ident:
246  return tree_expr_load(node->node, sema_ident(sema, node));
247  case ePl0Binary:
248  return sema_binary(sema, node);
249  case ePl0Unary:
250  return sema_unary(sema, node);
251  default:
252  CT_NEVER("sema-expr: %d", node->type);
253  }
254 }
255 
256 static vector_t *sema_stmt_vector(tree_t *sema, vector_t *body)
257 {
258  size_t len = vector_len(body);
259  arena_t *arena = get_global_arena();
260  vector_t *result = vector_of(len, arena);
261 
262  for (size_t i = 0; i < len; i++)
263  {
264  pl0_t *it = vector_get(body, i);
265  tree_t *temp = sema_stmt(sema, it);
266  vector_set(result, i, temp);
267  }
268 
269  return result;
270 }
271 
272 static tree_t *sema_stmts(tree_t *sema, pl0_t *node)
273 {
274  CTASSERTF(node->type == ePl0Stmts, "expected stmts, got %d", node->type);
275 
276  vector_t *stmts = sema_stmt_vector(sema, node->stmts);
277 
278  return tree_stmt_block(node->node, stmts);
279 }
280 
281 static tree_t *sema_call(tree_t *sema, pl0_t *node)
282 {
283  tree_t *proc = get_proc(sema, node->procedure);
284  if (proc == NULL)
285  {
286  report_pl0_unresolved(sema->reports, node->node, node->procedure);
287  return tree_error(node->node, &kEvent_FunctionNotFound, "unresolved procedure `%s`", node->procedure);
288  }
289 
290  return tree_expr_call(node->node, proc, &gEmptyVector);
291 }
292 
293 static tree_t *sema_branch(tree_t *sema, pl0_t *node)
294 {
295  tree_t *cond = sema_compare(sema, node->cond);
296  tree_t *then = sema_stmt(sema, node->then);
297 
298  return tree_stmt_branch(node->node, cond, then, NULL);
299 }
300 
301 static tree_t *sema_assign(tree_t *sema, pl0_t *node)
302 {
303  tree_t *dst = get_var(sema, node->dst);
304  tree_t *src = sema_expr(sema, node->src);
305 
306  if (dst == NULL)
307  {
308  report_pl0_unresolved(sema->reports, node->node, node->dst);
309  return tree_error(node->node, &kEvent_VariableNotFound, "unresolved destination variable `%s`", node->dst);
310  }
311 
312  const tree_t *dst_type = tree_get_type(dst);
313  tree_quals_t quals = tree_ty_get_quals(dst_type);
314 
315  if (quals & eQualConst)
316  {
317  msg_notify(sema->reports, &kEvent_MutationOfConst, node->node, "cannot assign to constant value");
318  }
319 
320  return tree_stmt_assign(node->node, dst, src);
321 }
322 
323 static tree_t *sema_loop(tree_t *sema, pl0_t *node)
324 {
325  tree_t *cond = sema_compare(sema, node->cond);
326  tree_t *body = sema_stmt(sema, node->then);
327 
328  return tree_stmt_loop(node->node, cond, body, NULL);
329 }
330 
331 static tree_t *sema_print(tree_t *sema, pl0_t *node)
332 {
333  tree_t *expr = sema_expr(sema, node->print);
334 
335  arena_t *arena = get_global_arena();
336  vector_t *args = vector_init(expr, arena);
337 
338  return tree_expr_call(node->node, gPrint, args);
339 }
340 
341 static tree_t *sema_stmt(tree_t *sema, pl0_t *node)
342 {
343  switch (node->type)
344  {
345  case ePl0Stmts: return sema_stmts(sema, node);
346  case ePl0Call: return sema_call(sema, node);
347  case ePl0Branch: return sema_branch(sema, node);
348  case ePl0Loop: return sema_loop(sema, node);
349  case ePl0Assign: return sema_assign(sema, node);
350  case ePl0Print: return sema_print(sema, node);
351  default: CT_NEVER("sema-stmt: %d", node->type);
352  }
353 }
354 
355 static tree_t *sema_global(tree_t *sema, pl0_t *node)
356 {
357  pl0_t *val = node->value;
358  if (val == NULL)
359  {
360  mpz_t zero;
361  mpz_init_set_ui(zero, 0);
362  return tree_expr_digit(node->node, gIntType, zero);
363  }
364 
365  return sema_expr(sema, val);
366 }
367 
368 static tree_t *sema_odd(tree_t *sema, pl0_t *node)
369 {
370  // desugar odd(n) -> n % 2 == 1
371  mpz_t two;
372  mpz_init_set_ui(two, 2);
373 
374  mpz_t one;
375  mpz_init_set_ui(one, 1);
376 
377  tree_t *val = sema_expr(sema, node->operand);
378  tree_t *two_value = tree_expr_digit(node->node, gIntType, two);
379  tree_t *one_value = tree_expr_digit(node->node, gIntType, one);
380  tree_t *rem = tree_expr_binary(node->node, gIntType, eBinaryRem, val, two_value);
381  tree_t *eq = tree_expr_compare(node->node, gBoolType, eCompareEq, rem, one_value);
382 
383  return eq;
384 }
385 
386 static tree_t *sema_comp(tree_t *sema, pl0_t *node)
387 {
388  tree_t *lhs = sema_expr(sema, node->lhs);
389  tree_t *rhs = sema_expr(sema, node->rhs);
390 
391  return tree_expr_compare(node->node, gBoolType, node->compare, lhs, rhs);
392 }
393 
394 static tree_t *sema_compare(tree_t *sema, pl0_t *node)
395 {
396  switch (node->type)
397  {
398  case ePl0Odd: return sema_odd(sema, node);
399  case ePl0Compare: return sema_comp(sema, node);
400  default: CT_NEVER("sema-compare: %d", node->type);
401  }
402 }
403 
404 static void sema_proc(tree_t *sema, tree_t *tree, pl0_t *node)
405 {
406  size_t len = vector_len(node->locals);
407  size_t sizes[ePl0TagTotal] = {[ePl0TagValues] = len};
408 
409  tree_t *nest = tree_module(sema, node->node, node->name, ePl0TagTotal, sizes);
410 
411  const tree_storage_t storage = get_mutable_storage(gIntType);
412 
413  for (size_t i = 0; i < len; i++)
414  {
415  pl0_t *local = vector_get(node->locals, i);
416  tree_t *it = tree_decl_local(local->node, local->name, storage, gIntRef);
417  set_var(nest, ePl0TagValues, local->name, it);
418  tree_add_local(tree, it);
419  }
420 
421  vector_t *inner = sema_stmt_vector(nest, node->body);
422 
423  // make sure we always have a return statement
424  tree_t *ret = tree_stmt_return(node->node, tree_expr_unit(node->node, gVoidType));
425  vector_push(&inner, ret);
426 
427  // make sure we have a return statement
428  tree_t *stmts = tree_stmt_block(node->node, inner);
429 
430  tree_close_function(tree, stmts);
431 }
432 
433 static void resolve_global(tree_t *sema, tree_t *decl, void *user)
434 {
435  tree_close_global(decl, sema_global(sema, user));
436 }
437 
438 static void resolve_proc(tree_t *sema, tree_t *decl, void *user)
439 {
440  sema_proc(sema, decl, user);
441 }
442 
443 static void insert_module(tree_t *sema, tree_t *other)
444 {
445  map_iter_t other_values = map_iter(tree_module_tag(other, ePl0TagValues));
446  map_iter_t other_procs = map_iter(tree_module_tag(other, ePl0TagProcs));
447 
448  const char *name = NULL;
449  tree_t *decl = NULL;
450 
451  while (CTU_MAP_NEXT(&other_values, &name, &decl))
452  {
453  if (!tree_has_vis(decl, eVisiblePublic)) continue;
454 
455  set_var(sema, ePl0TagImportedValues, tree_get_name(decl), decl);
456  }
457 
458  while (CTU_MAP_NEXT(&other_procs, &name, &decl))
459  {
460  if (!tree_has_vis(decl, eVisiblePublic)) continue;
461 
462  set_proc(sema, ePl0TagImportedProcs, tree_get_name(decl), decl);
463  }
464 }
465 
467 {
468  CT_UNUSED(runtime);
469 
470  pl0_t *ast = unit_get_ast(context);
471  size_t const_count = vector_len(ast->consts);
472  size_t global_count = vector_len(ast->globals);
473  size_t proc_count = vector_len(ast->procs);
474 
475  tree_t *root = context->tree;
476  const tree_storage_t const_storage = get_const_storage(gIntType);
477  const tree_storage_t mutable_storage = get_mutable_storage(gIntType);
478 
479  // forward declare everything
480  for (size_t i = 0; i < const_count; i++)
481  {
482  pl0_t *it = vector_get(ast->consts, i);
483 
484  tree_resolve_info_t resolve = {
485  .sema = root,
486  .user = it,
487  .fn_resolve = resolve_global
488  };
489 
490  tree_t *tree = tree_open_global(it->node, it->name, gIntRef, resolve);
491  tree_set_storage(tree, const_storage);
492  tree_set_attrib(tree, &kExportAttrib);
493 
494  set_var(root, ePl0TagValues, it->name, tree);
495  }
496 
497  for (size_t i = 0; i < global_count; i++)
498  {
499  pl0_t *it = vector_get(ast->globals, i);
500 
501  tree_resolve_info_t resolve = {
502  .sema = root,
503  .user = it,
504  .fn_resolve = resolve_global
505  };
506 
507  tree_t *tree = tree_open_global(it->node, it->name, gIntRef, resolve);
508  tree_set_storage(tree, mutable_storage);
509  tree_set_attrib(tree, &kExportAttrib);
510 
511  set_var(root, ePl0TagValues, it->name, tree);
512  }
513 
514  for (size_t i = 0; i < proc_count; i++)
515  {
516  pl0_t *it = vector_get(ast->procs, i);
517 
518  tree_t *signature = tree_type_closure(it->node, it->name, gVoidType, &kEmptyVector, eArityFixed);
519  tree_resolve_info_t resolve = {
520  .sema = root,
521  .user = it,
522  .fn_resolve = resolve_proc
523  };
524 
525  tree_t *tree = tree_open_function(it->node, it->name, signature, resolve);
526  tree_set_attrib(tree, &kExportAttrib);
527 
528  set_proc(root, ePl0TagProcs, it->name, tree);
529  }
530 
531  unit_update(context, ast, root);
532 }
533 
535 {
536  pl0_t *ast = unit_get_ast(context);
537  arena_t *arena = runtime->arena;
538  tree_t *root = context->tree;
539 
540  size_t import_count = vector_len(ast->imports);
541  for (size_t i = 0; i < import_count; i++)
542  {
543  pl0_t *import_decl = vector_get(ast->imports, i);
544  CTASSERT(import_decl->type == ePl0Import);
545 
546  unit_id_t id = build_unit_id(import_decl->path, arena);
547  compile_unit_t *imported = lang_get_unit(runtime, id);
548 
549  if (imported == NULL)
550  {
551  msg_notify(root->reports, &kEvent_ImportNotFound, import_decl->node, "cannot import `%s`, failed to find module", str_join(".", import_decl->path, arena));
552  continue;
553  }
554 
555  if (imported->tree == root)
556  {
557  msg_notify(root->reports, &kEvent_CirclularImport, import_decl->node, "module cannot import itself");
558  continue;
559  }
560 
561  insert_module(root, imported->tree);
562  }
563 }
564 
566 {
567  CT_UNUSED(runtime);
568 
569  pl0_t *ast = unit_get_ast(context);
570 
571  if (ast->entry != NULL)
572  {
573  tree_t *mod = context->tree;
574  const char *name = tree_get_name(mod);
575 
576  CTASSERTF(ast->entry->type == ePl0Stmts, "expected stmts, got %d", ast->entry->type);
577  vector_t *stmts = sema_stmt_vector(mod, ast->entry->stmts);
578  vector_push(&stmts, tree_stmt_return(ast->node, tree_expr_unit(ast->node, gVoidType)));
579 
580  tree_t *body = tree_stmt_block(ast->node, stmts);
581 
582  // this is the entry point, we only support cli entry points in pl/0 for now
583  tree_t *signature = tree_type_closure(ast->node, name, gVoidType, &kEmptyVector, eArityFixed);
584  tree_t *entry = tree_decl_function(ast->node, name, signature, &kEmptyVector, &gEmptyVector, body);
585  tree_set_attrib(entry, &kEntryAttrib);
586 
587  // TODO: this is a hack until we support anonymous declarations
588  set_decl(mod, ePl0TagProcs, name, entry);
589  }
590 }
CT_NODISCARD size_t size
Definition: scan.h:128
CT_PUREFN CT_TREE_API const node_t * tree_get_node(const tree_t *tree)
Definition: context.c:94
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_TREE_API void tree_set_storage(tree_t *tree, tree_storage_t storage)
Definition: context.c:58
CT_TREE_API void tree_set_qualifiers(tree_t *tree, tree_quals_t qualifiers)
Definition: context.c:42
CT_PUREFN CT_TREE_API tree_quals_t tree_ty_get_quals(const tree_t *self)
Definition: query.c:257
CT_TREE_API bool tree_has_vis(const tree_t *self, tree_visibility_t visibility)
Definition: query.c:98
CT_BROKER_API void * unit_get_ast(compile_unit_t *unit)
Definition: broker.c:511
CT_BROKER_API void unit_update(compile_unit_t *unit, void *ast, tree_t *tree)
Definition: broker.c:519
CT_BROKER_API compile_unit_t * lang_get_unit(language_runtime_t *runtime, unit_id_t id)
Definition: broker.c:494
CT_BROKER_API text_view_t build_unit_id(const vector_t *parts, arena_t *arena)
Definition: broker.c:532
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
CT_MEMORY_API arena_t * get_global_arena(void)
get the global memory arena
Definition: memory.c:16
#define CTU_MAP_NEXT(iter, key, value)
get the next key-value pair from a map iterator
Definition: map.h:250
CT_NODISCARD CT_PUREFN CT_STD_API map_iter_t map_iter(const map_t *map)
create a new map iterator
Definition: map.c:456
#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
CT_NOTIFY_API void msg_note(event_builder_t builder, STA_FORMAT_STRING const char *fmt,...)
add a note to an existing 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_NODISCARD CT_STD_API char * str_join(const char *sep, const vector_t *parts, arena_t *arena)
join strings
Definition: str.c:274
CT_NODISCARD CT_STD_API char * str_lower(const char *str, arena_t *arena)
lowercase an ascii string this allocates a new string in the provided arena
Definition: str.c:952
CT_TREE_API tree_t * tree_open_function(const node_t *node, const char *name, const tree_t *signature, tree_resolve_info_t resolve)
Definition: decl.c:147
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_type_reference(const node_t *node, const char *name, const tree_t *reference)
create a reference type
Definition: tree.c:185
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_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_expr_digit(const node_t *node, const tree_t *type, const mpz_t value)
Definition: tree.c:217
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
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_open_global(const node_t *node, const char *name, const tree_t *type, tree_resolve_info_t resolve)
Definition: decl.c:140
tree_quals_t
all type qualifiers
Definition: ops.h:25
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 void tree_close_function(tree_t *self, tree_t *body)
Definition: decl.c:168
map_t * tree_module_tag(const tree_t *self, size_t tag)
Definition: sema.c:125
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
tree_cookie_t * tree_get_cookie(tree_t *sema)
return a resolution cookie
Definition: sema.c:136
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_decl_param(const node_t *node, const char *name, const tree_t *type)
Definition: decl.c:188
CT_TREE_API void tree_close_global(tree_t *self, tree_t *value)
Definition: decl.c:162
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_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_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 tree_t * tree_resolve(tree_cookie_t *cookie, const tree_t *decl)
Definition: decl.c:47
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
CT_TREE_API void tree_set_attrib(tree_t *self, const tree_attribs_t *attrib)
Definition: decl.c:251
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_function(const node_t *node, const char *name, const tree_t *signature, const vector_t *params, vector_t *locals, tree_t *body)
Definition: decl.c:224
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
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
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 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_STD_API void vector_set(vector_t *vector, size_t index, void *value)
set a value in a vector
Definition: vector.c:125
CT_STD_API vector_t gEmptyVector
a global empty vector used to avoid allocating alot of empty vectors
Definition: vector.c:24
CT_NODISCARD CT_STD_API vector_t * vector_init(void *value, arena_t *arena)
create a new vector with a single initial value
Definition: vector.c:79
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
void pl0_process_imports(language_runtime_t *runtime, compile_unit_t *context)
Definition: sema.c:534
void pl0_init(language_runtime_t *runtime, tree_t *root)
Definition: sema.c:153
void pl0_forward_decls(language_runtime_t *runtime, compile_unit_t *context)
Definition: sema.c:466
void pl0_compile_module(language_runtime_t *runtime, compile_unit_t *context)
Definition: sema.c:565
pl0_tag_t
Definition: sema.h:11
@ ePl0TagTotal
Definition: sema.h:14
an allocator object
Definition: arena.h:86
tree_t * tree
the tree for this unit is NULL if the unit has not been forward declared yet
Definition: broker.h:289
an event builder handles adding additional information to an event
Definition: notify.h:68
arena_t * arena
default memory arena
Definition: broker.h:266
a logging sink
Definition: notify.c:14
a map iterator handle
Definition: map.h:183
a position in a source file
Definition: node.h:23
Definition: ast.h:24
struct pl0_t * print
Definition: ast.h:39
const char * procedure
Definition: ast.h:36
unary_t unary
Definition: ast.h:44
const char * name
Definition: ast.h:80
pl0_type_t type
Definition: ast.h:25
const char * ident
Definition: ast.h:33
struct pl0_t * lhs
Definition: ast.h:51
vector_t * path
Definition: ast.h:99
struct pl0_t * value
Definition: ast.h:94
vector_t * locals
Definition: ast.h:87
const vector_t * globals
Definition: ast.h:107
const vector_t * consts
Definition: ast.h:104
const vector_t * imports
Definition: ast.h:116
struct pl0_t * cond
Definition: ast.h:70
vector_t * stmts
Definition: ast.h:75
const node_t * node
Definition: ast.h:26
binary_t binary
Definition: ast.h:55
const vector_t * procs
Definition: ast.h:110
mpz_t digit
Definition: ast.h:30
struct pl0_t * src
Definition: ast.h:64
const char * dst
Definition: ast.h:63
vector_t * body
Definition: ast.h:90
compare_t compare
Definition: ast.h:56
struct pl0_t * entry
Definition: ast.h:119
struct pl0_t * then
Definition: ast.h:71
struct pl0_t * operand
Definition: ast.h:45
struct pl0_t * rhs
Definition: ast.h:52
a non-owning view of text
Definition: text.h:24
tree_linkage_t link
the link type of the declaration
Definition: tree.h:51
tree_t * sema
Definition: tree.h:60
storage for a value
Definition: context.h:23
const tree_t * storage
the underlying storage type
Definition: context.h:25
Definition: tree.h:67
logger_t * reports
Definition: tree.h:227
size_t length
Definition: tree.h:174
a generic vector of pointers
Definition: vector.c:16