1 //
2 // PrinterFactory.cs
3 //
4 // Authors:
5 // 	Alexander Chebaturkin (chebaturkin@gmail.com)
6 //
7 // Copyright (C) 2011 Alexander Chebaturkin
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 
29 using System;
30 using System.Collections.Generic;
31 using System.IO;
32 using Mono.CodeContracts.Static.AST;
33 using Mono.CodeContracts.Static.AST.Visitors;
34 using Mono.CodeContracts.Static.ControlFlow;
35 using Mono.CodeContracts.Static.DataStructures;
36 using Mono.CodeContracts.Static.Providers;
37 
38 namespace Mono.CodeContracts.Static.Analysis {
39 	static class PrinterFactory {
Create(IILDecoder<Label, Source, Dest, Context, EdgeData> ilDecoder, IMetaDataProvider metaDataProvider, Func<Source, string> sourceToString, Func<Dest, string> destToString)40 		public static ILPrinter<Label> Create<Label, Source, Dest, Context, EdgeData>
41 			(IILDecoder<Label, Source, Dest, Context, EdgeData> ilDecoder,
42 			 IMetaDataProvider metaDataProvider,
43 			 Func<Source, string> sourceToString, Func<Dest, string> destToString)
44 		{
45 			return new Printer<Label, Source, Dest, Context, EdgeData> (ilDecoder, metaDataProvider, sourceToString, destToString).PrintCodeAt;
46 		}
47 
48 		#region Nested type: Printer
49 		private class Printer<Label, Source, Dest, Context, EdgeData> : IILVisitor<Label, Source, Dest, TextWriter, Dummy> {
50 			private readonly Func<Dest, string> dest_to_string;
51 			private readonly IILDecoder<Label, Source, Dest, Context, EdgeData> il_decoder;
52 			private readonly IMetaDataProvider meta_data_provider;
53 			private readonly Func<Source, string> source_to_string;
54 			private string prefix = "";
55 
Printer(IILDecoder<Label, Source, Dest, Context, EdgeData> ilDecoder, IMetaDataProvider metaDataProvider, Func<Source, string> sourceToString, Func<Dest, string> destToString)56 			public Printer (IILDecoder<Label, Source, Dest, Context, EdgeData> ilDecoder, IMetaDataProvider metaDataProvider,
57 			                Func<Source, string> sourceToString, Func<Dest, string> destToString)
58 			{
59 				this.il_decoder = ilDecoder;
60 				this.meta_data_provider = metaDataProvider;
61 				this.source_to_string = sourceToString;
62 				this.dest_to_string = destToString;
63 			}
64 
65 			#region IILVisitor<Label,Source,Dest,TextWriter,Dummy> Members
Binary(Label pc, BinaryOperator op, Dest dest, Source operand1, Source operand2, TextWriter data)66 			public Dummy Binary (Label pc, BinaryOperator op, Dest dest, Source operand1, Source operand2, TextWriter data)
67 			{
68 				data.WriteLine ("{0}{1} = {2} {3} {4}", this.prefix, DestName (dest), SourceName (operand1), op.ToString (), SourceName (operand2));
69 				return Dummy.Value;
70 			}
71 
Isinst(Label pc, TypeNode type, Dest dest, Source obj, TextWriter data)72 			public Dummy Isinst (Label pc, TypeNode type, Dest dest, Source obj, TextWriter data)
73 			{
74 				data.WriteLine ("{0}{2} = isinst {1} {3}", this.prefix, this.meta_data_provider.FullName (type), DestName (dest), SourceName (obj));
75 				return Dummy.Value;
76 			}
77 
LoadNull(Label pc, Dest dest, TextWriter polarity)78 			public Dummy LoadNull (Label pc, Dest dest, TextWriter polarity)
79 			{
80 				polarity.WriteLine ("{0}{1} = ldnull", this.prefix, DestName (dest));
81 				return Dummy.Value;
82 			}
83 
LoadConst(Label pc, TypeNode type, object constant, Dest dest, TextWriter data)84 			public Dummy LoadConst (Label pc, TypeNode type, object constant, Dest dest, TextWriter data)
85 			{
86 				data.WriteLine ("{0}{2} = ldc ({3}) '{1}'", this.prefix, constant, DestName (dest), this.meta_data_provider.FullName (type));
87 				return Dummy.Value;
88 			}
89 
Sizeof(Label pc, TypeNode type, Dest dest, TextWriter data)90 			public Dummy Sizeof (Label pc, TypeNode type, Dest dest, TextWriter data)
91 			{
92 				data.WriteLine ("{0}{2} = sizeof {1}", this.prefix, this.meta_data_provider.FullName (type), DestName (dest));
93 				return Dummy.Value;
94 			}
95 
Unary(Label pc, UnaryOperator op, bool unsigned, Dest dest, Source source, TextWriter data)96 			public Dummy Unary (Label pc, UnaryOperator op, bool unsigned, Dest dest, Source source, TextWriter data)
97 			{
98 				data.WriteLine ("{0}{3} = {2}{1} {4}", this.prefix, unsigned ? "_un" : null, op, DestName (dest), SourceName (source));
99 				return Dummy.Value;
100 			}
101 
Entry(Label pc, Method method, TextWriter data)102 			public Dummy Entry (Label pc, Method method, TextWriter data)
103 			{
104 				data.WriteLine ("{0}method_entry {1}", this.prefix, this.meta_data_provider.FullName (method));
105 				return Dummy.Value;
106 			}
107 
Assume(Label pc, EdgeTag tag, Source condition, TextWriter data)108 			public Dummy Assume (Label pc, EdgeTag tag, Source condition, TextWriter data)
109 			{
110 				data.WriteLine ("{0}assume({1}) {2}", this.prefix, tag, SourceName (condition));
111 				return Dummy.Value;
112 			}
113 
Assert(Label pc, EdgeTag tag, Source condition, TextWriter data)114 			public Dummy Assert (Label pc, EdgeTag tag, Source condition, TextWriter data)
115 			{
116 				data.WriteLine ("{0}assert({1}) {2}", this.prefix, tag, SourceName (condition));
117 				return Dummy.Value;
118 			}
119 
BeginOld(Label pc, Label matchingEnd, TextWriter data)120 			public Dummy BeginOld (Label pc, Label matchingEnd, TextWriter data)
121 			{
122 				throw new NotImplementedException ();
123 			}
124 
EndOld(Label pc, Label matchingBegin, TypeNode type, Dest dest, Source source, TextWriter data)125 			public Dummy EndOld (Label pc, Label matchingBegin, TypeNode type, Dest dest, Source source, TextWriter data)
126 			{
127 				throw new NotImplementedException ();
128 			}
129 
LoadStack(Label pc, int offset, Dest dest, Source source, bool isOld, TextWriter data)130 			public Dummy LoadStack (Label pc, int offset, Dest dest, Source source, bool isOld, TextWriter data)
131 			{
132 				data.WriteLine ("{0}{1} = {4}ldstack.{2} {3}", this.prefix, DestName (dest), offset, SourceName (source), isOld ? "old." : null);
133 				return Dummy.Value;
134 			}
135 
LoadStackAddress(Label pc, int offset, Dest dest, Source source, TypeNode type, bool isOld, TextWriter data)136 			public Dummy LoadStackAddress (Label pc, int offset, Dest dest, Source source, TypeNode type, bool isOld, TextWriter data)
137 			{
138 				data.WriteLine ("{0}{1} = {4}ldstacka.{2} {3}", this.prefix, DestName (dest), offset, SourceName (source), isOld ? "old." : null);
139 				return Dummy.Value;
140 			}
141 
LoadResult(Label pc, TypeNode type, Dest dest, Source source, TextWriter data)142 			public Dummy LoadResult (Label pc, TypeNode type, Dest dest, Source source, TextWriter data)
143 			{
144 				data.WriteLine ("{0}{1} = ldresult {2}", this.prefix, DestName (dest), SourceName (source));
145 				return Dummy.Value;
146 			}
147 
Arglist(Label pc, Dest dest, TextWriter data)148 			public Dummy Arglist (Label pc, Dest dest, TextWriter data)
149 			{
150 				throw new NotImplementedException ();
151 			}
152 
Branch(Label pc, Label target, bool leavesExceptionBlock, TextWriter data)153 			public Dummy Branch (Label pc, Label target, bool leavesExceptionBlock, TextWriter data)
154 			{
155 				data.WriteLine ("{0}branch", this.prefix);
156 				return Dummy.Value;
157 			}
158 
BranchCond(Label pc, Label target, BranchOperator bop, Source value1, Source value2, TextWriter data)159 			public Dummy BranchCond (Label pc, Label target, BranchOperator bop, Source value1, Source value2, TextWriter data)
160 			{
161 				data.WriteLine ("{0}br.{1} {2},{3}", this.prefix, bop, SourceName (value1), SourceName (value2));
162 				return Dummy.Value;
163 			}
164 
BranchTrue(Label pc, Label target, Source cond, TextWriter data)165 			public Dummy BranchTrue (Label pc, Label target, Source cond, TextWriter data)
166 			{
167 				data.WriteLine ("{0}br.true {1}", this.prefix, SourceName (cond));
168 				return Dummy.Value;
169 			}
170 
BranchFalse(Label pc, Label target, Source cond, TextWriter data)171 			public Dummy BranchFalse (Label pc, Label target, Source cond, TextWriter data)
172 			{
173 				data.WriteLine ("{0}br.false {1}", this.prefix, SourceName (cond));
174 				return Dummy.Value;
175 			}
176 
Break(Label pc, TextWriter data)177 			public Dummy Break (Label pc, TextWriter data)
178 			{
179 				data.WriteLine ("{0}break", this.prefix);
180 				return Dummy.Value;
181 			}
182 
183 			public Dummy Call<TypeList, ArgList> (Label pc, Method method, bool virt, TypeList extraVarargs, Dest dest, ArgList args, TextWriter data) where TypeList : IIndexable<TypeNode>
184 				where ArgList : IIndexable<Source>
185 			{
186 				data.Write ("{0}{3} = call{2} {1}(", this.prefix, this.meta_data_provider.FullName (method), virt ? "virt" : null, DestName (dest));
187 				if (args != null) {
188 					for (int i = 0; i < args.Count; i++)
189 						data.Write ("{0} ", SourceName (args [i]));
190 				}
191 				data.WriteLine (")");
192 				return Dummy.Value;
193 			}
194 
195 			public Dummy Calli<TypeList, ArgList> (Label pc, TypeNode returnType, TypeList argTypes, bool instance, Dest dest, Source functionPointer, ArgList args, TextWriter data)
196 				where TypeList : IIndexable<TypeNode> where ArgList : IIndexable<Source>
197 			{
198 				data.Write ("{0}{1} = calli {2}(", this.prefix, DestName (dest), SourceName (functionPointer));
199 				if (args != null) {
200 					for (int i = 0; i < args.Count; i++)
201 						data.Write ("{0} ", SourceName (args [i]));
202 				}
203 				data.WriteLine (")");
204 				return Dummy.Value;
205 			}
206 
CheckFinite(Label pc, Dest dest, Source source, TextWriter data)207 			public Dummy CheckFinite (Label pc, Dest dest, Source source, TextWriter data)
208 			{
209 				data.WriteLine ("{0}{1} = chfinite {2}", this.prefix, DestName (dest), SourceName (source));
210 				return Dummy.Value;
211 			}
212 
CopyBlock(Label pc, Source destAddress, Source srcAddress, Source len, TextWriter data)213 			public Dummy CopyBlock (Label pc, Source destAddress, Source srcAddress, Source len, TextWriter data)
214 			{
215 				data.WriteLine ("{0}cpblk {1} {2} {3}", this.prefix, SourceName (destAddress), SourceName (srcAddress), SourceName (len));
216 				return Dummy.Value;
217 			}
218 
EndFilter(Label pc, Source decision, TextWriter data)219 			public Dummy EndFilter (Label pc, Source decision, TextWriter data)
220 			{
221 				throw new NotImplementedException ();
222 			}
223 
EndFinally(Label pc, TextWriter data)224 			public Dummy EndFinally (Label pc, TextWriter data)
225 			{
226 				throw new NotImplementedException ();
227 			}
228 
Jmp(Label pc, Method method, TextWriter data)229 			public Dummy Jmp (Label pc, Method method, TextWriter data)
230 			{
231 				throw new NotImplementedException ();
232 			}
233 
LoadArg(Label pc, Parameter argument, bool isOld, Dest dest, TextWriter data)234 			public Dummy LoadArg (Label pc, Parameter argument, bool isOld, Dest dest, TextWriter data)
235 			{
236 				data.WriteLine ("{0}{2} = {3}ldarg {1}", this.prefix, this.meta_data_provider.Name (argument), DestName (dest), isOld ? "old." : null);
237 				return Dummy.Value;
238 			}
239 
LoadArgAddress(Label pc, Parameter argument, bool isOld, Dest dest, TextWriter data)240 			public Dummy LoadArgAddress (Label pc, Parameter argument, bool isOld, Dest dest, TextWriter data)
241 			{
242 				data.WriteLine ("{0}{2} = {3}ldarga {1}", this.prefix, this.meta_data_provider.Name (argument), DestName (dest), isOld ? "old." : null);
243 				return Dummy.Value;
244 			}
245 
LoadLocal(Label pc, Local local, Dest dest, TextWriter data)246 			public Dummy LoadLocal (Label pc, Local local, Dest dest, TextWriter data)
247 			{
248 				data.WriteLine ("{0}{2} = ldloc {1}", this.prefix, this.meta_data_provider.Name (local), DestName (dest));
249 				return Dummy.Value;
250 			}
251 
LoadLocalAddress(Label pc, Local local, Dest dest, TextWriter data)252 			public Dummy LoadLocalAddress (Label pc, Local local, Dest dest, TextWriter data)
253 			{
254 				data.WriteLine ("{0}{2} = ldloca {1}", this.prefix, this.meta_data_provider.Name (local), DestName (dest));
255 				return Dummy.Value;
256 			}
257 
Nop(Label pc, TextWriter data)258 			public Dummy Nop (Label pc, TextWriter data)
259 			{
260 				data.WriteLine ("{0}nop", this.prefix);
261 				return Dummy.Value;
262 			}
263 
Pop(Label pc, Source source, TextWriter data)264 			public Dummy Pop (Label pc, Source source, TextWriter data)
265 			{
266 				data.WriteLine ("{0}pop {1}", this.prefix, SourceName (source));
267 				return Dummy.Value;
268 			}
269 
Return(Label pc, Source source, TextWriter data)270 			public Dummy Return (Label pc, Source source, TextWriter data)
271 			{
272 				data.WriteLine ("{0}ret {1}", this.prefix, SourceName (source));
273 				return Dummy.Value;
274 			}
275 
StoreArg(Label pc, Parameter argument, Source source, TextWriter data)276 			public Dummy StoreArg (Label pc, Parameter argument, Source source, TextWriter data)
277 			{
278 				data.WriteLine ("{0}starg {1} {2}", this.prefix, this.meta_data_provider.Name (argument), SourceName (source));
279 				return Dummy.Value;
280 			}
281 
StoreLocal(Label pc, Local local, Source source, TextWriter data)282 			public Dummy StoreLocal (Label pc, Local local, Source source, TextWriter data)
283 			{
284 				data.WriteLine ("{0}stloc {1} {2}", this.prefix, this.meta_data_provider.Name (local), SourceName (source));
285 				return Dummy.Value;
286 			}
287 
Switch(Label pc, TypeNode type, IEnumerable<Pair<object, Label>> cases, Source value, TextWriter data)288 			public Dummy Switch (Label pc, TypeNode type, IEnumerable<Pair<object, Label>> cases, Source value, TextWriter data)
289 			{
290 				data.WriteLine ("{0}switch {1}", this.prefix, SourceName (value));
291 				return Dummy.Value;
292 			}
293 
Box(Label pc, TypeNode type, Dest dest, Source source, TextWriter data)294 			public Dummy Box (Label pc, TypeNode type, Dest dest, Source source, TextWriter data)
295 			{
296 				data.WriteLine ("{0}{2} = box {1} {3}", this.prefix, this.meta_data_provider.FullName (type), DestName (dest), SourceName (source));
297 				return Dummy.Value;
298 			}
299 
300 			public Dummy ConstrainedCallvirt<TypeList, ArgList> (Label pc, Method method, TypeNode constraint, TypeList extraVarargs, Dest dest, ArgList args, TextWriter data)
301 				where TypeList : IIndexable<TypeNode> where ArgList : IIndexable<Source>
302 			{
303 				data.Write ("{0}{3} = constrained({1}).callvirt {2}(", this.prefix, this.meta_data_provider.FullName (constraint), this.meta_data_provider.FullName (method), DestName (dest));
304 				if (args != null) {
305 					for (int i = 0; i < args.Count; i++)
306 						data.Write ("{0} ", SourceName (args [i]));
307 				}
308 				data.WriteLine (")");
309 				return Dummy.Value;
310 			}
311 
CastClass(Label pc, TypeNode type, Dest dest, Source obj, TextWriter data)312 			public Dummy CastClass (Label pc, TypeNode type, Dest dest, Source obj, TextWriter data)
313 			{
314 				data.WriteLine ("{0}{2} = castclass {1} {3}", this.prefix, this.meta_data_provider.FullName (type), DestName (dest), SourceName (obj));
315 				return Dummy.Value;
316 			}
317 
CopyObj(Label pc, TypeNode type, Source destPtr, Source sourcePtr, TextWriter data)318 			public Dummy CopyObj (Label pc, TypeNode type, Source destPtr, Source sourcePtr, TextWriter data)
319 			{
320 				data.WriteLine ("{0}cpobj {1} {2} {3}", this.prefix, this.meta_data_provider.FullName (type), SourceName (destPtr), SourceName (sourcePtr));
321 				return Dummy.Value;
322 			}
323 
Initobj(Label pc, TypeNode type, Source ptr, TextWriter data)324 			public Dummy Initobj (Label pc, TypeNode type, Source ptr, TextWriter data)
325 			{
326 				data.WriteLine ("{0}initobj {1} {2}", this.prefix, this.meta_data_provider.FullName (type), SourceName (ptr));
327 				return Dummy.Value;
328 			}
329 
LoadElement(Label pc, TypeNode type, Dest dest, Source array, Source index, TextWriter data)330 			public Dummy LoadElement (Label pc, TypeNode type, Dest dest, Source array, Source index, TextWriter data)
331 			{
332 				data.WriteLine ("{0}{2} = ldelem {1} {3}[{4}]", this.prefix, this.meta_data_provider.FullName (type), DestName (dest), SourceName (array), SourceName (index));
333 				return Dummy.Value;
334 			}
335 
LoadField(Label pc, Field field, Dest dest, Source obj, TextWriter data)336 			public Dummy LoadField (Label pc, Field field, Dest dest, Source obj, TextWriter data)
337 			{
338 				data.WriteLine ("{0}{2} = ldfld {1} {3}", this.prefix, this.meta_data_provider.Name (field), DestName (dest), SourceName (obj));
339 				return Dummy.Value;
340 			}
341 
LoadFieldAddress(Label pc, Field field, Dest dest, Source obj, TextWriter data)342 			public Dummy LoadFieldAddress (Label pc, Field field, Dest dest, Source obj, TextWriter data)
343 			{
344 				data.WriteLine ("{0}{2} = ldflda {1} {3}", this.prefix, this.meta_data_provider.Name (field), DestName (dest), SourceName (obj));
345 				return Dummy.Value;
346 			}
347 
LoadLength(Label pc, Dest dest, Source array, TextWriter data)348 			public Dummy LoadLength (Label pc, Dest dest, Source array, TextWriter data)
349 			{
350 				data.WriteLine ("{0}{1} = ldlen {2}", this.prefix, DestName (dest), SourceName (array));
351 				return Dummy.Value;
352 			}
353 
LoadStaticField(Label pc, Field field, Dest dest, TextWriter data)354 			public Dummy LoadStaticField (Label pc, Field field, Dest dest, TextWriter data)
355 			{
356 				data.WriteLine ("{0}{2} = ldsfld {1}", this.prefix, this.meta_data_provider.Name (field), DestName (dest));
357 				return Dummy.Value;
358 			}
359 
LoadStaticFieldAddress(Label pc, Field field, Dest dest, TextWriter data)360 			public Dummy LoadStaticFieldAddress (Label pc, Field field, Dest dest, TextWriter data)
361 			{
362 				data.WriteLine ("{0}{2} = ldsflda {1}", this.prefix, this.meta_data_provider.Name (field), DestName (dest));
363 				return Dummy.Value;
364 			}
365 
LoadTypeToken(Label pc, TypeNode type, Dest dest, TextWriter data)366 			public Dummy LoadTypeToken (Label pc, TypeNode type, Dest dest, TextWriter data)
367 			{
368 				throw new NotImplementedException ();
369 			}
370 
LoadFieldToken(Label pc, Field type, Dest dest, TextWriter data)371 			public Dummy LoadFieldToken (Label pc, Field type, Dest dest, TextWriter data)
372 			{
373 				throw new NotImplementedException ();
374 			}
375 
LoadMethodToken(Label pc, Method type, Dest dest, TextWriter data)376 			public Dummy LoadMethodToken (Label pc, Method type, Dest dest, TextWriter data)
377 			{
378 				throw new NotImplementedException ();
379 			}
380 
381 			public Dummy NewArray<ArgList> (Label pc, TypeNode type, Dest dest, ArgList lengths, TextWriter data) where ArgList : IIndexable<Source>
382 			{
383 				throw new NotImplementedException ();
384 			}
385 
386 			public Dummy NewObj<ArgList> (Label pc, Method ctor, Dest dest, ArgList args, TextWriter data) where ArgList : IIndexable<Source>
387 			{
388 				data.Write ("{0}{2} = newobj {1}(", this.prefix, this.meta_data_provider.FullName (ctor), DestName (dest));
389 				if (args != null) {
390 					for (int i = 0; i < args.Count; ++i)
391 						data.Write ("{0} ", SourceName (args [i]));
392 				}
393 
394 				data.WriteLine (")");
395 				return Dummy.Value;
396 			}
397 
MkRefAny(Label pc, TypeNode type, Dest dest, Source obj, TextWriter data)398 			public Dummy MkRefAny (Label pc, TypeNode type, Dest dest, Source obj, TextWriter data)
399 			{
400 				throw new NotImplementedException ();
401 			}
402 
RefAnyType(Label pc, Dest dest, Source source, TextWriter data)403 			public Dummy RefAnyType (Label pc, Dest dest, Source source, TextWriter data)
404 			{
405 				throw new NotImplementedException ();
406 			}
407 
RefAnyVal(Label pc, TypeNode type, Dest dest, Source source, TextWriter data)408 			public Dummy RefAnyVal (Label pc, TypeNode type, Dest dest, Source source, TextWriter data)
409 			{
410 				throw new NotImplementedException ();
411 			}
412 
Rethrow(Label pc, TextWriter data)413 			public Dummy Rethrow (Label pc, TextWriter data)
414 			{
415 				throw new NotImplementedException ();
416 			}
417 
StoreElement(Label pc, TypeNode type, Source array, Source index, Source value, TextWriter data)418 			public Dummy StoreElement (Label pc, TypeNode type, Source array, Source index, Source value, TextWriter data)
419 			{
420 				throw new NotImplementedException ();
421 			}
422 
StoreField(Label pc, Field field, Source obj, Source value, TextWriter data)423 			public Dummy StoreField (Label pc, Field field, Source obj, Source value, TextWriter data)
424 			{
425 				data.WriteLine ("{0}stfld {1} {2} {3}", this.prefix, this.meta_data_provider.Name (field), SourceName (obj), SourceName (value));
426 				return Dummy.Value;
427 			}
428 
StoreStaticField(Label pc, Field field, Source value, TextWriter data)429 			public Dummy StoreStaticField (Label pc, Field field, Source value, TextWriter data)
430 			{
431 				data.WriteLine ("{0}stsfld {1} {2}", this.prefix, this.meta_data_provider.Name (field), SourceName (value));
432 				return Dummy.Value;
433 			}
434 
Throw(Label pc, Source exception, TextWriter data)435 			public Dummy Throw (Label pc, Source exception, TextWriter data)
436 			{
437 				throw new NotImplementedException ();
438 			}
439 
Unbox(Label pc, TypeNode type, Dest dest, Source obj, TextWriter data)440 			public Dummy Unbox (Label pc, TypeNode type, Dest dest, Source obj, TextWriter data)
441 			{
442 				throw new NotImplementedException ();
443 			}
444 
UnboxAny(Label pc, TypeNode type, Dest dest, Source obj, TextWriter data)445 			public Dummy UnboxAny (Label pc, TypeNode type, Dest dest, Source obj, TextWriter data)
446 			{
447 				throw new NotImplementedException ();
448 			}
449 			#endregion
450 
PrintCodeAt(Label label, string prefix, TextWriter tw)451 			public void PrintCodeAt (Label label, string prefix, TextWriter tw)
452 			{
453 				this.prefix = prefix;
454 				this.il_decoder.ForwardDecode<TextWriter, Dummy, Printer<Label, Source, Dest, Context, EdgeData>> (label, this, tw);
455 			}
456 
SourceName(Source src)457 			private string SourceName (Source src)
458 			{
459 				return this.source_to_string != null ? this.source_to_string (src) : null;
460 			}
461 
DestName(Dest dest)462 			private string DestName (Dest dest)
463 			{
464 				return this.dest_to_string != null ? this.dest_to_string (dest) : null;
465 			}
466 		}
467 		#endregion
468 	}
469 }
470