public override void OutputIL(NitroIL into){
			if(Size!=null){
				Size.OutputIL(into);
			}else{
				into.Emit(OpCodes.Ldc_I4,DirectSize);
			}
			Type ElementType=ArrayType.GetElementType();
			into.Emit(OpCodes.Newarr,ElementType);
			
			
			if(DefaultValues==null || DefaultValues.Length==0){
				return;
			}
			LocalBuilder temp=into.DeclareLocal(ArrayType);
			into.Emit(OpCodes.Stloc,temp);
			// Emit a series of SET's into the array.
			for(int i=0;i<DefaultValues.Length;i++){
				into.Emit(OpCodes.Ldloc,temp);
				into.Emit(OpCodes.Ldc_I4,i);
				DefaultValues[i].OutputIL(into);
				if(ElementType.IsValueType){
					into.Emit(OpCodes.Stelem,ElementType);
				}else{
					into.Emit(OpCodes.Stelem_Ref);
				}
			}
			into.Emit(OpCodes.Ldloc,temp);
		}
		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);
		}
		public void OutputTarget(NitroIL into){
			if(ElementType==null){
				Error("Unused index operation");
			}
			AppliedTo.OutputIL(into);
			Index.OutputIL(into);
		}
		public override void OutputIL(NitroIL into){
			// Emit any set operations before the block itself (e.g. i=0):
			for(int i=0;i<Parameters.Length;i++){
				CompiledFragment parameter=Parameters[i];
				if(Types.IsTypeOf(parameter,typeof(SetOperation))){
					// Make sure it isn't a self set - e.g. i++, i=i+10.
					SetOperation set=(SetOperation)parameter;
					if(!set.SelfReferencing()){
						set.OutputIL(into);
						Parameters[i]=null;
					}else{
						set.Output=false;
					}
				}else{
					// Compute it's output type:
					// Note that this must NOT be done for the SET ops as it makes them think
					// We want to use their output, which isn't true!
					parameter.OutputType(out parameter);
					Parameters[i]=parameter;
				}
			}
			Label continuePoint=into.DefineLabel();
			Label start=into.DefineLabel();
			Label end=into.DefineLabel();
			Method.AddBreakPoint(new BreakPoint(continuePoint,end));
			into.MarkLabel(start);
			
			// Logical operations (e.g. i<10):
			for(int i=0;i<Parameters.Length;i++){
				CompiledFragment parameter=Parameters[i];
				if(parameter==null){
					continue;
				}
				if(Types.IsTypeOf(parameter,typeof(SetOperation))){
					// Just checking for a logical operation will make an incremental (i++) operation think
					// It's being daisy chained. That's because its output type is checked for boolean in IsLogical.
					continue;
				}
				if(parameter.IsLogical()){
					parameter.OutputIL(into);
					into.Emit(OpCodes.Brfalse,end);
					Parameters[i]=null;
				}
			}
			
			Body.CompileBody(Method);
			into.MarkLabel(continuePoint);
			
			// Increment/decrement ops (e.g. i++):
			for(int i=0;i<Parameters.Length;i++){
				CompiledFragment cfrag=Parameters[i];
				if(cfrag==null){
					continue;
				}
				cfrag.OutputIL(into);
			}
			into.Emit(OpCodes.Br,start);
			into.MarkLabel(end);
			Method.PopBreakPoint();
		}
		public override void OutputIL(NitroIL into){
			if(FromType==null){
				FromType=ToBox.OutputType(out ToBox);
			}
			ToBox.OutputIL(into);
			into.Emit(OpCodes.Box,FromType);
		}
		public override void OutputSet(NitroIL into,Type setting){
			
			if(VariableType==null){
				
				VariableType=setting;
				
			}else if(setting!=VariableType){
				
				// Overwriting the variable with something of a different type. Create a new one.
				VariableType=setting;
				Builder=null;
				
			}
			
			if(VariableType==null){
				VariableType=typeof(object);
			}
			
			if(Builder==null){
				
				Builder=into.DeclareLocal(VariableType);
				
			}
			
			into.Emit(OpCodes.Stloc,Builder);
		}
		/// <summary>Outputs this variable into IL.</summary>
		/// <param name="into">The IL stream to output it into.</param>
		/// <param name="accessingMember">True if we are accessing a field/method of this variable.</param>
		public override void OutputIL(NitroIL into,bool accessingMember){
			if(accessingMember&&ParameterType.IsValueType){
				// Must load by reference. It's a value type and we want some property of it.
				into.Emit(OpCodes.Ldarga,Builder.Position);
			}else{
				into.Emit(OpCodes.Ldarg,Builder.Position);
			}
		}
		public override void OutputIL(NitroIL into){
			Input0.OutputIL(into);
			Input1.OutputIL(into);
			into.Emit(OpCodes.Ceq);
			// Flip by comparing with 0:
			into.Emit(OpCodes.Ldc_I4_0);
			into.Emit(OpCodes.Ceq);
		}
		public override void OutputIL(NitroIL into){
			if(Input0==null){
				Input1.OutputIL(into);
				into.Emit(OpCodes.Neg);
			}else{
				Input0.OutputIL(into);
				Input1.OutputIL(into);
				into.Emit(OpCodes.Sub);
			}
		}
        /// <summary>Adds a break into the given IL stream, breaking out of the given number of loops.</summary>
        /// <param name="into">The IL stream to emit the break into.</param>
        /// <param name="depth">The amount of loops to break from.
        /// Can be affected with e.g. break 2; for getting out of a loop in a loop.</param>
        /// <returns>True if it could locate the loop and added the command.</returns>
        public bool Break(NitroIL into, int depth)
        {
            if (depth > BreakPoints.Count)
            {
                return(false);
            }
            BreakPoint point = BreakPoints[BreakPoints.Count - depth];

            point.Break(into);
            return(true);
        }
