def specializeFreeVariableMapping(self,
                freeVariableMapping,
                specializationFunc,
                lookupFunc,
                finalVariableValueValidator
                ):
        """Allow an expression containing expressions like 'm.x' to be specialized.

        If we know what 'm' binds to, and

            specializationFunc(freeVariableMapping[m], 'x')

        produces a non-null value, we rebind the free variable to a new name with the result
        of specialzationFunc.

        Finally, we call 'finalVariableValueValidator' with the value each variable chain
        has been resolved to, along with a string of dot-separated identifiers. This function
        should return an error string if the intermediate value that has been bound is invalid.
        """
        done = False
        checkedNames = set()
        expr = self

        dotSequences = {}

        # Search through all the free variables and look up their values using the given lookup
        # function.
        for varname in self.freeVariables:
            dotSequences[varname] = varname
            if freeVariableMapping not in varname:
                varValue = lookupFunc(varname)

                if varValue is None:
                    codeLocations = self.freeVariableUsePoints(varname)

                    raise ParseException.ParseException(
                        ForaNative.FunctionParseError(
                            "Couldn't resolve free variable '%s'" % (varname,),
                            codeLocations[0].range
                            ),
                        self.codeDefinitionPoint_
                        )

                elif isinstance(varValue, NameExistsButDoesntParseException):
                    raise ParseException.ParseException(
                        ForaNative.FunctionParseError(
                            "Some modules did not parse correctly.",
                            self.freeVariableUsePoints(varname)[0].range
                            ),
                        self.codeDefinitionPoint_
                        )

                freeVariableMapping[varname] = varValue



        while not done:
            done = True
            #freeVariables = expr.freeVariables
            freeVariablesBound = expr.freeVariableMemberAccesses

            for varname, memberName in freeVariablesBound:
                if varname not in freeVariableMapping:
                    freeVariableMapping[varname] = lookupFunc(varname)
                mapsTo = freeVariableMapping[varname]
                if (mapsTo is not None and varname not in checkedNames):
                    subNode = specializationFunc(mapsTo, memberName)
                    if subNode is not None:
                        #we can bind this value to the node
                        newName = freshVarname(varname + "_" + memberName, set(expr.mentionedVariables))

                        dotSequences[newName] = dotSequences[varname] + "." + memberName

                        expr = expr.rebindFreeVariableMemberAccess(varname, memberName, newName)
                        freeVariableMapping[newName] = subNode
                        done = False
                    else:
                        checkedNames.add(varname)

        for var in expr.freeVariables:
            errString = finalVariableValueValidator(freeVariableMapping[var], dotSequences[var])

            if errString is not None:
                raise ParseException.ParseException(
                    ForaNative.FunctionParseError(
                        errString,
                        expr.freeVariableUsePoints(var)[0].range
                        ),
                    self.codeDefinitionPoint_
                    )

        return expr
dataset/ETHPy150Open ufora/ufora/ufora/FORA/python/Expression.py/Expression.specializeFreeVariableMapping/swapped operands of `not in`