Example #1
0
        public override Type OutputType(out CompiledFragment newOperation)
        {
            newOperation = this;
            Type typeB = Input1.OutputType(out Input1);
            Type typeA = Input0.OutputType(out Input0);

            if (typeA != typeB)
            {
                bool BString = (typeB == typeof(string));
                if (typeA == typeof(string) || BString)
                {
                    if (BString)
                    {
                        // This is alright - convert Input0 to a ToString operation.
                        Input0 = Types.ToStringMethod(Method, Input0, typeA);
                        typeA  = typeof(string);
                    }
                    else
                    {
                        Input1 = Types.ToStringMethod(Method, Input1, typeB);
                        typeB  = typeof(string);
                    }
                }
            }
            if (typeA == typeof(string) && typeB == typeof(string))
            {
                // Adding two strings (concat).
                newOperation = new MethodOperation(Method, typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) }), Input0, Input1);
            }
            else
            {
                typeA = Numerical(typeA, typeB, "Addition", ref newOperation);
            }
            return(typeA);
        }
        public override Type OutputType(out CompiledFragment v)
        {
            v = this;
            Type TypeA = Input1.OutputType(out Input1);
            Type TypeB = Input0.OutputType(out Input0);

            return(Numerical(TypeA, TypeB, "Multiply", ref v));
        }
Example #3
0
        public override Type OutputType(out CompiledFragment v)
        {
            v = this;
            Type typeA = Input1.OutputType(out Input1);
            Type typeB = Input0.OutputType(out Input0);

            return(Numerical(typeA, typeB, "Division", ref v));
        }
Example #4
0
        public override Type OutputType(out CompiledFragment newOperation)
        {
            newOperation = this;
            Type typeB = Input1.OutputType(out Input1);

            if (Input0 == null)
            {
                // Negation
                return(Numerical(ref Input1, typeB, typeof(float)));
            }
            Type typeA = Input0.OutputType(out Input0);

            return(Numerical(typeA, typeB, "Subtraction", ref newOperation));
        }
Example #5
0
        public override Type OutputType(out CompiledFragment v)
        {
            v = this;
            if (ElementType == null)
            {
                Type type      = AppliedTo.OutputType(out AppliedTo);
                Type indexType = Index.OutputType(out Index);
                if (!type.IsArray)
                {
                    // Using an index on something that isn't an array - this maps to the get_Item/set_Item functions.
                    MethodInfo[] allMethods = type.GetMethods();

                    MethodOperation mOp = null;

                    if (Input0 != null)
                    {
                        // Set. Input0 is the object we're setting.
                        Type       setType = Input0.OutputType(out Input0);
                        MethodInfo mInfo   = Types.GetOverload(allMethods, "set_Item", new Type[] { indexType, setType });
                        if (mInfo == null)
                        {
                            Error("This object does not support setting values with [" + indexType + "]=" + setType + ".");
                        }
                        mOp          = new MethodOperation(Method, mInfo, Index, Input0);
                        v            = mOp;
                        mOp.CalledOn = AppliedTo;
                        return(setType);
                    }
                    else
                    {
                        // Get.
                        MethodInfo mInfo = Types.GetOverload(allMethods, "get_Item", new Type[] { indexType });
                        if (mInfo == null)
                        {
                            Error("Unable to index [] something that as it is not an array.");
                        }
                        mOp          = new MethodOperation(Method, mInfo, Index);
                        v            = mOp;
                        mOp.CalledOn = AppliedTo;
                        return(mInfo.ReturnType);
                    }
                }
                else
                {
                    EnforceType(ref Index, indexType, typeof(int));
                }
                ElementType = type.GetElementType();
            }
            return(ElementType);
        }
Example #6
0
        public override Type OutputType(out CompiledFragment v)
        {
            v = this;
            Type typeA = Input0.OutputType(out Input0);
            Type typeB = Input1.OutputType(out Input1);

            CompiledFragment equalityOverload = null;

            FindOverload("Equality", typeA, typeB, ref equalityOverload);
            if (equalityOverload != null)
            {
                v = equalityOverload;
            }
            return(typeof(bool));
        }
        public override Type OutputType(out CompiledFragment v)
        {
            v = this;
            Type typeA = Input0.OutputType(out Input0);
            Type typeB = Input1.OutputType(out Input1);

            CompiledFragment overload = null;

            FindOverload("GreaterThan", typeA, typeB, ref overload);

            if (overload != null)
            {
                v = overload;
            }

            return(typeof(bool));
        }
Example #8
0
        public override Type OutputType(out CompiledFragment v)
        {
            v = this;

            if (Input0 != null)
            {
                Type i0Type = Input0.OutputType(out Input0);

                if (i0Type != null && i0Type.IsValueType)
                {
                    // Create a box operation:
                    Input0 = new BoxOperation(Method, Input0);
                }
            }

            return(typeof(string));
        }
