Exemplo n.º 1
0
        /// <summary>Compiles a set of parameters into an array of compiled fragments.</summary>
        /// <param name="brackets">The parent block which contains each parameter as a child.</param>
        /// <param name="parentBlock">The method the parameters are for.</param>
        /// <returns>A set of compiled fragments.</returns>
        public static CompiledFragment[] CompileParameters(CodeFragment brackets, CompiledMethod parentBlock)
        {
            if (!brackets.IsParent)
            {
                return(null);
            }

            int count = 0;

            brackets.Compile(parentBlock);
            CodeFragment child = brackets.FirstChild;

            CompiledFragment[] output = new CompiledFragment[brackets.ChildCount()];

            while (child != null)
            {
                CompiledFragment frag = (CompiledFragment)child;

                if (frag == null)
                {
                    return(null);
                }

                output[count] = frag;
                count++;
                child = child.NextChild;
            }

            return(output);
        }
Exemplo n.º 2
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));
        }
Exemplo n.º 3
0
        /// <summary>Defines a new field on this class.</summary>
        /// <param name="name">The name of the field.</param>
        /// <param name="type">The type of the value held by this field.</param>
        /// <returns>A new FieldBuilder.</returns>
        protected virtual void DefineField(string name, VariableFragment nameFragment, bool isPublic, CodeFragment defaultValue)
        {
            Type type = null;

            if (nameFragment.GivenType != null)
            {
                type = nameFragment.GivenType.FindType(Script);
                nameFragment.GivenType = null;

                if (type == null)
                {
                    nameFragment.Error(name + " has a type that was not recognised.");
                }
            }
            else if (defaultValue != null)
            {
                // Try and compile it:
                CompiledFragment frag = defaultValue.Compile(GetInit());

                // Get the output type:
                type = frag.OutputType(out frag);
            }

            if (type == null)
            {
                nameFragment.Error(name + "'s type isn't given. Should be e.g. " + name + ":String if it has no default value.");
            }

            FieldBuilder field = Builder.DefineField(name, type, isPublic?FieldAttributes.Public:FieldAttributes.Private);

            Fields[name] = field;
        }
		public override Type OutputType(out CompiledFragment newOperation){
			newOperation=this;
			if(FromType==null){
				FromType=ToBox.OutputType(out ToBox);
			}
			return typeof(object);
		}
Exemplo n.º 5
0
        /// <summary>Looks for the use of the given property within this operation. E.g. this.hello=this.hello+1;</summary>
        /// <param name="cfrag">The fragment to look in, e.g. this.Input1.</param>
        /// <param name="findingProp">The property being searched for.</param>
        /// <returns>True if it was found in there, false otherwise.</returns>
        public bool LookFor(CompiledFragment cfrag, PropertyOperation findingProp)
        {
            if (cfrag == null)
            {
                return(false);
            }

            // Try as operation:
            Operation op = cfrag as Operation;

            if (op != null)
            {
                // Specifically a property operation?
                PropertyOperation prop = op as PropertyOperation;

                if (prop != null && prop.Equals(findingProp))
                {
                    // Got a match!
                    return(true);
                }

                if (LookFor(op.Input0, findingProp))
                {
                    return(true);
                }

                if (LookFor(op.Input1, findingProp))
                {
                    return(true);
                }
            }

            return(false);
        }
		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;
		}
		protected override Operation Compile(CompiledFragment left,CompiledFragment right,CompiledMethod method){
			CompiledFragment frag=left;
			if(left==null){
				frag=right;
			}
			return new SetOperation(method,frag,new AddOperation(method,frag,new CompiledFragment(1)));
		}
        /// <summary>Looks for the use of the given variable within this operation.</summary>
        /// <param name="cfrag">The fragment to look in, e.g. this.Input1.</param>
        /// <param name="findingVar">The variable being searched for.</param>
        /// <returns>True if it was found in there, false otherwise.</returns>
        public bool LookFor(CompiledFragment cfrag, Variable findingVar)
        {
            if (cfrag == null)
            {
                return(false);
            }

            if (cfrag.Value == null && Types.IsTypeOf(cfrag, typeof(Operation)))
            {
                Operation op = (Operation)cfrag;

                if (LookFor(op.Input0, findingVar))
                {
                    return(true);
                }

                if (LookFor(op.Input1, findingVar))
                {
                    return(true);
                }
            }
            else if (cfrag.Value != null && Types.IsTypeOf(cfrag.Value, typeof(Variable)))
            {
                return(((Variable)cfrag.Value).Equals(findingVar));
            }

            return(false);
        }
 public override Type OutputType(out CompiledFragment newOperation)
 {
     newOperation = this;
     if (Size != null && Size.OutputType(out Size) != typeof(int))
     {
         Error("The size of a new array must be an integer.");
     }
     if (DefaultValues != null)
     {
         Type elementType = ArrayType.GetElementType();
         for (int i = 0; i < DefaultValues.Length; i++)
         {
             CompiledFragment p     = DefaultValues[i];
             Type             pType = p.OutputType(out p);
             if (pType == null)
             {
                 if (elementType.IsValueType)
                 {
                     Error("Null cannot be used in an array of value types.");
                 }
             }
             else if (!elementType.IsAssignableFrom(pType))
             {
                 Error("A value defined in an array is not a type that will go into the array.");
             }
             DefaultValues[i] = p;
         }
     }
     return(ArrayType);
 }