예제 #11
0
 public void OutputSet(NitroIL into, Type setting)
 {
     if (ElementType.IsValueType)
     {
         into.Emit(OpCodes.Stelem, ElementType);
     }
     else
     {
         into.Emit(OpCodes.Stelem_Ref);
     }
 }
		public override void OutputIL(NitroIL into){
			if(Types.IsDynamic(Constructor)){
				if(Parameters!=null){
					for(int i=0;i<Parameters.Length;i++){
						Parameters[i].OutputIL(into);
					}
				}
			}else{
				Types.OutputParameters(Parameters,Method,into,Constructor.GetParameters());
			}
			into.Emit(OpCodes.Newobj,Constructor);
		}
예제 #13
0
 /// <summary>Outputs this variable into IL.</summary>
 /// <param name="into">The IL stream to output it into.</param>
 /// <param name="accessingMember">True if we are accessing a field/method of this variable.</param>
 public override void OutputIL(NitroIL into, bool accessingMember)
 {
     if (accessingMember && ParameterType.IsValueType)
     {
         // Must load by reference. It's a value type and we want some property of it.
         into.Emit(OpCodes.Ldarga, Builder.Position);
     }
     else
     {
         into.Emit(OpCodes.Ldarg, Builder.Position);
     }
 }
 public override void OutputIL(NitroIL into)
 {
     OutputTarget(into);
     if (ElementType.IsValueType)
     {
         into.Emit(OpCodes.Ldelem, ElementType);
     }
     else
     {
         into.Emit(OpCodes.Ldelem_Ref);
     }
 }
예제 #15
0
        public override void OutputIL(NitroIL into)
        {
            GetMethodInfo();

            // First, the instance this method is on:
            bool useVirtual = (CalledOn != null);

            if (useVirtual)
            {
                Type type = CalledOn.OutputType(out CalledOn);
                CalledOn.OutputIL(into);
                if (type.IsValueType)
                {
                    if (!CalledOn.EmitsAddress)
                    {
                        // Value must be set into a temporary local and reloaded (but as an address).
                        // Future optimization may be to pool these.
                        LocalBuilder builder = into.DeclareLocal(type);
                        into.Emit(OpCodes.Stloc, builder);
                        into.Emit(OpCodes.Ldloca, builder);
                    }

                    useVirtual = false;
                }
            }

            // Next, its arguments:
            if (Types.IsDynamic(MethodToCall))
            {
                if (Arguments != null)
                {
                    for (int i = 0; i < Arguments.Length; i++)
                    {
                        Arguments[i].OutputIL(into);
                    }
                }
            }
            else
            {
                Types.OutputParameters(Arguments, Method, into, MethodToCall.GetParameters());
            }

            // And emit the call:
            if (useVirtual)
            {
                into.Emit(OpCodes.Callvirt, MethodToCall);
            }
            else
            {
                into.Emit(OpCodes.Call, MethodToCall);
            }
        }
예제 #16
0
        public override void OutputIL(NitroIL into)
        {
            // Two args for the create call:
            // - Note that the first is the scope/ variable set
            into.Emit(OpCodes.Ldnull);
            into.Emit(OpCodes.Ldftn, ToDelegate);

            // Get the constructor:
            ConstructorInfo ctr = DelegateType.GetConstructors()[0];

            // Create the delegate:
            into.Emit(OpCodes.Newobj, ctr);
        }
