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;
26 static const tree_t *gIntRef = NULL;
28 static tree_t *gPrint = NULL;
29 static tree_t *gRuntimePrint = NULL;
33 .visibility = eVisiblePrivate,
39 .visibility = eVisiblePublic
43 .
link = eLinkEntryCli,
44 .visibility = eVisiblePrivate
47 static char *pl0_normalize(
const char *name)
53 static void report_pl0_shadowing(
logger_t *reports,
const char *name,
const node_t *prev,
const node_t *next)
56 msg_note(
id,
"PL/0 is case insensitive");
61 char *
id = pl0_normalize(name);
62 for (
size_t i = 0; i < len; i++)
66 if (decl != NULL) {
return decl; }
72 static const pl0_tag_t kVarTags[] = { ePl0TagValues, ePl0TagImportedValues };
76 return get_decl(sema, name, kVarTags,
sizeof(kVarTags) /
sizeof(
pl0_tag_t));
79 static const pl0_tag_t kProcTags[] = { ePl0TagProcs, ePl0TagImportedProcs };
83 return get_decl(sema, name, kProcTags,
sizeof(kProcTags) /
sizeof(
pl0_tag_t));
88 char *
id = pl0_normalize(name);
94 tree_t *other = get_proc(sema, name);
95 if (other != NULL && other != proc)
99 report_pl0_shadowing(sema->
reports, name, other_node, node);
103 set_decl(sema, tag, name, proc);
108 tree_t *other = get_var(sema, name);
109 if (other != NULL && other != tree)
114 report_pl0_shadowing(sema->
reports, name, other_node, node);
118 set_decl(sema, tag, name, tree);
147 .quals = eQualMutable
162 gCharType = character;
163 gBoolType = get_bool_type(node);
169 tree_t *string_type = get_string_type(node, 4);
186 tree_t *putd_signature =
tree_type_closure(node,
"__builtin_pl0_print", gVoidType, rt_print_params, eArityFixed);
191 set_proc(root, ePl0TagProcs,
"__builtin_pl0_print", gPrint);
192 set_proc(root, ePl0TagProcs,
"printf", gRuntimePrint);
195 static void report_pl0_unresolved(
logger_t *reports,
const node_t *node,
const char *name)
198 msg_note(
id,
"symbol resolution is case sensitive");
220 return tree_error(node->
node, &kEvent_SymbolNotFound,
"unresolved identifier `%s`", node->
ident);
228 tree_t *lhs = sema_expr(sema, node->
lhs);
229 tree_t *rhs = sema_expr(sema, node->
rhs);
244 return sema_digit(node);
248 return sema_binary(sema, node);
250 return sema_unary(sema, node);
262 for (
size_t i = 0; i < len; i++)
265 tree_t *temp = sema_stmt(sema, it);
295 tree_t *cond = sema_compare(sema, node->
cond);
304 tree_t *src = sema_expr(sema, node->
src);
309 return tree_error(node->
node, &kEvent_VariableNotFound,
"unresolved destination variable `%s`", node->
dst);
315 if (quals & eQualConst)
325 tree_t *cond = sema_compare(sema, node->
cond);
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);
361 mpz_init_set_ui(zero, 0);
365 return sema_expr(sema, val);
372 mpz_init_set_ui(two, 2);
375 mpz_init_set_ui(one, 1);
388 tree_t *lhs = sema_expr(sema, node->
lhs);
389 tree_t *rhs = sema_expr(sema, node->
rhs);
398 case ePl0Odd:
return sema_odd(sema, node);
399 case ePl0Compare:
return sema_comp(sema, node);
413 for (
size_t i = 0; i < len; i++)
417 set_var(nest, ePl0TagValues, local->
name, it);
433 static void resolve_global(
tree_t *sema,
tree_t *decl,
void *user)
438 static void resolve_proc(
tree_t *sema,
tree_t *decl,
void *user)
440 sema_proc(sema, decl, user);
448 const char *name = NULL;
455 set_var(sema, ePl0TagImportedValues,
tree_get_name(decl), decl);
462 set_proc(sema, ePl0TagImportedProcs,
tree_get_name(decl), decl);
477 const tree_storage_t mutable_storage = get_mutable_storage(gIntType);
480 for (
size_t i = 0; i < const_count; i++)
487 .fn_resolve = resolve_global
494 set_var(root, ePl0TagValues, it->
name, tree);
497 for (
size_t i = 0; i < global_count; i++)
504 .fn_resolve = resolve_global
511 set_var(root, ePl0TagValues, it->
name, tree);
514 for (
size_t i = 0; i < proc_count; i++)
522 .fn_resolve = resolve_proc
528 set_proc(root, ePl0TagProcs, it->
name, tree);
541 for (
size_t i = 0; i < import_count; i++)
549 if (imported == NULL)
555 if (imported->
tree == root)
557 msg_notify(root->
reports, &kEvent_CirclularImport, import_decl->
node,
"module cannot import itself");
561 insert_module(root, imported->
tree);
571 if (ast->
entry != NULL)
588 set_decl(mod, ePl0TagProcs, name, entry);
CT_PUREFN CT_TREE_API const node_t * tree_get_node(const tree_t *tree)
CT_PUREFN CT_TREE_API const char * tree_get_name(const tree_t *tree)
CT_PUREFN CT_TREE_API const tree_t * tree_get_type(const tree_t *tree)
CT_TREE_API void tree_set_storage(tree_t *tree, tree_storage_t storage)
CT_TREE_API void tree_set_qualifiers(tree_t *tree, tree_quals_t qualifiers)
CT_PUREFN CT_TREE_API tree_quals_t tree_ty_get_quals(const tree_t *self)
CT_TREE_API bool tree_has_vis(const tree_t *self, tree_visibility_t visibility)
CT_BROKER_API void * unit_get_ast(compile_unit_t *unit)
CT_BROKER_API void unit_update(compile_unit_t *unit, void *ast, tree_t *tree)
CT_BROKER_API compile_unit_t * lang_get_unit(language_runtime_t *runtime, unit_id_t id)
CT_BROKER_API text_view_t build_unit_id(const vector_t *parts, arena_t *arena)
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
CT_MEMORY_API arena_t * get_global_arena(void)
get the global memory arena
#define CTU_MAP_NEXT(iter, key, value)
get the next key-value pair from a map iterator
CT_NODISCARD CT_PUREFN CT_STD_API map_iter_t map_iter(const map_t *map)
create a new map iterator
#define CT_UNUSED(x)
mark a variable as unused
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
#define CTASSERT(expr)
assert a condition, prints the condition as a message
#define CTASSERTF(expr,...)
assert a condition with a message and optional format arguments
CT_NODISCARD CT_STD_API char * str_join(const char *sep, const vector_t *parts, arena_t *arena)
join strings
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
CT_TREE_API tree_t * tree_open_function(const node_t *node, const char *name, const tree_t *signature, tree_resolve_info_t resolve)
CT_TREE_API tree_t * tree_expr_unit(const node_t *node, const tree_t *type)
CT_TREE_API tree_t * tree_type_reference(const node_t *node, const char *name, const tree_t *reference)
create a reference type
CT_TREE_API tree_t * tree_stmt_loop(const node_t *node, tree_t *cond, tree_t *body, tree_t *other)
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
CT_TREE_API tree_t * tree_expr_digit(const node_t *node, const tree_t *type, const mpz_t value)
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
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
CT_TREE_API tree_t * tree_open_global(const node_t *node, const char *name, const tree_t *type, tree_resolve_info_t resolve)
tree_quals_t
all type qualifiers
CT_TREE_API tree_t * tree_expr_unary(const node_t *node, unary_t unary, tree_t *expr)
CT_TREE_API void tree_close_function(tree_t *self, tree_t *body)
map_t * tree_module_tag(const tree_t *self, size_t tag)
CT_TREE_API tree_t * tree_stmt_return(const node_t *node, const tree_t *value)
create a return statement
CT_TREE_API tree_t * tree_error(const node_t *node, const diagnostic_t *diagnostic, const char *message,...)
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)
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
tree_cookie_t * tree_get_cookie(tree_t *sema)
return a resolution cookie
CT_TREE_API tree_t * tree_expr_call(const node_t *node, const tree_t *callee, const vector_t *args)
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
CT_TREE_API tree_t * tree_decl_param(const node_t *node, const char *name, const tree_t *type)
CT_TREE_API void tree_close_global(tree_t *self, tree_t *value)
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)
CT_TREE_API tree_t * tree_expr_load(const node_t *node, tree_t *expr)
load a value from a pointer or storage
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
CT_TREE_API tree_t * tree_stmt_assign(const node_t *node, tree_t *dst, const tree_t *src)
CT_TREE_API tree_t * tree_stmt_block(const node_t *node, const vector_t *stmts)
create a block statement
CT_TREE_API void tree_add_local(tree_t *self, tree_t *decl)
CT_TREE_API tree_t * tree_resolve(tree_cookie_t *cookie, const tree_t *decl)
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
void * tree_module_set(tree_t *self, size_t tag, const char *name, void *value)
set a declaration in the current module
CT_TREE_API void tree_set_attrib(tree_t *self, const tree_attribs_t *attrib)
CT_TREE_API tree_t * tree_stmt_branch(const node_t *node, tree_t *cond, tree_t *then, tree_t *other)
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)
CT_TREE_API tree_t * tree_decl_local(const node_t *node, const char *name, tree_storage_t storage, const tree_t *type)
void * tree_module_get(tree_t *self, size_t tag, const char *name)
recursively search for a declaration in a module
CT_NODISCARD CT_PUREFN CT_STD_API void * vector_get(const vector_t *vector, size_t index)
get a value from a vector
CT_NODISCARD CT_STD_API vector_t * vector_of(size_t len, arena_t *arena)
create a new vector with a specified length
CT_STD_API const vector_t kEmptyVector
a global empty vector used to avoid allocating alot of empty vectors
CT_STD_API void vector_push(vector_t **vector, void *value)
push a value onto the end of a vector
CT_STD_API void vector_set(vector_t *vector, size_t index, void *value)
set a value in a vector
CT_STD_API vector_t gEmptyVector
a global empty vector used to avoid allocating alot of empty vectors
CT_NODISCARD CT_STD_API vector_t * vector_init(void *value, arena_t *arena)
create a new vector with a single initial value
CT_NODISCARD CT_PUREFN CT_STD_API size_t vector_len(const vector_t *vector)
get the length of a vector
void pl0_process_imports(language_runtime_t *runtime, compile_unit_t *context)
void pl0_init(language_runtime_t *runtime, tree_t *root)
void pl0_forward_decls(language_runtime_t *runtime, compile_unit_t *context)
void pl0_compile_module(language_runtime_t *runtime, compile_unit_t *context)
tree_t * tree
the tree for this unit is NULL if the unit has not been forward declared yet
an event builder handles adding additional information to an event
arena_t * arena
default memory arena
a position in a source file
a non-owning view of text
tree_linkage_t link
the link type of the declaration
const tree_t * storage
the underlying storage type
a generic vector of pointers