Exemplo n.º 10
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);
        }
Exemplo n.º 11
0
        public override CompiledFragment Compile(CompiledMethod method)
        {
            if (FirstChild == null)
            {
                return(null);
            }

            // Apply the current line:
            method.CurrentLine = LineNumber;

            try{
                // Compile operator chains: (d=a+b+c;)
                CompilationServices.CompileOperators(this, method);

                // Compile the now singular operator:
                CompiledFragment cFrag = FirstChild.Compile(method) as CompiledFragment;

                return(cFrag);
            }catch (CompilationException e) {
                if (e.LineNumber == -1)
                {
                    // Setup line number:
                    e.LineNumber = LineNumber;
                }

                // Rethrow:
                throw e;
            }
        }
		/// <summary>Loads the MethodToCall value if it needs to.</summary>
		private void GetMethodInfo(){
			if(MethodToCall!=null){
				return;
			}
			if(Arguments!=null){
				for(int i=0;i<Arguments.Length;i++){
					CompiledFragment p=Arguments[i];
					p.OutputType(out p);
					Arguments[i]=p;
				}
			}
			
			// Note: Most things go via a DynamicMethod here.
			// This is because CalledOn is mostly a PropertyOperation.
			// It's converted to a static singular MethodInfo with GetOverload below though.
			
			Type fragType=CalledOn.OutputType(out CalledOn);
			PropertyOperation prop=CalledOn as PropertyOperation;
				
			if(prop!=null&&prop.MethodReturnType!=null){
				MethodToCall=prop.GetOverload(Arguments);
				if(MethodToCall==null){
					Error("Method "+prop.Name+" was not found.");
				}
				CalledOn=MethodToCall.IsStatic?null:prop.Of;
			}else{
				MethodToCall=Types.GetCallable(fragType);
			}
			
			if(MethodToCall==null){
				Error("Unable to run '"+Name+"' as a method.");
			}
		}
		public PropertyOperation(CompiledMethod method,CompiledFragment of,string name):base(method){
			if(of!=null){
				of.ParentFragment=this;
			}
			Of=(of!=null)?of:new ThisOperation(method);
			Name=name;	
		}
Exemplo n.º 14
0
 /// <summary>Forces this operation to have a numerical output.</summary>
 /// <param name="input">A reference to this operation which may be replaced with a cast operation.</param>
 /// <param name="inputType">The current output type of this operation.</param>
 /// <param name="newType">The type that the output of this operation must be.</param>
 /// <returns>The new output type if successful. Throws an error otherwise.</returns>
 public Type Numerical(ref CompiledFragment input, Type inputType, Type defaultType)
 {
     if (Types.IsNumeric(inputType))
     {
         return(inputType);
     }
     return(EnforceType(ref input, inputType, defaultType));
 }