예제 #17
0
        public bool OutputTarget(NitroIL into)
        {
            if (ElementType == null)
            {
                // Error("Unused index operation");
                return(false);
            }

            AppliedTo.OutputIL(into);
            Index.OutputIL(into);

            return(true);
        }
예제 #18
0
        public void OutputSet(NitroIL into, Type setting)
        {
            if (Field != null)
            {
                if (IsStatic)
                {
                    into.Emit(OpCodes.Stsfld, Field);
                }
                else
                {
                    into.Emit(OpCodes.Stfld, Field);
                }
            }
            else if (Property != null)
            {
                bool       useVirtual = !IsStatic && !Property.PropertyType.IsValueType;
                MethodInfo setMethod  = Property.GetSetMethod();

                if (setMethod == null)
                {
                    Error(Name + " is a readonly property.");
                }

                into.Emit(useVirtual?OpCodes.Callvirt:OpCodes.Call, setMethod);
            }
            else if (Methods != null)
            {
                // Extension property (hopefully!). Look for a set method lookalike.

                // Get types:
                Type[] argTypes = new Type[] { OfType(), setting };

                // Get the overload:
                MethodInfo setMethod = Types.GetOverload(Methods, argTypes);

                if (setMethod == null)
                {
                    Error(Name + " is a 'readonly' extension property.");
                }

                // Call the set method:
                into.Emit(OpCodes.Call, setMethod);
            }
            else
            {
                Error(Name + " is a function! Unable to set it's value.");
            }
        }
		/// <summary>Outputs this variable into IL.</summary>
		/// <param name="into">The IL stream to output it into.</param>
		/// <param name="accessingMember">True if we are accessing a field/method of this variable.</param>
		public override void OutputIL(NitroIL into,bool accessingMember){
			
			if(Builder==null){
				
				// This variable hasn't been written to yet, so this is always like reading a null or zero.
				return;
				
			}
			
			if(accessingMember&&VariableType.IsValueType){
				// Must load by reference. It's a value type and we want some property of it.
				into.Emit(OpCodes.Ldloca,Builder);
			}else{
				into.Emit(OpCodes.Ldloc,Builder);
			}
			
		}
        public void OutputTarget(NitroIL into)
        {
            if (IsStatic && (Field != null || Property != null))
            {
                return;
            }

            if (Of == null || (Field == null && Property == null && MethodReturnType == null))
            {
                Error("Unused or invalid property.");
            }

            if (MethodReturnType == null)
            {
                Of.OutputIL(into);
            }
        }
        public override void OutputIL(NitroIL into)
        {
            // Get the input type:
            Type casting = ToCast.OutputType(out ToCast);

            // Special case - if the thing being casted is an object and
            // the thing we're casting to is a value type, we must unbox instead.
            if (ToType.IsValueType && casting == typeof(object))
            {
                ToCast.OutputIL(into);
                into.Emit(OpCodes.Unbox_Any, ToType);
                return;
            }

            ToCast.OutputIL(into);
            into.Emit(OpCodes.Castclass, ToType);
        }
예제 #22
0
 public override void OutputIL(NitroIL into)
 {
     if (Types.IsDynamic(Constructor))
     {
         if (Parameters != null)
         {
             for (int i = 0; i < Parameters.Length; i++)
             {
                 Parameters[i].OutputIL(into);
             }
         }
     }
     else
     {
         Types.OutputParameters(Parameters, Method, into, Constructor.GetParameters());
     }
     into.Emit(OpCodes.Newobj, Constructor);
 }
예제 #23
0
        /// <summary>Outputs this variable into IL.</summary>
        /// <param name="into">The IL stream to output it into.</param>
        /// <param name="accessingMember">True if we are accessing a field/method of this variable.</param>
        public override void OutputIL(NitroIL into, bool accessingMember)
        {
            if (Builder == null)
            {
                // This variable hasn't been written to yet, so this is always like reading a null or zero.
                return;
            }

            if (accessingMember && VariableType.IsValueType)
            {
                // Must load by reference. It's a value type and we want some property of it.
                into.Emit(OpCodes.Ldloca, Builder);
            }
            else
            {
                into.Emit(OpCodes.Ldloc, Builder);
            }
        }
		public override void OutputIL(NitroIL into){
			
			// Get Input0 onto the stack:
			if(Input0==null){
				into.Emit(OpCodes.Ldnull,typeof(object));
			}else{
				Input0.OutputIL(into);
			}
			// Run GetObjectType() method:
			#if NETFX_CORE
			MethodInfo getType=typeof(TypeofOperation).GetTypeInfo().GetMethod("GetObjectType");
			#else
			MethodInfo getType=typeof(TypeofOperation).GetMethod("GetObjectType");
			#endif
			
			// Call it:
			into.Emit(OpCodes.Call,getType);
			
		}
