/// <summary> /// Provides the surface of this function if it has been statically defined /// </summary> /// <param name="context">the context used to create the surface</param> /// <param name="xParam">The X axis of this surface</param> /// <param name="yParam">The Y axis of this surface</param> /// <param name="explain"></param> /// <returns>The surface which corresponds to this expression</returns> public override Surface CreateSurface(InterpretationContext context, Parameter xParam, Parameter yParam, ExplanationPart explain) { Surface retVal = base.CreateSurface(context, xParam, yParam, explain); Surface surface = InitialValue.CreateSurface(context, xParam, yParam, explain); if (surface != null) { ListValue value = ListExpression.GetValue(context, explain) as ListValue; if (value != null) { int token = PrepareIteration(context); AccumulatorVariable.Value = surface.Function; foreach (IValue v in value.Val) { if (v != EfsSystem.Instance.EmptyValue) { // All elements should always be != from EmptyValue ElementFound = true; IteratorVariable.Value = v; if (ConditionSatisfied(context, explain)) { MatchingElementFound = true; AccumulatorVariable.Value = IteratorExpression.GetValue(context, explain); } } NextIteration(); } Function function = AccumulatorVariable.Value as Function; if (function != null) { retVal = function.Surface; } else { throw new Exception("Expression does not reduces to a function"); } EndIteration(context, explain, token); } } else { throw new Exception("Cannot create surface for initial value " + InitialValue); } retVal.XParameter = xParam; retVal.YParameter = yParam; return retVal; }
/// <summary> /// Creates the graph associated to this expression, when the given parameter ranges over the X axis /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameters of *the enclosing function* for which the graph should be created</param> /// <param name="explain"></param> /// <returns></returns> public override Graph createGraph(InterpretationContext context, Parameter parameter, ExplanationPart explain) { Graph retVal = base.createGraph(context, parameter, explain); retVal = Graph.createGraph(GetValue(context, explain), parameter, explain); if (retVal == null) { throw new Exception("Cannot create graph for " + ToString()); } return retVal; }
/// <summary> /// Creates the graph associated to this expression, when the given parameter ranges over the X axis /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameters of *the enclosing function* for which the graph should be created</param> /// <param name="explain"></param> /// <returns></returns> public override Graph CreateGraph(InterpretationContext context, Parameter parameter, ExplanationPart explain) { Graph retVal = base.CreateGraph(context, parameter, explain); if (Term != null) { retVal = Graph.createGraph(GetValue(context, explain), parameter, explain); } else if (Expression != null) { if (UnaryOp == null) { retVal = Expression.CreateGraph(context, parameter, explain); } else if (UnaryOp == Minus) { retVal = Expression.CreateGraph(context, parameter, explain); retVal.Negate(); } else { throw new Exception("Cannot create graph where NOT operator is defined"); } } return retVal; }
/// <summary> /// Provides the surface of this function if it has been statically defined /// </summary> /// <param name="context">the context used to create the surface</param> /// <param name="xParam">The X axis of this surface</param> /// <param name="yParam">The Y axis of this surface</param> /// <param name="explain"></param> /// <returns>The surface which corresponds to this expression</returns> public virtual Surface CreateSurface(InterpretationContext context, Parameter xParam, Parameter yParam, ExplanationPart explain) { return null; }
/// <summary> /// Creates the graph associated to this expression, when the given parameter ranges over the X axis /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameters of *the enclosing function* for which the graph should be created</param> /// <returns></returns> public override Functions.Graph createGraph(InterpretationContext context, Parameter parameter) { Functions.Graph retVal = base.createGraph(context, parameter); Functions.Graph graph = InitialValue.createGraph(context, parameter); if (graph != null) { Values.ListValue value = ListExpression.GetValue(context) as Values.ListValue; if (value != null) { int token = PrepareIteration(context); AccumulatorVariable.Value = graph.Function; foreach (Values.IValue v in value.Val) { if (v != EFSSystem.EmptyValue) { IteratorVariable.Value = v; if (conditionSatisfied(context)) { AccumulatorVariable.Value = IteratorExpression.GetValue(context); } } NextIteration(); } Functions.Function function = AccumulatorVariable.Value as Functions.Function; if (function != null) { retVal = function.Graph; } else { retVal = Functions.Function.createGraphForValue(AccumulatorVariable.Value); } EndIteration(context, token); } } else { throw new Exception("Cannot create graph for initial value " + InitialValue.ToString()); } return retVal; }
/// <summary> /// Provides the surface of this function if it has been statically defined /// </summary> /// <param name="context">the context used to create the surface</param> /// <param name="xParam">The X axis of this surface</param> /// <param name="yParam">The Y axis of this surface</param> /// <returns>The surface which corresponds to this expression</returns> public override Functions.Surface createSurface(Interpreter.InterpretationContext context, Parameter xParam, Parameter yParam) { Functions.Surface retVal = base.createSurface(context, xParam, yParam); retVal = Functions.Surface.createSurface(GetValue(context), xParam, yParam); if (retVal == null) { throw new Exception("Cannot create surface for " + ToString()); } retVal.XParameter = xParam; retVal.YParameter = yParam; return retVal; }
/// <summary> /// Provides the surface of this function if it has been statically defined /// </summary> /// <param name="context">the context used to create the surface</param> /// <param name="xParam">The X axis of this surface</param> /// <param name="yParam">The Y axis of this surface</param> /// <returns>The surface which corresponds to this expression</returns> public override Functions.Surface createSurface(Interpreter.InterpretationContext context, Parameter xParam, Parameter yParam) { Functions.Surface retVal = base.createSurface(context, xParam, yParam); if (xParam == null || yParam == null) { AddError("Cannot have null parameters for Function expression " + ToString()); } else { int token = context.LocalScope.PushContext(); Parameter xAxis = Parameters[0]; Parameter yAxis = Parameters[1]; context.LocalScope.setSurfaceParameters(xAxis, yAxis); retVal = Expression.createSurface(context, xAxis, yAxis); context.LocalScope.PopContext(token); } retVal.XParameter = xParam; retVal.YParameter = yParam; return retVal; }
/// <summary> /// Provides the graph of this function if it has been statically defined /// </summary> /// <param name="context">the context used to create the graph</param> /// <returns></returns> public virtual Graph createGraph(Interpreter.InterpretationContext context, Parameter parameter) { Graph retVal = Graph; if (retVal == null) { try { Interpreter.InterpretationContext ctxt = new Interpreter.InterpretationContext(context); if (Cases.Count > 0) { // For now, just create graphs for functions using 0 or 1 parameter. if (FormalParameters.Count == 0) { Values.IValue value = Evaluate(ctxt, new Dictionary<Variables.Actual, Values.IValue>()); retVal = Graph.createGraph(value, parameter); } else if (FormalParameters.Count == 1) { Parameter param = (Parameter)FormalParameters[0]; int token = ctxt.LocalScope.PushContext(); Values.IValue actualValue = null; if (parameter != null) { Variables.IVariable actual = ctxt.findOnStack(parameter); if (actual != null) { actualValue = actual.Value; } else { actualValue = new Values.PlaceHolder(parameter.Type, 1); } ctxt.LocalScope.setParameter(param, actualValue); } retVal = createGraphForParameter(ctxt, param); if (getCacheable() && actualValue is Values.PlaceHolder) { Graph = retVal; } ctxt.LocalScope.PopContext(token); } else { Values.IValue value = Evaluate(ctxt, new Dictionary<Variables.Actual, Values.IValue>()); retVal = Graph.createGraph(value, parameter); } } } catch (Exception e) { AddError("Cannot create graph of function, reason : " + e.Message); } } return retVal; }
/// <summary> /// Creates the graph for a given parameter, the other parameters are considered fixed by the interpretation context /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameter for the X axis</param> /// <returns></returns> public virtual Graph createGraphForParameter(Interpreter.InterpretationContext context, Parameter parameter) { Graph retVal = Graph; if (retVal == null) { retVal = new Graph(); foreach (Case cas in Cases) { if (PreconditionSatisfied(context, cas, parameter)) { Graph subGraph = cas.Expression.createGraph(context, parameter); ReduceGraph(context, subGraph, cas, parameter); retVal.Merge(subGraph); } } } return retVal; }
/// <summary> /// Reduces the X axis of the surface according to the preconditions of this case /// </summary> /// <param name="context">The context used to reduce the surface</param> /// <param name="cas">The case used to reduce the surface</param> /// <param name="surface">The surface to reduce</param> /// <param name="parameter">The parameter for which the reduction has been performed</param> /// <returns>The reduced surface</returns> private Surface ReduceSurface(Interpreter.InterpretationContext context, Case cas, Surface surface, out Parameter parameter) { Surface retVal; // Evaluate the axis parameter = null; foreach (Rules.PreCondition preCondition in cas.PreConditions) { List<Graph.Segment> boundaries = EvaluateBoundaries(context, preCondition, surface.XParameter); if (boundaries.Count != 0 && !fullRange(boundaries)) { if (parameter != surface.YParameter) { parameter = surface.XParameter; } else { throw new Exception("Cannot reduce a graph on both X axis and Y axis on the same time (1)"); } } else { boundaries = EvaluateBoundaries(context, preCondition, surface.YParameter); if (boundaries.Count != 0 && !fullRange(boundaries)) { if (parameter != surface.XParameter) { parameter = surface.YParameter; } else { throw new Exception("Cannot reduce a graph on both X axis and Y axis on the same time (2)"); } } } } if (parameter == surface.XParameter) { // Reduce the surface on the X axis retVal = new Surface(surface.XParameter, surface.YParameter); foreach (Surface.Segment segment in surface.Segments) { retVal.AddSegment(new Surface.Segment(segment)); } // Reduces the segments according to this preconditions foreach (Rules.PreCondition preCondition in cas.PreConditions) { List<Graph.Segment> boundaries = EvaluateBoundaries(context, preCondition, surface.XParameter); retVal.Reduce(boundaries); } } else if (parameter == surface.YParameter) { // Reduce the surface, for all segments of the X axis, on the Y axis retVal = new Surface(surface.XParameter, surface.YParameter); foreach (Surface.Segment segment in surface.Segments) { // Reduces the segments according to this preconditions foreach (Rules.PreCondition preCondition in cas.PreConditions) { List<Graph.Segment> boundaries = EvaluateBoundaries(context, preCondition, surface.YParameter); segment.Graph.Reduce(boundaries); } if (!segment.Empty()) { retVal.AddSegment(segment); } } } else { retVal = surface; } return retVal; }
/// <summary> /// Selects the Y axis of the surface, according to the X parameter /// </summary> /// <returns>the Y axis if the surface</returns> private Parameter SelectYAxisParameter(Parameter Xparameter) { Parameter retVal = (Parameter)FormalParameters[0]; if (retVal == Xparameter) { retVal = (Parameter)FormalParameters[1]; } return retVal; }
/// <summary> /// Reduces the graph to the only part releated to the preconditions /// </summary> /// <param name="context">The context used to evaluate the precondition and segment value</param> /// <param name="graph">The graph to reduce</param> /// <param name="cas">The case which is used to reduce the graph</param> /// <param name="parameter"></param> /// <returns></returns> private void ReduceGraph(Interpreter.InterpretationContext context, Graph graph, Case cas, Parameter parameter) { foreach (Rules.PreCondition preCondition in cas.PreConditions) { List<Graph.Segment> boundaries = EvaluateBoundaries(context, preCondition, parameter); graph.Reduce(boundaries); } }
/// <summary> /// Indicates whether all preconditions are satisfied for a given case, ignoring expressions like x (y) <= xxx or x (y) >= xxx /// </summary> /// <param name="context">The interpretation context</param> /// <param name="cas">The case to evaluate</param> /// <param name="x">First parameter</param> /// <param name="y">Second parameter</param> /// <returns></returns> private bool PreconditionSatisfied(Interpreter.InterpretationContext context, Case cas, Parameter x, Parameter y) { bool retVal = true; foreach (Rules.PreCondition preCondition in cas.PreConditions) { if (!ExpressionBasedOnParameter(x, preCondition.ExpressionTree) && !ExpressionBasedOnParameter(y, preCondition.ExpressionTree)) { Values.BoolValue boolValue = preCondition.ExpressionTree.GetValue(context) as Values.BoolValue; if (boolValue == null) { throw new Exception("Cannot evaluate precondition " + preCondition.Name); } else if (!boolValue.Val) { retVal = false; break; } } } return retVal; }
/// <summary> /// Indicates that the expression is a function call using the parameter as argument value /// </summary> /// <param name="expression">The expression to evaluate</param> /// <param name="parameter">The parameter</param> /// <returns></returns> private bool FunctionCallOnParameter(Interpreter.Expression expression, Parameter parameter) { bool retVal = false; Interpreter.Call call = expression as Interpreter.Call; if (call != null) { foreach (Interpreter.Expression expr in call.AllParameters) { foreach (Types.ITypedElement element in expr.GetRightSides()) { if (element == parameter) { retVal = true; break; } } } } return retVal; }
/// <summary> /// Selects the X and Y axis of the surface to be created according to the function for which the surface need be /// created and the parameters on which the surface is created /// </summary> /// <param name="context">The interpretation context</param> /// <param name="xParam">The X parameter for which the surface need be created</param> /// <param name="yParam">The Y parameter for which the surface need be created</param> /// <param name="function">The function creating the surface</param> /// <param name="Xaxis">The resulting X axis</param> /// <param name="Yaxis">The resulting Y axis</param> /// <returns>true if the axis could be selected</returns> private void SelectXandYAxis(InterpretationContext context, Parameter xParam, Parameter yParam, Function function, out Parameter Xaxis, out Parameter Yaxis) { Xaxis = null; Yaxis = null; Dictionary<Parameter, Expression> association = getParameterAssociation(function); if (association != null) { foreach (KeyValuePair<Parameter, Expression> pair in association) { if (pair.Value.Ref == xParam) { if (Xaxis == null) { Xaxis = pair.Key; } else { Root.AddError("Cannot evaluate surface for function call " + ToString() + " which has more than 1 X axis parameter"); Xaxis = null; break; } } if (pair.Value.Ref == yParam) { if (Yaxis == null) { Yaxis = pair.Key; } else { Root.AddError("Cannot evaluate surface for function call " + ToString() + " which has more than 1 Y axis parameter"); Yaxis = null; break; } } } } }
/// <summary> /// Provides the surface of this function if it has been statically defined /// </summary> /// <param name="context">the context used to create the graph</param> /// <param name="Xparameter">The parameter used for the X axis</param> /// <param name="Yparameter">The parameter used for the Y axis</param> /// <returns></returns> public virtual Surface createSurfaceForParameters(Interpreter.InterpretationContext context, Parameter Xparameter, Parameter Yparameter) { Surface retVal = Surface; if (retVal == null) { if (Xparameter != null) { if (Yparameter != null) { if (Cases.Count > 0) { retVal = new Surface(Xparameter, Yparameter); foreach (Case cas in Cases) { if (PreconditionSatisfied(context, cas, Xparameter, Yparameter)) { Surface surface = cas.Expression.createSurface(context, Xparameter, Yparameter); if (surface != null) { Parameter parameter = null; surface = ReduceSurface(context, cas, surface, out parameter); if (parameter == null || parameter == surface.XParameter) { retVal.MergeX(surface); } else { retVal = Surface.MergeY(retVal, surface); } } else { AddError("Cannot create surface for expression " + cas.ExpressionText); retVal = null; break; } } } } else if (Graph != null) { // The function is defined by a graph // Extend it to a surface // TODO: Check the right parameter retVal = Graph.ToSurfaceX(); retVal.XParameter = Xparameter; retVal.YParameter = Yparameter; } else { AddError("cannot create surface for function " + Name + " with given parameters"); } } else { // Function with 1 parameter that ranges over the Xaxis retVal = new Surface(Xparameter, Yparameter); Functions.Graph graph = createGraphForParameter(context, Xparameter); foreach (Graph.Segment segment in graph.Segments) { Graph newGraph = Graph.createGraph(segment.Expression.v0); Surface.Segment newSegment = new Surface.Segment(segment.Start, segment.End, newGraph); retVal.AddSegment(newSegment); } } } else if (Yparameter != null) { // TODO : Remove check code if ((Yparameter.Enclosing != this)) { System.Diagnostics.Debugger.Break(); } // Function with 1 parameter that ranges over the Yaxis retVal = new Surface(Xparameter, Yparameter); Graph graph = createGraphForParameter(context, Yparameter); Surface.Segment segment = new Functions.Surface.Segment(0, double.MaxValue, graph); retVal.AddSegment(segment); } else { AddError("Invalid parameters for surface creation"); } } retVal.XParameter = Xparameter; retVal.YParameter = Yparameter; return retVal; }
/// <summary> /// Creates the graph associated to this expression, when the given parameter ranges over the X axis /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameters of *the enclosing function* for which the graph should be created</param> /// <returns></returns> public override Functions.Graph createGraph(InterpretationContext context, Parameter parameter) { Functions.Graph retVal = base.createGraph(context, parameter); retVal = Functions.Graph.createGraph(GetValue(context), parameter); if (retVal == null) { throw new Exception("Cannot create graph for " + ToString()); } return retVal; }
/// <summary> /// Provides the surface which corresponds to the parameters provided /// </summary> /// <param name="X"></param> /// <param name="Y"></param> /// <returns></returns> public Surface getSurface(Parameter X, Parameter Y) { Surface retVal = null; if (Surface != null) { // TODO : Ensure parameters are OK retVal = Surface; } else if (Graph != null) { // TODO : Check parameters name for conversion to X surface (or not done here) Y surface Parameter parameter = (Parameter)FormalParameters[0]; retVal = this.Graph.ToSurfaceX(); } if (getCacheable()) { Surface = retVal; } return retVal; }
/// <summary> /// Creates the graph associated to this expression, when the given parameter ranges over the X axis /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameters of *the enclosing function* for which the graph should be created</param> /// <returns></returns> public override Functions.Graph createGraph(InterpretationContext context, Parameter parameter) { Functions.Graph retVal = base.createGraph(context, parameter); if (parameter == Parameters[0] || parameter == Parameters[1]) { retVal = Expression.createGraph(context, parameter); } else { throw new Exception("Cannot create graph for parameter " + parameter.Name); } return retVal; }
/// <summary> /// Evaluates the boundaries associated to a specific preCondition /// </summary> /// <param name="context">The context used to evaluate the precondition and segment value</param> /// <param name="preCondition">The precondition to evaluate the range</param> /// <param name="parameter"></param> /// <returns></returns> private List<Graph.Segment> EvaluateBoundaries(Interpreter.InterpretationContext context, Rules.PreCondition preCondition, Parameter parameter) { List<Graph.Segment> retVal = new List<Graph.Segment>(); if (parameter != null) { Interpreter.BinaryExpression expression = preCondition.ExpressionTree as Interpreter.BinaryExpression; if (ExpressionBasedOnParameter(parameter, expression)) { Values.IValue val; if (expression.Right.Ref == parameter) { // Expression like xxx <= Parameter val = expression.Left.GetValue(context); switch (expression.Operation) { case Interpreter.BinaryExpression.OPERATOR.LESS: case Interpreter.BinaryExpression.OPERATOR.LESS_OR_EQUAL: retVal.Add(new Graph.Segment(getDoubleValue(val), double.MaxValue, new Graph.Segment.Curve())); break; case Interpreter.BinaryExpression.OPERATOR.GREATER: case Interpreter.BinaryExpression.OPERATOR.GREATER_OR_EQUAL: retVal.Add(new Graph.Segment(0, getDoubleValue(val), new Graph.Segment.Curve())); break; default: throw new Exception("Invalid comparison operator while evaluating Graph of function"); } } else { if (expression.Left.Ref == parameter) { // Expression like Parameter <= xxx val = expression.Right.GetValue(context); switch (expression.Operation) { case Interpreter.BinaryExpression.OPERATOR.LESS: case Interpreter.BinaryExpression.OPERATOR.LESS_OR_EQUAL: retVal.Add(new Graph.Segment(0, getDoubleValue(val), new Graph.Segment.Curve())); break; case Interpreter.BinaryExpression.OPERATOR.GREATER: case Interpreter.BinaryExpression.OPERATOR.GREATER_OR_EQUAL: retVal.Add(new Graph.Segment(getDoubleValue(val), double.MaxValue, new Graph.Segment.Curve())); break; default: throw new Exception("Invalid comparison operator while evaluating Graph of function"); } } else { if (FunctionCallOnParameter(expression.Right, parameter)) { Graph graph = expression.Right.createGraph(context, parameter); if (graph != null) { // Expression like xxx <= f(Parameter) val = expression.Left.GetValue(context); retVal = graph.GetSegments(Interpreter.BinaryExpression.Inverse(expression.Operation), getDoubleValue(val)); } else { AddError("Cannot create graph for " + expression.Right); } } else { Graph graph = expression.Left.createGraph(context, parameter); if (graph != null) { // Expression like f(Parameter) <= xxx val = expression.Right.GetValue(context); retVal = graph.GetSegments(expression.Operation, getDoubleValue(val)); } else { throw new Exception("Cannot evaluate bounds of segment"); } } } } } else { if (!ExpressionBasedOnPlaceHolder(context, expression)) { Values.BoolValue value = preCondition.ExpressionTree.GetValue(context) as Values.BoolValue; if (value != null && value.Val) { retVal.Add(new Graph.Segment(0, double.MaxValue, new Graph.Segment.Curve())); } } } } else { AddError("Parameter is null"); } return retVal; }
/// <summary> /// Creates the graph associated to this expression, when the given parameter ranges over the X axis /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameters of *the enclosing function* for which the graph should be created</param> /// <param name="explain"></param> /// <returns></returns> public virtual Graph CreateGraph(InterpretationContext context, Parameter parameter, ExplanationPart explain) { return null; }
/// <summary> /// Indicates if the expression if of the form parameter <= xxx or xxx <= parameter /// </summary> /// <param name="parameter">The parameter of the template</param> /// <param name="expression">The expression to analyze</param> /// <returns></returns> private bool ExpressionBasedOnParameter(Parameter parameter, Interpreter.Expression expression) { bool retVal = false; Interpreter.BinaryExpression binaryExpression = expression as Interpreter.BinaryExpression; if (binaryExpression != null) { retVal = binaryExpression.Right.Ref == parameter || binaryExpression.Left.Ref == parameter || FunctionCallOnParameter(binaryExpression.Right, parameter) || FunctionCallOnParameter(binaryExpression.Left, parameter); } return retVal; }
/// <summary> /// Creates the graph associated to this expression, when the given parameter ranges over the X axis /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameters of *the enclosing function* for which the graph should be created</param> /// <param name="explain"></param> /// <returns></returns> public override Graph CreateGraph(InterpretationContext context, Parameter parameter, ExplanationPart explain) { Graph retVal = Graph.createGraph(GetValue(context, explain), parameter, explain); return retVal; }
/// <summary> /// Creates the graph associated to this expression, when the given parameter ranges over the X axis /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameters of *the enclosing function* for which the graph should be created</param> /// <param name="explain"></param> /// <returns></returns> public override Graph createGraph(InterpretationContext context, Parameter parameter, ExplanationPart explain) { Graph retVal = base.createGraph(context, parameter, explain); Cast cast = Called.Ref as Cast; if (cast != null) { // In case of cast, just take the graph of the enclosed expression Parameter param = (Parameter) cast.FormalParameters[0]; retVal = cast.createGraphForParameter(context, param, explain); } Function calledFunction = Called.Ref as Function; Dictionary<Parameter, Expression> parameterAssociation = null; if (calledFunction == null) { calledFunction = Called.GetValue(context, explain) as Function; parameterAssociation = createParameterAssociation(calledFunction); } else { parameterAssociation = ParameterAssociation; } Parameter Xaxis = null; foreach (KeyValuePair<Parameter, Expression> pair in parameterAssociation) { if (pair.Value.Ref == parameter) { if (Xaxis == null) { Xaxis = pair.Key; } else { Root.AddError("Cannot evaluate graph for function call " + ToString() + " which has more than 1 parameter used as X axis"); Xaxis = null; break; } } } int token = context.LocalScope.PushContext(); calledFunction.AssignParameters(context, AssignParameterValues(context, calledFunction, false, explain)); if (Xaxis != null) { retVal = calledFunction.createGraphForParameter(context, Xaxis, explain); } else { retVal = Function.createGraphForValue(GetValue(context, explain)); } context.LocalScope.PopContext(token); return retVal; }
/// <summary> /// Provides the surface of this function if it has been statically defined /// </summary> /// <param name="context">the context used to create the surface</param> /// <param name="xParam">The X axis of this surface</param> /// <param name="yParam">The Y axis of this surface</param> /// <returns>The surface which corresponds to this expression</returns> public override Functions.Surface createSurface(Interpreter.InterpretationContext context, Parameter xParam, Parameter yParam) { Functions.Surface retVal = base.createSurface(context, xParam, yParam); Functions.Surface surface = InitialValue.createSurface(context, xParam, yParam); if (surface != null) { Values.ListValue value = ListExpression.GetValue(context) as Values.ListValue; if (value != null) { int token = PrepareIteration(context); AccumulatorVariable.Value = surface.Function; foreach (Values.IValue v in value.Val) { if (v != EFSSystem.EmptyValue) { IteratorVariable.Value = v; if (conditionSatisfied(context)) { AccumulatorVariable.Value = IteratorExpression.GetValue(context); } } NextIteration(); } Functions.Function function = AccumulatorVariable.Value as Functions.Function; if (function != null) { retVal = function.Surface; } else { throw new Exception("Expression does not reduces to a function"); } EndIteration(context, token); } } else { throw new Exception("Cannot create surface for initial value " + InitialValue.ToString()); } retVal.XParameter = xParam; retVal.YParameter = yParam; return retVal; }
/// <summary> /// Provides the surface of this function if it has been statically defined /// </summary> /// <param name="context">the context used to create the surface</param> /// <param name="xParam">The X axis of this surface</param> /// <param name="yParam">The Y axis of this surface</param> /// <param name="explain"></param> /// <returns>The surface which corresponds to this expression</returns> public override Surface createSurface(InterpretationContext context, Parameter xParam, Parameter yParam, ExplanationPart explain) { Surface retVal = base.createSurface(context, xParam, yParam, explain); Function function = getFunction(context, explain); Cast cast = Called.Ref as Cast; if (cast != null) { // In case of cast, just take the surface of the enclosed expression Expression actual = (Expression) ActualParameters[0]; retVal = actual.createSurface(context, xParam, yParam, explain); } else { Parameter Xaxis = null; Parameter Yaxis = null; if (function == null) { function = Called.getCalled(context, explain) as Function; } SelectXandYAxis(context, xParam, yParam, function, out Xaxis, out Yaxis); if (Xaxis != null || Yaxis != null) { int token = context.LocalScope.PushContext(); function.AssignParameters(context, AssignParameterValues(context, function, true, explain)); retVal = function.createSurfaceForParameters(context, Xaxis, Yaxis, explain); context.LocalScope.PopContext(token); } else { IValue value = GetValue(context, explain); if (value != null) { retVal = Surface.createSurface(value, xParam, yParam); } else { throw new Exception("Cannot create surface for expression"); } } } retVal.XParameter = xParam; retVal.YParameter = yParam; return retVal; }
/// <summary> /// Provides the surface of this function if it has been statically defined /// </summary> /// <param name="context">the context used to create the surface</param> /// <param name="xParam">The X axis of this surface</param> /// <param name="yParam">The Y axis of this surface</param> /// <param name="explain"></param> /// <returns>The surface which corresponds to this expression</returns> public override Surface createSurface(InterpretationContext context, Parameter xParam, Parameter yParam, ExplanationPart explain) { Surface retVal = base.createSurface(context, xParam, yParam, explain); retVal = Surface.createSurface(GetValue(context, explain), xParam, yParam); if (retVal == null) { throw new Exception("Cannot create surface for " + ToString()); } retVal.XParameter = xParam; retVal.YParameter = yParam; return retVal; }
private void CheckActualAgainstFormal(Dictionary<string, Expression> actuals, Expression expression, Parameter parameter) { actuals[parameter.Name] = expression; expression.checkExpression(); Type argumentType = expression.GetExpressionType(); if (argumentType == null) { AddError("Cannot evaluate argument type for argument " + expression.ToString()); } else { if (parameter.Type == null) { AddError("Cannot evaluate formal parameter type for " + parameter.Name); } else { if (!parameter.Type.Match(argumentType)) { AddError("Invalid argument " + expression.ToString() + " type, expected " + parameter.Type.FullName + ", actual " + argumentType.FullName); } } } }
/// <summary> /// Provides the surface of this function if it has been statically defined /// </summary> /// <param name="context">the context used to create the surface</param> /// <param name="xParam">The X axis of this surface</param> /// <param name="yParam">The Y axis of this surface</param> /// <param name="explain"></param> /// <returns>The surface which corresponds to this expression</returns> public override Surface CreateSurface(InterpretationContext context, Parameter xParam, Parameter yParam, ExplanationPart explain) { Surface retVal = base.CreateSurface(context, xParam, yParam, explain); if (Term != null) { retVal = Surface.createSurface(xParam, yParam, GetValue(context, explain), explain); } else if (Expression != null) { if (UnaryOp == null) { retVal = Expression.CreateSurface(context, xParam, yParam, explain); } else { if (UnaryOp == Minus) { retVal = Expression.CreateSurface(context, xParam, yParam, explain); retVal.Negate(); } else { AddError("Cannot create surface with unary op " + UnaryOp); } } } retVal.XParameter = xParam; retVal.YParameter = yParam; return retVal; }
/// <summary> /// Creates the graph associated to this expression, when the given parameter ranges over the X axis /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameters of *the enclosing function* for which the graph should be created</param> /// <param name="explain"></param> /// <returns></returns> public override Graph CreateGraph(InterpretationContext context, Parameter parameter, ExplanationPart explain) { Graph retVal = base.CreateGraph(context, parameter, explain); Graph graph = InitialValue.CreateGraph(context, parameter, explain); if (graph != null) { ListValue value = ListExpression.GetValue(context, explain) as ListValue; if (value != null) { int token = PrepareIteration(context); AccumulatorVariable.Value = graph.Function; foreach (IValue v in value.Val) { if (v != EfsSystem.Instance.EmptyValue) { // All elements should always be != from EmptyValue ElementFound = true; IteratorVariable.Value = v; if (ConditionSatisfied(context, explain)) { MatchingElementFound = true; AccumulatorVariable.Value = IteratorExpression.GetValue(context, explain); } } NextIteration(); } Function function = AccumulatorVariable.Value as Function; if (function != null) { retVal = function.Graph; } else { retVal = Function.CreateGraphForValue(AccumulatorVariable.Value); } EndIteration(context, explain, token); } } else { throw new Exception("Cannot create graph for initial value " + InitialValue); } return retVal; }