2004-03-29 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / class / corlib / System.Reflection.Emit / DynamicMethod.cs
1 //
2 // System.Reflection.Emit/DynamicMethod.cs
3 //
4 // Author:
5 //   Paolo Molaro (lupus@ximian.com)
6 //   Zoltan Varga (vargaz@freemail.hu)
7 //
8 // (C) 2003 Ximian, Inc.  http://www.ximian.com
9 //
10
11 #if NET_1_2
12
13 using System;
14 using System.Reflection;
15 using System.Reflection.Emit;
16 using System.Globalization;
17 using System.Runtime.CompilerServices;
18 using System.Runtime.InteropServices;
19
20 namespace System.Reflection.Emit {
21
22         public sealed class DynamicMethod : MethodInfo {
23                 #region Sync with reflection.h
24                 private RuntimeMethodHandle mhandle;
25                 private string name;
26                 private Type returnType;
27                 private Type[] parameters;
28                 private MethodAttributes attributes;
29                 private CallingConventions callingConvention;
30                 private Module module;
31                 private bool skipVisibility;
32                 private bool init_locals = true;
33                 private ILGenerator ilgen;
34                 private int nrefs;
35                 private object[] refs;
36                 #endregion
37                 private Delegate deleg;
38                 private MonoMethod method;
39                 private ParameterBuilder[] pinfo;
40
41                 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Module m) : this (name, returnType, parameterTypes, m, false) {
42                 }
43
44                 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Type owner) : this (name, returnType, parameterTypes, owner, false) {
45                 }
46
47                 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility) : this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, m, skipVisibility) {
48                 }
49
50                 public DynamicMethod (string name, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility) : this (name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, owner, skipVisibility) {
51                 }
52
53                 public DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility) : this (name, attributes, callingConvention, returnType, parameterTypes, owner.Module, skipVisibility) {
54                 }
55
56                 public DynamicMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility) {
57                         if (name == null)
58                                 throw new ArgumentNullException ("name");
59                         if (name == String.Empty)
60                                 throw new ArgumentException ("Name can't be empty", "name");
61                         if (returnType == null)
62                                 throw new ArgumentNullException ("returnType");
63                         if (m == null)
64                                 throw new ArgumentNullException ("m");
65                         if (returnType.IsByRef)
66                                 throw new ArgumentException ("Return type can't be a byref type", "returnType");
67                         if (parameterTypes != null) {
68                                 for (int i = 0; i < parameterTypes.Length; ++i)
69                                         if (parameterTypes [i] == null)
70                                                 throw new ArgumentException ("Parameter " + i + " is null", "parameterTypes");
71                         }
72
73                         this.name = name;
74                         this.attributes = attributes | MethodAttributes.Static;
75                         this.callingConvention = callingConvention;
76                         this.returnType = returnType;
77                         this.parameters = parameterTypes;
78                         this.module = m;
79                         this.skipVisibility = skipVisibility;
80                 }
81
82                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
83                 private extern void create_dynamic_method (DynamicMethod m);
84
85                 private void CreateDynMethod () {
86                         if (mhandle.Value == IntPtr.Zero)
87                                 create_dynamic_method (this);
88                 }
89
90                 public Delegate CreateDelegate (Type delegateType) {
91                         if (delegateType == null)
92                                 throw new ArgumentNullException ("delegateType");
93                         if (deleg != null)
94                                 return deleg;
95
96                         CreateDynMethod ();
97
98                         deleg = Delegate.CreateDelegate (delegateType, this);
99                         return deleg;
100                 }
101
102                 [MonoTODO]
103                 public ParameterBuilder DefineParameter (int position, ParameterAttributes attributes, string strParamName)
104                 {
105                         //
106                         // Extension: Mono allows position == 0 for the return attribute
107                         //
108                         if ((position < 0) || (position > parameters.Length))
109                                 throw new ArgumentOutOfRangeException ("position");
110
111                         RejectIfCreated ();
112
113                         throw new NotImplementedException ();
114                 }
115
116                 public override MethodInfo GetBaseDefinition () {
117                         return this;
118                 }
119
120                 [MonoTODO]
121                 public override object[] GetCustomAttributes (bool inherit) {
122                         throw new NotImplementedException ();
123                 }
124
125                 [MonoTODO]
126                 public override object[] GetCustomAttributes (Type attributeType,
127                                                                                                           bool inherit) {
128                         throw new NotImplementedException ();
129                 }
130
131                 public ILGenerator GetILGenerator () {
132                         return GetILGenerator (64);
133                 }
134
135                 public ILGenerator GetILGenerator (int size) {
136                         if (((GetMethodImplementationFlags () & MethodImplAttributes.CodeTypeMask) != 
137                                  MethodImplAttributes.IL) ||
138                                 ((GetMethodImplementationFlags () & MethodImplAttributes.ManagedMask) != 
139                                  MethodImplAttributes.Managed))
140                                 throw new InvalidOperationException ("Method body should not exist.");
141                         if (ilgen != null)
142                                 return ilgen;
143                         ilgen = new ILGenerator (Module, new DynamicMethodTokenGenerator (this), size);
144                         return ilgen;
145                 }               
146
147                 public override MethodImplAttributes GetMethodImplementationFlags () {
148                         return MethodImplAttributes.IL | MethodImplAttributes.Managed;
149                 }
150
151                 public override ParameterInfo[] GetParameters () {
152                         if (parameters == null)
153                                 return new ParameterInfo [0];
154
155                         ParameterInfo[] retval = new ParameterInfo [parameters.Length];
156                         for (int i = 0; i < parameters.Length; i++) {
157                                 retval [i] = new ParameterInfo (pinfo == null ? null : pinfo [i + 1], parameters [i], this, i + 1);
158                         }
159                         return retval;
160                 }
161
162                 public override object Invoke (object obj, object[] parameters) {
163                         CreateDynMethod ();
164                         if (method == null)
165                                 method = new MonoMethod (mhandle);
166                         return method.Invoke (obj, parameters);
167                 }
168
169                 public override object Invoke (object obj, BindingFlags invokeAttr,
170                                                                            Binder binder, object[] parameters,
171                                                                            CultureInfo culture) {
172                         CreateDynMethod ();
173                         if (method == null)
174                                 method = new MonoMethod (mhandle);
175                         return method.Invoke (obj, parameters);
176                 }
177
178                 [MonoTODO]
179                 public override bool IsDefined (Type attributeType, bool inherit) {
180                         throw new NotImplementedException ();
181                 }
182
183                 public override string ToString () {
184                         string parms = "";
185                         ParameterInfo[] p = GetParameters ();
186                         for (int i = 0; i < p.Length; ++i) {
187                                 if (i > 0)
188                                         parms = parms + ", ";
189                                 parms = parms + p [i].ParameterType.Name;
190                         }
191                         return ReturnType.Name+" "+Name+"("+parms+")";
192                 }
193
194                 public override MethodAttributes Attributes {
195                         get {
196                                 return attributes;
197                         }
198                 }
199
200                 public override CallingConventions CallingConvention {
201                         get {
202                                 return callingConvention;
203                         }
204                 }
205
206                 public override Type DeclaringType {
207                         get {
208                                 return null;
209                         }
210                 }
211
212                 public bool InitLocals {
213                         get {
214                                 return init_locals;
215                         }
216                         set {
217                                 init_locals = value;
218                         }
219                 }
220
221                 public override RuntimeMethodHandle MethodHandle {
222                         get {
223                                 return mhandle;
224                         }
225                 }
226
227                 public Module Module {
228                         get {
229                                 return module;
230                         }
231                 }
232
233                 public override string Name {
234                         get {
235                                 return name;
236                         }
237                 }
238
239                 public override Type ReflectedType {
240                         get {
241                                 return null;
242                         }
243                 }
244
245                 [MonoTODO]
246                 public ParameterInfo ReturnParameter {
247                         get {
248                                 throw new NotImplementedException ();
249                         }
250                 }
251
252                 public override Type ReturnType {
253                         get {
254                                 return returnType;
255                         }
256                 }
257
258                 [MonoTODO]
259                 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
260                         get {
261                                 throw new NotImplementedException ();
262                         }
263                 }
264
265                 private void RejectIfCreated () {
266                         if (mhandle.Value != IntPtr.Zero)
267                                 throw new InvalidOperationException ("Type definition of the method is complete.");
268                 }
269
270                 private Exception NotSupported () {
271                         return new NotSupportedException ("The invoked member is not supported on a dynamic method.");
272                 }
273
274                 internal int AddRef (object reference) {
275                         if (refs == null)
276                                 refs = new object [4];
277                         if (nrefs >= refs.Length) {
278                                 object [] new_refs = new object [refs.Length * 2];
279                                 System.Array.Copy (refs, new_refs, refs.Length);
280                                 refs = new_refs;
281                         }
282                         refs [nrefs] = reference;
283                         nrefs ++;
284                         return nrefs;
285                 }
286         }
287
288         internal class DynamicMethodTokenGenerator : TokenGenerator {
289
290                 private DynamicMethod m;
291
292                 public DynamicMethodTokenGenerator (DynamicMethod m) {
293                         this.m = m;
294                 }
295
296                 public int GetToken (string str) {
297                         return m.AddRef (str);
298                 }
299
300                 public int GetToken (MemberInfo member) {
301                         return m.AddRef (member);
302                 }
303
304                 public int GetToken (SignatureHelper helper) {
305                         return m.AddRef (helper);
306                 }
307         }
308 }
309
310 #endif