ObjectInfoPtr ConfigObjectLoader::getObjectInfo( expr_cref expr, str_cref name ) const { if( !name.empty() ) { ObjectInfoPtr obj; // already found. if( Utility::mapLookup( m_objects, name, obj ) ) { return obj; } } if( expr.type() == EObject ) // it's an object expression { std::string className = expr.value(); ClassInfoPtr classInfo = getClassInfo( className ); BuilderPtr builder = classInfo->createBuilder( name, expr ); ObjectInfoPtr obj( new ObjectInfo( name, expr, *classInfo, builder ) ); // It needs to be in the map before we bind its parameters so a circular reference can be detected m_objects[name] = obj; builder->bindParams( *this ); return obj; } else if( expr.type() == EVariable ) { // this could recurse indefinitely with circular reference.. // NOTE: if anything throws here, let ParamBinderBase manage the context of the error. std::string objName; expr_cref expr2 = underlying( expr, &objName ); return getObjectInfo( expr2, objName ); } else // this isn't a class. It might be a map or list or whatever but isn't an object { std::ostringstream oss; oss << expr.value() << " is not an object"; // Do not throw TypeError here. If it isn't an object it can't be a proxy either throw std::invalid_argument( oss.str() ); } }