예제 #1
0
        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);
            }
        }
예제 #2
0
        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);
        }