Exemplo n.º 15
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));
        }
Exemplo n.º 16
0
        public override Type OutputType(out CompiledFragment newOperation)
        {
            newOperation = this;

            // No need to call ToDelegate.OutputType(out ToDelegate) here; it's certainly already been done.

            return(DelegateType);
        }
        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));
        }
Exemplo n.º 18
0
        /// <summary>Outputs the given argument set into the given IL stream.</summary>
        /// <param name="args">The compiled set of arguments to be outputted.</param>
        /// <param name="method">The method that they are being used in.</param>
        /// <param name="into">The IL stream to output the arguments into.</param>
        /// <param name="parameters">The parameter info used to correctly match the location of the parameters.</param>
        public static void OutputParameters(CompiledFragment[] args, CompiledMethod method, NitroIL into, ParameterInfo[] parameters)
        {
            int argID    = 0;
            int argCount = 0;

            if (args != null)
            {
                argCount = args.Length;
            }
            for (int paramID = 0; paramID < parameters.Length; paramID++)
            {
                ParameterInfo param     = parameters[paramID];
                Type          paramType = param.ParameterType;

                if (IsParams(param))
                {
                    // The rest are going into an array Operation.
                    // Get the type we want to cast them all to (because paramType at this stage must be an array):
                    paramType = paramType.GetElementType();

                    CompiledFragment[] ops = new CompiledFragment[argCount - argID];
                    int Index = 0;
                    for (int i = argID; i < argCount; i++)
                    {
                        CompiledFragment frag     = args[i];
                        Type             fragType = frag.OutputType(out frag);
                        if (fragType != paramType)
                        {
                            frag = TryCast(method, frag, paramType);
                            if (frag == null)
                            {
                                args[i].Error("Unable to box or cast " + fragType + " to " + paramType + " at parameter " + argID + ". Note that you can't null a value type.");
                            }
                        }
                        ops[Index++] = frag;
                    }
                    CompiledFragment arrayOp = new ArrayOperation(method, paramType, ops);
                    arrayOp.OutputType(out arrayOp);

                    arrayOp.OutputIL(into);
                    return;
                }

                CompiledFragment argFrag = args[argID++];
                Type             argType = argFrag.OutputType(out argFrag);
                if (argType != paramType)
                {
                    CompiledFragment originalFragment = argFrag;
                    argFrag = TryCast(method, argFrag, paramType);
                    if (argFrag == null)
                    {
                        originalFragment.Error("Unable to box or cast " + argType + " to " + paramType + " at parameter " + argID + " of method call " + param.Member.Name + ". Note that you can't null a value type.");
                    }
                }

                argFrag.OutputIL(into);
            }
        }
		public IndexOperation(CompiledMethod method,CompiledFragment appliedTo,CompiledFragment[] indices):base(method){
			AppliedTo=appliedTo;
			if(indices.Length==0){
				Error("No index value given. must be e.g. array[1].");
			}else if(indices.Length>1){
				Error("Multidimension arrays are not currently supported.");
			}
			Index=indices[0];
		}
Exemplo n.º 20
0
 public override Type OutputType(out CompiledFragment newOperation)
 {
     newOperation = this;
     if (FromType == null)
     {
         FromType = ToBox.OutputType(out ToBox);
     }
     return(typeof(object));
 }
Exemplo n.º 21
0
 public PropertyOperation(CompiledMethod method, CompiledFragment of, string name) : base(method)
 {
     if (of != null)
     {
         of.ParentFragment = this;
     }
     Of   = (of != null)?of:new ThisOperation(method);
     Name = name;
 }
		/// <summary>Sets the default/ intial values for this array instance.</summary>
		/// <param name="defaultValues">The set of default values to use.</param>
		private void SetDefaults(CompiledFragment[] defaultValues){
			if(defaultValues!=null&&defaultValues.Length==0){
				defaultValues=null;
			}
			DefaultValues=defaultValues;
			if(Size==null&&defaultValues!=null){
				DirectSize=defaultValues.Length;
			}
		}
