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;
		}
Beispiel #2
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);
        }
Beispiel #3
0
        /// <summary>Looks for an overloaded numerical operator by the given name (e.g. "Addition").
        /// The name will then have op_ appended to the start of it (as used internally by .NET). If found,
        /// the output type of the operation is returned.</summary>
        /// <param name="methodName">The name of the method to look for.</param>
        /// <param name="typeA">The type of the input on the left of the operator (Input0).</param>
        /// <param name="typeB">The type of the input on the right of the operator (Input1).</param>
        /// <param name="newOperation">A method call operation if it was found which is already correctly linked to Input0 and Input1.</param>
        /// <returns>The output type of the method if found.</returns>
        public Type FindOverload(string methodName, Type typeA, Type typeB, ref CompiledFragment newOperation)
        {
            if (typeA == null || typeB == null)
            {
                return(null);
            }
            methodName = "op_" + methodName;
            // Find an overloaded operator (always static):
            MethodInfo mI = typeA.GetMethod(methodName, new Type[] { typeA, typeB });

            if (mI == null)
            {
                mI = typeB.GetMethod(methodName, new Type[] { typeB, typeA });
                if (mI == null)
                {
                    return(null);
                }
                newOperation = new MethodOperation(Method, mI, Input1, Input0);
            }
            else
            {
                newOperation = new MethodOperation(Method, mI, Input0, Input1);
            }
            return(newOperation.OutputType(out newOperation));
        }
Beispiel #4
0
        /// <summary>Gets the ToString method of the given type, being called on the given fragment.</summary>
        /// <param name="method">The function this operation is occuring in.</param>
        /// <param name="frag">The object that the ToString method is being called on.</param>
        /// <param name="type">The type that fragment contains and the one that the ToString operation must be found on.</param>
        /// <returns>A methodOperation representing the ToString call. Throws an error if frag is null.</returns>
        public static MethodOperation ToStringMethod(CompiledMethod method, CompiledFragment frag, Type type)
        {
            if (type == null)
            {
                frag.Error("Unable to convert null to a string.");
            }
            MethodOperation mo = new MethodOperation(method, type.GetMethod("ToString", new Type[0]));

            mo.CalledOn         = frag;
            frag.ParentFragment = mo;
            return(mo);
        }
Beispiel #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);
        }
		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;
		}
		/// <summary>Gets the ToString method of the given type, being called on the given fragment.</summary>
		/// <param name="method">The function this operation is occuring in.</param>
		/// <param name="frag">The object that the ToString method is being called on.</param>
		/// <param name="type">The type that fragment contains and the one that the ToString operation must be found on.</param>
		/// <returns>A methodOperation representing the ToString call. Throws an error if frag is null.</returns>
		public static MethodOperation ToStringMethod(CompiledMethod method,CompiledFragment frag,Type type){
			if(type==null){
				frag.Error("Unable to convert null to a string.");
			}
			MethodOperation mo=new MethodOperation(method,type.GetMethod("ToString",new Type[0]));
			mo.CalledOn=frag;
			frag.ParentFragment=mo;
			return mo;
		}
        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);
            }
        }
		public override Type OutputType(out CompiledFragment v){
			v=this;
			
			Type type=OfType();
			
			// Map to functionality:
			CompiledClass Class=null;
			bool isDynamic=Types.IsDynamic(type);
			
			if(!isDynamic){
				if(!Method.Script.AllowUse(type)){
					Error("Unable to access properties of type "+type+" as it has not been made accessible.");
				}
			}else{
				Class=Method.Script.GetClass(type);
			}
			
			if(isDynamic){
				Field=Class.GetField(Name);
			}else{
				Field=type.GetField(Name,BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
			}
			
			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,BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
			}
			
			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){
					// It doesn't exist!
					Error("Property '"+ToString()+"' is not a property of "+type.ToString()+".");
				}
				
				// 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){
					// It doesn't exist!
					Error("'"+ToString()+"' is not a property of "+type.ToString()+".");
				}
				
				// It exists - create the method operation now:
				mOp=new MethodOperation(Method,mInfo,new CompiledFragment(Name));
				v=mOp;
				mOp.CalledOn=Of;
				return mInfo.ReturnType;
			}
			
		}
		/// <summary>Looks for an overloaded numerical operator by the given name (e.g. "Addition").
		/// The name will then have op_ appended to the start of it (as used internally by .NET). If found,
		/// the output type of the operation is returned.</summary>
		/// <param name="methodName">The name of the method to look for.</param>
		/// <param name="typeA">The type of the input on the left of the operator (Input0).</param>
		/// <param name="typeB">The type of the input on the right of the operator (Input1).</param>
		/// <param name="newOperation">A method call operation if it was found which is already correctly linked to Input0 and Input1.</param>
		/// <returns>The output type of the method if found.</returns>
		public Type FindOverload(string methodName,Type typeA,Type typeB,ref CompiledFragment newOperation){
			if(typeA==null||typeB==null){
				return null;
			}
			methodName="op_"+methodName;
			// Find an overloaded operator (always static):
			MethodInfo mI=typeA.GetMethod(methodName,new Type[]{typeA,typeB});
			if(mI==null){
				mI=typeB.GetMethod(methodName,new Type[]{typeB,typeA});
				if(mI==null){
					return null;
				}
				newOperation=new MethodOperation(Method,mI,Input1,Input0);
			}else{
				newOperation=new MethodOperation(Method,mI,Input0,Input1);
			}
			return newOperation.OutputType(out newOperation);
		}