/// <summary> /// Accepts operation /// </summary> /// <param name="type">Argument type</param> /// <returns>The operation</returns> public IObjectOperation Accept(object type) { IObjectOperation ownOp = acceptor.Accept(type); if (ownOp != null) { return(ownOp); } if (type is ArrayReturnType) { ArrayReturnType a = type as ArrayReturnType; if (a.IsObjectType) { IObjectOperation op = acceptor.Accept(a.ElementType); if (op == null) { return(null); } IObjectOperation dop = GetDynamicalOperation(a, op); if (dop != null) { return(dop); } return(new ArrayOperation(op, new object[] { type })); } } IObjectOperation ope = acceptor.Accept(type); if (ope != null) { return(ope); } if (type is ArrayReturnType) { ArrayReturnType a = type as ArrayReturnType; IObjectOperation op = acceptor.Accept(a.ElementType); if (op == null) { return(null); } IObjectOperation dop = GetDynamicalOperation(a, op); if (dop != null) { return(dop); } return(new ArrayOperation(op, new object[] { type })); } return(null); }
/// <summary> /// Implements the Visitor design pattern. /// </summary> /// <param name="acceptor"> /// The object accepting this operation. /// </param> public override void Visit(IOperationAcceptor acceptor) { Guard.NotNull(acceptor, nameof(acceptor)); acceptor.Accept(this); }
/// <summary> /// Processes ordinary operation /// </summary> /// <param name="formula">Formula</param> /// <param name="creator">Formula creator</param> /// <returns>True if operation exists and false otherwise</returns> protected bool processOperation(MathFormula formula, IFormulaObjectCreator creator) { int braCount = 0; ObjectFormulaTree tree = null; for (int i = 0; i < creator.OperationCount; i++) { IOperationDetector detector = creator.GetDetector(i); IOperationAcceptor acceptor = detector.Detect(formula[braCount]); if (acceptor == null) { continue; } TypeInfo dt = detector.ToTypeInfo(); TreeTransformationAttribute attr = detector.GetAttribute <TreeTransformationAttribute>(); if (attr != null) { ITreeTransformation trans = acceptor as ITreeTransformation; if (tree == null) { tree = CreateTree(new MathFormula(formula, 2 * braCount + 1, formula.Count - 1), creator); } if (tree != null) { ObjectFormulaTree tr = trans.Transform(tree); if (tr != null) { operation = tr.operation; children = tr.children; y = tr.y; return(true); } } } object type = null; if (formula.Count > 1) { if (tree == null) { tree = CreateTree(new MathFormula(formula, 2 * braCount + 1, formula.Count - 1), creator); } type = tree.ReturnType; } if (acceptor is IMultiVariableOperationAcceptor) { IMultiVariableOperationAcceptor ma = acceptor as IMultiVariableOperationAcceptor; IMultiVariableOperation multiOp = ma.AcceptOperation(formula[0]); MathSymbol s = formula[0]; ObjectFormulaTree[] trees = null; object[] types = null; if (s.HasChildren) { int n = 0; for (int j = 0; j < s.Count; j++) { if (s[j] != null) { if (!s[j].IsEmpty) { ++n; } } } trees = new ObjectFormulaTree[n]; types = new object[n]; n = 0; for (int j = 0; j < s.Count; j++) { if (s[j] != null) { if (!s[j].IsEmpty) { ObjectFormulaTree tr = CreateTree(s[j], creator); if (tr == null) { operation = null; goto mo; } trees[j] = tr; types[j] = trees[j].ReturnType; ++n; } } } } operation = multiOp.Accept(types); mo: if (operation == null) { continue; } y = new object[types.Length]; if (trees != null) { foreach (ObjectFormulaTree t in trees) { if (t != null) { children.Add(t); } } } return(true); } IObjectOperation op = acceptor.Accept(type); if (op != null) { if (op.IsPowered()) { if (formula.First.HasChildren) { ObjectFormulaTree pow = CreateTree(formula.First[0], creator); ObjectFormulaTree val = new ObjectFormulaTree(); val.operation = op; val.y = new object[op.InputTypes.Length]; val.CreateResult(); if (tree != null) { val.children.Add(tree); } IObjectOperation powOp = creator.GetPowerOperation(val.ReturnType, pow.ReturnType); if (powOp == null) { return(false); } operation = powOp; children.Add(val); children.Add(pow); y = new object[2]; return(true); } } operation = op; if (tree != null) { children.Add(tree); y = new object[1]; } return(true); } } return(false); }