/** # Interface for the Abstract Syntax Tree (AST) library It is divided in two parts: a first part for functions which are meant to be independent from the grammar, and a second part for (Basilisk C) grammar-dependent functions. ## Grammar-independent functions */ #include #include #include #include #include "allocator.h" #include "stack.h" typedef struct _Ast Ast; struct _Ast { int sym; Ast ** child, * parent; }; typedef struct { Ast ast; char * before, * start, * after; const char * file; int line; void * value; } AstTerminal; typedef struct { Ast ast; char * before, * after; const char * file; Allocator * alloc; Stack * stack; bool type_already_specified; } AstRoot; AstRoot * ast_parse (const char * code, AstRoot * parent); Ast * ast_parse_expression (const char * expr, AstRoot * parent); Ast * ast_parse_external_declaration (const char * decl, AstRoot * parent); void ast_destroy (Ast * n); AstRoot * ast_parse_file (FILE * fp, AstRoot * parent); char * ast_str_print (const Ast * n, char * s, int kind, int real); void ast_print (const Ast * n, FILE * fp, int kind); void ast_print_tree (Ast * n, FILE * fp, const char * indent, bool compress, int maxdepth); void ast_print_file_line (Ast * n, FILE * fp); AstRoot * ast_get_root (const Ast * n); void ast_identifier_print (Ast * identifier, FILE * fp); void ast_stack_print (Stack * stack, FILE * fp); const char * ast_crop_before (const char * s); double ast_evaluate_constant_expression (const Ast * n); static inline Ast * ast_last_child (const Ast * n) { if (!n) return NULL; Ast ** c = n->child; if (!c) return NULL; while (*(c + 1)) c++; return *c; } extern Ast * const ast_placeholder; static inline Ast * ast_child (const Ast * n, int sym) { if (!n) return NULL; Ast ** c = n->child; if (c == NULL) return NULL; while (*c && (*c == ast_placeholder || (*c)->sym != sym)) c++; return *c; } static inline Ast * ast_parent (const Ast * n, int sym) { if (!n || n == ast_placeholder) return NULL; Ast * parent = n->parent; while (parent && parent->sym != sym) parent = parent->parent; return parent; } static inline AstTerminal * ast_left_terminal (const Ast * n) { while (n && n != ast_placeholder && n->child) { Ast ** c = n->child; while (*c && *c == ast_placeholder) c++; n = *c; } return (AstTerminal *) (n != ast_placeholder ? n : NULL); } static inline AstTerminal * ast_right_terminal (const Ast * n) { while (n && n != ast_placeholder && n->child) n = ast_last_child (n); return (AstTerminal *) (n != ast_placeholder ? n : NULL); } AstTerminal * ast_next_terminal (const Ast * n); AstTerminal * ast_terminal_new (Ast * parent, int symbol, const char * start); #define ast_terminal_new_char(p,s) \ (Ast *) ast_terminal_new (p, token_symbol((s)[0]), s) Ast * ast_new_internal (Ast * parent, ...); #define ast_new(parent,...) ast_new_internal (parent, __VA_ARGS__, -1) Ast * ast_schema_internal (const Ast * n, ...); #define ast_schema(n,...) ast_schema_internal (n, __VA_ARGS__, -1) Ast * ast_find_internal (const Ast * n, ...); #define ast_find(n,...) ast_find_internal (n, __VA_ARGS__, -1) Ast * ast_copy_single (const Ast * n, AstRoot ** dst_root, AstRoot ** src_root); Ast * ast_copy_internal (const Ast * n, ...); #define ast_copy(n,...) ast_copy_internal (n, __VA_ARGS__ + 0, -1) Ast * ast_attach_internal (Ast * parent, ...); #define ast_attach(p,...) ast_attach_internal (p, __VA_ARGS__, NULL) Ast * ast_new_children_internal (Ast * parent, ...); #define ast_new_children(p,...) \ ast_new_children_internal (p, __VA_ARGS__, NULL) void ast_set_child (Ast * parent, int index, Ast * child); void ast_replace_child (Ast * parent, int index, Ast * child); static inline int ast_child_index (const Ast * n) { assert (n->parent); int index = 0; Ast ** c; for (c = n->parent->child; *c && *c != n; c++, index++); return *c == n ? index : - 1; } static inline Ast * ast_ancestor (Ast * n, int i) { while (n && i) n = n->parent, i--; return n; } char * str_append_realloc (char * dst, ...); #define str_append(dst, ...) \ do { dst = str_append_realloc (dst, __VA_ARGS__, NULL); } while(0) char * str_prepend_realloc (char * dst, ...); #define str_prepend(dst, ...) \ do { dst = str_prepend_realloc (dst, __VA_ARGS__, NULL); } while(0) #define ast_before(n,...) str_append(ast_left_terminal (n)->before, __VA_ARGS__) #define ast_after(n,...) str_append(ast_right_terminal (n)->after, __VA_ARGS__) #define ast_terminal(n) ((n)->child ? NULL : (AstTerminal *)(n)) #define ast_root(n) ((n)->parent ? NULL : (AstRoot *)(n)) char * ast_str_append (const Ast * n, char * s); static inline void ast_hide (AstTerminal * n) { for (char * s = n->start; *s != '\0'; s++) *s = ' '; } char * ast_line (AstTerminal * t); #define ast_file_line(n, nolineno) \ "\"", ast_terminal((Ast *)n)->file, "\",", \ nolineno ? "0" : ast_line(ast_terminal((Ast *)n)) void ast_set_line (Ast * n, AstTerminal * l); Ast * ast_flatten (Ast * n, AstTerminal * t); AstTerminal * ast_replace (Ast * n, const char * terminal, Ast * with); #define NN(parent,sym,...) ast_new_children (ast_new (parent, sym), __VA_ARGS__) static inline AstTerminal * NB (Ast * parent, int sym, const char * name) { AstTerminal * t = ast_terminal_new (parent, sym, name); AstTerminal * r = ast_left_terminal (parent); t->before = r->before, r->before = NULL; return t; } static inline AstTerminal * NA (Ast * parent, int sym, const char * name) { AstTerminal * t = ast_terminal_new (parent, sym, name); AstTerminal * r = ast_right_terminal (parent); t->line = r->line; return t; } #define NCB(parent,sym) NB(parent, token_symbol((sym)[0]), sym) #define NCA(parent,sym) NA(parent, token_symbol((sym)[0]), sym) /** ## Grammar-specific functions */ void ast_push_declaration (Stack * stack, Ast * declaration); Ast * ast_push_function_definition (Stack * stack, Ast * declarator); void ast_pop_scope (Stack * stack, Ast * scope); Ast * ast_push_declarations (Ast * n, Stack * stack); void ast_traverse (Ast * n, Stack * stack, void func (Ast *, Stack *, void *), void * data); #define foreach_item(list, index, item) \ for (Ast * _list = list, * item = _list && _list != ast_placeholder ? \ (_list->child[1] ? _list->child[index] : _list->child[0]) : NULL; \ (_list = _list && _list != ast_placeholder && \ _list->child[1] ? _list->child[0] : NULL), item; \ item = _list && _list != ast_placeholder ? \ (_list->child[1] ? _list->child[index] : \ _list->child[0]) : NULL \ ) #define foreach_item_r(list, symbol, arg) \ while (list->child[0]->sym == list->sym) \ list = list->child[0]; \ for (Ast * arg = ast_child (list, symbol); arg; \ list = list->parent, arg = ast_child (list, symbol)) Ast * ast_identifier_declaration (Stack * stack, const char * identifier); Ast * ast_identifier_declaration_from_to (Stack * stack, const char * identifier, const Ast * start, const Ast * end); Ast * ast_function_identifier (const Ast * function_definition); Ast * ast_function_call_identifier (const Ast * n); void ast_set_char (Ast * n, int c); void ast_remove_internal (Ast * n, AstTerminal * before); void ast_remove (Ast * n, AstTerminal * before); void ast_erase (Ast * n); void ast_check (Ast * n); Ast * ast_is_typedef (const Ast * identifier); Ast * ast_find_function (Ast * n, const char * name); Ast * ast_list_append_list (Ast * list, Ast * list1); Ast * ast_block_list_append (Ast * list, int item_sym, Ast * item); Ast * ast_block_list_prepend (Ast * list, int item_sym, Ast * item); Ast * ast_block_list_insert_after (Ast * insert, Ast * item); Ast * ast_block_list_insert_before (Ast * insert, Ast * item); Ast * ast_block_list_insert_before2 (Ast * insert, Ast * item); Ast * ast_block_list_get_item (Ast * statement); Ast * ast_list_append (Ast * list, int item_sym, Ast * item); Ast * ast_list_prepend (Ast * list, int item_sym, Ast * item); Ast * ast_list_remove (Ast * list, Ast * item); Ast * ast_list_insert_after (Ast * insert, Ast * item); void ast_argument_list (Ast * expression); Ast * ast_new_cast_expression (Ast * parent); Ast * ast_new_unary_expression (Ast * parent); Ast * ast_new_constant (Ast * parent, int symbol, const char * value); Ast * ast_new_identifier (Ast * parent, const char * name); Ast * ast_new_member_identifier (Ast * parent, const char * name); Ast * ast_new_function_call (Ast * parent, const char * func); Ast * ast_new_empty_scalar (Ast * parent); Ast * ast_new_empty_vector (Ast * parent, int dimension); Ast * ast_new_empty_tensor (Ast * parent, int dimension); Ast * ast_is_unary_expression (const Ast * n); Ast * ast_is_identifier_expression (const Ast * n); Ast * ast_is_simple_expression (const Ast * n); Ast * ast_get_struct_name (Ast * declaration_specifiers); bool ast_are_identical (const Ast * a, const Ast * b); Ast * ast_declaration_from_type (const Ast * type); Ast * ast_expression_type (Ast * expr, Stack * stack, bool higher_dimension); AstTerminal * ast_type (const Ast * identifier); char * ast_typedef_name (const Ast * identifier); bool ast_is_field (const char * typename); Ast * ast_check_grammar (Ast * n, bool recursive, bool stencils); Ast * ast_get_function_definition (Stack * stack, Ast * identifier, Ast * declaration); bool ast_is_foreach_stencil (const Ast * n); bool ast_is_stencil_function (Ast * n); Ast * ast_is_point_function (const Ast * declarator); Ast * ast_stencil (Ast * n, bool parallel, bool overflow, bool nowarning); Ast * ast_is_point_point (const Ast * identifier); void ast_stencil_access (Ast * n, Stack * stack, int dimension); Ast * ast_constant_postfix_expression (const Ast * n, Stack * stack); /** ## Types */ extern AstTerminal ast_int, ast_long, ast_enum, ast_char, ast_void, ast_float, ast_double, ast_function; typedef struct { int pointer; Ast ** dimension; } AstDimensions; Ast * ast_identifier_type (Ast * n, AstDimensions * d, Stack * stack); Ast * ast_base_type (Ast * type, AstDimensions * d, Stack * stack); Ast * ast_get_array_dimensions (Ast * direct_declarator, int symbol, AstDimensions * d, int nd, Stack * stack); /** ## Kernels */ void ast_non_local_references (Ast * n, Ast * argument); void ast_kernel (Ast * n, Ast * argument); /** ## Interface for the generic C interpreter */ int ast_run (AstRoot * root, Ast * n, int verbosity, int maxcalls, void * data); /** ## Interface for dimensional analysis */ bool ast_check_dimensions (AstRoot * root, Ast * n, int verbosity, int maxcalls, FILE * dimensions, int finite, int redundant, int lineno, int warn);