/// <summary>Adds a method that was found into this classes set of methods to compile.</summary> /// <param name="fragment">The first fragment of the method, used for generating errors. This gives a valid line number.</param> /// <param name="body">The block of code for this method.</param> /// <param name="name">The name of the method. Null if anonymous is true.</param> /// <param name="anonymous">True if this method is an anonymous one and requires a name.</param> /// <param name="parameters">The set of parameters for this method.</param> /// <param name="returnType">The type that this method returns.</param> /// <param name="isPublic">True if this is a public method; false for private.</param> /// <returns>The first fragment following the method, if there is one.</returns> protected virtual CodeFragment AddFoundMethod(CodeFragment fragment, CodeFragment body, string name, bool anonymous, BracketFragment parameters, TypeFragment returnType, bool isPublic) { if (body == null) { fragment.Error("Invalid function definition (" + name + "). The content block {} is missing or isnt valid."); } if (anonymous) { name = "Compiler-Generated-$" + AnonymousCount; AnonymousCount++; } // The following is the explicit code block for this function: BracketFragment codeBlock = (BracketFragment)body; CompiledMethod cMethod = new CompiledMethod(this, name, parameters, codeBlock, returnType, isPublic); MethodOverloads set = MakeOrFind(name, cMethod.Builder.ReturnType); CodeFragment next = body.NextChild; if (anonymous) { CodeFragment newChild = DynamicMethodCompiler.Compile(cMethod, name, set.ReturnType, new ThisOperation(cMethod)); newChild.AddAfter(body); } body.Remove(); set.AddMethod(cMethod); FindMethods(codeBlock); return(next); }
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); } }