Example #9
0
        public override void OutputIL(NitroIL into)
        {
            Type methodType = Method.ReturnType();

            if (Input0 != null)
            {
                Type type = Input0.OutputType(out Input0);
                if (type == null)
                {
                    if (methodType.IsValueType)
                    {
                        // We're returning null and the method returns a value type - this isn't allowed.
                        Error("Can't return null here as the output type of the method is a value type.");
                    }
                }
                else if (!methodType.IsAssignableFrom(type))
                {
                    if (Types.IsVoid(methodType))
                    {
                        Error("This method cannot return anything (it's got no return type)");
                    }
                    else
                    {
                        Error("Must return something of type " + methodType + " (the methods return type)");
                    }
                }
                Input0.OutputIL(into);
            }
            else if (!Types.IsVoid(methodType))
            {
                Error("Must return a value of type " + methodType);
            }
            if (Method.ReturnBay != null)
            {
                into.Emit(OpCodes.Stloc, Method.ReturnBay);
            }
            into.Emit(OpCodes.Br, Method.EndOfMethod);
        }
Example #10
0
 public override Type OutputType(out CompiledFragment v)
 {
     v = this;
     Input1.OutputType(out Input1);
     return(Input0.OutputType(out Input0));
 }
        public override void OutputIL(NitroIL into)
        {
            Type type2 = Input1.OutputType(out Input1);

            // Is it something which is being ["indexed"]? May apply to properties too.
            bool indexOperation    = (Input0.GetType() == typeof(IndexOperation));
            bool propertyOperation = (Input0.GetType() == typeof(PropertyOperation));

            if (indexOperation || propertyOperation)
            {
                // Hook up what we will be setting for the index to handle if it needs to.
                // Note that the object will not change as we have already run it's OutputType call above.
                ((Operation)Input0).Input0 = Input1;
            }

            // Update input0 by computing the type it outputs:
            Type type1 = Input0.OutputType(out Input0);

            object value = Input0.ActiveValue();

            if (value.GetType() != typeof(LocalVariable))
            {
                // Local vars can change type so this doesn't affect them.

                if (type1 == null)
                {
                    Error("Can't set to nothing.");
                }

                if (type2 == null)
                {
                    if (type1.IsValueType)
                    {
                        Error("Can't set " + type1 + " to null because it's a value type.");
                    }
                }
                else if (!type1.IsAssignableFrom(type2))
                {
                    Error("Can't implicity convert " + type2 + " to " + type1 + ".");
                }
            }

            if (Types.IsTypeOf(value, typeof(ISettable)))
            {
                ISettable Value = (ISettable)value;

                Value.OutputTarget(into);
                Input1.OutputIL(into);
                Value.OutputSet(into, type2);

                if (Output)
                {
                    // Daisy chaining these sets.
                    Input0.OutputIL(into);
                }
            }
            else if (indexOperation && value.GetType() == typeof(MethodOperation))
            {
                // This is ok! We've called something like obj["hello"]=input1;
                // Just output the method call:
                Input0.OutputIL(into);

                if (Output)
                {
                    Error("Can't daisy chain with an indexer. Place your indexed object furthest left.");
                }
            }
            else if (propertyOperation && value.GetType() == typeof(MethodOperation) && ((MethodOperation)value).MethodName == "set_Item")
            {
                // This is also ok - we've done something like object.property=value; and it mapped to object["property"]=value;
                // Just output the method call:
                Input0.OutputIL(into);

                if (Output)
                {
                    Error("Can't daisy chain with a property set here. Place your indexed object furthest left.");
                }
            }
            else
            {
                Error("Attempted to set to something (a " + value.GetType() + ") that isn't a variable.");
            }
        }
