/* * Functions for constructing/accessing the Abstract Syntax Tree. * * Copyright © 2025 Samuel Lidén Borell * * SPDX-License-Identifier: EUPL-1.2+ */ #include #include "compiler.h" #include "token.h" struct Module *module, *modules; struct Type *current_type; struct Func *current_func; static struct Type **type_nextptr, **inner_type_nextptr; static struct Func **func_nextptr; static struct Func **type_func_nextptr, **innertype_func_nextptr; void module_start(void) { struct Module *mod = malloc(sizeof(struct Module)); NO_NULL(mod); mod->types = NULL; mod->funcs = NULL; mod->types_list = NULL; mod->funcs_list = NULL; mod->next = modules; modules = mod; module = mod; current_type = NULL; current_func = NULL; type_nextptr = &module->types_list; func_nextptr = &module->funcs_list; } struct Type *map_named_type(const char *name, size_t len) { struct TreeNode **root; struct Type *t; /* If inside an type definition, then the sought type might be an inner/nested type defined later within the type being defined. So in that case we ONLY search among the inner types at this point, and only at the end we can search among the top-level types. */ /* XXX could perhaps require that inner types start with an underscore? */ root = (current_type ? ¤t_type->inner_types : &module->types); t = (struct Type *)tree_insert_str(root, name, len, NULL, sizeof(struct Type)); if (!t->ident.node.is_new) { return t; } t->outer = current_type; t->funcs = NULL; t->funcs_list = NULL; t->inner_types = NULL; t->inner_types_list = NULL; t->next = NULL; if (current_type) { *inner_type_nextptr = t; inner_type_nextptr = &t->next; } else { *type_nextptr = t; type_nextptr = &t->next; } return t; } void type_start(const char *name, size_t len) { struct Type *t; t = map_named_type(name, len); if (t->ident.node.is_defined) { error("Duplicate type name"); } t->ident.node.is_defined = 1; if (current_type) { innertype_func_nextptr = &t->funcs_list; } else { type_func_nextptr = &t->funcs_list; inner_type_nextptr = &t->inner_types_list; } current_type = t; } void type_end(void) { current_type = current_type->outer; } struct Func *map_named_func(const char *name, size_t len) { struct Func *f; struct TreeNode **root; /* XXX similar problem as for types */ root = (current_type ? ¤t_type->funcs : &module->funcs); f = (struct Func *)tree_insert_str(root, name, len, NULL, sizeof(struct Func)); f->class_ = current_type; f->params = NULL; f->returns = NULL; f->vardecls = NULL; f->vars = NULL; f->code = NULL; f->section_first = NULL; f->section_by_name = NULL; f->is_noreturn = 0; f->num_params = 0; f->num_returns = 0; f->next = NULL; if (current_type && current_type->outer) { *innertype_func_nextptr = f; innertype_func_nextptr = &f->next; } else if (current_type) { *type_func_nextptr = f; type_func_nextptr = &f->next; } else { *func_nextptr = f; func_nextptr = &f->next; } return f; } void func_start(const char *name, size_t len) { struct Func *f; f = map_named_func(name, len); if (f->ident.node.is_defined) { error("Duplicate function name"); } f->ident.node.is_defined = 1; current_func = f; } void func_end(void) { current_func = NULL; }