예제 #1
0
        public override PluginResult NewNode(ref ExpressionNode Node)
        {
            if (!CheckChildrenIdNodes(Node))
            {
                return(PluginResult.Failed);
            }

            var TempRes = ResolveLinkingAssigment(ref Node);

            if (TempRes != PluginResult.Succeeded)
            {
                return(TempRes);
            }

            var Extracted = false;

            for (var i = 0; i < Node.LinkedNodes.Count; i++)
            {
                var LNode = Node.LinkedNodes[i];
                SetIdNodeUsed(LNode.Node);

                LNode.Node = Extract(LNode.Node, ref Extracted);
                if (LNode.Node == null)
                {
                    return(PluginResult.Failed);
                }
            }

            var DontExtractProperties = false;
            var Ch = Node.Children;

            if (Node is OpExpressionNode)
            {
                var OpNode = Node as OpExpressionNode;
                var Op     = OpNode.Operator;

                if (Operators.IsIncDec(Op))
                {
                    var Linked   = new LinkedExprNode(Ch[0]);
                    var AddSubCh = new ExpressionNode[2]
                    {
                        Parent.NewNode(new LinkingNode(Linked, Node.Code)),
                        Parent.NewNode(Constants.GetIntValue(Container, 1, Node.Code, true)),
                    };

                    if (AddSubCh[0] == null || AddSubCh[1] == null)
                    {
                        return(PluginResult.Failed);
                    }

                    Operator AddSubOp;
                    if (Op == Operator.Increase)
                    {
                        AddSubOp = Operator.Add;
                    }
                    else if (Op == Operator.Decrease)
                    {
                        AddSubOp = Operator.Subract;
                    }
                    else
                    {
                        throw new ApplicationException();
                    }

                    var AssignmentCh = new ExpressionNode[2]
                    {
                        Parent.NewNode(new LinkingNode(Linked, Node.Code)),
                        Parent.NewNode(new OpExpressionNode(AddSubOp, AddSubCh, Node.Code))
                    };

                    if (AssignmentCh[0] == null || AssignmentCh[1] == null)
                    {
                        return(PluginResult.Failed);
                    }

                    Node = new OpExpressionNode(Operator.Assignment, AssignmentCh, Node.Code);
                    Node.LinkedNodes.Add(Linked);

                    if ((Node = Parent.NewNode(Node)) == null)
                    {
                        return(PluginResult.Failed);
                    }

                    return(PluginResult.Ready);
                }
                else if (Op == Operator.Assignment)
                {
                    PluginResult Res;
                    if (Ch[0] is IdExpressionNode && Ch[1] is IdExpressionNode)
                    {
                        var IdCh0 = Ch[0] as IdExpressionNode;
                        var IdCh1 = Ch[1] as IdExpressionNode;

                        if (IdCh0.Identifier.RealId is Variable && IdCh1.Identifier.RealId is Variable)
                        {
                            var Ch0NotUsed = Ch[1].CheckNodes(x =>
                            {
                                var xId = Expressions.GetIdentifier(x);
                                return(xId == null ? true : xId.RealId != IdCh0.Identifier.RealId);
                            });

                            if (Ch0NotUsed && DeclaredIds.Contains(IdCh1.Identifier.RealId))
                            {
                                var Ch1 = (ExpressionNode)IdCh1;
                                Res = ExpressionNode.ReplaceNodes(ref Ch1, Parent, (ref ExpressionNode x) =>
                                {
                                    var Idx = x as IdExpressionNode;
                                    if (Idx != null && Idx.Identifier.RealId == IdCh1.Identifier.RealId)
                                    {
                                        Vars.Remove(Idx);

                                        x = new IdExpressionNode(IdCh0.Identifier, Idx.Code);
                                        x.LinkedNodes.AddRange(Idx.LinkedNodes);
                                        return(Parent.NewNode(ref x));
                                    }

                                    return(PluginResult.Succeeded);
                                });

                                Node = Ch1;
                                DeclaredIds.Remove(IdCh1.Identifier.RealId);
                                return(Res == PluginResult.Failed ? Res : PluginResult.Ready);
                            }
                        }
                    }

                    var Ch0    = Ch[0];
                    var Linked = (LinkedExprNode)null;

                    Res = Expressions.ProcessTuple(Parent, ref Ch0, (x, Index) =>
                    {
                        if (x is IdExpressionNode)
                        {
                            var IdNode = x as IdExpressionNode;
                            Vars.AssignedIds.Add(IdNode);
                        }

                        Func <ExpressionNode> Value = () =>
                        {
                            LinkedExprNode LLinked;

                            var Ch1 = Ch[1];
                            var Ret = Expressions.GetTupleMember(Parent, ref Ch1, Index, out LLinked);
                            Ch[1]   = Ch1;

                            if (LLinked != null)
                            {
                                Linked = LLinked;
                            }

                            return(Ret);
                        };

                        var LRes = ExtractPropertySetter(x, Value, ref x, ref Extracted);
                        if (LRes == SimpleRecResult.Failed)
                        {
                            return(null);
                        }

                        return(x);
                    });

                    if (Res != PluginResult.Succeeded)
                    {
                        Ch0.LinkedNodes.AddRange(Node.LinkedNodes);
                        if (Linked != null)
                        {
                            Ch0.LinkedNodes.Add(Linked);
                        }
                        if (Res == PluginResult.Ready)
                        {
                            Node = Ch0;
                        }
                        return(Res);
                    }

                    SetIdNodeUsed(Ch[1]);
                }
                else if (Op == Operator.Member)
                {
                    var IdCh1 = Ch[1] as IdExpressionNode;
                    if (IdCh1 != null && IdCh1.Identifier.RealId is Property)
                    {
                        Ch[0] = ExtractPropertyGetter(Ch[0], ref Extracted);
                        if (Ch[0] == null)
                        {
                            return(PluginResult.Failed);
                        }

                        DontExtractProperties = true;
                    }

                    SetIdNodeUsed(Ch);
                }
                else if (Op == Operator.Index)
                {
                    var Id = Expressions.GetMemberIdentifier(Ch[0]);
                    if (Id != null && Id.RealId is Property)
                    {
                        for (var i = 1; i < Ch.Length; i++)
                        {
                            Ch[i] = ExtractPropertyGetter(Ch[i], ref Extracted);
                            if (Ch[i] == null)
                            {
                                return(PluginResult.Failed);
                            }
                        }

                        DontExtractProperties = true;
                    }

                    SetIdNodeUsed(Ch);
                }
                else if (Op == Operator.Address || Operators.IsReference(Op))
                {
                    var IdCh0 = Ch[0] as IdExpressionNode;
                    if (IdCh0 != null)
                    {
                        if (Op == Operator.Reference_IdMustBeAssigned)
                        {
                            if (IdCh0 != null)
                            {
                                Vars.UsedBeforeAssignIds.Add(IdCh0);
                            }
                        }
                        else if (Op == Operator.Reference_IdGetsAssigned)
                        {
                            if (IdCh0 != null)
                            {
                                Vars.AssignedIds.Add(IdCh0);
                            }

                            if (!Expressions.IsLValue(Ch[0]))
                            {
                                State.Messages.Add(MessageId.AddressOfRValue, Node.Code);
                                return(PluginResult.Failed);
                            }
                        }
                        else
                        {
                            if (IdCh0 != null)
                            {
                                Vars.AddressUsed.Add(IdCh0);
                            }
                        }
                    }
                }
                else if (Op == Operator.Cast)
                {
                    var From = Ch[0].Type;
                    var To   = Expressions.GetIdentifier(Ch[1]);

                    if (To.RealId is PointerType && From.RealId is ArrayType && Ch[0] is IdExpressionNode)
                    {
                        var IdCh0 = Ch[0] as IdExpressionNode;
                        Vars.AddressUsed.Add(IdCh0);
                    }
                    else
                    {
                        SetIdNodeUsed(Ch);
                    }
                }
                else if (Op == Operator.Tuple)
                {
                    DontExtractProperties = true;
                }
                else
                {
                    SetIdNodeUsed(Ch);
                }
            }
            else
            {
                SetIdNodeUsed(Ch);
            }

            if (Ch != null)
            {
                for (var i = 0; i < Ch.Length; i++)
                {
                    Ch[i] = ExtractPackedId(Ch[i], ref Extracted);
                    if (Ch[i] == null)
                    {
                        return(PluginResult.Failed);
                    }

                    if (!DontExtractProperties)
                    {
                        Ch[i] = ExtractPropertyGetter(Ch[i], ref Extracted);
                        if (Ch[i] == null)
                        {
                            return(PluginResult.Failed);
                        }
                    }

                    if (Expressions.GetOperator(Ch[i]) == Operator.Tuple)
                    {
                        var LocalExtracted = false;
                        var ChiCh          = Ch[i].Children;
                        for (var j = 0; j < ChiCh.Length; j++)
                        {
                            ChiCh[j] = ExtractPropertyGetter(ChiCh[j], ref LocalExtracted);
                            if (ChiCh[j] == null)
                            {
                                return(PluginResult.Failed);
                            }
                        }

                        if (LocalExtracted)
                        {
                            Ch[i] = Parent.NewNode(Ch[i]);
                            if (Ch[i] == null)
                            {
                                return(PluginResult.Failed);
                            }
                            Extracted = true;
                        }
                    }
                }
            }

            if (Extracted)
            {
                Node = Parent.NewNode(Node);
                return(PluginResult.Ready);
            }

            return(PluginResult.Succeeded);
        }