Exemplo n.º 23
0
 public override Type OutputType(out CompiledFragment nv)
 {
     nv = this;
     GetMethodInfo();
     if (Types.NoReturn(MethodToCall))
     {
         Error("'" + Name + "' does not return anything");
     }
     return(MethodToCall.ReturnType);
 }
Exemplo n.º 24
0
        /// <summary>Attempts to find the named numerical operation that the given types can perform.</summary>
        /// <param name="typeA">The type of the object on the left of the operator.</param>
        /// <param name="typeB">The type of the object on the right of the operator.</param>
        /// <param name="overloadMethod">The name of the method to look for, e.g. "Addition".</param>
        /// <param name="newOperation">The new method call if it was successfully found.</param>
        /// <returns>The new output type if successful. Throws an error otherwise.</returns>
        public Type Numerical(Type typeA, Type typeB, string overloadMethod, ref CompiledFragment newOperation)
        {
            Type type = FindOverload(overloadMethod, typeA, typeB, ref newOperation);

            if (type == null && ((type = MapNumerical(typeA, typeB)) == null))
            {
                Error("Could not find a suitable method to use with " + typeA + " and " + typeB + " using this operator.");
            }
            return(type);
        }
Exemplo n.º 25
0
        protected override Operation Compile(CompiledFragment left, CompiledFragment right, CompiledMethod method)
        {
            CompiledFragment frag = left;

            if (left == null)
            {
                frag = right;
            }
            return(new SetOperation(method, frag, new AddOperation(method, frag, new CompiledFragment(1))));
        }
		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);
		}
Exemplo n.º 27
0
        /// <summary>Attempts to make both Input0 and Input1 numerical, returning the output result of an operation if they are.
        /// Usually the returned type will be the one with higher accuracy. E.g. adding an int to a long will result in a long.</summary>
        /// <param name="typeA">The output type of Input0.</param>
        /// <param name="typeB">The output type of Input1.</param>
        /// <returns>The output result of a numerical operation with these types.</returns>
        public Type MapNumerical(Type typeA, Type typeB)
        {
            bool             isExplicit   = false;
            CompiledFragment frag0        = null;
            CompiledFragment frag1        = null;
            bool             typeANumeric = Types.IsNumeric(typeA);
            bool             typeBNumeric = Types.IsNumeric(typeB);

            if (typeANumeric && typeBNumeric)
            {
                if (typeA == typeB)
                {
                    return(typeA);
                }
                else
                {
                    // Which is higher accuracy? Map to that one and cast the other.
                    frag0 = Types.TryCast(Method, Input0, typeB, typeA, out isExplicit);
                    if (frag0 != null)
                    {
                        if (isExplicit)
                        {
                            // Other way is better:
                            frag1 = Types.TryCast(Method, Input1, typeA, typeB);
                            if (frag1 != null)
                            {
                                Input1 = frag1;
                                return(typeA);
                            }
                            else
                            {
                                Input0 = frag0;
                                return(typeB);
                            }
                        }
                        else
                        {
                            Input0 = frag0;
                            return(typeB);
                        }
                    }
                    else
                    {
                        frag1 = Types.TryCast(Method, Input1, typeA, typeB);
                        if (frag1 != null)
                        {
                            Input1 = frag1;
                            return(typeA);
                        }
                    }
                }
            }
            return(null);
        }
		public override Type OutputType(out CompiledFragment v){
			v=this;
			if(Parameters!=null){
				for(int i=0;i<Parameters.Length;i++){
					CompiledFragment p=Parameters[i];
					p.OutputType(out p);
					Parameters[i]=p;
				}
			}
			return ObjectType;
		}
        public override CompiledFragment Compile(CompiledMethod method)
        {
            CompiledFragment cfrag = MethodName.Compile(method);

            if (!Types.IsTypeOf(cfrag.ActiveValue(), typeof(ISettable)))
            {
                Error("Unable to compile a method call - didn't recognise an invokable object.");
            }
            CompiledFragment[] parameters = CompilationServices.CompileParameters(Brackets, method);
            return(new MethodOperation(method, cfrag, parameters));
        }
