public void Add(Token token, bool isOperator = false)
        {
            _source = _source ?? token.Source;

            ///////////////////////////////
            // SCRIPTING
            if (isOperator && _stack.Count < 2 && token.Type == TokenType.LogicalAnd && token.Lexeme == ";")
            {
                // most probably script char that represents empty statement
                // => ignore
                return;
            }
            //
            //////////////////////////////

            _stack.Push(token);
            if (!isOperator)
            {
                return;
            }

            try
            {
                var ast = _astBuilder.PopExpression(_stack, _p);
                _stack.Push(ast.ToToken());
            }
            catch (XPressionException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new XPressionException(token.Source, ex.Message, token.Position, ex);
            }
        }
Exemple #2
0
        // C# equivalents:
        // if(test,body) => return test ? body() : true;
        // if(test,trueBody,falseBody) => return test ? trueBody() : falseBody();
        // if parametercount==2 (falseBody is omitted), then the falseBody always
        // returns true (so then the trueBody MUST return a boolean value as well)
        public bool TryBuildExpression(ASTBuilder treeBuilder, FunctionToken functionToken, Stack <Token> stack, ParameterExpression p, out Expression output)
        {
            var ifFalse = functionToken.ParameterCount >= 3 ? treeBuilder.PopExpression(stack, p) : Expression.Constant(true);
            var ifTrue  = treeBuilder.PopExpression(stack, p);
            var test    = treeBuilder.PopExpression(stack, p);

            output = Expression.Condition(test.Convert <bool>(), ifTrue, ifFalse);
            return(true);
        }
Exemple #3
0
        public bool TryBuildExpression(ASTBuilder treeBuilder, FunctionToken functionToken, Stack <Token> stack, ParameterExpression p, out Expression output)
        {
            if (functionToken.ParameterCount == 0)
            {
                throw new XPressionException(functionToken.Source, "format requires at least one argument", functionToken.Position);
            }
            var args = new List <Expression>();

            for (var i = 0; i < functionToken.ParameterCount; i++)
            {
                args.Add(treeBuilder.PopExpression(stack, p));
            }

            args.Reverse(); // reverse stack order

            output =
                Expression.Call(
                    MemberTokens.String.FormatWithProvider,
                    Expression.Constant(CultureInfo.InvariantCulture),
                    args[0],
                    Expression.NewArrayInit(
                        typeof(object),
                        args.Skip(1).Select(e => e.Type == typeof(object) ? e : Expression.Convert(e, typeof(object)))
                        )
                    );
            return(true);
        }
Exemple #4
0
        public bool TryBuildExpression(ASTBuilder treeBuilder, FunctionToken functionToken, Stack <Token> stack, ParameterExpression p, out Expression output)
        {
            var rightToken = stack.Pop(); // must be a constant string
            var target     = treeBuilder.PopExpression(stack, p);

            if (target.IsNullConstant())
            {
                output = Expression.Convert(Expression.Constant(null), typeof(bool?));
                return(true);
            }
            Type type;

            try
            {
                type = treeBuilder.Grammar.GetType(rightToken.Lexeme);
            }
            catch (Exception ex)
            {
                throw new XPressionException(functionToken.Source, "Invalid type: " + rightToken.Lexeme, rightToken.Position, ex);
            }
            if ((!target.Type.IsValueType || target.Type.IsNullable()) && type.IsValueType && !type.IsNullable())
            {
                type = typeof(Nullable <>).MakeGenericType(type);
            }
            output = Expression.TypeEqual(target, type);
            return(true);
        }
Exemple #5
0
        public bool TryBuildExpression(ASTBuilder treeBuilder, FunctionToken functionToken, Stack <Token> stack, ParameterExpression p, out Expression output)
        {
            var target = treeBuilder.PopExpression(stack, p);

            if (target.Type.EnsureNotNullable() != typeof(DateTimeOffset))
            {
                throw new XPressionException(functionToken.Source, "expected a datatimeoffset argument", functionToken.Position);
            }
            if (target.IsNullConstant())
            {
                output = Expression.Convert(Expression.Constant(null), typeof(int?));
                return(true);
            }
            if (target.Type.IsNullable())
            {
                output = Expression.Convert(target, target.Type.EnsureNotNullable());
                return(true);
            }
            output = Expression.MakeMemberAccess(Expression.MakeMemberAccess(target, MemberTokens.DateTimeOffset.Offset), MemberTokens.TimeSpan.TotalMinutes);
            return(true);
        }
Exemple #6
0
 // in our case else is syntactic sugar: simply return the first expression on the stack
 public bool TryBuildExpression(ASTBuilder treeBuilder, FunctionToken functionToken, Stack <Token> stack, ParameterExpression p, out Expression output)
 {
     output = treeBuilder.PopExpression(stack, p);
     return(true);
 }
