public override Type OutputType(out CompiledFragment newOperation) { newOperation = this; Type typeB = Input1.OutputType(out Input1); Type typeA = Input0.OutputType(out Input0); if (typeA != typeB) { bool BString = (typeB == typeof(string)); if (typeA == typeof(string) || BString) { if (BString) { // This is alright - convert Input0 to a ToString operation. Input0 = Types.ToStringMethod(Method, Input0, typeA); typeA = typeof(string); } else { Input1 = Types.ToStringMethod(Method, Input1, typeB); typeB = typeof(string); } } } if (typeA == typeof(string) && typeB == typeof(string)) { // Adding two strings (concat). newOperation = new MethodOperation(Method, typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) }), Input0, Input1); } else { typeA = Numerical(typeA, typeB, "Addition", ref newOperation); } return(typeA); }
public override Type OutputType(out CompiledFragment v) { v = this; Type TypeA = Input1.OutputType(out Input1); Type TypeB = Input0.OutputType(out Input0); return(Numerical(TypeA, TypeB, "Multiply", ref v)); }
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)); }
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)); }
public override Type OutputType(out CompiledFragment v) { v = this; if (ElementType == null) { Type type = AppliedTo.OutputType(out AppliedTo); Type indexType = Index.OutputType(out Index); if (!type.IsArray) { // Using an index on something that isn't an array - this maps to the get_Item/set_Item functions. MethodInfo[] allMethods = type.GetMethods(); MethodOperation mOp = null; if (Input0 != null) { // Set. Input0 is the object we're setting. Type setType = Input0.OutputType(out Input0); MethodInfo mInfo = Types.GetOverload(allMethods, "set_Item", new Type[] { indexType, setType }); if (mInfo == null) { Error("This object does not support setting values with [" + indexType + "]=" + setType + "."); } mOp = new MethodOperation(Method, mInfo, Index, Input0); v = mOp; mOp.CalledOn = AppliedTo; return(setType); } else { // Get. MethodInfo mInfo = Types.GetOverload(allMethods, "get_Item", new Type[] { indexType }); if (mInfo == null) { Error("Unable to index [] something that as it is not an array."); } mOp = new MethodOperation(Method, mInfo, Index); v = mOp; mOp.CalledOn = AppliedTo; return(mInfo.ReturnType); } } else { EnforceType(ref Index, indexType, typeof(int)); } ElementType = type.GetElementType(); } return(ElementType); }
public override Type OutputType(out CompiledFragment v) { v = this; Type typeA = Input0.OutputType(out Input0); Type typeB = Input1.OutputType(out Input1); CompiledFragment equalityOverload = null; FindOverload("Equality", typeA, typeB, ref equalityOverload); if (equalityOverload != null) { v = equalityOverload; } return(typeof(bool)); }
public override Type OutputType(out CompiledFragment v) { v = this; Type typeA = Input0.OutputType(out Input0); Type typeB = Input1.OutputType(out Input1); CompiledFragment overload = null; FindOverload("GreaterThan", typeA, typeB, ref overload); if (overload != null) { v = overload; } return(typeof(bool)); }
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)); }
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 override Type OutputType(out CompiledFragment v) { v = this; Input1.OutputType(out Input1); return(Input0.OutputType(out Input0)); }
public override void OutputIL(NitroIL into) { Type type2 = Input1.OutputType(out Input1); // Is it something which is being ["indexed"]? May apply to properties too. bool indexOperation = (Input0.GetType() == typeof(IndexOperation)); bool propertyOperation = (Input0.GetType() == typeof(PropertyOperation)); if (indexOperation || propertyOperation) { // Hook up what we will be setting for the index to handle if it needs to. // Note that the object will not change as we have already run it's OutputType call above. ((Operation)Input0).Input0 = Input1; } // Update input0 by computing the type it outputs: Type type1 = Input0.OutputType(out Input0); object value = Input0.ActiveValue(); if (value.GetType() != typeof(LocalVariable)) { // Local vars can change type so this doesn't affect them. if (type1 == null) { Error("Can't set to nothing."); } if (type2 == null) { if (type1.IsValueType) { Error("Can't set " + type1 + " to null because it's a value type."); } } else if (!type1.IsAssignableFrom(type2)) { Error("Can't implicity convert " + type2 + " to " + type1 + "."); } } if (Types.IsTypeOf(value, typeof(ISettable))) { ISettable Value = (ISettable)value; Value.OutputTarget(into); Input1.OutputIL(into); Value.OutputSet(into, type2); if (Output) { // Daisy chaining these sets. Input0.OutputIL(into); } } else if (indexOperation && value.GetType() == typeof(MethodOperation)) { // This is ok! We've called something like obj["hello"]=input1; // Just output the method call: Input0.OutputIL(into); if (Output) { Error("Can't daisy chain with an indexer. Place your indexed object furthest left."); } } else if (propertyOperation && value.GetType() == typeof(MethodOperation) && ((MethodOperation)value).MethodName == "set_Item") { // This is also ok - we've done something like object.property=value; and it mapped to object["property"]=value; // Just output the method call: Input0.OutputIL(into); if (Output) { Error("Can't daisy chain with a property set here. Place your indexed object furthest left."); } } else { Error("Attempted to set to something (a " + value.GetType() + ") that isn't a variable."); } }
public override Type OutputType(out CompiledFragment v) { v = this; Type type = OfType(); // Map to functionality: CompiledClass Class = null; bool isDynamic = Types.IsDynamic(type); // (Constant) binding flags: BindingFlags flags = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; if (Name == "length" && type.IsGenericType && !isDynamic) { // Does length actually exist as a field/ property? Field = type.GetField(Name, flags); if (Field == null) { Property = type.GetProperty(Name, flags); if (Property == null) { // Assume we meant count instead: Name = "Count"; } } } if (isDynamic) { Class = Method.Script.GetClass(type); } else if (!Method.Script.AllowUse(type)) { Error("Unable to access properties of type " + type + " as it has not been made accessible."); } if (isDynamic) { Field = Class.GetField(Name); } else { Field = type.GetField(Name, flags); } if (Field != null) { if (IsStatic && !Field.IsStatic) { Error("Property " + Name + " is not static. You must use an object reference to access it."); } return(Field.FieldType); } if (isDynamic) { Property = Class.GetProperty(Name); } else { Property = type.GetProperty(Name, flags); } if (Property != null) { if (IsStatic) { MethodInfo staticTest = Property.GetGetMethod(); if (staticTest == null) { staticTest = Property.GetSetMethod(); } if (!staticTest.IsStatic) { Error("Property " + Name + " is not static. You must use an object reference to access it."); } } return(Property.PropertyType); } if (isDynamic) { MethodReturnType = Class.MethodReturnType(Name); } else { MethodReturnType = Types.MethodReturnType(type, Name); } if (MethodReturnType != null) { if (Types.IsVoid(MethodReturnType)) { MethodReturnType = typeof(Void); } return(DynamicMethodCompiler.TypeFor(MethodReturnType)); } if (Of.GetType() == typeof(ThisOperation)) { // This was the first property - it can potentially be a static type name too. Type staticType = Method.Script.GetType(Name); if (staticType != null) { // It's a static type! Generate a new type operation to replace this one and return the type. v = new TypeOperation(Method, staticType); return(v.OutputType(out v)); } } if (Name == "this") { // This is handled here as it allows variables called "This". Use case: PowerUI. v = new ThisOperation(Method); return(v.OutputType(out v)); } // Does it support indexing? If so, Do Parent["property"] instead. MethodOperation mOp = null; if (Input0 != null) { // This is a set. Input0 is the object we're setting. Type setType = Input0.OutputType(out Input0); // Get the set method: MethodInfo mInfo; if (isDynamic) { mInfo = Class.FindMethodOverload("set_Item", new Type[] { typeof(string), setType }); } else { // Grab all the methods of the type: MethodInfo[] allMethods = type.GetMethods(); mInfo = Types.GetOverload(allMethods, "set_Item", new Type[] { typeof(string), setType }); } if (mInfo == null) { // Try finding the extension method: mInfo = FindExtensionMethod(type, "set"); if (mInfo == null) { // It doesn't exist! // Error("Property '"+ToString()+"' is not a property or extension of "+type.ToString()+"."); // Create as a global: Field = Method.Script.MainClass.DefineField(Name, true, setType); return(setType); } // Extension property or method. // -> We only know which based on MethodOperation later calling GetOverload. // Or OutputSet/ OutputIL being called. return(mInfo.ReturnType); } // It exists - create the method operation now. mOp = new MethodOperation(Method, mInfo, new CompiledFragment(Name), Input0); v = mOp; mOp.CalledOn = Of; return(setType); } else { // Get. // Get the get method: MethodInfo mInfo; if (isDynamic) { mInfo = Class.FindMethodOverload("get_Item", new Type[] { typeof(string) }); } else { // Grab all the methods of the type: MethodInfo[] allMethods = type.GetMethods(); mInfo = Types.GetOverload(allMethods, "get_Item", new Type[] { typeof(string) }); } if (mInfo == null) { // Try finding the extension method: mInfo = FindExtensionMethod(type, "get"); if (mInfo == null) { // It doesn't exist! // Error("Property '"+ToString()+"' is not a property or extension of "+type.ToString()+"."); // Create as a global: Field = Method.Script.MainClass.DefineField(Name, true, typeof(object)); return(typeof(object)); } // Extension property or method. // -> We only know which based on MethodOperation later calling GetOverload. // Or OutputSet/ OutputIL being called. return(mInfo.ReturnType); } // It exists - create the method operation now: mOp = new MethodOperation(Method, mInfo, new CompiledFragment(Name)); v = mOp; mOp.CalledOn = Of; return(mInfo.ReturnType); } }