예제 #25
0
        public override void OutputIL(NitroIL into)
        {
            // Get Input0 onto the stack:
            if (Input0 == null)
            {
                into.Emit(OpCodes.Ldnull, typeof(object));
            }
            else
            {
                Input0.OutputIL(into);
            }
            // Run GetObjectType() method:
                        #if NETFX_CORE
            MethodInfo getType = typeof(TypeofOperation).GetTypeInfo().GetMethod("GetObjectType");
                        #else
            MethodInfo getType = typeof(TypeofOperation).GetMethod("GetObjectType");
                        #endif

            // Call it:
            into.Emit(OpCodes.Call, getType);
        }
예제 #26
0
		public override void OutputIL(NitroIL into){
			// Ensure our conditions output type is computed:
			OutputType();
			
			Label End=into.DefineLabel();
			Label Else=into.DefineLabel();
			Conditions[0].OutputIL(into);
			into.Emit(OpCodes.Brfalse,Else);
			AllRoutesReturn=IfTrue.CompileBody(Method);
			into.Emit(OpCodes.Br,End);
			into.MarkLabel(Else);
			
			if(IfFalse!=null){
				bool returns=IfFalse.CompileBody(Method);
				AllRoutesReturn=(AllRoutesReturn&&returns);
			}else{
				AllRoutesReturn=false;
			}
			
			into.MarkLabel(End);
		}
        public override void OutputIL(NitroIL into)
        {
            if (Size != null)
            {
                Size.OutputIL(into);
            }
            else
            {
                into.Emit(OpCodes.Ldc_I4, DirectSize);
            }
            Type ElementType = ArrayType.GetElementType();

            into.Emit(OpCodes.Newarr, ElementType);


            if (DefaultValues == null || DefaultValues.Length == 0)
            {
                return;
            }
            LocalBuilder temp = into.DeclareLocal(ArrayType);

            into.Emit(OpCodes.Stloc, temp);
            // Emit a series of SET's into the array.
            for (int i = 0; i < DefaultValues.Length; i++)
            {
                into.Emit(OpCodes.Ldloc, temp);
                into.Emit(OpCodes.Ldc_I4, i);
                DefaultValues[i].OutputIL(into);
                if (ElementType.IsValueType)
                {
                    into.Emit(OpCodes.Stelem, ElementType);
                }
                else
                {
                    into.Emit(OpCodes.Stelem_Ref);
                }
            }
            into.Emit(OpCodes.Ldloc, temp);
        }
예제 #28
0
        public bool OutputTarget(NitroIL into)
        {
            if (IsStatic && (Field != null || Property != null) && Methods == null)
            {
                return(true);
            }

            if (Of == null || (Field == null && Property == null && MethodReturnType == null && Methods == null))
            {
                // Error("Unused or invalid property.");
                // Essentially declaring a property but we can just ignore this.
                // I.e. something like "hello;" which is valid in JS.
                return(false);
            }

            if (MethodReturnType == null)
            {
                Of.OutputIL(into);
            }

            return(true);
        }
예제 #29
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);
        }
		/// <summary>Emits the Value held by this compiled fragment if possible.</summary>
		/// <param name="type">The type of the value (or one of the base types of the value).</param>
		/// <param name="into">The IL stream to output the IL into.</param>
		public void EmitValue(Type type,NitroIL into){
			if(type==typeof(string)){
				into.Emit(OpCodes.Ldstr,(string)Value);
			}else if(type==typeof(int)){
				into.Emit(OpCodes.Ldc_I4,(int)Value);
			}else if(type==typeof(uint)){
				into.Emit(OpCodes.Ldc_I4,(uint)Value);
			}else if(type==typeof(long)){
				into.Emit(OpCodes.Ldc_I8,(long)Value);
			}else if(type==typeof(ulong)){
				into.Emit(OpCodes.Ldc_I8,(ulong)Value);
			}else if(type==typeof(float)){
				into.Emit(OpCodes.Ldc_R4,(float)Value);
			}else if(type==typeof(double)){
				into.Emit(OpCodes.Ldc_R8,(double)Value);
			}else if(type==typeof(OpCode)){
				into.Emit((OpCode)Value);
			}else if(type==typeof(bool)){
				into.Emit(OpCodes.Ldc_I4,((bool)Value)?1:0);
			}else if(type==typeof(short)){
				into.Emit(OpCodes.Ldc_I4,(short)Value);
			}else if(type==typeof(ushort)){
				into.Emit(OpCodes.Ldc_I4,(ushort)Value);
			}else if(type==typeof(byte)){
				into.Emit(OpCodes.Ldc_I4,(byte)Value);
			}else if(type==typeof(sbyte)){
				into.Emit(OpCodes.Ldc_I4,(sbyte)Value);
			}else if(Types.IsSubclass(Value,typeof(Variable))){
				// Is parent a type of methodoperation or propertyoperation?
				// If it is, IsMemberAccessor is true.
				((Variable)Value).OutputIL(into, (ParentFragment!=null && ParentFragment.IsMemberAccessor()) );
			}else{
				Error("Didn't know how to output value "+Value+" (type is "+type+")");
			}
		}
