public dynamic Visit(CallFuncExpr expr)
 {
     if (expr.Arguments != null)
     {
         expr.Arguments = Visit((dynamic)expr.Arguments);
     }
     return(expr);
 }
Exemple #2
0
        public dynamic Visit(CallFuncExpr expr)
        {
            var node = new TreeNode("Function Call")
            {
                Tag = expr.Node
            };

            if (expr.Arguments != null)
            {
                node.Nodes.Add(Visit(expr.Arguments));
            }
            return(node);
        }
 public dynamic Visit(CallFuncExpr expr)
 {
     Visit((dynamic)expr.Function.Code);
     return(null);
 }
 public dynamic Visit(CallFuncExpr expr)
 {
     return(expr.Function.ReturnType);
 }
Exemple #5
0
        /// <summary>
        /// Rule: Variable -> IDENTIFIER ((Array | Call))? ;
        /// </summary>
        protected override object EvalVariable(ParseTree tree, params object[] paramlist)
        {
            var identNode  = GetNode(TokenType.IDENTIFIER);
            var name       = identNode.Token.Text;
            var isLeftSide = paramlist != null && paramlist.Any() && (bool)paramlist.First();

            if (GetNode(TokenType.Array) == null && GetNode(TokenType.Call) == null)
            {
                if (isLeftSide)
                {
                    return(new LeftSideExprVariable {
                        Name = name, Type = LeftSideExprType.Variable, Node = this
                    });
                }
                var existingSymbol = Namespaces.Current.Symbols.SingleOrDefault(x => x.Name == name);
                if (existingSymbol != null && existingSymbol.Type == SymbolType.Array)
                {
                    throw new ParseException($"Использование массива {name} без индексатора", identNode);
                }
                if (existingSymbol != null && existingSymbol.Type == SymbolType.Function)
                {
                    throw new ParseException($"Использование функции {name} без скобок", identNode);
                }
                if (existingSymbol != null && existingSymbol.Type != SymbolType.Unknown)
                {
                    existingSymbol.UsagesCount++;
                    return(new GetVariableExpr {
                        Type = existingSymbol.Type, Node = this, Name = name
                    });
                }

                throw new ParseException($"Использование непроинициализированной переменной {name}", identNode);
            }

            if (GetNode(TokenType.Array) != null)
            {
                var expr     = (ExpressionBase)GetNode(TokenType.Array).Eval(tree);
                var exprType = expr.GetExprType();
                if (isLeftSide)
                {
                    return(new LeftSideExprArray
                    {
                        ArrayKeyType = exprType,
                        Index = expr,
                        Node = this,
                        Type = LeftSideExprType.Array,
                        Name = name
                    });
                }
                var existingSymbol = Namespaces.Current.Symbols.SingleOrDefault(x => x.Name == name && x.Type == SymbolType.Array && x.ArrayKeyType == exprType);
                if (existingSymbol != null)
                {
                    existingSymbol.UsagesCount++;
                    return(new GetArrayExpr {
                        ValuesType = existingSymbol.ArrayValueType, Node = this, Name = name, Index = expr, KeysType = existingSymbol.ArrayKeyType
                    });
                }
                if (Namespaces.Current.Symbols.Any(x => x.Name == name && x.Type == SymbolType.Array))
                {
                    throw new ParseException("Невозможно изменить тип ключа у массива", identNode);
                }
                throw new ParseException($"Использование непроинициализированного массива {name}", identNode);
            }

            if (GetNode(TokenType.Call) != null)
            {
                var arguments       = ((Arguments)GetNode(TokenType.Call).Eval(tree));
                var funcDeclaration = AstCreator.FuncDeclarations.SingleOrDefault(x => x.Name == name && x.Arguments.Count == arguments.Values.Count);
                if (funcDeclaration == null)
                {
                    throw new ParseException($"Попытка использовать необъявленную функцию {name}", identNode);
                }

                var argumentsTypes = arguments.Values.Select(av => av.GetExprType()).ToList();
                if (AstCreator.FuncImplementation.Count > 0)
                {
                    if (AstCreator.FuncImplementation.Any(x => x.Name == name && x.ArgumentsTypes.SequenceEqual(argumentsTypes)))
                    {
                        throw new ParseException("Рекурсия не поддерживается", identNode);
                    }
                }
                var funcImplementation = AstCreator.FuncImplementations.SingleOrDefault(x => x.Name == name && x.ArgumentsTypes.SequenceEqual(argumentsTypes));
                if (funcImplementation == null)
                {
                    funcImplementation = new FuncImplementation {
                        Name = name, Node = this, ArgumentsTypes = argumentsTypes, Declaration = funcDeclaration
                    };
                    AstCreator.FuncImplementation.Push(funcImplementation);

                    var currentNamespace = Namespaces.Current;
                    Namespaces.Current = Namespaces.Root;
                    Namespaces.LevelDown(new Namespace($"{name}({string.Join(", ", argumentsTypes)})"));

                    for (var index = 0; index < arguments.Values.Count; index++)
                    {
                        var symbolType = argumentsTypes[index];
                        var symbol     = new Symbol(symbolType, funcDeclaration.Arguments[index]);
                        Namespaces.Current.AddSymbol(symbol, identNode);
                    }

                    funcDeclaration.Node.Eval(tree, true, this);
                    funcImplementation.Namespace = Namespaces.Current;
                    Namespaces.Current           = currentNamespace;
                    AstCreator.FuncImplementations.Add(AstCreator.FuncImplementation.Pop());
                }

                var callFuncExpr = new CallFuncExpr {
                    Node = this, Function = funcImplementation, Arguments = arguments
                };
                if (isLeftSide)
                {
                    return(new LeftSideExprCall {
                        Name = name, Type = LeftSideExprType.Call, Node = this, CallFunc = callFuncExpr
                    });
                }
                if (funcImplementation.ReturnType == SymbolType.Void || funcImplementation.ReturnType == SymbolType.Unknown)
                {
                    throw new ParseException("Невозможно использовать функции, возвращающие void в выражениях", this);
                }
                return(callFuncExpr);
            }
            return(null);
        }
        public dynamic Visit(CallFuncExpr expr)
        {
            var objects = expr.Arguments.Values.Select(x => Visit((dynamic)x)).Cast <Operand>().ToArray();

            return(_codeGen.This().Invoke(expr.Function.Name, objects));
        }