public dynamic Visit(CallOrAssign stm)
 {
     stm.AssignExpression = (ExpressionBase)(stm.AssignExpression?.Optimize() ?? stm.AssignExpression);
     if (OptimizeMode.Variables && LoopsCount <= 0)
     {
         var left = stm.LeftSideExpr as LeftSideExprVariable;
         if (left != null)
         {
             var symbol = left.Namespace.Symbols.FirstOrDefault(x => x.Name == left.Name);
             if (symbol != null)
             {
                 symbol.Value = null;
             }
             var right = stm.AssignExpression as LiteralExpr;
             if (right != null)
             {
                 if (symbol != null)
                 {
                     symbol.Value = right.Value;
                 }
             }
         }
     }
     return(stm);
 }
        public dynamic Visit(CallOrAssign stm)
        {
            stm.OrderNumber = _count;

            _callStack.Push(stm);
            Visit((dynamic)stm.LeftSideExpr);

            VisitNext(stm);

            return(null);
        }
Ejemplo n.º 3
0
        public dynamic Visit(CallOrAssign stm)
        {
            var node = new TreeNode("CallOrAssign")
            {
                Tag = stm.Node
            };

            node.Nodes.Add(new TreeNode("LeftSide")
            {
                Nodes = { Visit((dynamic)stm.LeftSideExpr) }
            });
            if (stm.AssignExpression != null)
            {
                node.Nodes.Add(new TreeNode("AssignExpr")
                {
                    Nodes = { Visit((dynamic)stm.AssignExpression) }
                });
            }
            return(node);
        }
        public dynamic Visit(CallOrAssign stm)
        {
            if (stm.AssignExpression == null)
            {
                Visit((dynamic)stm.LeftSideExpr);
                return(null);
            }

            string name = stm.LeftSideExpr.Name;

            var symbol = stm.Namespace.Symbols.SingleOrDefault(x => x.Name == name);

            if (symbol.Type == SymbolType.Array)
            {
                var left = stm.LeftSideExpr as LeftSideExprArray;

                if (ReferenceEquals(symbol.CodeGenField, null))
                {
                    var dict = _codeGen.Local(_currentMethod.ExpressionFactory.New(typeof(Hashtable)));
                    symbol.CodeGenField = dict;
                    _codeGen.Assign(dict[Visit((dynamic)left.Index)], Visit((dynamic)stm.AssignExpression));
                }
                else
                {
                    _codeGen.Assign(((ContextualOperand)symbol.CodeGenField)[Visit((dynamic)left.Index)], Visit((dynamic)stm.AssignExpression));
                }
                return(null);
            }

            if (ReferenceEquals(symbol.CodeGenField, null))
            {
                symbol.CodeGenField = _codeGen.Local(Visit((dynamic)stm.AssignExpression));
            }
            else
            {
                _codeGen.Assign(symbol.CodeGenField, Visit((dynamic)stm.AssignExpression));
            }
            return(null);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Rule: CallOrAssign -> Variable (Assign)? ;
        /// </summary>
        protected override object EvalCallOrAssign(ParseTree tree, params object[] paramlist)
        {
            var callOrAssignStm = new CallOrAssign {
                Node = this
            };
            var assignNode = GetNode(TokenType.Assign);
            var leftSide   = (LeftSideExprBase)GetNode(TokenType.Variable).Eval(tree, true);

            callOrAssignStm.LeftSideExpr = leftSide;
            if (assignNode != null)
            {
                if (leftSide.Type == LeftSideExprType.Call)
                {
                    throw new ParseException("Попытка присвоить значение вызову функции", assignNode);
                }
                var symbol = Namespaces.Current.Symbols.SingleOrDefault(x => x.Name == leftSide.Name);
                var expr   = (ExpressionBase)assignNode.Eval(tree);
                callOrAssignStm.AssignExpression = expr;
                var exprType = expr.GetExprType();
                if (leftSide.Type == LeftSideExprType.Variable)
                {
                    ((LeftSideExprVariable)leftSide).VariableType = exprType;
                    if (symbol != null)
                    {
                        if (symbol.Type == SymbolType.Unknown)
                        {
                            symbol.Type = exprType;
                        }
                        else
                        {
                            if (symbol.Type != exprType)
                            {
                                throw new ParseException("Невозможно изменить тип переменной", assignNode);
                            }
                        }
                    }
                    else
                    {
                        Namespaces.Current.AddSymbol(
                            new Symbol(exprType, leftSide.Name),
                            GetNode(TokenType.Variable));
                    }
                }
                if (leftSide.Type == LeftSideExprType.Array)
                {
                    var leftsidearray = (LeftSideExprArray)leftSide;
                    if (symbol != null)
                    {
                        if (symbol.Type == SymbolType.Array)
                        {
                            if (symbol.ArrayKeyType != leftsidearray.ArrayKeyType)
                            {
                                throw new ParseException("Невозможно изменить тип ключа у массива", assignNode);
                            }
                            if (symbol.ArrayValueType != exprType)
                            {
                                throw new ParseException("Невозможно изменить тип значений массива", assignNode);
                            }
                        }
                        else
                        {
                            throw new ParseException("Нельзя использовать скалярную переменную как массив!", assignNode);
                        }
                    }
                    else
                    {
                        Namespaces.Current.AddSymbol(
                            new Symbol(SymbolType.Array, leftSide.Name)
                        {
                            ArrayKeyType = leftsidearray.ArrayKeyType, ArrayValueType = exprType
                        },
                            GetNode(TokenType.Variable));
                    }
                }
            }

            if (assignNode == null)
            {
                if (leftSide.Type == LeftSideExprType.Variable || leftSide.Type == LeftSideExprType.Array)
                {
                    throw new ParseException("Отсутствует правая часть выражения", GetNode(TokenType.Variable));
                }
            }

            return(callOrAssignStm);
        }
        public dynamic Visit(ForStm stm)
        {
            LoopsCount++;
            stm.AssignExpression = Visit(stm.AssignExpression);
            stm.Statements       = Visit(stm.Statements);
            stm.ToExpression     = Visit(stm.ToExpression);
            if (stm.IncByExpression != null)
            {
                stm.IncByExpression = Visit(stm.IncByExpression);
            }
            var strNamespace = Namespaces.Current;

            Namespaces.Current = stm.Namespace;
            stm.Variable       = Visit(stm.Variable);
            if (OptimizeMode.LoopExpansion)
            {
                var assignExpr = stm.AssignExpression as LiteralExpr;
                var toExpr     = stm.ToExpression as LiteralExpr;
                if (toExpr != null && assignExpr != null && assignExpr.GetExprType() == SymbolType.Integer)
                {
                    int startValue = assignExpr.Value;
                    int toValue    = toExpr.Value;
                    int incByValue = 1;
                    if (stm.IncByExpression != null)
                    {
                        incByValue = ((LiteralExpr)Visit((dynamic)stm.IncByExpression))?.Value ?? 1;
                    }

                    var steps = (toValue - startValue) / incByValue;
                    if (steps >= 0 && steps < OptimizeMode.LoopExpansionRepeatLimit)
                    {
                        var block = new CodeBlock {
                            Namespace = stm.Namespace, Node = stm.Node, Statements = new List <StatementBase>()
                        };
                        for (var i = startValue; i <= toValue; i += incByValue)
                        {
                            var assig = Visit(new CallOrAssign
                            {
                                Namespace        = stm.AssignExpression.Namespace,
                                Node             = stm.AssignExpression.Node,
                                AssignExpression = new LiteralExpr {
                                    Namespace = stm.Namespace, SymbolType = stm.Variable.VariableType, Value = i
                                },
                                LeftSideExpr = new LeftSideExprVariable
                                {
                                    Name         = stm.Variable.Name,
                                    Namespace    = stm.Variable.Namespace,
                                    Type         = LeftSideExprType.Variable,
                                    VariableType = stm.Variable.VariableType
                                }
                            });
                            block.Statements.Add(assig);
                            block.Statements.AddRange(Visit(stm.Statements).Statements);
                        }
                        Namespaces.Current = strNamespace;
                        LoopsCount--;
                        return(block);
                    }
                }
            }

            var assign = new CallOrAssign
            {
                Namespace        = stm.Namespace,
                Node             = stm.AssignExpression.Node,
                AssignExpression = stm.AssignExpression,
                LeftSideExpr     = new LeftSideExprVariable
                {
                    Name         = stm.Variable.Name,
                    Namespace    = stm.Namespace,
                    Type         = LeftSideExprType.Variable,
                    VariableType = stm.Variable.VariableType
                }
            };

            var loopBody = new CodeBlock
            {
                Namespace  = stm.Namespace,
                Node       = stm.Node,
                Statements = new List <StatementBase>
                {
                    stm.Statements,
                    new CallOrAssign
                    {
                        Namespace        = stm.Namespace,
                        Node             = stm.AssignExpression.Node,
                        AssignExpression = Visit(new AddExpr
                        {
                            First = new GetVariableExpr
                            {
                                Name = assign.LeftSideExpr.Name, Type = stm.Variable.VariableType
                            },
                            Second = stm.IncByExpression ?? new LiteralExpr
                            {
                                SymbolType = SymbolType.Integer,
                                Value      = 1
                            },
                            OperationText = "+",
                            Namespace     = stm.Namespace
                        }),
                        LeftSideExpr = new LeftSideExprVariable
                        {
                            Name         = stm.Variable.Name,
                            Namespace    = stm.Namespace,
                            Type         = LeftSideExprType.Variable,
                            VariableType = stm.Variable.VariableType
                        }
                    }
                }
            };

            var loop = new DoWhileStm
            {
                Namespace = stm.Namespace,
                Condition = Visit(new CompareExpr
                {
                    First = Visit(new GetVariableExpr {
                        Name = assign.LeftSideExpr.Name, Type = stm.Variable.VariableType, Namespace = stm.Namespace
                    }),
                    OperationText = "<=",
                    Second        = stm.ToExpression,
                    Namespace     = stm.Namespace
                }),
                Statements = loopBody,
                Type       = LoopType.While
            };

            var outerBlock = new CodeBlock
            {
                Statements = new List <StatementBase>(),
                Namespace  = stm.Namespace
            };

            outerBlock.Statements.Add(assign);
            outerBlock.Statements.Add(loop);

            Namespaces.Current = strNamespace;
            LoopsCount--;
            return(outerBlock);
        }