private PluginResult Evaluate(ref ExpressionNode Node) { var OpNode = Node as OpExpressionNode; var Op = OpNode.Operator; var Ch = OpNode.Children; var Dst = Ch[0] as ConstExpressionNode; var Src = Ch.Length > 1 ? Ch[1] as ConstExpressionNode : null; var AllLinkedNodes = new AutoAllocatedList <LinkedExprNode>(); Node.GetLinkedNodes(ref AllLinkedNodes, true); if (Dst.Value is NullValue || (Src != null && Src.Value is NullValue)) { if (Dst.Type.UnderlyingClassOrRealId is ClassType) { if (Op == Operator.Equality || Op == Operator.Inequality) { var Value = Dst.Value is NullValue == Src.Value is NullValue; var Ret = Constants.GetBoolValue(Container, Value, Node.Code); Ret.LinkedNodes.AddRange(AllLinkedNodes); Node = Parent.NewNode(Ret); return(Node == null ? PluginResult.Failed : PluginResult.Ready); } } if (Dst.Type.RealId is StringType) { if (Op == Operator.Add) { var DstVal = Dst.Value is NullValue ? "" : Dst.String; var SrcVal = Src.Value is NullValue ? "" : Src.String; var Value = DstVal + SrcVal; var Ret = Constants.GetStringValue(Container, Value, Node.Code); Ret.LinkedNodes.AddRange(AllLinkedNodes); Node = Parent.NewNode(Ret); return(Node == null ? PluginResult.Failed : PluginResult.Ready); } } throw new ApplicationException(); } else { var DstType = Dst.Type; var SrcType = Src != null ? Src.Type : null; var SrcVal = Src != null ? Src.Value : null; var Ret = Dst.Value.DoOperation(SrcVal, Op, Node.Type); if (Ret is IntegerValue && Node.CheckingMode == CheckingMode.Unchecked) { var IRet = Ret as IntegerValue; IRet.Value = DataStoring.WrapToType(IRet.Value, Node.Type); } Node = Ret.ToExpression(State, Node.Type, Node.Code); if (Node == null) { return(PluginResult.Failed); } Node.LinkedNodes.AddRange(AllLinkedNodes); Node = Parent.NewNode(Node); return(Node == null ? PluginResult.Failed : PluginResult.Ready); } }
public PluginResult NewOpNode(ref ExpressionNode Node) { var OpNode = Node as OpExpressionNode; var Op = OpNode.Operator; var Ch = OpNode.Children; // ------------------------------------------------------------------------------------ if (Op == Operator.Reinterpret) { if (Ch[0] is ConstExpressionNode) { #warning WARNING } return(PluginResult.Succeeded); } // ------------------------------------------------------------------------------------ else if (Op == Operator.Tuple || Op == Operator.Array) { var Type = Node.Type.RealId as NonrefArrayType; if (Op != Operator.Array || (Type != null && Type.Lengths != null && !(Type.TypeOfValues is AutomaticType))) { if (Ch.TrueForAll(x => x is ConstExpressionNode)) { var Constants = Ch.Select(x => (x as ConstExpressionNode).Value); var SValue = new StructuredValue(Constants.ToList()); Node = Parent.NewNode(new ConstExpressionNode(Node.Type, SValue, Node.Code)); return(Node == null ? PluginResult.Failed : PluginResult.Ready); } } } // ------------------------------------------------------------------------------------ else if (Op == Operator.Index) { if (Ch.TrueForAll(x => x is ConstExpressionNode)) { var ConstCh0 = Ch[0] as ConstExpressionNode; var NonrefArray = Ch[0].Type.RealId as NonrefArrayType; var Dimensions = NonrefArray.Lengths; var Position = 0; var MulBy = 1; for (var i = Dimensions.Length - 1; i >= 0; i--) { var CChip1 = Ch[i + 1] as ConstExpressionNode; var Index = CChip1.Integer; if (Index < 0 || Index >= Dimensions[i]) { State.Messages.Add(MessageId.IndexOutOfRange, CChip1.Code); return(PluginResult.Failed); } Position += (int)Index * MulBy; MulBy *= Dimensions[i]; } var RetValue = ConstCh0.Value.GetMember(Position); var RetType = NonrefArray.TypeOfValues; Node = Parent.NewNode(new ConstExpressionNode(RetType, RetValue, Node.Code)); return(Node == null ? PluginResult.Failed : PluginResult.Ready); } } // ------------------------------------------------------------------------------------ else if (Op == Operator.Member) { var ConstCh0 = Ch[0] as ConstExpressionNode; var Member = Ch[1] as IdExpressionNode; if (ConstCh0 != null && Member != null) { if (ConstCh0.Value is StructuredValue || ConstCh0.Value is ZeroValue) { var SType = ConstCh0.Type.UnderlyingStructureOrRealId as StructuredType; var Members = SType.StructuredScope.IdentifierList; var MemberIndex = Members.IndexOf(Member.Identifier); var RetValue = ConstCh0.Value.GetMember(MemberIndex); var RetType = Member.Identifier.TypeOfSelf; Node = Parent.NewNode(new ConstExpressionNode(RetType, RetValue, Node.Code)); return(Node == null ? PluginResult.Failed : PluginResult.Ready); } } } // ------------------------------------------------------------------------------------ else if (Op == Operator.Cast) { var Child = Ch[0] as ConstExpressionNode; if (Child == null) { return(PluginResult.Succeeded); } var To = Expressions.GetIdentifier(Ch[1]); var RTo = To.RealId as Type; var RFrom = Child.Type.RealId as Type; if (Child.Value is NullValue || RFrom is AutomaticType) { var OldNode = Node; if ((Node = Node.DetachChild(0)) == null) { return(PluginResult.Failed); } Node.Type = OldNode.Type; Node.Flags |= ExpressionFlags.FixedType; return(PluginResult.Ready); } Predicate <Identifier> Func = x => { var Rx = x.RealId as Type; if (Rx is PointerType || Rx is ReferenceType || Rx is PointerAndLength || ((Rx.TypeFlags & TypeFlags.ReferenceValue) != 0 && !(Rx is StringType))) { return(false); } return(true); }; if (!Identifiers.ProcessTuple(RTo, Func)) { return(PluginResult.Succeeded); } if (RTo is TupleType && !(RFrom is TupleType)) { var TupleTo = RTo as TupleType; var ToMembers = TupleTo.StructuredScope.IdentifierList; var TupleCh = new ExpressionNode[ToMembers.Count]; for (var i = 0; i < ToMembers.Count; i++) { var ToType = ToMembers[i].Children[0]; var Value = Child.Value.Convert(ToType); if (Value == null) { var Params = new String[] { Child.Value.ToString(), ToType.Name.ToString() }; State.Messages.Add(MessageId.CannotConvertConst, Node.Code, Params); return(PluginResult.Failed); } TupleCh[i] = Value.ToExpression(Parent, ToType, Node.Code); if (TupleCh[i] == null) { return(PluginResult.Failed); } } Node = new OpExpressionNode(Operator.Tuple, TupleCh, Node.Code); Node.Type = To; Node = Parent.NewNode(Node); return(Node == null ? PluginResult.Failed : PluginResult.Ready); } var Ret = Child.Value.Convert(RTo); if (Ret == null) { var Params = new String[] { Child.Value.ToString(), To.Name.ToString() }; State.Messages.Add(MessageId.CannotConvertConst, Node.Code, Params); return(PluginResult.Failed); } if (Ret is IntegerValue && Node.CheckingMode == CheckingMode.Unchecked) { var IRet = Ret as IntegerValue; IRet.Value = DataStoring.WrapToType(IRet.Value, RTo); } Node = Ret.ToExpression(Parent, To, Node.Code); return(Node == null ? PluginResult.Failed : PluginResult.Ready); } // ------------------------------------------------------------------------------------ else if (Op == Operator.And || Op == Operator.Or) { var ConstIndex = Ch[0] is ConstExpressionNode ? 0 : (Ch[1] is ConstExpressionNode ? 1 : -1); if (ConstIndex != -1) { var CNode = Ch[ConstIndex] as ConstExpressionNode; var IsAnd = Op == Operator.And; if (CNode.Bool == IsAnd) { Node = Node.DetachChild(1 - ConstIndex); return(Node == null ? PluginResult.Failed : PluginResult.Ready); } Node = Parent.NewNode(new ConstExpressionNode(Node.Type, new BooleanValue(!IsAnd), Node.Code)); return(Node == null ? PluginResult.Failed : PluginResult.Ready); } } // ------------------------------------------------------------------------------------ else if (Op == Operator.Condition) { var Condition = Ch[0] as ConstExpressionNode; if (Condition != null) { Node = Condition.Bool ? Ch[1] : Ch[2]; return(PluginResult.Ready); } } // ------------------------------------------------------------------------------------ else if (Op == Operator.Call) { var Res = NewCallOpNode(ref Node); if (Res != PluginResult.Succeeded) { return(Res); } } // ------------------------------------------------------------------------------------ else if (Operators.IsCalculable(Op)) { if (Ch[0] is ConstExpressionNode && (Ch.Length == 1 || Ch[1] is ConstExpressionNode)) { return(Evaluate(ref Node)); } if (Operators.IsReversible(Op) && Ch[0] is ConstExpressionNode && Identifiers.IsScalarOrVectorNumber(Ch[0].Type) && !(Ch[1] is ConstExpressionNode)) { OpNode.Swap(); Op = OpNode.Operator; } if (Op == Operator.Add || Op == Operator.Subract) { var ConstCh1 = Ch[1] as ConstExpressionNode; if (ConstCh1 != null && Identifiers.IsScalarOrVectorNumber(ConstCh1.Type)) { if (Constants.CompareTupleValues(ConstCh1.Value, x => x.Double == 0)) { Node = Node.DetachChild(0); return(Node == null ? PluginResult.Failed : PluginResult.Ready); } var OpCh0 = Ch[0] as OpExpressionNode; if (OpCh0 != null) { var Ch0Op = OpCh0.Operator; var Ch0Ch = OpCh0.Children; if (Ch0Op == Operator.Add || Ch0Op == Operator.Subract) { var ConstIndex = -1; if (Ch0Ch[0] is ConstExpressionNode) { ConstIndex = 0; } else if (Ch0Ch[1] is ConstExpressionNode) { ConstIndex = 1; } if (ConstIndex != -1) { var ConstCh0Chx = Ch0Ch[ConstIndex] as ConstExpressionNode; var NewOp = Op == Ch0Op ? Operator.Add : Operator.Subract; ExpressionNode[] NewCh; // For strings if (NewOp == Operator.Add) { NewCh = new ExpressionNode[] { ConstCh0Chx, Ch[1] } } ; else { NewCh = new ExpressionNode[] { Ch[1], ConstCh0Chx } }; Ch[0] = OpCh0.Children[1 - ConstIndex]; Ch[1] = Parent.NewNode(new OpExpressionNode(NewOp, NewCh, Node.Code)); if (Ch[1] == null) { return(PluginResult.Failed); } } } } } } else if (Op == Operator.Multiply || Op == Operator.Divide) { var ConstCh1 = Ch[1] as ConstExpressionNode; if (ConstCh1 != null && Identifiers.IsScalarOrVectorNumber(ConstCh1.Type)) { if (Constants.CompareTupleValues(ConstCh1.Value, x => x.Double == 1)) { Node = Node.DetachChild(0); return(Node == null ? PluginResult.Failed : PluginResult.Ready); } if (Constants.CompareTupleValues(ConstCh1.Value, x => x.Double == 0) && Op == Operator.Multiply) { Node = Node.DetachChild(1); return(Node == null ? PluginResult.Failed : PluginResult.Ready); } var OpCh0 = Ch[0] as OpExpressionNode; if (OpCh0 != null) { var Ch0Op = OpCh0.Operator; var Ch0Ch = OpCh0.Children; if (Ch0Op == Operator.Multiply || Ch0Op == Operator.Divide) { var ConstIndex = -1; if (Ch0Ch[0] is ConstExpressionNode) { ConstIndex = 0; } else if (Ch0Ch[1] is ConstExpressionNode) { ConstIndex = 1; } if (ConstIndex != -1) { var ConstCh0Chx = Ch0Ch[ConstIndex] as ConstExpressionNode; var NewOp = Op == Ch0Op ? Operator.Multiply : Operator.Divide; var NewCh = new ExpressionNode[] { Ch[1], ConstCh0Chx }; Ch[0] = OpCh0.Children[1 - ConstIndex]; Ch[1] = Parent.NewNode(new OpExpressionNode(NewOp, NewCh, Node.Code)); if (Ch[1] == null) { return(PluginResult.Failed); } } } } } } else if (Operators.IsRelEquality(Op)) { if (Ch[0] is ConstExpressionNode && !(Ch[1] is ConstExpressionNode)) { OpNode.Swap(); Op = OpNode.Operator; } var ConstCh1 = Ch[1] as ConstExpressionNode; var Type = Ch[0].Type != null ? Ch[0].Type.RealId : null; if (Type is UnsignedType && ConstCh1 != null && ConstCh1.Integer == 0) { if (Op == Operator.GreaterEqual) { Node = Constants.GetBoolValue(Container, true, Node.Code); return(Node == null ? PluginResult.Failed : PluginResult.Ready); } else if (Op == Operator.Greater) { OpNode.Operator = Op = Operator.Inequality; } else if (Op == Operator.Less) { Node = Constants.GetBoolValue(Container, false, Node.Code); return(Node == null ? PluginResult.Failed : PluginResult.Ready); } else if (Op == Operator.LessEqual) { OpNode.Operator = Op = Operator.Equality; } } } if (Op == Operator.Subract && Ch[1] is ConstExpressionNode) { var ConstCh1 = Ch[1] as ConstExpressionNode; if (ConstCh1 != null && ConstCh1.Type.RealId is NumberType && ConstCh1.CDouble < 0.0) { var NewCh = new ExpressionNode[] { ConstCh1 }; Ch[1] = Parent.NewNode(new OpExpressionNode(Operator.Negation, NewCh, Node.Code)); if (Ch[1] == null) { return(PluginResult.Failed); } OpNode.Operator = Op = Operator.Add; } } } return(PluginResult.Succeeded); }