Exemplo n.º 30
0
		public override Type OutputType(out CompiledFragment v){
			v=this;
			
			for(int i=0;i<Conditions.Length;i++){
				CompiledFragment cond=Conditions[i];
				cond.OutputType(out cond);
				Conditions[i]=cond;
			}
			
			return null;
		}
		/// <summary>Returns the type that this fragment produces when it's executed.
		/// For example, int+int will output another int.</summary>
		/// <param name="v">In some cases, checking the output type will generate a new fragment. This value is the new fragment
		/// and it must always replace the original fragment that OutputType was called on.</param>
		/// <returns>The type that this fragment returns.</returns>
		public virtual Type OutputType(out CompiledFragment v){
			v=this;
			if(Value==null){
				return null;
			}
			Type type=Value.GetType();
			if(Types.IsTypeOf(Value,typeof(Variable))){
				type=((Variable)Value).Type();
			}
			return type;
		}
		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("Inequality",typeA,typeB,ref equalityOverload);
			if(equalityOverload!=null){
				v=equalityOverload;
			}
			return typeof(bool);
		}
Exemplo n.º 33
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);
        }
Exemplo n.º 34
0
		/// <summary>Gets the constructor overload for the given type and using the given arguments.</summary>
		/// <param name="type">The type to get the constructor from.</param>
		/// <param name="args">The set of arguments being passed to the constructor. Used to find the right overload.</param>
		/// <returns>A ConstructorInfo if a matching constructor overload was found; null otherwise.</returns>
		public static ConstructorInfo GetConstructor(Type type,CompiledFragment[] args){
			ConstructorInfo[] constructors=type.GetConstructors();
			if(constructors==null){
				return null;
			}
			Type[] paramSet=GetTypes(args);
			ConstructorInfo constructor=GetConstructor(constructors,paramSet,false);
			if(constructor!=null){
				return constructor;
			}
			return GetConstructor(constructors,paramSet,true);
		}
Exemplo n.º 35
0
 public IndexOperation(CompiledMethod method, CompiledFragment appliedTo, CompiledFragment[] indices) : base(method)
 {
     AppliedTo = appliedTo;
     if (indices.Length == 0)
     {
         Error("No index value given. must be e.g. array[1].");
     }
     else if (indices.Length > 1)
     {
         Error("Multidimension arrays are not currently supported.");
     }
     Index = indices[0];
 }
Exemplo n.º 36
0
        public override Type OutputType(out CompiledFragment v)
        {
            v = this;

            for (int i = 0; i < Conditions.Length; i++)
            {
                CompiledFragment cond = Conditions[i];
                cond.OutputType(out cond);
                Conditions[i] = cond;
            }

            return(null);
        }
		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);
		}
Exemplo n.º 38
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));
        }
Exemplo n.º 39
0
		/// <summary>Forces this operation to be a particular type by creating a cast.</summary>
		/// <param name="input">A reference to this operation which may be replaced with a cast operation.</param>
		/// <param name="inputType">The current output type of this operation.</param>
		/// <param name="newType">The type that the output of this operation must be.</param>
		/// <returns>The new output type if successful. Throws an error otherwise.</returns>
		public Type EnforceType(ref CompiledFragment input,Type inputType,Type newType){
			// If inputType inherits newType, it's ok anyway:
			if(newType.IsAssignableFrom(inputType)){
				return inputType;
			}
			bool isExplicit;
			CompiledFragment frag=Types.TryCast(Method,input,newType,out isExplicit);
			if(frag==null){
				Error("Unable to enforce type '"+newType+"' on something that is a '"+inputType+"'");
			}else{
				input=frag;
			}
			return newType;
		}
