def returnFreeVariableValues(self, locals, importFunction): """Return arguments for the free variables in expression. importFunction = a function to call with free symbols that aren't in locals to look them up """ boundVariables = [] for freeVariable in self.freeVariables: if freeVariable in locals: boundVariables += [locals[freeVariable]] else: binding = importFunction(freeVariable) if binding is None: raise ParseException.ParseException( ForaNative.FunctionParseError( "Couldn't resolve free variable '%s'" % freeVariable, self.freeVariableUsePoints(freeVariable)[0].range), self.codeDefinitionPoint_) else: boundVariables += [binding] return boundVariables
def parse(textToParse, codeDefinitionPoint=None, nameScope="<eval>", parseAsModule=False): """parse a string to an Expression object or throw a FunctionParseError. textToParse - a string containing the FORA expression parsePath - a list of strings containing the path to the code being parsed. this will show up in any stacktraces thrown by this expression or by code called by this expression nameScope - the name that functions and objects should descend from. If the expression is a simple 'fun' or 'object', this will be its name """ if codeDefinitionPoint is None: codeDefinitionPoint = \ ForaNative.CodeDefinitionPoint.ExternalFromStringList( [nameScope] ) if parseAsModule: nativeExpressionOrParseError = \ ForaNative.parseObjectDefinitionBodyToExpression( textToParse, ["Tsunami", nameScope + ".fora"], False, nameScope, nameScope ) else: nativeExpressionOrParseError = \ ForaNative.parseStringToExpression( textToParse, codeDefinitionPoint, nameScope ) if isinstance(nativeExpressionOrParseError, ForaNative.FunctionParseError): raise ParseException.ParseException(nativeExpressionOrParseError, codeDefinitionPoint) return Expression(nativeExpressionOrParseError, codeDefinitionPoint)
def parseToStatementTermList(textToParse, codeDefinitionPoint, nameScope): """parse a string to a list of StatementTerms, or throw an exception. textToParse - a string containing the FORA expression stacktraceIdentity - a list of strings containing the path to the code being parsed. this will show up in any stacktraces thrown by this expression or by code called by this expression """ statementTermListOrError = \ ForaNative.parseStringToStatementTermsWithLocationInfo( textToParse, codeDefinitionPoint, nameScope ) if isinstance(statementTermListOrError, ForaNative.FunctionParseError): raise ParseException.ParseException(statementTermListOrError, codeDefinitionPoint) return [StatementTerm(x, codeDefinitionPoint) for x in statementTermListOrError]
def importModuleFromMDS( mds, directory, fname, searchForFreeVariables=False, allowPrivate=False, moduleImportParentList=None, pathToCodeDefinitionStrings=lambda path: ["ModuleImporter", path]): if moduleImportParentList is None: moduleImportParentList = () importExpr, memberType = convertMDSToCreateObjectExpression( mds, os.path.join(directory, fname), allowPrivate, fname, pathToCodeDefinitionStrings) freeVars = importExpr.freeVariables freeVarDefs = {} if searchForFreeVariables: for f in freeVars: freeVarDefs[f] = importModuleAndMemberByName( f, moduleImportParentList) for f in freeVars: if f not in freeVarDefs or freeVarDefs[f] is None: codeLocation = importExpr.computeFreeVariableLocations(f)[0] raise ParseException.ParseException( ForaNative.FunctionParseError( "Couldn't resolve free variable '%s'" % f, codeLocation.range), codeLocation.defPoint) parser = ForaNative.ModuleParser() result = parser.bind(importExpr, freeVarDefs, False) assert result.isModule() assert result.asModule.result is not None return result.asModule.result
def convertMDSToCreateObjectExpression(mds, path, allowPrivate, name, pathToCodeDefinitionStrings): """given an MDS and a path, return an expression that creates a module member and the type of module member.""" tree = convertMDSToSourceCodeTree(mds, name) parser = ForaNative.ModuleParser() result = parser.parse( tree, allowPrivate, ForaNative.CodeDefinitionPoint.ExternalFromStringList( pathToCodeDefinitionStrings(path))) if len(result.errors) == 0: return result, symbol_package error = result.errors[0] raise ParseException.ParseException( ForaNative.FunctionParseError(error.error, error.location.range), error.location.defPoint)
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 varname not in freeVariableMapping: 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
def raiseParseException_(self, functionParseError): raise ParseException.ParseException(functionParseError, self.codeDefinitionPoint_)