Inferno
0.2
|
00001 /* 00002 * validate.cpp 00003 * 00004 * Created on: 30 Dec 2009 00005 * Author: jgraley 00006 */ 00007 00008 #include "validate.hpp" 00009 #include "typeof.hpp" 00010 #include "misc.hpp" 00011 #include "cpptree.hpp" 00012 00013 using namespace CPPTree; 00014 00015 void Validate::operator()( TreePtr<Node> context, 00016 TreePtr<Node> *proot ) 00017 { 00018 (void)context; 00019 decl_refs.clear(); 00020 total_refs.clear(); 00021 00022 // Is the proot reachable from context? If not that's probably because we haven't inserted 00023 // the subtree at proot into the program tree at context yet. 00024 bool connected = false; 00025 00026 // First walk over the entire context counting incoming links (because 00027 // incoming links from other than the subtree of interest still count 00028 // when validating link counts). 00029 Walk wcon( context ); 00030 FOREACH( const TreePtr<Node> x, wcon ) 00031 { 00032 if( x ) 00033 { 00034 // TODO use UniqueWalk for this! 00035 vector< Itemiser::Element * > members = x->Itemise(); 00036 FOREACH( Itemiser::Element *m, members ) 00037 { 00038 if( ContainerInterface *con = dynamic_cast<ContainerInterface *>(m) ) 00039 { 00040 FOREACH( const TreePtrInterface &tpi, *con ) 00041 OnLink( x, tpi ); 00042 } 00043 else if( TreePtrInterface *ptr = dynamic_cast<TreePtrInterface *>(m) ) 00044 { 00045 OnLink( x, *ptr ); 00046 } 00047 } 00048 if( x == *proot ) 00049 connected = true; 00050 } 00051 } 00052 00053 // Now do the actual validation, only on the specified subtree 00054 Walk w( *proot ); 00055 for( Walk::iterator wit = w.begin(); wit != w.end(); ++wit ) 00056 { 00057 const TreePtr<Node> x = *wit; 00058 if( !is_pattern ) // Don't do these checks on search/replace patterns 00059 { 00060 // NULL pointers not allowed in program tree (though they are allowed in search/replace patterns) 00061 ASSERT( x )("Found NULL pointer in tree at ")( wit ); 00062 00063 // Intermediate nodes are only allowed in search and replace patterns; the trees for programs 00064 // must be built from final nodes. 00065 TRACE("validating finality of ")(*x)(" as %d\n", (int)x->IsFinal() ); 00066 ASSERT( x->IsFinal() )( "Found intermediate (non-final) node ")(*x)(" at ")(wit); 00067 00068 // Check that we can successfully call TypeOf on every Expression 00069 if( TreePtr<Expression> e = dynamic_pointer_cast<Expression>(x) ) 00070 (void)TypeOf::instance(context, e); 00071 00072 // Check that every identifier has a declaration 00073 if( TreePtr<InstanceIdentifier> ii = dynamic_pointer_cast<InstanceIdentifier>(x) ) 00074 (void)GetDeclaration()(context, ii); 00075 00076 // if x is missing it's NODE_FUNCTIONS macro, then the Clone we get (y) will be a clone 00077 // of the most specialised base of x that does have NODE_FUNCTIONS. 00078 TreePtr<Node> y = dynamic_pointer_cast<Node>((*x).Clone()); 00079 ASSERT( typeid(*y)==typeid(*x) )(*x)(" apparently does not contain NODE_FUNCTIONS macro because it Clone()s to ")(*y)(" at ")(wit); 00080 } 00081 00082 if( x && x != context && connected ) // Skip the root, since we won't have counted any refs to it 00083 // Also, these rules may be broken for disconnected subtrees 00084 { 00085 TRACE("%p decl_refs=%d total refs=%d\n", x.get(), decl_refs[x], total_refs[x] ); 00086 // Check incoming pointers rule: Non-identifier nodes should be referenced exactly once 00087 // Identifiers should be referenced exactly once by the node that declares them, 00088 // and may be referenced zero or more times by other nodes. We skip the 00089 // identifier checks for patterns though (TODO decide what the rule becomes in this case) 00090 /* if( dynamic_pointer_cast<Identifier>(x) ) 00091 { 00092 if( !is_pattern && connected ) 00093 ASSERT( decl_refs[x] == 1 )("Identifier ")(*x)(" found with %d declaration references", decl_refs[x])(" at ")(wit) 00094 ("\nThere must be exactly 1 declaration and zero or more usages"); 00095 } 00096 else 00097 ASSERT( total_refs[x] == 1 )("Node ")(*x)(" found with %d references", total_refs[x] )(" at ")(wit) 00098 ("\nThere must be exactly 1 reference to nodes (except identifiers)");*/ 00099 } 00100 } 00101 } 00102 00103 void Validate::OnLink( TreePtr<Node> p, TreePtr<Node> c ) 00104 { 00105 TRACE("Ref %p to %p\n", p.get(), c.get() ); 00106 if( TreePtr<Instance> pi = dynamic_pointer_cast<Instance>(p) ) 00107 { 00108 if( c == pi->identifier ) 00109 decl_refs[c]++; 00110 } 00111 else if( TreePtr<UserType> pu = dynamic_pointer_cast<UserType>(p) ) 00112 { 00113 if( c == pu->identifier ) 00114 decl_refs[c]++; 00115 } 00116 else if( TreePtr<Label> pl = dynamic_pointer_cast<Label>(p) ) 00117 { 00118 if( c == pl->identifier ) 00119 decl_refs[c]++; 00120 } 00121 00122 total_refs[c]++; 00123 } 00124 00125