Exemplo n.º 40
0
 public override Type OutputType(out CompiledFragment v)
 {
     v = this;
     if (Parameters != null)
     {
         for (int i = 0; i < Parameters.Length; i++)
         {
             CompiledFragment p = Parameters[i];
             p.OutputType(out p);
             Parameters[i] = p;
         }
     }
     return(ObjectType);
 }
Exemplo n.º 41
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);
        }
Exemplo n.º 42
0
        /// <summary>Returns the type that this fragment produces when it's executed.
        /// For example, int+int will output another int.</summary>
        /// <param name="v">In some cases, checking the output type will generate a new fragment. This value is the new fragment
        /// and it must always replace the original fragment that OutputType was called on.</param>
        /// <returns>The type that this fragment returns.</returns>
        public virtual Type OutputType(out CompiledFragment v)
        {
            v = this;
            if (Value == null)
            {
                return(null);
            }
            Type type = Value.GetType();

            if (Types.IsTypeOf(Value, typeof(Variable)))
            {
                type = ((Variable)Value).Type();
            }
            return(type);
        }
Exemplo n.º 43
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;
			
			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);
		}
Exemplo n.º 45
0
		/// <summary>Converts the the given fragments into a compiled operation by first checking the fragments are ok for this operator.</summary>
		/// <param name="left">The fragment to the left of the operator.</param>
		/// <param name="right">The fragment to the right of the operation.</param>
		/// <param name="method">The method the operation will be compiled into.</param>
		public Operation ToOperation(CompiledFragment left,CompiledFragment right,CompiledMethod method){
			bool leftNull=(left==null);
			bool rightNull=(right==null);
			if(leftNull&&rightNull){
				return null;
			}
			if(leftNull&&!rightNull&&!RightOnly){
				return null;
			}
			if(!leftNull&&rightNull&&!LeftOnly){
				return null;
			}
			if(!leftNull&&!rightNull&&!LeftAndRight){
				return null;
			}
			return Compile(left,right,method);
		}
Exemplo n.º 46
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));
        }
Exemplo n.º 47
0
        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));
        }
		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;
		}
Exemplo n.º 49
0
		/// <summary>Looks for the use of the given variable within this operation.</summary>
		/// <param name="cfrag">The fragment to look in, e.g. this.Input1.</param>
		/// <param name="findingVar">The variable being searched for.</param>
		/// <returns>True if it was found in there, false otherwise.</returns>
		public bool LookFor(CompiledFragment cfrag,Variable findingVar){
			if(cfrag==null){
				return false;
			}
			
			if(cfrag.Value==null&&Types.IsTypeOf(cfrag,typeof(Operation))){
				Operation op=(Operation)cfrag;
				
				if(LookFor(op.Input0,findingVar)){
					return true;
				}
				
				if(LookFor(op.Input1,findingVar)){
					return true;
				}
				
			}else if(cfrag.Value!=null&&Types.IsTypeOf(cfrag.Value,typeof(Variable))){
				return ((Variable)cfrag.Value).Equals(findingVar);
			}
			
			return false;
		}
		public override Type OutputType(out CompiledFragment newOperation){
			newOperation=this;
			if(Size!=null&&Size.OutputType(out Size)!=typeof(int)){
				Error("The size of a new array must be an integer.");
			}
			if(DefaultValues!=null){
				Type elementType=ArrayType.GetElementType();
				for(int i=0;i<DefaultValues.Length;i++){
					CompiledFragment p=DefaultValues[i];
					Type pType=p.OutputType(out p);
					if(pType==null){
						if(elementType.IsValueType){
							Error("Null cannot be used in an array of value types.");
						}
					}else if(!elementType.IsAssignableFrom(pType)){
						Error("A value defined in an array is not a type that will go into the array.");
					}
					DefaultValues[i]=p;
				}
			}
			return ArrayType;
		}
		/// <summary>Gets a particular method (it may be overloaded) from this class.</summary>
		/// <param name="name">The name of the method.</param>
		/// <param name=arguments">The set of arguments being used in calling this method.</param>
		/// <returns>The MethodInfo for the method if found; null otherwise.</returns>
		public MethodInfo FindMethodOverload(string name,CompiledFragment[] arguments){
			MethodOverloads set=FindMethodSet(name);
			if(set==null){
				return Types.GetOverload(Builder.BaseType.GetMethods(),name,Types.GetTypes(arguments),true);
			}
			return set.GetOverload(Types.GetTypes(arguments));
		}