예제 #31
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);
			}
		}
		/// <summary>Generates the IL of this operation into the given stream.</summary>
		/// <param name="into">The IL stream to output the IL into</param>
		public virtual void OutputIL(NitroIL into){
			if(Value==null){
				into.Emit(OpCodes.Ldnull);
				return;
			}
			// Output the variable that represents the result. Note: used by operations which are variables too.
			EmitValue(Value.GetType(),into);
		}
예제 #33
0
 /// <summary>Emits a break - a jump to the end of the loop.</summary>
 /// <param name="into">The IL code to emit the instruction into.</param>
 public void Break(NitroIL into)
 {
     into.Emit(OpCodes.Br, End);
 }
예제 #34
0
		public override void OutputSet(NitroIL into,Type setting){
			into.Emit(OpCodes.Starg,Builder.Position);
		}
		public override void OutputIL(NitroIL into){
			GetMethodInfo();
			// First, the instance this method is on:
			bool useVirtual=(CalledOn!=null);
			
			if(useVirtual){
				Type type=CalledOn.OutputType(out CalledOn);
				CalledOn.OutputIL(into);
				if(type.IsValueType){
					
					if(!CalledOn.EmitsAddress){
						// Value must be set into a temporary local and reloaded (but as an address).
						// Future optimization may be to pool these.
						LocalBuilder builder=into.DeclareLocal(type);
						into.Emit(OpCodes.Stloc,builder);
						into.Emit(OpCodes.Ldloca,builder);
					}
					
					useVirtual=false;
				}
			}
			
			// Next, its arguments:
			if(Types.IsDynamic(MethodToCall)){
				if(Arguments!=null){
					for(int i=0;i<Arguments.Length;i++){
						Arguments[i].OutputIL(into);
					}
				}
			}else{
				Types.OutputParameters(Arguments,Method,into,MethodToCall.GetParameters());
			}
			
			// And emit the call:
			if(useVirtual){
				into.Emit(OpCodes.Callvirt,MethodToCall);
			}else{
				into.Emit(OpCodes.Call,MethodToCall);
			}
		}
 public override void OutputIL(NitroIL into)
 {
     Wrench.Log.Add("Switch operations are currently unsupported. The whole switch block will be ignored - use ifs instead.");
 }
		public CompiledMethod(CompiledClass parent,string name,BracketFragment parameterBlock,BracketFragment codeBlock,TypeFragment retType,bool isPublic){
			Name=name;
			Parent=parent;
			CodeBlock=codeBlock;
			Script=Parent.Script;
			ParameterBlock=parameterBlock;
			
			Type returnType=null;
			if(retType!=null){
				returnType=retType.FindType(Script);
				if(returnType==null){
					Error("Type '"+retType.Value+"' was not found.");
				}
			}
			string methodName=Name;
			MethodAttributes attrib=isPublic?MethodAttributes.Public:MethodAttributes.Private;
			if(methodName=="new"){
				methodName=".ctor";
				attrib|=MethodAttributes.HideBySig|MethodAttributes.SpecialName|MethodAttributes.RTSpecialName;
			}
			// Does the parent base type define this method?
			// If so, use it's name.
			Type baseType=Parent.Builder.BaseType;
			
			// Parse the parameter set right away:
			ParseParameters();
			
			MethodInfo mInfo=Types.GetOverload(baseType.GetMethods(),Name,ParameterTypes,true);
			
			if(mInfo!=null){
				methodName=mInfo.Name;
				attrib|=MethodAttributes.Virtual|MethodAttributes.HideBySig;//|MethodAttributes.NewSlot;
			}
			
			bool isVoid=Types.IsVoid(returnType);
			
			if(isVoid){
				returnType=typeof(void);
			}
			
			Builder=Parent.Builder.DefineMethod(
				methodName,
				attrib,
				returnType,
				null
			);
			
			ApplyParameters();
			
			ILStream=new NitroIL(Builder.GetILGenerator());
			EndOfMethod=ILStream.DefineLabel();
			if(!isVoid){
				ReturnBay=ILStream.DeclareLocal(returnType);
			}
		}
