| 204 | } |
| 205 | |
| 206 | Symbol* ScopeSymbolTable::LookupFunction( const InlineString& name, ASTNode* callNode, std::string& diagnosticMessage ) const |
| 207 | { |
| 208 | diagnosticMessage = ""; |
| 209 | |
| 210 | std::vector<std::pair<Symbol*, int>> overrides; |
| 211 | const ScopeSymbolTable* scope = this; |
| 212 | while( scope ) |
| 213 | { |
| 214 | for( auto it = scope->m_symbols.begin(); it != scope->m_symbols.end(); ++it ) |
| 215 | { |
| 216 | if( ( *it )->name == name ) |
| 217 | { |
| 218 | overrides.push_back( std::make_pair( *it, 100000 ) ); |
| 219 | } |
| 220 | } |
| 221 | scope = scope->m_parent; |
| 222 | } |
| 223 | if( overrides.empty() ) |
| 224 | { |
| 225 | return nullptr; |
| 226 | } |
| 227 | if( overrides.size() == 1 ) |
| 228 | { |
| 229 | return overrides[0].first; |
| 230 | } |
| 231 | |
| 232 | // overrides[i] is NT_FUNCTION_HEADER or NT_FUNCTION_DEFINITION |
| 233 | // callNode is NT_FUNCTION_CALL |
| 234 | Symbol* bestOverride = nullptr; |
| 235 | int bestScore = 0; |
| 236 | for( auto it = overrides.begin(); it != overrides.end(); ++it ) |
| 237 | { |
| 238 | ASTNode* node = it->first->definition; |
| 239 | if( node == nullptr ) |
| 240 | { |
| 241 | continue; |
| 242 | } |
| 243 | if( node->GetNodeType() == NT_FUNCTION_DEFINITION ) |
| 244 | { |
| 245 | node = node->GetChildOrNull( 0 ); |
| 246 | } |
| 247 | if( node == nullptr ) |
| 248 | { |
| 249 | continue; |
| 250 | } |
| 251 | auto parameterCount = node->GetChildrenCount(); |
| 252 | auto argumentCount = callNode->GetChildrenCount(); |
| 253 | |
| 254 | if( argumentCount > parameterCount ) |
| 255 | { |
| 256 | continue; |
| 257 | } |
| 258 | if( argumentCount < parameterCount ) |
| 259 | { |
| 260 | // Check if next parameter after callNode->GetChildrenCount() |
| 261 | // has default value. |
| 262 | ASTNode* nextParameter = node->GetChild( argumentCount ); |
| 263 | if( nextParameter == nullptr ) |
no test coverage detected