/// <summary> /// Replaces the variables in the expression with values from <paramref name="scope" />. /// </summary> /// <param name="scope">The scope object containing variable values.</param> /// <param name="result">[out] The new expression containing the replaced variables.</param> /// <returns> /// <c>true</c> if substitution was successful, <c>false</c> if something went wrong, in which case <paramref name="result" /> will likely be a <see cref="ParseErrorExpression" />. /// </returns> public override bool ReplaceVariables(InterpreterScope scope, out ExpressionBase result) { var functionDefinition = scope.GetFunction(FunctionName.Name); if (functionDefinition == null) { result = new ParseErrorExpression("Unknown function: " + FunctionName.Name, FunctionName); return(false); } var functionScope = GetParameters(functionDefinition, scope, out result); if (functionScope == null) { return(false); } if (functionScope.Depth >= 100) { result = new ParseErrorExpression("Maximum recursion depth exceeded", this); return(false); } functionScope.Context = this; if (!functionDefinition.ReplaceVariables(functionScope, out result)) { return(false); } CopyLocation(result); return(true); }
public override bool?IsTrue(InterpreterScope scope, out ParseErrorExpression error) { ExpressionBase result; if (!Evaluate(scope, true, out result)) { error = result as ParseErrorExpression; return(null); } var functionCall = result as FunctionCallExpression; if (functionCall != null) // prevent recursion { error = null; var funcDef = scope.GetFunction(functionCall.FunctionName.Name); if (funcDef is Functions.AlwaysTrueFunction) { return(true); } if (funcDef is Functions.AlwaysFalseFunction) { return(false); } return(null); } return(result.IsTrue(scope, out error)); }
/// <summary> /// Gets the return value from calling a function. /// </summary> /// <param name="scope">The scope object containing variable values.</param> /// <param name="result">[out] The new expression containing the function result.</param> /// <returns> /// <c>true</c> if invocation was successful, <c>false</c> if something went wrong, in which case <paramref name="result" /> will likely be a <see cref="ParseErrorExpression" />. /// </returns> public bool Evaluate(InterpreterScope scope, out ExpressionBase result) { var functionDefinition = scope.GetFunction(FunctionName.Name); if (functionDefinition == null) { result = new ParseErrorExpression("Unknown function: " + FunctionName.Name, FunctionName); return(false); } var functionScope = GetParameters(functionDefinition, scope, out result); if (functionScope == null) { return(false); } if (functionScope.Depth >= 100) { result = new ParseErrorExpression("Maximum recursion depth exceeded", this); return(false); } functionScope.Context = this; if (!functionDefinition.Evaluate(functionScope, out result)) { return(false); } scope.ReturnValue = result; return(true); }
protected FunctionDefinitionExpression GetFunctionParameter(InterpreterScope scope, string name, out ExpressionBase parseError) { var parameter = scope.GetVariable(name); if (parameter == null) { parseError = new ParseErrorExpression("No value provided for " + name + " parameter"); return(null); } var functionDefinition = parameter as FunctionDefinitionExpression; if (functionDefinition == null) { var functionReference = parameter as FunctionReferenceExpression; if (functionReference == null) { parseError = new ParseErrorExpression(name + " must be a function reference"); return(null); } functionDefinition = scope.GetFunction(functionReference.Name); if (functionDefinition == null) { parseError = new ParseErrorExpression("Undefined function: " + functionReference.Name); return(null); } } parseError = null; return(functionDefinition); }
/// <summary> /// Replaces the variables in the expression with values from <paramref name="scope" />. /// </summary> /// <param name="scope">The scope object containing variable values.</param> /// <param name="result">[out] The new expression containing the replaced variables.</param> /// <returns> /// <c>true</c> if substitution was successful, <c>false</c> if something went wrong, in which case <paramref name="result" /> will likely be a <see cref="ParseErrorExpression" />. /// </returns> public override bool ReplaceVariables(InterpreterScope scope, out ExpressionBase result) { ExpressionBase value = scope.GetVariable(Name); if (value == null) { var func = scope.GetFunction(Name); if (func != null) { // special wrapper for returning a function as a variable result = new FunctionReferenceExpression(Name); result.CopyLocation(this); return(true); } result = new UnknownVariableParseErrorExpression("Unknown variable: " + Name, this); return(false); } return(value.ReplaceVariables(scope, out result)); }
/// <summary> /// Replaces the variables in the expression with values from <paramref name="scope" />. /// </summary> /// <param name="scope">The scope object containing variable values.</param> /// <param name="result">[out] The new expression containing the replaced variables.</param> /// <returns> /// <c>true</c> if substitution was successful, <c>false</c> if something went wrong, in which case <paramref name="result" /> will likely be a <see cref="ParseErrorExpression" />. /// </returns> public override bool ReplaceVariables(InterpreterScope scope, out ExpressionBase result) { ExpressionBase value = scope.GetVariable(Name); if (value == null) { var func = scope.GetFunction(Name); if (func != null) { result = new ParseErrorExpression("Function used like a variable: " + Name, this); } else { result = new ParseErrorExpression("Unknown variable: " + Name, this); } return(false); } return(value.ReplaceVariables(scope, out result)); }
private bool Evaluate(InterpreterScope scope, bool inAssignment, out ExpressionBase result) { var functionDefinition = scope.GetFunction(FunctionName.Name); if (functionDefinition == null) { if (scope.GetVariable(FunctionName.Name) != null) { result = new UnknownVariableParseErrorExpression(FunctionName.Name + " is not a function", FunctionName); } else { result = new UnknownVariableParseErrorExpression("Unknown function: " + FunctionName.Name, FunctionName); } return(false); } var functionParametersScope = GetParameters(functionDefinition, scope, out result); if (functionParametersScope == null || result is ParseErrorExpression) { return(false); } if (functionParametersScope.Depth >= 100) { result = new ParseErrorExpression("Maximum recursion depth exceeded", this); return(false); } functionParametersScope.Context = this; if (inAssignment) { // in assignment, just replace variables functionDefinition.ReplaceVariables(functionParametersScope, out result); if (result.Type == ExpressionType.FunctionCall) { // if the result is a function call, check for any variable references. it can't be marked // as fully expanded if any variable references are present. var functionCall = (FunctionCallExpression)result; if (!functionCall.Parameters.Any(p => p is VariableReferenceExpression)) { functionCall._fullyExpanded = true; } // if there was no change, also mark the source as fully expanded. if (result == this) { _fullyExpanded = true; } // when expanding the parameters, a new functionCall object will be created without a name // location. if that has happened, replace the temporary name object with the real one. if (functionCall.FunctionName.Location.Start.Line == 0 && functionCall.FunctionName.Name == FunctionName.Name) { functionCall.FunctionName = FunctionName; } } } else { // not in assignment, evaluate the function functionDefinition.Evaluate(functionParametersScope, out result); } var error = result as ParseErrorExpression; if (error != null) { if (error.Location.Start.Line == 0) { this.CopyLocation(error); } result = ParseErrorExpression.WrapError(error, FunctionName.Name + " call failed", FunctionName); return(false); } return(true); }