예제 #38
0
 /// <summary>Emits the Value held by this compiled fragment if possible.</summary>
 /// <param name="type">The type of the value (or one of the base types of the value).</param>
 /// <param name="into">The IL stream to output the IL into.</param>
 public void EmitValue(Type type, NitroIL into)
 {
     if (type == typeof(string))
     {
         into.Emit(OpCodes.Ldstr, (string)Value);
     }
     else if (type == typeof(int))
     {
         into.Emit(OpCodes.Ldc_I4, (int)Value);
     }
     else if (type == typeof(uint))
     {
         into.Emit(OpCodes.Ldc_I4, (uint)Value);
     }
     else if (type == typeof(long))
     {
         into.Emit(OpCodes.Ldc_I8, (long)Value);
     }
     else if (type == typeof(ulong))
     {
         into.Emit(OpCodes.Ldc_I8, (ulong)Value);
     }
     else if (type == typeof(float))
     {
         into.Emit(OpCodes.Ldc_R4, (float)Value);
     }
     else if (type == typeof(double))
     {
         into.Emit(OpCodes.Ldc_R8, (double)Value);
     }
     else if (type == typeof(OpCode))
     {
         into.Emit((OpCode)Value);
     }
     else if (type == typeof(bool))
     {
         into.Emit(OpCodes.Ldc_I4, ((bool)Value)?1:0);
     }
     else if (type == typeof(short))
     {
         into.Emit(OpCodes.Ldc_I4, (short)Value);
     }
     else if (type == typeof(ushort))
     {
         into.Emit(OpCodes.Ldc_I4, (ushort)Value);
     }
     else if (type == typeof(byte))
     {
         into.Emit(OpCodes.Ldc_I4, (byte)Value);
     }
     else if (type == typeof(sbyte))
     {
         into.Emit(OpCodes.Ldc_I4, (sbyte)Value);
     }
     else if (Types.IsSubclass(Value, typeof(Variable)))
     {
         // Is parent a type of methodoperation or propertyoperation?
         // If it is, IsMemberAccessor is true.
         ((Variable)Value).OutputIL(into, (ParentFragment != null && ParentFragment.IsMemberAccessor()));
     }
     else
     {
         Error("Didn't know how to output value " + Value + " (type is " + type + ")");
     }
 }
		public override void OutputIL(NitroIL into){
			
			Wrench.Log.Add("Switch operations are currently unsupported. The whole switch block will be ignored - use ifs instead.");
			
		}
		public override void OutputIL(NitroIL into){
			into.Emit(OpCodes.Ldarg_0);
		}
		public void OutputTarget(NitroIL into){
			
			if(IsStatic&&(Field!=null || Property!=null)){
				return;
			}
			
			if(Of==null||(Field==null&&Property==null&&MethodReturnType==null)){
				Error("Unused or invalid property.");
			}
			
			if(MethodReturnType==null){
				Of.OutputIL(into);
			}
			
		}
		public void OutputSet(NitroIL into,Type setting){
			
			if(Field!=null){
				
				if(IsStatic){
					into.Emit(OpCodes.Stsfld,Field);
				}else{
					into.Emit(OpCodes.Stfld,Field);
				}
				
			}else if(Property!=null){
				bool useVirtual=!IsStatic && !Property.PropertyType.IsValueType;
				MethodInfo setMethod=Property.GetSetMethod();
				
				if(setMethod==null){
					Error(Name+" is a readonly property.");
				}
				
				into.Emit(useVirtual?OpCodes.Callvirt:OpCodes.Call,setMethod);
			}else{
				Error(Name+" is a function! Unable to set it's value.");
			}
			
		}
		public override void OutputIL(NitroIL into){
			OutputTarget(into);
			if(Field!=null){
				if(Field.IsLiteral){
					// Special case - this field isn't actually a field at all!
					// Load it's literal value:
					object literalFieldValue=Field.GetValue(null);
					
					// Get ready to write out the literal value:
					CompiledFragment literalValue=new CompiledFragment(literalFieldValue);
					
					// It might even be from an enum - let's check:
					if(Field.FieldType.IsEnum){
						// Ok great it's from an enum. What type is it?
						Type literalValueType=Enum.GetUnderlyingType(Field.FieldType);
						
						// Use that type to emit the value:
						literalValue.EmitValue(literalValueType,into);
					}else{
						literalValue.OutputIL(into);
					}
				}else if(ParentFragment!=null && ParentFragment.IsMemberAccessor() && Field.FieldType.IsValueType){
					// Are we followed by another PropertyOperation?
					// A following operation in this sitation ends up being the parent.
					// If we are, and we output a valuetype, Ldflda must be used.
					
					if(IsStatic){
						into.Emit(OpCodes.Ldsflda,Field);
					}else{
						into.Emit(OpCodes.Ldflda,Field);
					}
					
				}else if(IsStatic){
					into.Emit(OpCodes.Ldsfld,Field);
				}else{
					into.Emit(OpCodes.Ldfld,Field);
				}
			}else if(Property!=null){
				bool useVirtual=!IsStatic && !Property.PropertyType.IsValueType;
				into.Emit(useVirtual?OpCodes.Callvirt:OpCodes.Call,Property.GetGetMethod());
			}else{
				DynamicMethodCompiler.Compile(Method,Name,MethodReturnType,Of).OutputIL(into);
			}
		}