Example #12
0
        public override Type OutputType(out CompiledFragment v)
        {
            v = this;

            Type type = OfType();

            // Map to functionality:
            CompiledClass Class     = null;
            bool          isDynamic = Types.IsDynamic(type);

            // (Constant) binding flags:
            BindingFlags flags = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static;

            if (Name == "length" && type.IsGenericType && !isDynamic)
            {
                // Does length actually exist as a field/ property?

                Field = type.GetField(Name, flags);

                if (Field == null)
                {
                    Property = type.GetProperty(Name, flags);

                    if (Property == null)
                    {
                        // Assume we meant count instead:
                        Name = "Count";
                    }
                }
            }

            if (isDynamic)
            {
                Class = Method.Script.GetClass(type);
            }
            else if (!Method.Script.AllowUse(type))
            {
                Error("Unable to access properties of type " + type + " as it has not been made accessible.");
            }

            if (isDynamic)
            {
                Field = Class.GetField(Name);
            }
            else
            {
                Field = type.GetField(Name, flags);
            }

            if (Field != null)
            {
                if (IsStatic && !Field.IsStatic)
                {
                    Error("Property " + Name + " is not static. You must use an object reference to access it.");
                }

                return(Field.FieldType);
            }

            if (isDynamic)
            {
                Property = Class.GetProperty(Name);
            }
            else
            {
                Property = type.GetProperty(Name, flags);
            }

            if (Property != null)
            {
                if (IsStatic)
                {
                    MethodInfo staticTest = Property.GetGetMethod();
                    if (staticTest == null)
                    {
                        staticTest = Property.GetSetMethod();
                    }
                    if (!staticTest.IsStatic)
                    {
                        Error("Property " + Name + " is not static. You must use an object reference to access it.");
                    }
                }
                return(Property.PropertyType);
            }

            if (isDynamic)
            {
                MethodReturnType = Class.MethodReturnType(Name);
            }
            else
            {
                MethodReturnType = Types.MethodReturnType(type, Name);
            }

            if (MethodReturnType != null)
            {
                if (Types.IsVoid(MethodReturnType))
                {
                    MethodReturnType = typeof(Void);
                }
                return(DynamicMethodCompiler.TypeFor(MethodReturnType));
            }

            if (Of.GetType() == typeof(ThisOperation))
            {
                // This was the first property - it can potentially be a static type name too.
                Type staticType = Method.Script.GetType(Name);
                if (staticType != null)
                {
                    // It's a static type! Generate a new type operation to replace this one and return the type.
                    v = new TypeOperation(Method, staticType);
                    return(v.OutputType(out v));
                }
            }

            if (Name == "this")
            {
                // This is handled here as it allows variables called "This". Use case: PowerUI.
                v = new ThisOperation(Method);
                return(v.OutputType(out v));
            }

            // Does it support indexing? If so, Do Parent["property"] instead.

            MethodOperation mOp = null;

            if (Input0 != null)
            {
                // This is a set. Input0 is the object we're setting.

                Type setType = Input0.OutputType(out Input0);

                // Get the set method:
                MethodInfo mInfo;

                if (isDynamic)
                {
                    mInfo = Class.FindMethodOverload("set_Item", new Type[] { typeof(string), setType });
                }
                else
                {
                    // Grab all the methods of the type:
                    MethodInfo[] allMethods = type.GetMethods();
                    mInfo = Types.GetOverload(allMethods, "set_Item", new Type[] { typeof(string), setType });
                }

                if (mInfo == null)
                {
                    // Try finding the extension method:
                    mInfo = FindExtensionMethod(type, "set");

                    if (mInfo == null)
                    {
                        // It doesn't exist!
                        // Error("Property '"+ToString()+"' is not a property or extension of "+type.ToString()+".");

                        // Create as a global:
                        Field = Method.Script.MainClass.DefineField(Name, true, setType);

                        return(setType);
                    }

                    // Extension property or method.
                    // -> We only know which based on MethodOperation later calling GetOverload.
                    //    Or OutputSet/ OutputIL being called.

                    return(mInfo.ReturnType);
                }

                // It exists - create the method operation now.
                mOp          = new MethodOperation(Method, mInfo, new CompiledFragment(Name), Input0);
                v            = mOp;
                mOp.CalledOn = Of;
                return(setType);
            }
            else
            {
                // Get.

                // Get the get method:
                MethodInfo mInfo;

                if (isDynamic)
                {
                    mInfo = Class.FindMethodOverload("get_Item", new Type[] { typeof(string) });
                }
                else
                {
                    // Grab all the methods of the type:
                    MethodInfo[] allMethods = type.GetMethods();
                    mInfo = Types.GetOverload(allMethods, "get_Item", new Type[] { typeof(string) });
                }


                if (mInfo == null)
                {
                    // Try finding the extension method:
                    mInfo = FindExtensionMethod(type, "get");

                    if (mInfo == null)
                    {
                        // It doesn't exist!
                        // Error("Property '"+ToString()+"' is not a property or extension of "+type.ToString()+".");

                        // Create as a global:
                        Field = Method.Script.MainClass.DefineField(Name, true, typeof(object));

                        return(typeof(object));
                    }

                    // Extension property or method.
                    // -> We only know which based on MethodOperation later calling GetOverload.
                    //    Or OutputSet/ OutputIL being called.

                    return(mInfo.ReturnType);
                }

                // It exists - create the method operation now:
                mOp          = new MethodOperation(Method, mInfo, new CompiledFragment(Name));
                v            = mOp;
                mOp.CalledOn = Of;
                return(mInfo.ReturnType);
            }
        }