AST_t AST_t::get_enclosing_class_specifier(bool jump_templates) const { AST node = _ast; while (node != NULL && ASTType(node) != AST_CLASS_SPECIFIER) { node = ASTParent(node); } while (node != NULL && ASTType(node) != AST_SIMPLE_DECLARATION) { node = ASTParent(node); } if (jump_templates) { while (node != NULL && ASTParent(node) != NULL && ASTType(ASTParent(node)) == AST_TEMPLATE_DECLARATION) { node = ASTParent(node); } } AST_t result(node); return node; }
bool AST_t::is_extensible_block(AST node) { return (ASTType(node) == AST_COMPOUND_STATEMENT || ASTType(node) == AST_CLASS_SPECIFIER || ASTType(node) == AST_TRANSLATION_UNIT || ASTType(node) == AST_NAMESPACE_DEFINITION); }
void AST_t::replace(AST_t ast) { if (ast._ast == NULL) { internal_error("Trying to replace a tree with an empty tree", 0); } if (this->_ast == NULL) { internal_error("Trying to replace an empty tree with another tree", 0); } if (ASTType(ast._ast) == AST_NODE_LIST) { // If the replacement is a list but the original is not, let's check two cases // maybe this list is a one-element list or not. if (ASTType(this->_ast) != AST_NODE_LIST) { // If it is a one element list if (ASTSon0(ast._ast) == NULL) { // then replace the whole thing with the list information AST_t repl_tree(ASTSon1(ast._ast)); replace_with(repl_tree); } // If this is not a one-element list then try to replace using // a typical replace_in_list but this may fail sometimes // because we'll look for the first enclosing list else { // Maybe we should yield a message here // std::cerr << "Warning: Replacing a non-list tree at '" // << this->get_locus() // << "' with a list tree of more than one element" << std::endl; replace_in_list(ast); } } // If both are lists is easy else { replace_in_list(ast); } } // If the thing being replaced is a list, but the replacement // is not, then convert the latter into a list else if (ASTType(_ast) == AST_NODE_LIST && ASTType(_ast) != AST_NODE_LIST) { // Create a single element list AST single(ASTListLeaf(ast._ast)); replace_in_list(single); } // Otherwise replace directly. Neither the replaced nor the replacement // are lists in this case. else { replace_with(ast); } }
AST_t AST_t::get_enclosing_namespace_definition() const { AST node = _ast; while (node != NULL && ASTType(node) != AST_NAMESPACE_DEFINITION && ASTType(node) != AST_GCC_NAMESPACE_DEFINITION) { node = ASTParent(node); } AST_t result(node); return node; }
void AST_t::prepend(AST_t t) { if (t._ast == NULL) { // Do nothing return; } if (ASTType(t._ast) != AST_NODE_LIST) { std::cerr << "The prepended tree is not a list. No prepend performed" << std::endl; return; } AST prepended_list = t._ast; AST enclosing_list = get_enclosing_list(this->_ast); if (enclosing_list == NULL) { std::cerr << "Cannot found a suitable list to prepend" << std::endl; } prepend_list(enclosing_list, prepended_list); }
void AST_t::remove_in_list() { AST list = this->_ast; // Look for the enclosing list while (list != NULL && ASTType(list) != AST_NODE_LIST) { list = ASTParent(list); } if (list == NULL) { std::cerr << "A suitable list has not been found" << std::endl; return; } AST parent = ASTParent(list); AST previous = ASTSon0(list); if (previous != NULL) { ast_set_parent(previous, parent); } int i; for (i = 0; i < ASTNumChildren(parent); i++) { if (ASTChild(parent, i) == list) { ast_set_child(parent, i, previous); break; } } }
bool ASTIterator::is_last() { if (_current == NULL) return true; AST _possible_next = ASTParent(_current); if (_possible_next == NULL || ASTType(_possible_next) != AST_NODE_LIST) { return true; } else if (ASTType(_possible_next) == AST_NODE_LIST && ASTSon0(_possible_next) != _current) { return true; } return false; }
// static ASTType ASTType::greaterType(const ASTType& left, const ASTType& right) { if ( left.greater(right) ) return right; else if ( right.greater(left) ) return left; return ASTType(); }
static void ast_dump_html_rec(AST a, FILE* f, const char* root_id, int id_node) { if (a == NULL) return; char current_id_node[64]; memset(current_id_node, 0, sizeof(current_id_node)); snprintf(current_id_node, 63, "%s.%d", root_id, id_node); current_id_node[63] = '\0'; fprintf(f, "<div id=\"%s\" class=\"node\" style=\"display: none;\">\n" "<div class=\"node_info\">" "<span id=\"%s.handle\" class=\"handle\">+</span>" "<span id=\"%s.kind\" class=\"node_kind\">%s</span>" "<span id=\"%s.locus\" class=\"node_locus\">%s</span>", current_id_node, // div current_id_node, // handle current_id_node, ast_node_type_name(ASTType(a)), current_id_node, mini_strip_html(ast_location(a)) ); // kind if (ASTText(a) != NULL) { fprintf(f, "<span id=\"%s.text\" class=\"node_text\">%s</span>", current_id_node, mini_strip_html(ASTText(a))); } fprintf(f, "</div>\n"); if (ASTType(a) == AST_NODE_LIST) { fprintf(f, "%s", "<div class=\"node_list\">"); int k = 0; AST list = a, iter; for_each_element(list, iter) { AST element = ASTSon1(iter); ast_dump_html_rec(element, f, current_id_node, k); k++; }
AST AST_t::get_translation_unit(AST node) { if (node == NULL) return NULL; while (node != NULL && ASTType(node) != AST_TRANSLATION_UNIT) { node = ASTParent(node); } return node; }
// XXX - Fixme, implement it using ast_list_concat void AST_t::prepend_list(AST orig_list, AST prepended_list) { if (ASTType(orig_list) != AST_NODE_LIST || ASTType(prepended_list) != AST_NODE_LIST) { std::cerr << "You tried to prepend two lists that are not " << "orig_list=" << ast_print_node_type(ASTType(orig_list)) << " " << "prepend_list=" << ast_print_node_type(ASTType(prepended_list)) << std::endl; return; } // Relink the parent, first remove pointer to the prepended_list if (ASTParent(prepended_list) != NULL) { AST parent = ASTParent(prepended_list); for (int i = 0; i < ASTNumChildren(parent); i++) { if (ASTChild(parent, i) == prepended_list) { ast_set_child(parent, i, NULL); break; } } } // Now make the prepended_list as the son AST original_previous = ASTSon0(orig_list); ast_set_child(orig_list, 0, prepended_list); // Go to the deeper node of prepended_list AST iter = prepended_list; while (ASTSon0(iter) != NULL) { iter = ASTSon0(iter); } ast_set_child(iter, 0, original_previous); }
AST_t ASTIterator::get_parent_of_list() { // This is similar to a rewind, actually, but without modifying // _current AST it = _ast; while (it != NULL && ASTType(it) == AST_NODE_LIST) { it = ASTParent(it); } return AST_t(it); }
AST_t AST_t::get_enclosing_function_definition(bool jump_templates, bool jump_external_decl) const { AST node = _ast; while (node != NULL && ASTType(node) != AST_FUNCTION_DEFINITION) { node = ASTParent(node); } // Jump over template declarations if (jump_templates) { // Now the node is an AST_FUNCTION_DEFINITION while (node != NULL && ASTParent(node) != NULL && ASTType(ASTParent(node)) == AST_TEMPLATE_DECLARATION) { node = ASTParent(node); } } // Extern declarations pose a problem, let's jump them as well if (jump_external_decl) { while (node != NULL && ASTParent(node) != NULL && ASTType(ASTParent(node)) == AST_LINKAGE_SPEC_DECL) { node = ASTParent(node); } } AST_t result(node); return result; }
// XXX - Fixme, implement it using ast_list_concat void AST_t::append_list(AST orig_list, AST appended_list) { if (ASTType(orig_list) != AST_NODE_LIST || ASTType(appended_list) != AST_NODE_LIST) { std::cerr << "You tried to append two lists that are not" << std::endl; return; } // Appending one list to another is as easy as making the deeper node // "appended_list" to point to the top node of "orig_list" // First replace appended_list as the new child of the parent of orig_list relink_parent(orig_list, appended_list); // Now link the deeper node of the list to the top node of "orig_list" AST iter = appended_list; while (ASTSon0(iter) != NULL) { iter = ASTSon0(iter); } ast_set_child(iter, 0, orig_list); }
ASTIterator::ASTIterator(AST ast) : _ast(ast), _current(ast) { if (ast == NULL || ASTType(ast) != AST_NODE_LIST) { if (ast != NULL) { std::cerr << "Node at '" << ast_get_filename(ast) << ":" << ASTLine(ast) << "' is not a list" << std::endl; } _ast = NULL; _current = NULL; } }
AST AST_t::get_enclosing_list(AST ast) { if (ast == NULL) { return NULL; } AST list = ast; // Look for the enclosing list while (list != NULL && ASTType(list) != AST_NODE_LIST) { list = ASTParent(list); } return list; }
void SymbolCheckVisitor::visit(ASTInstanceOf& ast) { mCurrentType.clear(); checkUnknown(ast.getInstanceType()); ast.getObject().accept(*this); if ( !(mCurrentType.isObject() || mCurrentType.isArray()) ) { error(E0027, UTEXT("Operator instanceof can only be called against objects/arrays."), ast); } else if ( !mCurrentType.isDerivedFrom(ast.getInstanceType()) ) { error(E0028, UTEXT("Instanceof operator can never be true for ") + mCurrentType.toString() + UTEXT(" and ") + ast.getInstanceType().toString(), ast); } mCurrentType = ASTType(ASTType::eBoolean); }
std::string AST_t::prettyprint(bool with_commas) const { // This is always internal prettyprint_set_internal_output(); const char *c = NULL; if (with_commas && ASTType(this->_ast) == AST_NODE_LIST) { c = list_handler_in_buffer(this->_ast); } else { c = prettyprint_in_buffer(this->_ast); } std::string result(c == NULL ? "" : c); if (c != NULL) free((void*)c); return result; }
void Source::fortran_check_expression_adapter(AST a, decl_context_t decl_context, nodecl_t* nodecl_output) { if (ASTType(a) == AST_COMMON_NAME) { // We allow common names in expressions scope_entry_t* entry = ::query_common_name(decl_context, ASTText(ASTSon0(a)), ast_get_locus(ASTSon0(a))); if (entry != NULL) { *nodecl_output = ::nodecl_make_symbol(entry, ast_get_locus(a)); } else { *nodecl_output = ::nodecl_make_err_expr(ast_get_locus(a)); } } else { ::fortran_check_expression(a, decl_context, nodecl_output); } }
void AST_t::replace_in_list(AST_t ast) { if (ast._ast == NULL) { std::cerr << "Cannot replace a list using an empty tree" << std::endl; return; } if (this->_ast == NULL) { std::cerr << "This tree is empty" << std::endl; return; } if (ASTType(ast._ast) != AST_NODE_LIST) { std::cerr << "The replacement tree is not a list. No replacement performed" << std::endl; return; } AST list = get_enclosing_list(this->_ast); if (list == NULL) { std::cerr << "A suitable list has not been found" << std::endl; return; } AST previous = ASTSon0(list); AST_t replaced(list); replaced.replace_with(ast); while (ASTSon0(list) != NULL) { list = ASTSon0(list); } ast_set_child(list, 0, previous); }
AST AST_t::get_list_of_extensible_block(AST node) { switch ((int)ASTType(node)) { case AST_COMPOUND_STATEMENT : { // This can be null return ASTSon0(node); break; } case AST_CLASS_SPECIFIER : { // This can be null return ASTSon1(node); break; } case AST_TRANSLATION_UNIT : { // This can be null return ASTSon0(node); break; } case AST_NAMESPACE_DEFINITION : { // This can be null return ASTSon1(node); break; } case AST_NODE_LIST : { return node; break; } } return NULL; }
void SymbolCheckVisitor::visit(ASTConcatenate& ast) { ast.getLeft().accept(*this); ASTType lefttype = mCurrentType; mCurrentType.clear(); ast.getRight().accept(*this); switch ( ast.getMode() ) { case ASTConcatenate::eMul: case ASTConcatenate::eDiv: case ASTConcatenate::eRem: case ASTConcatenate::ePlus: case ASTConcatenate::eMinus: { ASTType righttype = mCurrentType; mCurrentType = ASTType::greaterType(lefttype, righttype); if ( mCurrentType.isValid() ) { // optionally add casts if necessary if ( mCurrentType.isChar() && lefttype.isString() ) { // add char is now allowed directly: // str = str + char <- no casts // str = char + str <- casts char to string break; } if ( !lefttype.equals(mCurrentType) ) { ASTCast* pcast = new ASTCast(); pcast->setType(mCurrentType.clone()); pcast->setNode(ast.useLeft()); ast.setLeft(pcast); } if ( !righttype.equals(mCurrentType) ) { ASTCast* pcast = new ASTCast(); pcast->setType(mCurrentType.clone()); pcast->setNode(ast.useRight()); ast.setRight(pcast); } } else { String op = UTEXT("+"); error(E0022, UTEXT("Can not execute operator ") + op + UTEXT(" on types ") + lefttype.toString() + UTEXT(" and ") + righttype.toString(), ast); } } break; case ASTConcatenate::eBitwiseOr: case ASTConcatenate::eBitwiseXor: case ASTConcatenate::eBitwiseAnd: case ASTConcatenate::eShiftLeft: case ASTConcatenate::eShiftRight: { ASTType righttype = mCurrentType; if ( !lefttype.isInt() || !righttype.isInt() ) { error(E0023, UTEXT("Bitwise operators only operate on int values."), ast); } } break; case ASTConcatenate::eAnd: case ASTConcatenate::eOr: { if ( !lefttype.isBoolean() || !mCurrentType.isBoolean() ) { String op = UTEXT("&&"); // add toString to Mode error(E0024, UTEXT("Operator ") + op + UTEXT(" requires boolean expressions."), ast); } } break; case ASTConcatenate::eEquals: case ASTConcatenate::eUnequals: case ASTConcatenate::eSmallerEqual: case ASTConcatenate::eSmaller: case ASTConcatenate::eGreater: case ASTConcatenate::eGreaterEqual: { ASTType comp = ASTType::greaterType(lefttype, mCurrentType); if ( !comp.isValid() ) { error(E0025, UTEXT("Can not compare ") + lefttype.toString() + UTEXT(" with ") + mCurrentType.toString(), ast); } else if ( ast.getMode() >= ASTConcatenate::eSmallerEqual ) { if ( comp.isObject() || comp.isArray() || comp.isBoolean() ) { error(E0026, UTEXT("Invalid type ") + comp.toString() + UTEXT(" for operator."), ast); } } mCurrentType = ASTType(ASTType::eBoolean); } break; case ASTConcatenate::eInvalid: error(E0001, UTEXT("Invalid compiler state!"), ast); break; } }
static void ast_dump_graphviz_rec(AST a, FILE* f, size_t parent_node, int position, char is_extended UNUSED_PARAMETER) { // static char* octagon = "octagon"; // static char* doubleoctagon = "doubleoctagon"; static char* ellipse = "ellipse"; static char* mdiamond = "Mdiamond"; static char* box = "box"; char* shape; // I know this is not exact, but there is a %z qualifier in printf // while there is not such thing for intptr_t size_t current_node = (size_t)a; if (a != NULL) { // Select shape shape = box; if (ASTType(a) == AST_AMBIGUITY) shape = ellipse; if (ASTType(a) == AST_NODE_LIST) shape = mdiamond; // if (a->construct_type == CT_SPECIFICATION) shape = ellipse; // else if (a->construct_type == CT_OMP_SPECIFICATION) shape = mdiamond; // else if (a->construct_type == CT_EXECUTABLE) shape = octagon; // else if (a->construct_type == CT_OMP_EXECUTABLE) shape = doubleoctagon; if (ASTText(a)) { char *quoted = quote_protect(ASTText(a)); fprintf(f, "n%zd[shape=%s,label=\"%s\\nNode=%p\\nParent=%p\\n%s\\nText: \\\"%s\\\"\"]\n", current_node, shape, ast_print_node_type(ASTType(a)), a, ASTParent(a), ast_location(a), quoted); free(quoted); } else { fprintf(f, "n%zd[shape=%s,label=\"%s\\nNode=%p\\nParent=%p\\n%s\"]\n", current_node, shape, ast_print_node_type(ASTType(a)), a, ASTParent(a), ast_location(a)); } // Print this only for non extended referenced nodes if (parent_node != 0) { fprintf(f, "n%zd -> n%zd [label=\"%d\"]\n", parent_node, current_node, position); } if (ASTType(a) != AST_AMBIGUITY) { int i; if (!is_extended) { for(i = 0; i < ASTNumChildren(a); i++) { if (ASTChild(a, i) != NULL) { ast_dump_graphviz_rec(ASTChild(a, i), f, current_node, i, /* is_extended */ is_extended); } } } // Now print all extended trees referenced here // First get all TL_AST in 'orig' that point to its childrens extensible_struct_t* extended_data = ast_get_extensible_struct(a); if (extended_data != NULL && !is_extended) { int num_fields = 0; const char** keys = NULL; const void** values = NULL; extensible_struct_get_all_data(extended_data, &num_fields, &keys, &values); for (i = 0; i < num_fields; i++) { const char* field_name = keys[i]; tl_type_t* tl_data = (tl_type_t*)values[i]; if (tl_data->kind == TL_AST) { if (tl_data->data._ast != a) { ast_dump_graphviz_rec(tl_data->data._ast, f, /* parent_node */ 0, /* position */ 0, /* is_extended */ 1); } // Add an edge fprintf(f, "n%zd -> n%zd [label=\"%s\",style=dashed]\n", current_node, (size_t)(tl_data->data._ast), field_name); } } } } else if (ASTType(a) == AST_AMBIGUITY) { int i; for(i = 0; i < ast_get_num_ambiguities(a); i++) { ast_dump_graphviz_rec(ast_get_ambiguity(a, i), f, current_node, i, /* is_extended */ 0); } } } else { fprintf(f, "n%zd[shape=circle,label=\"\",fixedsize=true,style=filled,fillcolor=black,height=0.1,width=0.1]\n", current_node); if (parent_node != 0) { fprintf(f, "n%zd -> n%zd [label=\"%d\"]\n", parent_node, current_node, position); } } }
static void fortran_simplify_tree_stmt(AST a, AST *out) { // FIXME: Think ways of improving this switch (ASTType(a)) { case AST_ALLOCATE_STATEMENT: case AST_ARITHMETIC_IF_STATEMENT: case AST_ASSIGNED_GOTO_STATEMENT: case AST_BREAK_STATEMENT: case AST_CLOSE_STATEMENT: case AST_COMPUTED_GOTO_STATEMENT: case AST_CONTINUE_STATEMENT: case AST_DEALLOCATE_STATEMENT: case AST_EMPTY_STATEMENT: case AST_EXPRESSION_STATEMENT: case AST_GOTO_STATEMENT: case AST_IO_STATEMENT: case AST_LABEL_ASSIGN_STATEMENT: case AST_NULLIFY_STATEMENT: case AST_OPEN_STATEMENT: case AST_PRINT_STATEMENT: case AST_READ_STATEMENT: case AST_RETURN_STATEMENT: case AST_STOP_STATEMENT: case AST_PAUSE_STATEMENT: case AST_WRITE_STATEMENT: case AST_PRAGMA_CUSTOM_DIRECTIVE: { // Simple copy *out = ast_copy_with_scope_link(a, CURRENT_COMPILED_FILE->scope_link); break; } case AST_BLOCK_CONSTRUCT: { AST block = ASTSon1(a); AST new_block = NULL; AST it; for_each_element(block, it) { AST stmt = ASTSon1(it); AST new_stmt = NULL; fortran_simplify_tree_stmt(stmt, &new_stmt); if (new_stmt != NULL) { new_block = ASTList(new_block, new_stmt); } } *out = ASTMake1(AST_COMPOUND_STATEMENT, new_block, ASTFileName(a), ASTLine(a), NULL); break; } case AST_COMPOUND_STATEMENT: { AST list = ASTSon0(a); AST new_list = NULL; AST it; for_each_element(list, it) { AST stmt = ASTSon1(it); AST new_stmt = NULL; fortran_simplify_tree_stmt(stmt, &new_stmt); if (new_stmt != NULL) { new_list = ASTList(new_list, new_stmt); } } *out = ASTMake1(AST_COMPOUND_STATEMENT, new_list, ASTFileName(a), ASTLine(a), NULL); break; }
std::string AST_t::internal_ast_type() const { char* inner_name = ast_node_names[ASTType(this->_ast)]; std::string result(inner_name); return result; }
bool AST_t::is_list() const { return is_valid() && ASTType(_ast) == AST_NODE_LIST; }
node_t AST_t::internal_ast_type_() const { return ASTType(this->_ast); }
static void ast_dump_graphviz_rec(AST a, FILE* f, int parent_node, int position) { // static char* octagon = "octagon"; // static char* doubleoctagon = "doubleoctagon"; static char* ellipse = "ellipse"; static char* mdiamond = "Mdiamond"; static char* box = "box"; char* shape; int node_actual = nodes_counter++; if (a != NULL) { // Select shape shape = box; if (ASTType(a) == AST_AMBIGUITY) shape = ellipse; if (ASTType(a) == AST_NODE_LIST) shape = mdiamond; // if (a->construct_type == CT_SPECIFICATION) shape = ellipse; // else if (a->construct_type == CT_OMP_SPECIFICATION) shape = mdiamond; // else if (a->construct_type == CT_EXECUTABLE) shape = octagon; // else if (a->construct_type == CT_OMP_EXECUTABLE) shape = doubleoctagon; if (ASTText(a)) { fprintf(f, "n%d[shape=%s,label=\"%s\\nNode=%p\\nParent=%p\\n%s\\nText: -%s-\"]\n", node_actual, shape, ast_print_node_type(ASTType(a)), a, ASTParent(a), ast_location(a), ASTText(a)); } else { fprintf(f, "n%d[shape=%s,label=\"%s\\nNode=%p\\nParent=%p\\n%s\"]\n", node_actual, shape, ast_print_node_type(ASTType(a)), a, ASTParent(a), ast_location(a)); } if (parent_node != 0) { fprintf(f, "n%d -> n%d [label=\"%d\"]\n", parent_node, node_actual, position); } if (ASTType(a) != AST_AMBIGUITY) { int i; for(i = 0; i < ASTNumChildren(a); i++) { ast_dump_graphviz_rec(ASTChild(a, i),f, node_actual, i); } } else if (ASTType(a) == AST_AMBIGUITY) { int i; for(i = 0; i < ast_get_num_ambiguities(a); i++) { ast_dump_graphviz_rec(ast_get_ambiguity(a, i), f, node_actual, i); } } } else { fprintf(f, "n%d[shape=circle,label=\"\",fixedsize=true,style=filled,fillcolor=black,height=0.1,width=0.1]\n", node_actual); if (parent_node != 0) { fprintf(f, "n%d -> n%d [label=\"%d\"]\n", parent_node, node_actual, position); } } }