public object Visit(ParameterExpression parameter)
 {
     return(new XsParameter(parameter.Name, ctx.GetClrType(parameter.Type)));
 }
        private object ArithmethicOperation(BinaryExpression binaryOp, OpCode op, XzaarType resultType = null)
        {
            if (resultType == null)
            {
                resultType = XzaarBaseTypes.Number;
            }

            var il = ctx.GetILGenerator();

            if (resultType.Name == "string")
            {
                // determine which side is a string
                var leftType  = binaryOp.Left.Type;
                var rightType = binaryOp.Right.Type;
                var boxLeft   = false;
                var boxRight  = false;
                // if both are strings, we can just find the normal string,string concat function and call that one.
                // if one of the types are a valuetype (not a class or 'any'), then that type needs to be boxed
                //     then use the object,object concat function instead
                MethodInfo targetConcatMethod = typeof(string).GetMethod("Concat", new[] { typeof(object), typeof(object) });
                if (leftType.Name == "string")
                {
                    if (rightType.Name == "string")
                    {
                        targetConcatMethod = typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string) });
                    }
                    else
                    {
#warning Concating string requires struct's to be boxed. TODO: Add boxing for structs!
                        boxRight = rightType.IsNumeric;
                        // numbers and structs needs to be boxed, right now we don't know if one is a struct or not
                        // check if boxing is necessary on the 'right' type.
                    }
                }
                else
                {
                    boxLeft = leftType.IsNumeric;
                    // check if boxing is necessary on the 'left' type.
                }

                var l = Visit(binaryOp.Left);
                TryLoadReference(l, il);

                if (boxLeft)
                {
                    il.Box(ctx.GetClrType(leftType));
                }

                var r = Visit(binaryOp.Right);
                TryLoadReference(r, il);

                if (boxRight)
                {
                    il.Box(ctx.GetClrType(rightType));
                }

                il.Call(targetConcatMethod);

                return(true);
            }



            // NOTE: arithmetic operations does NOT necessarily have to introduce a
            // temporary variable, but COULD. I decided to skip it for simplicity

            var left = Visit(binaryOp.Left);

            TryLoadReference(left, il);
            // if its not any of the ones above, it must be either a function call or constant

            var right = Visit(binaryOp.Right);

            TryLoadReference(right, il);

            il.Emit(op);

            return(true);
        }