Exemple #7
0
        public bool TryBuildExpression(ASTBuilder astBuilder, FunctionToken functionToken, Stack <Token> stack, ParameterExpression p, out Expression output)
        {
            output = null;

            IFunctionBuilder builder;

            if (_builders.TryGetValue(functionToken.Lexeme, out builder))
            {
                if (builder.TryBuildExpression(astBuilder, functionToken, stack, p, out output))
                {
                    return(true);
                }
            }


            ConcurrentDictionary <FunctionSignature, FunctionBuilder> lookup;

            if (!_members.TryGetValue(functionToken.Lexeme, out lookup))
            {
                return(false);
            }

            var args = new List <Expression>();

            for (var i = 0; i < functionToken.ParameterCount; i++)
            {
                args.Add(astBuilder.PopExpression(stack, p));
            }

            args.Add(p);    // always initially probe instance call

            args.Reverse(); // reverse stack order

            FunctionBuilder factory;
            FunctionSignature
                fs1 = null, // instance
                fs2 = null; // static

            if (!TryFindFactory(lookup, fs1 = new FunctionSignature(args.Select(fp => fp.Type)), out factory))
            {
                if (TryFindFactory(lookup, fs2 = new FunctionSignature(args.Skip(1).Select(fp => fp.Type)), out factory))
                {
                    args = args.Skip(1).ToList();
                }
            }

            if (factory != null)
            {
                // found
                if (args.Any() && factory.ParameterTypes.Any())
                {
                    if (factory.ParameterTypes.Last().IsArray&& !args.Last().Type.IsArray)
                    {
                        // we need an argument conversion to params <some-type>[]
                        if (fs2 != null)
                        {
                            // static invocation
                            if (factory.ParameterTypes[0] == typeof(object[]))
                            {
                                args = new List <Expression>(new[] { Expression.NewArrayInit(typeof(object), args.Select(a => a.Convert <object>())) });
                            }
                            else
                            {
                                args = new List <Expression>(new[] { Expression.NewArrayInit(args[0].Type, args) });
                            }
                        }
                        else
                        {
                            // instane invocation
                            if (factory.ParameterTypes[1] == typeof(object[]))
                            {
                                args = new List <Expression>(new[] { args[0], Expression.NewArrayInit(typeof(object), args.Skip(1).Select(a => a.Convert <object>())) });
                            }
                            else
                            {
                                args = new List <Expression>(new[] { args[0], Expression.NewArrayInit(args[0].Type, args.Skip(1)) });
                            }
                        }
                    }
                }
                output = factory.BuildExpression(args, p);
                return(true);
            }

            FunctionSignature signature;

            /////////////////////////////////////////////////////////////////////////////////////////////////////////
            // 1. try instance
            if (args.Count == 2 || args.Skip(1).Select(x => x.Type).Distinct().Count() == 1)
            {
                signature = new FunctionSignature(new[] { args[0].Type, args[1].Type.MakeArrayType() });
                if (TryFindFactory(lookup, signature, out factory))
                {
                    // probably params <type>[] arg
                    args = new List <Expression>
                    {
                        args[0],
                        Expression.NewArrayInit(args[1].Type, args.Skip(1))
                    };
                    lookup.TryAdd(fs1, factory);// register in lookup
                    output = factory.BuildExpression(args, p);
                    return(true);
                }
            }

            // any delegates?
            var args1     = args;
            var factories = lookup.Values.Where(f => f.HasDelegateArg && f.ParameterTypes.Count == args1.Count);

            foreach (var f in factories)
            {
                var ismatch = true;
                var i       = 0;
                foreach (var t in f.ParameterTypes)
                {
                    if (!(typeof(Delegate).IsAssignableFrom(t) || t.IsAssignableFrom(args[i].Type)))
                    {
                        ismatch = false;
                        break;
                    }
                    i++;
                }
                if (ismatch)
                {
                    lookup.TryAdd(fs1, f);// register in lookup
                    output = f.BuildExpression(args, p);
                    return(true);
                }
            }

            // params object[] ?
            signature = new FunctionSignature(new[] { args[0].Type, typeof(object).MakeArrayType() });
            if (TryFindFactory(lookup, signature, out factory))
            {
                // probably params object[] arg
                args = new List <Expression>
                {
                    args[0],
                    Expression.NewArrayInit(typeof(object), args.Skip(1).Select(e => e.Convert <object>()))
                };
                lookup.TryAdd(fs1, factory);// register in lookup
                output = factory.BuildExpression(args, p);
                return(true);
            }
            //
            //////////////////////////////////////////////////////////////////////////////////////////////////////

            /////////////////////////////////////////////////////////////////////////////////////////////////////
            // 2. try static
            args = args.Skip(1).ToList();

            if (args.Count == 1 || args.Select(x => x.Type).Distinct().Count() == 1)
            {
                // all argumens have same type, look for array type
                signature = new FunctionSignature(new[] { args[0].Type.MakeArrayType() });
                if (TryFindFactory(lookup, signature, out factory))
                {
                    // probably params <type>[] arg
                    args = new List <Expression>
                    {
                        Expression.NewArrayInit(args[0].Type, args)
                    };
                    lookup.TryAdd(fs2, factory);// register in lookup
                    output = factory.BuildExpression(args, p);
                    return(true);
                }
            }

            // any delegate?
            var args2 = args;

            factories = lookup.Values.Where(f => f.HasDelegateArg && f.ParameterTypes.Count - 1 == args2.Count);
            foreach (var f in factories)
            {
                var ismatch = true;
                var i       = 0;
                foreach (var t in f.ParameterTypes.Skip(1))
                {
                    if (!(typeof(Delegate).IsAssignableFrom(t) || t.IsAssignableFrom(args[i].Type)))
                    {
                        ismatch = false;
                        break;
                    }
                    i++;
                }
                if (ismatch)
                {
                    lookup.TryAdd(fs2, f);// register in lookup
                    output = f.BuildExpression(args, p);
                    return(true);
                }
            }

            // params object[] ?
            signature = new FunctionSignature(new[] { typeof(object).MakeArrayType() });
            if (TryFindFactory(lookup, signature, out factory))
            {
                // probably params object[] arg
                args = new List <Expression>
                {
                    args[0],
                    Expression.NewArrayInit(typeof(object), args.Skip(1).Select(e => e.Convert <object>()))
                };
                lookup.TryAdd(fs2, factory);// register in lookup
                output = factory.BuildExpression(args, p);
                return(true);
            }
            throw new XPressionException(functionToken.Source, "invalid arguments, overload not found for method " + functionToken.Lexeme, functionToken.Position);
        }