protected object AssignIndexer(AssignmentExpression node, object value)
        {
            var exp = (IndexExpression)node.Left;
            var obj = exp.Target.Accept(this);

            if (obj == null)
            {
                ExecutionException.ThrowNullError(exp.Target, node);
            }
            var args = exp.Arguments.Map(arg => arg.Accept(this)).AddLast(value);

            if (exp.Setter is null)
            {
                var indexer = exp.Target.Type
                              .FindSetIndexer(args, out ArgumentConversions conversions);
                if (indexer is null)
                {
                    ExecutionException.ThrowMissingIndexer(exp.Target.Type, "set", exp.Target, node);
                }

                exp.Conversions = conversions;
                exp.Setter      = indexer;
                // ok to be node.Right.Type instead of indexer.GetParameters().Last().ParameterType
                var valueBind = conversions[args.Length - 1];
                node.Type = (valueBind == null) ? node.Right.Type : valueBind.Type;
            }
            exp.Conversions.Invoke(ref args);
            SafeInvoke(exp, exp.Setter, obj, args);
            return(value);
        }
        private object Invoke(BinaryExpression node, string opName)
        {
            if (opName is null)
            {
                ExecutionException.ThrowInvalidOp(node);
            }
            var left  = node.Left.Accept(this);
            var right = node.Right.Accept(this);

            return(Invoke(node, opName, left, right));
        }
        static void ResolveIndexer(IndexExpression node, object[] args)
        {
            System.Reflection.MethodInfo indexer;
            var type = node.Target.Type;

            indexer = type
                      .FindGetIndexer(args, out ArgumentConversions conversions);
            if (indexer is null)
            {
                ExecutionException.ThrowMissingIndexer(type, "get", node);
            }
            node.Type        = indexer.ReturnType;
            node.Conversions = conversions;
            node.Getter      = indexer;
        }
        static object Invoke(BinaryExpression node, string opName, object left, object right)
        {
            if (left is null)
            {
                ExecutionException.ThrowNullError(node.Left, node);
            }
            if (right is null)
            {
                ExecutionException.ThrowNullError(node.Right, node);
            }

            if (node.Method is null)
            {
                var leftType  = left.GetType();
                var rightType = right.GetType();
                var types     = new Type[2] {
                    leftType, rightType
                };
                ArgumentConversions          conversions = new ArgumentConversions(2);
                System.Reflection.MethodInfo method;
                if (leftType.IsPrimitive || rightType.IsPrimitive)
                {
                    var initial = (ReflectionUtils.FromSystemType(ref types));
                    method = ReflectionUtils.
                             GetOperatorOverload(opName, conversions, types);
                    conversions.SetInitial(initial);
                }
                else
                {
                    method = ReflectionUtils.
                             GetOperatorOverload(opName, conversions, types);
                }
                if (method is null)
                {
                    ExecutionException.ThrowInvalidOp(node);
                }
                node.Method      = method;
                node.Type        = method.ReturnType;
                node.Conversions = conversions;
            }
            object[] args = new object[2] {
                left, right
            };
            node.Conversions.Invoke(ref args);
            // operator overload invoke
            return(node.Method.Invoke(null, System.Reflection.BindingFlags.Default, null, args, null));
        }
        object IExpressionVisitor <object> .VisitIndex(IndexExpression node)
        {
            var obj = node.Target.Accept(this);

            if (obj is null)
            {
                ExecutionException.ThrowNullError(node);
            }
            var args = node.Arguments.Map(arg => arg.Accept(this));

            if (node.Getter is null)
            {
                ResolveIndexer(node, args);
            }
            node.Conversions.Invoke(ref args);
            return(SafeInvoke(node, node.Getter, obj, args));
        }
 /// <summary>
 /// Safe compiler invoke for exceptions
 /// </summary>
 /// <param name="exp">Invoking expression</param>
 /// <param name="method">method to Invoke</param>
 /// <param name="target">method target</param>
 /// <param name="parmeters">parameters for invoke</param>
 /// <returns>result of invoke</returns>
 public static object SafeInvoke(Expression exp, System.Reflection.MethodBase method, object target, object[] parmeters)
 {
     try
     {
         return(method.Invoke(target, System.Reflection.BindingFlags.Default, null, parmeters, null));
     }
     catch (System.Reflection.TargetInvocationException)
     {
         throw ExecutionException.ThrowInvalidOp(exp);
     }
     catch (ArgumentException ex)
     {
         throw ExecutionException.ThrowInvalidOp(exp, new NameExpression(ex.ParamName, ExpressionType.Identifier));
     }
     catch (System.Reflection.TargetParameterCountException)
     {
         throw ExecutionException.ThrowArgumentMisMatch(exp);
     }
 }
        /// <inheritdoc/>
        public object VisitConvert(ConvertExpression node)
        {
            var value = node.Target.Accept(this);

            if (node.Type is null)
            {
                var type = node.TypeName.ResolveType(TypeContext);
                if (!TypeUtils.AreReferenceAssignable(type, node.Target.Type))
                {
                    if (!node.Target.Type.TryImplicitConvert(type, out System.Reflection.MethodInfo method) &&
                        !node.Target.Type.TryExplicitConvert(type, out method))
                    {
                        ExecutionException.ThrowInvalidCast(type, node);
                    }
                    node.Method = method;
                }

                node.Type = type;
            }
            return(value);
        }
        private object VisitExponentiation(BinaryExpression node)
        {
            var left  = node.Left.Accept(this);
            var right = node.Right.Accept(this);

            if (left is null)
            {
                ExecutionException.ThrowNullError(node, node.Left);
            }
            if (right is null)
            {
                ExecutionException.ThrowNullError(node, node.Right);
            }
            object[] args = new object[2] {
                left, right
            };
            if (node.Method is null)
            {
                Type leftType    = left.GetType();
                Type rightType   = right.GetType();
                var  types       = new Type[] { leftType, rightType };
                var  conversions = new ArgumentConversions(2);
                if (leftType.IsPrimitive || rightType.IsPrimitive)
                {
                    conversions.SetInitial(ReflectionUtils.FromSystemType(ref types));
                }
                if (!ReflectionHelpers.MathPow.MatchesArgumentTypes(types, conversions))
                {
                    ExecutionException.ThrowArgumentMisMatch(node);
                }
                node.Conversions = conversions;
                node.Method      = ReflectionHelpers.MathPow;
                node.Type        = TypeProvider.DoubleType;
            }
            node.Conversions.Invoke(ref args);
            return(node.Method.Invoke(null, args));
        }
 public MethodInfo Resolve(InvocationExpression node, string name, object obj, object[] args)
 {
     throw ExecutionException.ThrowMissingMethod(obj.GetType(), name, node);
 }
        public object VisitUnary(UnaryExpression node)
        {
            var value = node.Operand.Accept(this);

            if (node.NodeType == ExpressionType.Parenthesized)
            {
                node.Type = node.Operand.Type;
                return(value);
            }
            //modified a++; updated new value
            bool modified = false, updated = true;

            switch (node.NodeType)
            {
            case ExpressionType.PostfixPlusPlus:
                modified = true;
                updated  = false;
                break;

            case ExpressionType.PrefixPlusPlus:
                modified = true;
                break;

            case ExpressionType.PostfixMinusMinus:
                modified = true;
                updated  = false;
                break;

            case ExpressionType.PrefixMinusMinus:
                modified = true;
                break;

            case ExpressionType.Bang:
                // here value is null it is as not defined
                if (value is null)
                {
                    return(Boolean.True);
                }
                break;
            }
            if (value is null)
            {
                ExecutionException.ThrowNullError(node.Operand, node);
            }
            // no primitive supported it should be wrapped

            //resolve call
            if (node.Method is null)
            {
                Type type = node.Operand.Type;
                ArgumentConversions          conversions = new ArgumentConversions(1);
                System.Reflection.MethodInfo method;
                if (type.IsPrimitive)
                {
                    type   = TypeProvider.Find(Type.GetTypeCode(type));
                    method = ReflectionUtils.GetOperatorOverload(node.MethodName, conversions, type);
                    conversions.AddFirst(new ParamConversion(0, ReflectionHelpers.ToAny));
                }
                else
                {
                    method = ReflectionUtils.GetOperatorOverload(node.MethodName, conversions, type);
                }
                if (method is null)
                {
                    ExecutionException.ThrowInvalidOp(node);
                }
                node.Conversions = conversions;
                node.Method      = method;
                node.Type        = method.ReturnType;
            }
            object[] args = new object[1] {
                value
            };
            node.Conversions.Invoke(ref args);
            object obj = node.Method.Invoke(null, args);

            if (modified)
            {
                if (node.Operand.NodeType == ExpressionType.Literal)
                {
                    ExecutionException.ThrowNotSupported(node);
                }
                var exp = new AssignmentExpression(node.Operand, new LiteralExpression(obj));
                exp.Accept(this);
            }
            return(updated ? obj : value);
        }
        public virtual object VisitArrayLiteral(ArrayListExpression node)
        {
            Type type = node.ArrayType != null?node.ArrayType.ResolveType(TypeContext) : TypeProvider.AnyType;

            node.Type        = typeof(Collections.List <>).MakeGenericType(type);
            node.ElementType = type;
            var items  = node.Expressions;
            var length = items.Count;

            object[] args;
            if (node.Arguments != null)
            {
                args = node.Arguments.Map(arg => arg.Accept(this));
                if (node.Constructor is null)
                {
                    var methods = node.Type.GetConstructors(ReflectionUtils.PublicInstance);
                    var ctor    = ReflectionUtils.BindToMethod(methods, args, out ArgumentConversions conversions);
                    if (ctor is null)
                    {
                        ExecutionException.ThrowMissingMethod(node.Type, ".ctor", node);
                    }
                    node.Constructor         = ctor;
                    node.ArgumentConversions = conversions;
                }
                node.ArgumentConversions.Invoke(ref args);
            }
            else
            {
                args = new object[1] {
                    new Integer(length)
                };
                if (node.Constructor is null)
                {
                    node.Constructor = node.Type.GetConstructor(ReflectionUtils.PublicInstance, null, new Type[] { TypeProvider.IntType }, null);
                }
            }

            var array = (System.Collections.IList)node.Constructor.Invoke(System.Reflection.BindingFlags.Default, null, args, null);

            if (length > 0)
            {
                var arrayConversions = node.ArrayConversions ?? new ArgumentConversions(items.Count);
                for (int index = 0; index < length; index++)
                {
                    Expression expression = items[index];
                    var        value      = expression.Accept(this);
                    var        conversion = arrayConversions[index];
                    if (conversion == null && !TypeUtils.AreReferenceAssignable(type, expression.Type) && expression.Type.TryImplicitConvert(type, out System.Reflection.MethodInfo implicitCall))
                    {
                        conversion = new ParamConversion(index, implicitCall);
                        arrayConversions.Append(index, conversion);
                    }
                    if (conversion != null && conversion.ConversionType == ConversionType.Normal)
                    {
                        value = conversion.Invoke(value);
                    }
                    array.Add(value);
                }
                node.ArrayConversions = arrayConversions;
            }
            return(array);
        }