From 2c0d6517565ff0e6ee60470b2d28ec8381734b24 Mon Sep 17 00:00:00 2001 From: Michael Becker Date: Thu, 29 Apr 2021 23:02:32 -0400 Subject: [PATCH] refactor .NET-specific CodeProvider code into separate ILCodeProvider class --- .../Editors/Executable/CodeProvider.cs | 287 +------------ .../CodeProviders/CSharpCodeProvider.cs | 80 +--- .../CodeProviders/ILCodeProvider.cs | 394 ++++++++++++++++++ .../CodeProviders/VisualBasicCodeProvider.cs | 61 ++- ...or.Plugins.Executable.UserInterface.csproj | 1 + 5 files changed, 456 insertions(+), 367 deletions(-) create mode 100644 Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/Editors/Executable/CodeProviders/ILCodeProvider.cs diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/Editors/Executable/CodeProvider.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/Editors/Executable/CodeProvider.cs index 2bad6921..1b0fc2a2 100644 --- a/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/Editors/Executable/CodeProvider.cs +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/Editors/Executable/CodeProvider.cs @@ -33,7 +33,7 @@ namespace UniversalEditor.Plugins.Executable.UserInterface.Editors.Executable /// /// Gets the /// - /// The CS harp. + /// The C# code provider. public static CodeProviders.CSharpCodeProvider CSharp { get; } = new CodeProviders.CSharpCodeProvider(); public abstract string Title { get; } @@ -186,290 +186,5 @@ namespace UniversalEditor.Plugins.Executable.UserInterface.Editors.Executable { return GetMethodSignatureInternal(mi); } - - private static BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; - - public MethodInfo[] GetMethods(Type type) - { - MethodInfo[] meths = type.GetMethods(bindingFlags); - List list = new List(); - for (int j = 0; j < meths.Length; j++) - { - if (meths[j].IsSpecialName && (meths[j].Name.StartsWith("set_", StringComparison.OrdinalIgnoreCase) || meths[j].Name.StartsWith("get_", StringComparison.OrdinalIgnoreCase)) && (type.GetProperty(meths[j].Name.Substring(4), bindingFlags) != null)) - { - // we can be REASONABLY sure that this is a property setter / getter, - // and as we've already gotten all the properties, ignore it - continue; - } - list.Add(meths[j]); - } - return list.ToArray(); - } - public FieldInfo[] GetFields(Type type, out List AutoPropertyNames) - { - List list = new List(); - AutoPropertyNames = new List(); - - FieldInfo[] fields = type.GetFields(bindingFlags); - for (int j = 0; j < fields.Length; j++) - { - if (fields[j].Name.StartsWith("<", StringComparison.OrdinalIgnoreCase) && fields[j].Name.Contains(">")) - { - // might be a backing field - int k__backingfield_name_start = fields[j].Name.IndexOf('<'); - int k__backingfield_name_end = fields[j].Name.IndexOf('>', k__backingfield_name_start); - - string k__backingfield_name = fields[j].Name.Substring(k__backingfield_name_start + 1, k__backingfield_name_end - k__backingfield_name_start - 1); - PropertyInfo pi = type.GetProperty(k__backingfield_name, bindingFlags); - if (pi != null) - { - AutoPropertyNames.Add(pi.Name); - continue; - } - } - else - { - list.Add(fields[j]); - } - } - return list.ToArray(); - } - - public string GetILOpcodeStr(short opcode) - { - return GetILOpcodeStr((ILOpcode)opcode); - } - public string GetILOpcodeStr(ILOpcode opcode) - { - switch (opcode) - { - case ILOpcode.Add: return "add"; - case ILOpcode.AddOvf: return "add.ovf"; - case ILOpcode.AddOvfUn: return "add.ovf.un"; - case ILOpcode.And: return "and"; - case ILOpcode.ArgList: return "arglist"; - case ILOpcode.Beq: return "beq "; - case ILOpcode.BeqS: return "beq "; - case ILOpcode.Bge: return "bge "; - case ILOpcode.BgeS: return "bge.s "; - case ILOpcode.BgeUn: return "bge.un "; - case ILOpcode.BgeUnS: return "bge.un.s "; - case ILOpcode.Bgt: return "bgt "; - case ILOpcode.BgtS: return "bgt.s "; - case ILOpcode.BgtUn: return "bgt.un "; - case ILOpcode.BgtUnS: return "bgt.un.s "; - case ILOpcode.Ble: return "ble "; - case ILOpcode.BleS: return "ble.s "; - case ILOpcode.BleUn: return "ble.un "; - case ILOpcode.BleUnS: return "ble.un.s "; - case ILOpcode.Blt: return "blt "; - case ILOpcode.BltS: return "blt.s "; - case ILOpcode.BltUn: return "blt.un "; - case ILOpcode.BltUnS: return "blt.un.s "; - case ILOpcode.BneUn: return "bne.un "; - case ILOpcode.BneUnS: return "bne.un.s "; - case ILOpcode.Box: return "box "; - case ILOpcode.Br: return "br "; - case ILOpcode.BrS: return "br.s "; - case ILOpcode.Break: return "break"; - case ILOpcode.BrFalse: return "brfalse "; - case ILOpcode.BrFalseS: return "brfalse.s "; - case ILOpcode.BrTrue: return "brtrue "; - case ILOpcode.BrTrueS: return "brtrue.s "; - case ILOpcode.Call: return "call "; - case ILOpcode.CallI: return "calli "; - case ILOpcode.CallVirt: return "callvirt "; - case ILOpcode.CastClass: return "castclass "; - case ILOpcode.Ceq: return "ceq"; - case ILOpcode.Cgt: return "cgt"; - case ILOpcode.CgtUn: return "cgt.un"; - case ILOpcode.CkFinite: return "ckfinite"; - case ILOpcode.Clt: return "clt"; - case ILOpcode.CltUn: return "clt.un"; - case ILOpcode.Constrained: return "constrained "; - case ILOpcode.ConvI: return "conv.i"; - case ILOpcode.ConvI1: return "conv.i1"; - case ILOpcode.ConvI2: return "conv.i2"; - case ILOpcode.ConvI4: return "conv.i4"; - case ILOpcode.ConvI8: return "conv.i8"; - case ILOpcode.ConvOvfI: return "conv.ovf.i"; - case ILOpcode.ConvOvfIUn: return "conv.ovf.i.un"; - case ILOpcode.ConvOvfI1: return "conv.ovf.i1"; - case ILOpcode.ConvOvfI1Un: return "conv.ovf.i1.un"; - case ILOpcode.ConvOvfI2: return "conv.ovf.i2"; - case ILOpcode.ConvOvfI2Un: return "conv.ovf.i2.un"; - case ILOpcode.ConvOvfI4: return "conv.ovf.i4"; - case ILOpcode.ConvOvfI4Un: return "conv.ovf.i4.un"; - case ILOpcode.ConvOvfI8: return "conv.ovf.i8"; - case ILOpcode.ConvOvfI8Un: return "conv.ovf.i8.un"; - case ILOpcode.ConvOvfU: return "conv.ovf.u"; - case ILOpcode.ConvOvfUUn: return "conv.ovf.u.un"; - case ILOpcode.ConvOvfU1: return "conv.ovf.u1"; - case ILOpcode.ConvOvfU1Un: return "conv.ovf.u1.un"; - case ILOpcode.ConvOvfU2: return "conv.ovf.u2"; - case ILOpcode.ConvOvfU2Un: return "conv.ovf.u2.un"; - case ILOpcode.ConvOvfU4: return "conv.ovf.u4"; - case ILOpcode.ConvOvfU4Un: return "conv.ovf.u4.un"; - case ILOpcode.ConvOvfU8: return "conv.ovf.u8"; - case ILOpcode.ConvOvfU8Un: return "conv.ovf.u8.un"; - case ILOpcode.ConvRUn: return "conv.r.un"; - case ILOpcode.ConvR4: return "conv.r4"; - case ILOpcode.ConvR8: return "conv.r8"; - case ILOpcode.ConvU: return "conv.u"; - case ILOpcode.ConvU1: return "conv.u1"; - case ILOpcode.ConvU2: return "conv.u2"; - case ILOpcode.ConvU4: return "conv.u4"; - case ILOpcode.ConvU8: return "conv.u8"; - case ILOpcode.CpBlk: return "cpblk"; - case ILOpcode.CpObj: return "cpobj "; - case ILOpcode.Div: return "div"; - case ILOpcode.DivUn: return "div.un"; - case ILOpcode.Dup: return "dup"; - case ILOpcode.EndFault: return "endfault"; - case ILOpcode.EndFilter: return "endfilter"; - // case ILOpcode.EndFinally: return "endfinally"; // same as endfault? - case ILOpcode.InitBlk: return "initblk"; - case ILOpcode.InitObj: return "initobj "; - case ILOpcode.IsInst: return "isinst "; - case ILOpcode.Jmp: return "jmp"; - case ILOpcode.LdArg: return "ldarg "; - case ILOpcode.LdArg0: return "ldarg.0"; - case ILOpcode.LdArg1: return "ldarg.1"; - case ILOpcode.LdArg2: return "ldarg.2"; - case ILOpcode.LdArg3: return "ldarg.3"; - case ILOpcode.LdArgS: return "ldarg.s "; - case ILOpcode.LdArgA: return "ldarg.a "; - case ILOpcode.LdArgAS: return "ldarg.a.s "; - case ILOpcode.LdCI4: return "ldc.i4 "; - case ILOpcode.LdCI4_M1: return "ldc.i4.m1"; - case ILOpcode.LdCI4_0: return "ldc.i4.0"; - case ILOpcode.LdCI4_1: return "ldc.i4.1"; - case ILOpcode.LdCI4_2: return "ldc.i4.2"; - case ILOpcode.LdCI4_3: return "ldc.i4.3"; - case ILOpcode.LdCI4_4: return "ldc.i4.4"; - case ILOpcode.LdCI4_5: return "ldc.i4.5"; - case ILOpcode.LdCI4_6: return "ldc.i4.6"; - case ILOpcode.LdCI4_7: return "ldc.i4.7"; - case ILOpcode.LdCI4_8: return "ldc.i4.8"; - case ILOpcode.LdCI4S: return "ldc.i4.s "; - case ILOpcode.LdCI8: return "ldc.i8 "; - case ILOpcode.LdCR4: return "ldc.r4 "; - case ILOpcode.LdCR8: return "ldc.r8 "; - case ILOpcode.LdElem: return "ldelem "; - case ILOpcode.LdElemI: return "ldelem.i"; - case ILOpcode.LdElemI1: return "ldelem.i1"; - case ILOpcode.LdElemU1: return "ldelem.u1"; - case ILOpcode.LdElemI2: return "ldelem.i2"; - case ILOpcode.LdElemU2: return "ldelem.u2"; - case ILOpcode.LdElemI4: return "ldelem.i4"; - case ILOpcode.LdElemU4: return "ldelem.u4"; - case ILOpcode.LdElemI8: return "ldelem.i8"; - case ILOpcode.LdElemR4: return "ldelem.r4"; - case ILOpcode.LdElemR8: return "ldelem.r8"; - case ILOpcode.LdElemRef: return "ldelem.ref"; - case ILOpcode.LdElemA: return "ldelema "; - case ILOpcode.LdFld: return "ldfld "; - case ILOpcode.LdFldA: return "ldflda "; - case ILOpcode.LdFtn: return "ldftn "; - case ILOpcode.LdIndI: return "ldind.i"; - case ILOpcode.LdIndI1: return "ldind.i1"; - case ILOpcode.LdIndU1: return "ldind.u1"; - case ILOpcode.LdIndI2: return "ldind.i2"; - case ILOpcode.LdIndU2: return "ldind.u2"; - case ILOpcode.LdIndI4: return "ldind.i4"; - case ILOpcode.LdIndU4: return "ldind.u4"; - case ILOpcode.LdIndI8: return "ldind.i8"; - case ILOpcode.LdIndR4: return "ldind.r4"; - case ILOpcode.LdIndR8: return "ldind.r8"; - case ILOpcode.LdLen: return "ldlen"; - case ILOpcode.LdLoc: return "ldloc "; - case ILOpcode.LdLoc0: return "ldloc.0"; - case ILOpcode.LdLoc1: return "ldloc.1"; - case ILOpcode.LdLoc2: return "ldloc.2"; - case ILOpcode.LdLoc3: return "ldloc.3"; - case ILOpcode.LdLocS: return "ldloc.s "; - case ILOpcode.LdLocA: return "ldloca "; - case ILOpcode.LdLocAS: return "ldloca.s "; - case ILOpcode.LdNull: return "ldnull"; - case ILOpcode.LdObj: return "ldobj "; - case ILOpcode.LdSFld: return "ldsfld "; - case ILOpcode.LdSFldA: return "ldsflda "; - case ILOpcode.LdStr: return "ldstr "; - case ILOpcode.LdToken: return "ldtoken "; - case ILOpcode.LdVirtFtn: return "ldvirtftn "; - case ILOpcode.Leave: return "leave "; - case ILOpcode.LeaveS: return "leave "; - case ILOpcode.LocAlloc: return "localloc"; - case ILOpcode.MkRefAny: return "mkrefany "; - case ILOpcode.Mul: return "mul"; - case ILOpcode.MulOvf: return "mul.ovf"; - case ILOpcode.MulOvfUn: return "mul.ovf.un"; - case ILOpcode.Neg: return "neg"; - case ILOpcode.NewArr: return "newarr "; - case ILOpcode.NewObj: return "newobj "; - case ILOpcode.No: return "no.{typecheck, rangecheck, nullcheck}"; - case ILOpcode.Nop: return "nop"; - case ILOpcode.Not: return "not"; - case ILOpcode.Or: return "or"; - case ILOpcode.Pop: return "pop"; - case ILOpcode.Readonly: return "readonly."; - case ILOpcode.RefAnyType: return "refanytype"; - case ILOpcode.RefAnyVal: return "refanyval "; - case ILOpcode.Rem: return "rem"; - case ILOpcode.RemUn: return "rem.un"; - case ILOpcode.Ret: return "ret"; - case ILOpcode.Rethrow: return "rethrow"; - case ILOpcode.Shl: return "shl"; - case ILOpcode.Shr: return "shl"; - case ILOpcode.ShrUn: return "shl"; - case ILOpcode.SizeOf: return "sizeof "; - case ILOpcode.StArg: return "starg "; - case ILOpcode.StArgS: return "starg.s "; - case ILOpcode.StElem: return "stelem "; - case ILOpcode.StElemI: return "stelem.i"; - case ILOpcode.StElemI1: return "stelem.i1"; - case ILOpcode.StElemI2: return "stelem.i2"; - case ILOpcode.StElemI4: return "stelem.i4"; - case ILOpcode.StElemI8: return "stelem.i8"; - case ILOpcode.StElemR4: return "stelem.r4"; - case ILOpcode.StElemR8: return "stelem.r8"; - case ILOpcode.StElemRef: return "stelem.ref"; - case ILOpcode.StFld: return "stfld "; - case ILOpcode.StIndI: return "stind.i"; - case ILOpcode.StIndI1: return "stind.i1"; - case ILOpcode.StIndI2: return "stind.i2"; - case ILOpcode.StIndI4: return "stind.i4"; - case ILOpcode.StIndI8: return "stind.i8"; - case ILOpcode.StIndR4: return "stind.r4"; - case ILOpcode.StIndR8: return "stind.r8"; - case ILOpcode.StIndRef: return "stind.ref"; - case ILOpcode.StLoc: return "stloc "; - case ILOpcode.StLoc0: return "stloc.0"; - case ILOpcode.StLoc1: return "stloc.1"; - case ILOpcode.StLoc2: return "stloc.2"; - case ILOpcode.StLoc3: return "stloc.3"; - case ILOpcode.StLocS: return "stloc.s "; - case ILOpcode.StObj: return "stobj "; - case ILOpcode.StSFld: return "stsfld "; - case ILOpcode.Sub: return "sub"; - case ILOpcode.SubOvf: return "sub.ovf"; - case ILOpcode.SubOvfUn: return "sub.ovf.un"; - case ILOpcode.Switch: return "switch "; - case ILOpcode.Tail: return "tail."; - case ILOpcode.Throw: return "throw"; - case ILOpcode.Unaligned: return "unaligned.(alignment)"; - case ILOpcode.Unbox: return "unbox "; - case ILOpcode.UnboxAny: return "unbox.any "; - case ILOpcode.Volatile: return "volatile."; - case ILOpcode.Xor: return "xor"; - } - return ""; - } - - public string GetVariableName(MethodInfo mi, LocalVariableInfo localVariableInfo) - { - // TODO: read the PDB file (if exists) to get the local variable info - return "local_" + localVariableInfo.LocalIndex.ToString(); - } } } diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/Editors/Executable/CodeProviders/CSharpCodeProvider.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/Editors/Executable/CodeProviders/CSharpCodeProvider.cs index 1c4621c1..083fde1a 100644 --- a/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/Editors/Executable/CodeProviders/CSharpCodeProvider.cs +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/Editors/Executable/CodeProviders/CSharpCodeProvider.cs @@ -31,7 +31,7 @@ namespace UniversalEditor.Plugins.Executable.UserInterface.Editors.Executable.Co /// /// Provides a that translates MSIL code into C#. /// - public class CSharpCodeProvider : CodeProvider + public class CSharpCodeProvider : ILCodeProvider { public override string Title => "C#"; public override string CodeFileExtension => ".cs"; @@ -191,84 +191,6 @@ namespace UniversalEditor.Plugins.Executable.UserInterface.Editors.Executable.Co return sb.ToString(); } - private int? OpcodeToLiteralInt(ILOpcode opcode) - { - switch (opcode) - { - case ILOpcode.LdCI4_0: - { - return 0; - } - case ILOpcode.LdCI4_1: - { - return 1; - } - case ILOpcode.LdCI4_2: - { - return 2; - } - case ILOpcode.LdCI4_3: - { - return 3; - } - case ILOpcode.LdCI4_4: - { - return 4; - } - case ILOpcode.LdCI4_5: - { - return 5; - } - case ILOpcode.LdCI4_6: - { - return 6; - } - case ILOpcode.LdCI4_7: - { - return 7; - } - case ILOpcode.LdCI4_8: - { - return 8; - } - case ILOpcode.LdCI4_M1: - { - return -1; - } - } - return null; - } - - private ILOpcode PeekOpcode(Reader r) - { - int sz = 0; - ILOpcode opcode = ReadOpcode(r, out sz); - if (sz == 0) - return opcode; - - r.Seek(-sz, SeekOrigin.Current); - return opcode; - } - private ILOpcode ReadOpcode(Reader r, out int size) - { - if (r.EndOfStream) - { - size = 0; - return ILOpcode.Nop; - } - - byte bytecode_b = r.ReadByte(); - short bytecode_s = bytecode_b; - size = 1; - - if (bytecode_s == 0xFE) - { - bytecode_s = BitConverter.ToInt16(new byte[] { bytecode_b, r.ReadByte() }, 0); - size = 2; - } - return (ILOpcode)bytecode_s; - } - protected override string GetSourceCodeInternal(FieldInfo fi, int indentLevel) { StringBuilder sb = new StringBuilder(); diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/Editors/Executable/CodeProviders/ILCodeProvider.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/Editors/Executable/CodeProviders/ILCodeProvider.cs new file mode 100644 index 00000000..eb32c3da --- /dev/null +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/Editors/Executable/CodeProviders/ILCodeProvider.cs @@ -0,0 +1,394 @@ +// +// ILCodeProvider.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2021 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using System.Collections.Generic; +using System.Reflection; +using UniversalEditor.IO; + +namespace UniversalEditor.Plugins.Executable.UserInterface.Editors.Executable.CodeProviders +{ + public abstract class ILCodeProvider : CodeProvider + { + protected int? OpcodeToLiteralInt(ILOpcode opcode) + { + switch (opcode) + { + case ILOpcode.LdCI4_0: + { + return 0; + } + case ILOpcode.LdCI4_1: + { + return 1; + } + case ILOpcode.LdCI4_2: + { + return 2; + } + case ILOpcode.LdCI4_3: + { + return 3; + } + case ILOpcode.LdCI4_4: + { + return 4; + } + case ILOpcode.LdCI4_5: + { + return 5; + } + case ILOpcode.LdCI4_6: + { + return 6; + } + case ILOpcode.LdCI4_7: + { + return 7; + } + case ILOpcode.LdCI4_8: + { + return 8; + } + case ILOpcode.LdCI4_M1: + { + return -1; + } + } + return null; + } + + protected ILOpcode PeekOpcode(Reader r) + { + int sz = 0; + ILOpcode opcode = ReadOpcode(r, out sz); + if (sz == 0) + return opcode; + + r.Seek(-sz, SeekOrigin.Current); + return opcode; + } + protected ILOpcode ReadOpcode(Reader r, out int size) + { + if (r.EndOfStream) + { + size = 0; + return ILOpcode.Nop; + } + + byte bytecode_b = r.ReadByte(); + short bytecode_s = bytecode_b; + size = 1; + + if (bytecode_s == 0xFE) + { + bytecode_s = BitConverter.ToInt16(new byte[] { bytecode_b, r.ReadByte() }, 0); + size = 2; + } + return (ILOpcode)bytecode_s; + } + + + private static BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; + + public MethodInfo[] GetMethods(Type type) + { + MethodInfo[] meths = type.GetMethods(bindingFlags); + List list = new List(); + for (int j = 0; j < meths.Length; j++) + { + if (meths[j].IsSpecialName && (meths[j].Name.StartsWith("set_", StringComparison.OrdinalIgnoreCase) || meths[j].Name.StartsWith("get_", StringComparison.OrdinalIgnoreCase)) && (type.GetProperty(meths[j].Name.Substring(4), bindingFlags) != null)) + { + // we can be REASONABLY sure that this is a property setter / getter, + // and as we've already gotten all the properties, ignore it + continue; + } + list.Add(meths[j]); + } + return list.ToArray(); + } + public FieldInfo[] GetFields(Type type, out List AutoPropertyNames) + { + List list = new List(); + AutoPropertyNames = new List(); + + FieldInfo[] fields = type.GetFields(bindingFlags); + for (int j = 0; j < fields.Length; j++) + { + if (fields[j].Name.StartsWith("<", StringComparison.OrdinalIgnoreCase) && fields[j].Name.Contains(">")) + { + // might be a backing field + int k__backingfield_name_start = fields[j].Name.IndexOf('<'); + int k__backingfield_name_end = fields[j].Name.IndexOf('>', k__backingfield_name_start); + + string k__backingfield_name = fields[j].Name.Substring(k__backingfield_name_start + 1, k__backingfield_name_end - k__backingfield_name_start - 1); + PropertyInfo pi = type.GetProperty(k__backingfield_name, bindingFlags); + if (pi != null) + { + AutoPropertyNames.Add(pi.Name); + continue; + } + } + else + { + list.Add(fields[j]); + } + } + return list.ToArray(); + } + + public string GetILOpcodeStr(short opcode) + { + return GetILOpcodeStr((ILOpcode)opcode); + } + public string GetILOpcodeStr(ILOpcode opcode) + { + switch (opcode) + { + case ILOpcode.Add: return "add"; + case ILOpcode.AddOvf: return "add.ovf"; + case ILOpcode.AddOvfUn: return "add.ovf.un"; + case ILOpcode.And: return "and"; + case ILOpcode.ArgList: return "arglist"; + case ILOpcode.Beq: return "beq "; + case ILOpcode.BeqS: return "beq "; + case ILOpcode.Bge: return "bge "; + case ILOpcode.BgeS: return "bge.s "; + case ILOpcode.BgeUn: return "bge.un "; + case ILOpcode.BgeUnS: return "bge.un.s "; + case ILOpcode.Bgt: return "bgt "; + case ILOpcode.BgtS: return "bgt.s "; + case ILOpcode.BgtUn: return "bgt.un "; + case ILOpcode.BgtUnS: return "bgt.un.s "; + case ILOpcode.Ble: return "ble "; + case ILOpcode.BleS: return "ble.s "; + case ILOpcode.BleUn: return "ble.un "; + case ILOpcode.BleUnS: return "ble.un.s "; + case ILOpcode.Blt: return "blt "; + case ILOpcode.BltS: return "blt.s "; + case ILOpcode.BltUn: return "blt.un "; + case ILOpcode.BltUnS: return "blt.un.s "; + case ILOpcode.BneUn: return "bne.un "; + case ILOpcode.BneUnS: return "bne.un.s "; + case ILOpcode.Box: return "box "; + case ILOpcode.Br: return "br "; + case ILOpcode.BrS: return "br.s "; + case ILOpcode.Break: return "break"; + case ILOpcode.BrFalse: return "brfalse "; + case ILOpcode.BrFalseS: return "brfalse.s "; + case ILOpcode.BrTrue: return "brtrue "; + case ILOpcode.BrTrueS: return "brtrue.s "; + case ILOpcode.Call: return "call "; + case ILOpcode.CallI: return "calli "; + case ILOpcode.CallVirt: return "callvirt "; + case ILOpcode.CastClass: return "castclass "; + case ILOpcode.Ceq: return "ceq"; + case ILOpcode.Cgt: return "cgt"; + case ILOpcode.CgtUn: return "cgt.un"; + case ILOpcode.CkFinite: return "ckfinite"; + case ILOpcode.Clt: return "clt"; + case ILOpcode.CltUn: return "clt.un"; + case ILOpcode.Constrained: return "constrained "; + case ILOpcode.ConvI: return "conv.i"; + case ILOpcode.ConvI1: return "conv.i1"; + case ILOpcode.ConvI2: return "conv.i2"; + case ILOpcode.ConvI4: return "conv.i4"; + case ILOpcode.ConvI8: return "conv.i8"; + case ILOpcode.ConvOvfI: return "conv.ovf.i"; + case ILOpcode.ConvOvfIUn: return "conv.ovf.i.un"; + case ILOpcode.ConvOvfI1: return "conv.ovf.i1"; + case ILOpcode.ConvOvfI1Un: return "conv.ovf.i1.un"; + case ILOpcode.ConvOvfI2: return "conv.ovf.i2"; + case ILOpcode.ConvOvfI2Un: return "conv.ovf.i2.un"; + case ILOpcode.ConvOvfI4: return "conv.ovf.i4"; + case ILOpcode.ConvOvfI4Un: return "conv.ovf.i4.un"; + case ILOpcode.ConvOvfI8: return "conv.ovf.i8"; + case ILOpcode.ConvOvfI8Un: return "conv.ovf.i8.un"; + case ILOpcode.ConvOvfU: return "conv.ovf.u"; + case ILOpcode.ConvOvfUUn: return "conv.ovf.u.un"; + case ILOpcode.ConvOvfU1: return "conv.ovf.u1"; + case ILOpcode.ConvOvfU1Un: return "conv.ovf.u1.un"; + case ILOpcode.ConvOvfU2: return "conv.ovf.u2"; + case ILOpcode.ConvOvfU2Un: return "conv.ovf.u2.un"; + case ILOpcode.ConvOvfU4: return "conv.ovf.u4"; + case ILOpcode.ConvOvfU4Un: return "conv.ovf.u4.un"; + case ILOpcode.ConvOvfU8: return "conv.ovf.u8"; + case ILOpcode.ConvOvfU8Un: return "conv.ovf.u8.un"; + case ILOpcode.ConvRUn: return "conv.r.un"; + case ILOpcode.ConvR4: return "conv.r4"; + case ILOpcode.ConvR8: return "conv.r8"; + case ILOpcode.ConvU: return "conv.u"; + case ILOpcode.ConvU1: return "conv.u1"; + case ILOpcode.ConvU2: return "conv.u2"; + case ILOpcode.ConvU4: return "conv.u4"; + case ILOpcode.ConvU8: return "conv.u8"; + case ILOpcode.CpBlk: return "cpblk"; + case ILOpcode.CpObj: return "cpobj "; + case ILOpcode.Div: return "div"; + case ILOpcode.DivUn: return "div.un"; + case ILOpcode.Dup: return "dup"; + case ILOpcode.EndFault: return "endfault"; + case ILOpcode.EndFilter: return "endfilter"; + // case ILOpcode.EndFinally: return "endfinally"; // same as endfault? + case ILOpcode.InitBlk: return "initblk"; + case ILOpcode.InitObj: return "initobj "; + case ILOpcode.IsInst: return "isinst "; + case ILOpcode.Jmp: return "jmp"; + case ILOpcode.LdArg: return "ldarg "; + case ILOpcode.LdArg0: return "ldarg.0"; + case ILOpcode.LdArg1: return "ldarg.1"; + case ILOpcode.LdArg2: return "ldarg.2"; + case ILOpcode.LdArg3: return "ldarg.3"; + case ILOpcode.LdArgS: return "ldarg.s "; + case ILOpcode.LdArgA: return "ldarg.a "; + case ILOpcode.LdArgAS: return "ldarg.a.s "; + case ILOpcode.LdCI4: return "ldc.i4 "; + case ILOpcode.LdCI4_M1: return "ldc.i4.m1"; + case ILOpcode.LdCI4_0: return "ldc.i4.0"; + case ILOpcode.LdCI4_1: return "ldc.i4.1"; + case ILOpcode.LdCI4_2: return "ldc.i4.2"; + case ILOpcode.LdCI4_3: return "ldc.i4.3"; + case ILOpcode.LdCI4_4: return "ldc.i4.4"; + case ILOpcode.LdCI4_5: return "ldc.i4.5"; + case ILOpcode.LdCI4_6: return "ldc.i4.6"; + case ILOpcode.LdCI4_7: return "ldc.i4.7"; + case ILOpcode.LdCI4_8: return "ldc.i4.8"; + case ILOpcode.LdCI4S: return "ldc.i4.s "; + case ILOpcode.LdCI8: return "ldc.i8 "; + case ILOpcode.LdCR4: return "ldc.r4 "; + case ILOpcode.LdCR8: return "ldc.r8 "; + case ILOpcode.LdElem: return "ldelem "; + case ILOpcode.LdElemI: return "ldelem.i"; + case ILOpcode.LdElemI1: return "ldelem.i1"; + case ILOpcode.LdElemU1: return "ldelem.u1"; + case ILOpcode.LdElemI2: return "ldelem.i2"; + case ILOpcode.LdElemU2: return "ldelem.u2"; + case ILOpcode.LdElemI4: return "ldelem.i4"; + case ILOpcode.LdElemU4: return "ldelem.u4"; + case ILOpcode.LdElemI8: return "ldelem.i8"; + case ILOpcode.LdElemR4: return "ldelem.r4"; + case ILOpcode.LdElemR8: return "ldelem.r8"; + case ILOpcode.LdElemRef: return "ldelem.ref"; + case ILOpcode.LdElemA: return "ldelema "; + case ILOpcode.LdFld: return "ldfld "; + case ILOpcode.LdFldA: return "ldflda "; + case ILOpcode.LdFtn: return "ldftn "; + case ILOpcode.LdIndI: return "ldind.i"; + case ILOpcode.LdIndI1: return "ldind.i1"; + case ILOpcode.LdIndU1: return "ldind.u1"; + case ILOpcode.LdIndI2: return "ldind.i2"; + case ILOpcode.LdIndU2: return "ldind.u2"; + case ILOpcode.LdIndI4: return "ldind.i4"; + case ILOpcode.LdIndU4: return "ldind.u4"; + case ILOpcode.LdIndI8: return "ldind.i8"; + case ILOpcode.LdIndR4: return "ldind.r4"; + case ILOpcode.LdIndR8: return "ldind.r8"; + case ILOpcode.LdLen: return "ldlen"; + case ILOpcode.LdLoc: return "ldloc "; + case ILOpcode.LdLoc0: return "ldloc.0"; + case ILOpcode.LdLoc1: return "ldloc.1"; + case ILOpcode.LdLoc2: return "ldloc.2"; + case ILOpcode.LdLoc3: return "ldloc.3"; + case ILOpcode.LdLocS: return "ldloc.s "; + case ILOpcode.LdLocA: return "ldloca "; + case ILOpcode.LdLocAS: return "ldloca.s "; + case ILOpcode.LdNull: return "ldnull"; + case ILOpcode.LdObj: return "ldobj "; + case ILOpcode.LdSFld: return "ldsfld "; + case ILOpcode.LdSFldA: return "ldsflda "; + case ILOpcode.LdStr: return "ldstr "; + case ILOpcode.LdToken: return "ldtoken "; + case ILOpcode.LdVirtFtn: return "ldvirtftn "; + case ILOpcode.Leave: return "leave "; + case ILOpcode.LeaveS: return "leave "; + case ILOpcode.LocAlloc: return "localloc"; + case ILOpcode.MkRefAny: return "mkrefany "; + case ILOpcode.Mul: return "mul"; + case ILOpcode.MulOvf: return "mul.ovf"; + case ILOpcode.MulOvfUn: return "mul.ovf.un"; + case ILOpcode.Neg: return "neg"; + case ILOpcode.NewArr: return "newarr "; + case ILOpcode.NewObj: return "newobj "; + case ILOpcode.No: return "no.{typecheck, rangecheck, nullcheck}"; + case ILOpcode.Nop: return "nop"; + case ILOpcode.Not: return "not"; + case ILOpcode.Or: return "or"; + case ILOpcode.Pop: return "pop"; + case ILOpcode.Readonly: return "readonly."; + case ILOpcode.RefAnyType: return "refanytype"; + case ILOpcode.RefAnyVal: return "refanyval "; + case ILOpcode.Rem: return "rem"; + case ILOpcode.RemUn: return "rem.un"; + case ILOpcode.Ret: return "ret"; + case ILOpcode.Rethrow: return "rethrow"; + case ILOpcode.Shl: return "shl"; + case ILOpcode.Shr: return "shl"; + case ILOpcode.ShrUn: return "shl"; + case ILOpcode.SizeOf: return "sizeof "; + case ILOpcode.StArg: return "starg "; + case ILOpcode.StArgS: return "starg.s "; + case ILOpcode.StElem: return "stelem "; + case ILOpcode.StElemI: return "stelem.i"; + case ILOpcode.StElemI1: return "stelem.i1"; + case ILOpcode.StElemI2: return "stelem.i2"; + case ILOpcode.StElemI4: return "stelem.i4"; + case ILOpcode.StElemI8: return "stelem.i8"; + case ILOpcode.StElemR4: return "stelem.r4"; + case ILOpcode.StElemR8: return "stelem.r8"; + case ILOpcode.StElemRef: return "stelem.ref"; + case ILOpcode.StFld: return "stfld "; + case ILOpcode.StIndI: return "stind.i"; + case ILOpcode.StIndI1: return "stind.i1"; + case ILOpcode.StIndI2: return "stind.i2"; + case ILOpcode.StIndI4: return "stind.i4"; + case ILOpcode.StIndI8: return "stind.i8"; + case ILOpcode.StIndR4: return "stind.r4"; + case ILOpcode.StIndR8: return "stind.r8"; + case ILOpcode.StIndRef: return "stind.ref"; + case ILOpcode.StLoc: return "stloc "; + case ILOpcode.StLoc0: return "stloc.0"; + case ILOpcode.StLoc1: return "stloc.1"; + case ILOpcode.StLoc2: return "stloc.2"; + case ILOpcode.StLoc3: return "stloc.3"; + case ILOpcode.StLocS: return "stloc.s "; + case ILOpcode.StObj: return "stobj "; + case ILOpcode.StSFld: return "stsfld "; + case ILOpcode.Sub: return "sub"; + case ILOpcode.SubOvf: return "sub.ovf"; + case ILOpcode.SubOvfUn: return "sub.ovf.un"; + case ILOpcode.Switch: return "switch "; + case ILOpcode.Tail: return "tail."; + case ILOpcode.Throw: return "throw"; + case ILOpcode.Unaligned: return "unaligned.(alignment)"; + case ILOpcode.Unbox: return "unbox "; + case ILOpcode.UnboxAny: return "unbox.any "; + case ILOpcode.Volatile: return "volatile."; + case ILOpcode.Xor: return "xor"; + } + return ""; + } + + public string GetVariableName(MethodInfo mi, LocalVariableInfo localVariableInfo) + { + // TODO: read the PDB file (if exists) to get the local variable info + return "local_" + localVariableInfo.LocalIndex.ToString(); + } + } +} diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/Editors/Executable/CodeProviders/VisualBasicCodeProvider.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/Editors/Executable/CodeProviders/VisualBasicCodeProvider.cs index 26852377..06d1c497 100644 --- a/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/Editors/Executable/CodeProviders/VisualBasicCodeProvider.cs +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/Editors/Executable/CodeProviders/VisualBasicCodeProvider.cs @@ -22,13 +22,15 @@ using System; using System.Reflection; using System.Text; +using UniversalEditor.Accessors; +using UniversalEditor.IO; namespace UniversalEditor.Plugins.Executable.UserInterface.Editors.Executable.CodeProviders { /// /// Provides a that translates MSIL code into VB.NET. /// - public class VisualBasicCodeProvider : CodeProvider + public class VisualBasicCodeProvider : ILCodeProvider { public override string Title => "VB.NET"; public override string CodeFileExtension => ".vb"; @@ -185,7 +187,62 @@ namespace UniversalEditor.Plugins.Executable.UserInterface.Editors.Executable.Co } protected override string GetSourceCodeInternal(MethodInfo mi, int indentLevel) { - throw new NotImplementedException(); + StringBuilder sb = new StringBuilder(); + string indentStr = new string('\t', indentLevel); + sb.Append(indentStr); + sb.Append(GetMethodSignature(mi)); + + MethodBody mb = mi.GetMethodBody(); + if (mb != null) + { + sb.AppendLine(); + sb.Append(GetBeginBlock(mi, indentLevel)); + sb.AppendLine(); + + for (int i = 0; i < mb.LocalVariables.Count; i++) + { + sb.Append(new string('\t', indentLevel + 1)); + sb.Append("Dim "); + sb.Append(GetVariableName(mi, mb.LocalVariables[i])); + sb.Append(" As "); + sb.Append(GetTypeName(mb.LocalVariables[i].LocalType)); + sb.AppendLine(); + } + + if (mb.LocalVariables.Count > 0) + sb.AppendLine(); + + byte[] bytecode = mb.GetILAsByteArray(); + MemoryAccessor ma = new MemoryAccessor(bytecode); + Reader r = new Reader(ma); + while (!r.EndOfStream) + { + int sz = 0; + ILOpcode opcode = ReadOpcode(r, out sz); + ILOpcode opcode2 = PeekOpcode(r); + + sb.Append(new string('\t', indentLevel + 1)); + + + if (opcode2 == ILOpcode.NewArr) + { + int? lit = OpcodeToLiteralInt(opcode); + sb.Append(String.Format("Dim X As **TYPE**() = New X({0})", lit.GetValueOrDefault(0))); + } + else + { + sb.AppendLine(GetILOpcodeStr(opcode)); + continue; + } + } + + sb.Append(GetEndBlock(mi, indentLevel)); + } + else + { + sb.Append(';'); + } + return sb.ToString(); } protected override string GetMethodSignatureInternal(MethodInfo mi) diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/UniversalEditor.Plugins.Executable.UserInterface.csproj b/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/UniversalEditor.Plugins.Executable.UserInterface.csproj index 76eb7e81..24a7abb2 100644 --- a/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/UniversalEditor.Plugins.Executable.UserInterface.csproj +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Executable.UserInterface/UniversalEditor.Plugins.Executable.UserInterface.csproj @@ -37,6 +37,7 @@ +