gemstone/src/ast/ast.h

284 lines
8.1 KiB
C

#ifndef _AST_H_
#define _AST_H_
#include <io/files.h>
#include <stdio.h>
/**
* @brief The type of a AST node
* @attention The last element is not to be used in the AST
* as it is used as a lazy way to get the total number of available
* variants of this enum.
*/
enum AST_SyntaxElement_t {
AST_Stmt = 0,
AST_Module,
AST_Expr,
// Literals
AST_Int,
AST_Float,
AST_String,
// Control flow
AST_While,
AST_If,
AST_IfElse,
AST_Else,
AST_Condition,
// Variable management
AST_Decl,
AST_Assign,
AST_Def,
AST_Ident,
// Arithmetic operators
AST_Add,
AST_Sub,
AST_Mul,
AST_Div,
// Bitwise operators
AST_BitAnd,
AST_BitOr,
AST_BitXor,
AST_BitNot,
// Boolean operators
AST_BoolAnd,
AST_BoolOr,
AST_BoolXor,
AST_BoolNot,
// Logical operators
AST_Eq,
AST_Greater,
AST_Less,
// Casts
AST_Typecast, // type cast
AST_Transmute, // reinterpret cast
AST_Call, // function call
AST_Macro, // builtin functions: lineno(), filename(), ...
// Defintions
AST_Typedef,
AST_Box,
AST_FunDecl,
AST_FunDef,
AST_ProcDecl,
AST_ProcDef,
AST_Import,
// amount of variants
// in this enums
AST_List,
AST_ExprList,
AST_ArgList,
AST_ParamList,
AST_StmtList,
AST_IdentList,
AST_Storage,
AST_Type,
AST_Typekind,
AST_Sign,
AST_Scale,
AST_Negate,
AST_Parameter,
AST_Qualifyier,
AST_ParamDecl,
AST_AddressOf,
AST_Dereference,
AST_Reference,
AST_Include,
AST_Char,
AST_Return,
AST_ModuleRef,
AST_ELEMENT_COUNT
};
typedef enum AST_AnnotationKind_t {
AnnotationKindFlag,
AnnotationKindVariable,
AnnotationKindArray,
AnnotationKindNone
} AST_AnnotationKind;
struct AST_Annotation_t;
typedef enum AST_AnnotationValueKind_t {
AnnotationValueKindAnnotation,
AnnotationValueKindString,
AnnotationValueKindInteger
} AST_AnnotationValueKind;
typedef struct AST_AnnotationValue_t {
AST_AnnotationValueKind kind;
union {
struct AST_Annotation_t* annotation;
char* string;
int64_t integer;
} impl;
} AST_AnnotationValue;
typedef struct AST_Annotation_t {
AST_AnnotationKind kind;
union {
// array of annotation values
GArray* array;
struct {
char* name;
AST_AnnotationValue value;
} variable;
char* flag;
} impl;
} AST_Annotation;
bool AST_annotation_array_contains_flag(AST_Annotation*, const char*);
/**
* @brief A single node which can be joined with other nodes like a graph.
* Every node can have one ancestor (parent) but multiple (also none) children.
* Nodes have two properties:
* - kind: The type of the node. Such as AST_Expr, AST_Add, ...
* - value: A string representing an optional value. Can be a integer literal
* for kind AST_int
*/
typedef struct AST_Node_t {
// parent node that owns this node
struct AST_Node_t* parent;
// type of AST node: if, declaration, ...
enum AST_SyntaxElement_t kind;
// optional value: integer literal, string literal, ...
const char* value;
TokenLocation location;
AST_Annotation annotation;
// children array
GArray* children;
} AST_Node;
/**
* Shorthand type for a single AST node
*/
typedef struct AST_Node_t* AST_NODE_PTR;
/**
* @brief Initalize the global state of this module. Required for some
* functionality to work correctly.
*/
void AST_init(void);
/**
* @brief Returns the string representation of the supplied node
* @attention The retuned pointer is not to be freed as it may either be a
* statically stored string or used by the node after this function call.
* @param node to return string representation of
* @return string represenation of the node
*/
[[maybe_unused]] [[gnu::nonnull(1)]]
const char* AST_node_to_string(const struct AST_Node_t* node);
/**
* @brief Create a new node struct on the system heap. Initializes the struct
* with the given values. All other fields are set to either NULL or 0. No
* allocation for children array is preformed.
* @attention parameter value can be NULL in case no value can be provided for
* the node
* @param kind the type of this node
* @param value an optional value for this node
* @return
*/
[[maybe_unused]] [[nodiscard("pointer must be freed")]] [[gnu::returns_nonnull]]
struct AST_Node_t* AST_new_node(TokenLocation location,
enum AST_SyntaxElement_t kind,
const char* value);
/**
* @brief Deallocate this node and all of its children.
* @attention This function will detach this node from its parent if one is
* present Use of the supplied node after this call is undefined behavior
* @param node The node to deallocate
*/
[[maybe_unused]] [[gnu::nonnull(1)]]
void AST_delete_node(struct AST_Node_t* node);
/**
* @brief Add a new child node to a parent node
* @attention This can reallocate the children array
* @param owner node to add a child to
* @param child node to be added as a child
*/
[[maybe_unused]] [[gnu::nonnull(1), gnu::nonnull(2)]]
void AST_push_node(struct AST_Node_t* owner, struct AST_Node_t* child);
/**
* @brief Remove the specified child from the owner.
* @attention The parent of the removed node is set to NULL.
* The returned pointer is still valid. It must be freed at some
* pointer later.
* @param owner Node to remove the child from
* @param idx the index of the child to remove
* @return a pointer to the child which was removed
*/
[[maybe_unused]] [[nodiscard("pointer must be freed")]] [[gnu::nonnull(1)]]
struct AST_Node_t* AST_remove_child(struct AST_Node_t* owner, size_t idx);
/**
* @brief Detach a child from its parent. This involves removing the child from
* its parent and marking the parent of the child as NULL.
* @attention The returned pointer is still valid. It must be freed at some
* pointer later.
* @param owner the owner to remove the child from
* @param child the child to detach
* @return a pointer to child detached
*/
[[nodiscard("pointer must be freed")]] [[gnu::nonnull(1), gnu::nonnull(1)]]
struct AST_Node_t* AST_detach_child(struct AST_Node_t* owner,
const struct AST_Node_t* child);
/**
* @brief Return a pointer to the n-th child of a node
* @attention Pointer to childen nodes will never change.
* However, the index a node is stored within a parent can change
* if a child of lower index is removed, thus reducing the childrens
* index by one.
* @param owner the parent node which owns the children
* @param idx the index of the child to get a pointer to
* @return a pointer to the n-th child of the owner node
*/
[[maybe_unused]] [[gnu::nonnull(1)]]
struct AST_Node_t* AST_get_node(struct AST_Node_t* owner, size_t idx);
AST_NODE_PTR AST_get_last_node(AST_NODE_PTR node);
/**
* @brief Execute a function for every child, grandchild, ... and the supplied
* node as topmost ancestor
* @param root the root to recursively execute a function for
* @param for_each the function to execute
*/
[[maybe_unused]] [[gnu::nonnull(1), gnu::nonnull(2)]]
void AST_visit_nodes_recurse(struct AST_Node_t* root,
void (*for_each)(struct AST_Node_t* node,
size_t depth));
/**
* @brief Prints a graphviz graph of the node and all its ancestors.
* @param stream The stream to print to. Can be a file, stdout, ...
* @param node the topmost ancestor
*/
[[maybe_unused]] [[gnu::nonnull(1), gnu::nonnull(2)]]
void AST_fprint_graphviz(FILE* stream, const struct AST_Node_t* node);
AST_NODE_PTR AST_get_node_by_kind(AST_NODE_PTR owner,
enum AST_SyntaxElement_t kind);
[[gnu::nonnull(1), gnu::nonnull(3)]]
void AST_merge_modules(AST_NODE_PTR dst, size_t i, AST_NODE_PTR src);
[[gnu::nonnull(1), gnu::nonnull(3)]]
void AST_import_module(AST_NODE_PTR dst, size_t i, AST_NODE_PTR src);
[[gnu::nonnull(1), gnu::nonnull(3)]]
void AST_insert_node(AST_NODE_PTR owner, size_t idx, AST_NODE_PTR child);
size_t AST_get_child_count(AST_NODE_PTR node);
#endif