예제 #44
0
        public override void OutputIL(NitroIL into)
        {
            if (!OutputTarget(into))
            {
                return;
            }

            if (Field != null)
            {
                if (Field.IsLiteral)
                {
                    // Special case - this field isn't actually a field at all!
                    // Load it's literal value:
                    object literalFieldValue = Field.GetValue(null);

                    // Get ready to write out the literal value:
                    CompiledFragment literalValue = new CompiledFragment(literalFieldValue);

                    // It might even be from an enum - let's check:
                    if (Field.FieldType.IsEnum)
                    {
                        // Ok great it's from an enum. What type is it?
                        Type literalValueType = Enum.GetUnderlyingType(Field.FieldType);

                        // Use that type to emit the value:
                        literalValue.EmitValue(literalValueType, into);
                    }
                    else
                    {
                        literalValue.OutputIL(into);
                    }
                }
                else if (ParentFragment != null && ParentFragment.IsMemberAccessor() && Field.FieldType.IsValueType)
                {
                    // Are we followed by another PropertyOperation?
                    // A following operation in this sitation ends up being the parent.
                    // If we are, and we output a valuetype, Ldflda must be used.

                    if (IsStatic)
                    {
                        into.Emit(OpCodes.Ldsflda, Field);
                    }
                    else
                    {
                        into.Emit(OpCodes.Ldflda, Field);
                    }
                }
                else if (IsStatic)
                {
                    into.Emit(OpCodes.Ldsfld, Field);
                }
                else
                {
                    into.Emit(OpCodes.Ldfld, Field);
                }
            }
            else if (Property != null)
            {
                bool useVirtual = !IsStatic && !Property.PropertyType.IsValueType;

                into.Emit(useVirtual?OpCodes.Callvirt:OpCodes.Call, Property.GetGetMethod());
            }
            else if (Methods != null)
            {
                // Extension property (hopefully!). Look for a get method lookalike.

                // Get types:
                Type[] argTypes = new Type[] { OfType() };

                // Get the overload:
                MethodInfo getMethod = Types.GetOverload(Methods, argTypes);

                if (getMethod == null)
                {
                    Error(Name + " is a 'write only' extension property.");
                }

                // Call the set method:
                into.Emit(OpCodes.Call, getMethod);
            }
            else
            {
                DynamicMethodCompiler.Compile(Method, Name, MethodReturnType, Of).OutputIL(into);
            }
        }
        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.");
            }
        }
		public override void OutputIL(NitroIL into){
			Input0.OutputIL(into);
			Input1.OutputIL(into);
			into.Emit(OpCodes.Cgt);
		}