Exemplo n.º 52
0
		/// <summary>Attempts to generate a cast operation for the given fragment to the given type.</summary>
		/// <param name="method">The method this operation is occuring in.</param>
		/// <param name="frag">The fragment containing the object to cast.</param>
		/// <param name="to">The type to cast it to if possible.</param>
		/// <param name="isExplicit">True if the casting is explicit. False if it is implicit.</param>
		/// <returns>A cast operation if it is possible; throws an error otherwise.</returns>
		public static CompiledFragment TryCast(CompiledMethod method,CompiledFragment frag,Type to,out bool isExplicit){
			isExplicit=false;
			
			Type from=frag.OutputType(out frag);
			
			if(from==null){
				if(to.IsValueType){
					return null;
				}else{
					return frag;
				}
			}
			
			if(to==typeof(object) && from.IsValueType){
				return new BoxOperation(method,frag);
			}
			
			if(from==to||to.IsAssignableFrom(from)){
				return frag;
			}
			
			// IsAssignableFrom is true if TO inherits FROM:
			if(from.IsAssignableFrom(to)){
				return new CastOperation(method,frag,to);
			}
			
			MethodInfo cast=IsCastableTo(from,to,out isExplicit);
			
			if(cast==null){
				return null;
			}else{
				return new MethodOperation(method,cast,frag);
			}
		}
Exemplo n.º 53
0
		/// <summary>Converts a set of compiled fragments into a set of their outputted types.
		/// E.g. if a certain fragment is "a string", one of the types will be a string.</summary>
		/// <param name="frags">The set of fragments to convert.</param>
		/// <returns>A set of types. Each one is the output type of each fragment.</returns>
		public static Type[] GetTypes(CompiledFragment[] frags){
			if(frags==null){
				return new Type[0];
			}
			Type[] result=new Type[frags.Length];
			for(int i=frags.Length-1;i>=0;i--){
				result[i]=frags[i].OutputType();
			}
			return result;
		}
Exemplo n.º 54
0
		public SetOperation(CompiledMethod method,CompiledFragment input0,CompiledFragment input1):base(method){
			Input0=input0;
			Input1=input1;
		}
Exemplo n.º 55
0
		public override Type OutputType(out CompiledFragment v){
			v=this;
			Output=true;
			return Input0.OutputType(out Input0);
		}
		protected override Operation Compile(CompiledFragment left,CompiledFragment right,CompiledMethod method){
			return new SetOperation(method,left,new SubtractOperation(method,left,right));
		}
Exemplo n.º 57
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;
		}
Exemplo n.º 58
0
		/// <summary>Attempts to generate a cast operation for the given fragment to the given type.</summary>
		/// <param name="method">The method this operation is occuring in.</param>
		/// <param name="frag">The fragment containing the object to cast.</param>
		/// <param name="to">The type to cast it to if possible.</param>
		/// <returns>A cast operation if it is possible; throws an error otherwise.</returns>
		public static CompiledFragment TryCast(CompiledMethod method,CompiledFragment frag,Type to){
			bool isExplicit;
			return TryCast(method,frag,to,out isExplicit);
		}
		protected override Operation Compile(CompiledFragment left,CompiledFragment right,CompiledMethod method){
			return new MultiplyOperation(method,left,right);
		}
		protected override Operation Compile(CompiledFragment left,CompiledFragment right,CompiledMethod method){
			return new GreaterThanOrEqualOperation(method,left,right);
		}