예제 #47
0
        public override void OutputIL(NitroIL into)
        {
            // Emit any set operations before the block itself (e.g. i=0):
            for (int i = 0; i < Parameters.Length; i++)
            {
                CompiledFragment parameter = Parameters[i];

                if (Types.IsTypeOf(parameter, typeof(SetOperation)))
                {
                    // Make sure it isn't a self set - e.g. i++, i=i+10.
                    SetOperation set = (SetOperation)parameter;

                    if (!set.SelfReferencing())
                    {
                        set.OutputIL(into);
                        Parameters[i] = null;
                    }
                    else
                    {
                        set.Output = false;
                    }
                }
                else
                {
                    // Compute it's output type:
                    // Note that this must NOT be done for the SET ops as it makes them think
                    // We want to use their output, which isn't true!
                    parameter.OutputType(out parameter);
                    Parameters[i] = parameter;
                }
            }

            Label continuePoint = into.DefineLabel();
            Label start         = into.DefineLabel();
            Label end           = into.DefineLabel();

            Method.AddBreakPoint(new BreakPoint(continuePoint, end));
            into.MarkLabel(start);

            // Logical operations (e.g. i<10):
            for (int i = 0; i < Parameters.Length; i++)
            {
                CompiledFragment parameter = Parameters[i];

                if (parameter == null)
                {
                    continue;
                }

                if (Types.IsTypeOf(parameter, typeof(SetOperation)))
                {
                    // Just checking for a logical operation will make an incremental (i++) operation think
                    // It's being daisy chained. That's because its output type is checked for boolean in IsLogical.
                    continue;
                }

                if (parameter.IsLogical())
                {
                    parameter.OutputIL(into);
                    into.Emit(OpCodes.Brfalse, end);
                    Parameters[i] = null;
                }
            }

            Body.CompileBody(Method);
            into.MarkLabel(continuePoint);

            // Increment/decrement ops (e.g. i++):
            for (int i = 0; i < Parameters.Length; i++)
            {
                CompiledFragment cfrag = Parameters[i];
                if (cfrag == null)
                {
                    continue;
                }
                cfrag.OutputIL(into);
            }
            into.Emit(OpCodes.Br, start);
            into.MarkLabel(end);
            Method.PopBreakPoint();
        }
        public CompiledMethod(CompiledClass parent, string name, BracketFragment parameterBlock, BracketFragment codeBlock, TypeFragment retType, bool isPublic)
        {
            Name           = name;
            Parent         = parent;
            CodeBlock      = codeBlock;
            Script         = Parent.Script;
            ParameterBlock = parameterBlock;

            Type returnType = null;

            if (retType != null)
            {
                returnType = retType.FindType(Script);
                if (returnType == null)
                {
                    Error("Type '" + retType.Value + "' was not found.");
                }
            }
            string           methodName = Name;
            MethodAttributes attrib     = isPublic?MethodAttributes.Public:MethodAttributes.Private;

            if (methodName == "new")
            {
                methodName = ".ctor";
                attrib    |= MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
            }
            // Does the parent base type define this method?
            // If so, use it's name.
            Type baseType = Parent.Builder.BaseType;

            // Parse the parameter set right away:
            ParseParameters();

            MethodInfo mInfo = Types.GetOverload(baseType.GetMethods(), Name, ParameterTypes, true);

            if (mInfo != null)
            {
                methodName = mInfo.Name;
                attrib    |= MethodAttributes.Virtual | MethodAttributes.HideBySig;         //|MethodAttributes.NewSlot;
            }

            bool isVoid = Types.IsVoid(returnType);

            if (isVoid)
            {
                returnType = typeof(void);
            }

            Builder = Parent.Builder.DefineMethod(
                methodName,
                attrib,
                returnType,
                null
                );

            ApplyParameters();

            ILStream    = new NitroIL(Builder.GetILGenerator());
            EndOfMethod = ILStream.DefineLabel();
            if (!isVoid)
            {
                ReturnBay = ILStream.DeclareLocal(returnType);
            }
        }
예제 #49
0
		public override void OutputIL(NitroIL into){
			into.Emit(OpCodes.Ldtoken,TypeObject);
			MethodInfo methodToCall=typeof(System.Type).GetMethod("GetTypeFromHandle");
			into.Emit(OpCodes.Call,methodToCall);
		}
		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.");
			}
			
		}
예제 #51
0
		/// <summary>Outputs this variable to read its content.</summary>
		/// <param name="into">The IL stream it should be put into.</param>
		/// <param name="accessingMember">True if the variable is being outputted and immediately having
		/// a method/property/field accessed. This is important for value type fields.</param>
		public virtual void OutputIL(NitroIL into,bool accessingMember){}
 public override void OutputIL(NitroIL into)
 {
     into.Emit(OpCodes.Ldarg_0);
 }
예제 #53
0
		/// <summary>Outputs this variable to write its content.</summary>
		/// <param name="into">The IL stream a set should be put into.</param>
		/// <param name="setting">The type being set to this variable.</param>
		public virtual void OutputSet(NitroIL into,Type setting){}
예제 #54
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);
            }
        }
예제 #55
0
		/// <summary>Used with OutputSet, this outputs any additional information that 'targets' where this variable is located.</summary>
		/// <param name="into">The IL stream a set should be put into.</param>
		public virtual void OutputTarget(NitroIL into){}
예제 #56
0
 /// <summary>Emits a continue - a jump to the start of the loop.</summary>
 /// <param name="into">The IL code to emit the instruction into.</param>
 public void Continue(NitroIL into)
 {
     into.Emit(OpCodes.Br, ContinuePoint);
 }
		public override void OutputIL(NitroIL into){
			if(!Method.Break(into,Depth)){
				Error("Nothing to break from!");
			}
		}