Engine.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSim Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. /* Original code: Tedd Hansen */
  28. using System;
  29. using System.IO;
  30. using System.Reflection;
  31. using System.Reflection.Emit;
  32. using System.Text;
  33. using System.Threading;
  34. using OpenSim.Region.ScriptEngine.Common;
  35. namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO
  36. {
  37. public class Engine
  38. {
  39. //private string LSO_FileName = @"LSO\AdditionTest.lso";
  40. private string LSO_FileName; // = @"LSO\CloseToDefault.lso";
  41. private AppDomain appDomain;
  42. public string Compile(string LSOFileName)
  43. {
  44. LSO_FileName = LSOFileName;
  45. //appDomain = AppDomain.CreateDomain("AlternateAppDomain");
  46. appDomain = Thread.GetDomain();
  47. // Create Assembly Name
  48. AssemblyName asmName = new AssemblyName();
  49. asmName.Name = Path.GetFileNameWithoutExtension(LSO_FileName);
  50. //asmName.Name = "TestAssembly";
  51. string DLL_FileName = asmName.Name + ".dll";
  52. string DLL_FileName_WithPath = Path.GetDirectoryName(LSO_FileName) + @"\" + DLL_FileName;
  53. Common.SendToLog("LSO File Name: " + Path.GetFileName(LSO_FileName));
  54. Common.SendToLog("Assembly name: " + asmName.Name);
  55. Common.SendToLog("Assembly File Name: " + asmName.Name + ".dll");
  56. Common.SendToLog("Starting processing of LSL ByteCode...");
  57. Common.SendToLog(String.Empty);
  58. // Create Assembly
  59. AssemblyBuilder asmBuilder = appDomain.DefineDynamicAssembly(
  60. asmName,
  61. AssemblyBuilderAccess.RunAndSave
  62. );
  63. //// Create Assembly
  64. //AssemblyBuilder asmBuilder =
  65. // Thread.GetDomain().DefineDynamicAssembly
  66. //(asmName, AssemblyBuilderAccess.RunAndSave);
  67. // Create a module (and save to disk)
  68. ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule
  69. (asmName.Name,
  70. DLL_FileName);
  71. //Common.SendToDebug("asmName.Name is still \String.Empty + asmName.Name + "\String.Empty);
  72. // Create a Class (/Type)
  73. TypeBuilder typeBuilder = modBuilder.DefineType(
  74. "LSL_ScriptObject",
  75. TypeAttributes.Public | TypeAttributes.BeforeFieldInit,
  76. typeof (BuiltIn_Commands_BaseClass));
  77. //,
  78. // typeof());
  79. //, typeof(LSL_BuiltIn_Commands_Interface));
  80. //,
  81. // typeof(object),
  82. // new Type[] { typeof(LSL_CLRInterface.LSLScript) });
  83. /*
  84. * Generate the IL itself
  85. */
  86. LSO_Parser LSOP = new LSO_Parser(LSO_FileName, typeBuilder);
  87. LSOP.OpenFile();
  88. LSOP.Parse();
  89. // Constructor has to be created AFTER LSO_Parser because of accumulated variables
  90. if (Common.IL_CreateConstructor)
  91. IL_CREATE_CONSTRUCTOR(typeBuilder, LSOP);
  92. LSOP.CloseFile();
  93. /*
  94. * Done generating. Create a type and run it.
  95. */
  96. Common.SendToLog("Attempting to compile assembly...");
  97. // Compile it
  98. Type type = typeBuilder.CreateType();
  99. Common.SendToLog("Compilation successful!");
  100. Common.SendToLog("Saving assembly: " + DLL_FileName);
  101. asmBuilder.Save(DLL_FileName);
  102. Common.SendToLog("Returning assembly filename: " + DLL_FileName);
  103. return DLL_FileName;
  104. //Common.SendToLog("Creating an instance of new assembly...");
  105. //// Create an instance we can play with
  106. ////LSLScript hello = (LSLScript)Activator.CreateInstance(type);
  107. ////LSL_CLRInterface.LSLScript MyScript = (LSL_CLRInterface.LSLScript)Activator.CreateInstance(type);
  108. //object MyScript = (object)Activator.CreateInstance(type);
  109. //System.Reflection.MemberInfo[] Members = type.GetMembers();
  110. //Common.SendToLog("Members of assembly " + type.ToString() + ":");
  111. //foreach (MemberInfo member in Members)
  112. // Common.SendToLog(member.ToString());
  113. //// Play with it
  114. ////MyScript.event_state_entry("Test");
  115. //object[] args = { null };
  116. ////System.Collections.Generic.List<string> Functions = (System.Collections.Generic.List<string>)type.InvokeMember("GetFunctions", BindingFlags.InvokeMethod, null, MyScript, null);
  117. //string[] ret = { };
  118. //if (Common.IL_CreateFunctionList)
  119. // ret = (string[])type.InvokeMember("GetFunctions", BindingFlags.InvokeMethod, null, MyScript, null);
  120. //foreach (string s in ret)
  121. //{
  122. // Common.SendToLog(String.Empty);
  123. // Common.SendToLog("*** Executing LSL Server Event: " + s);
  124. // //object test = type.GetMember(s);
  125. // //object runner = type.InvokeMember(s, BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, MyScript, args);
  126. // //runner();
  127. // //objBooks_Late = type.InvokeMember(s, BindingFlags.CreateInstance, null, objApp_Late, null);
  128. // type.InvokeMember(s, BindingFlags.InvokeMethod, null, MyScript, new object[] { "Test" });
  129. //}
  130. }
  131. private static void IL_CREATE_CONSTRUCTOR(TypeBuilder typeBuilder, LSO_Parser LSOP)
  132. {
  133. Common.SendToDebug("IL_CREATE_CONSTRUCTOR()");
  134. //ConstructorBuilder constructor = typeBuilder.DefineConstructor(
  135. // MethodAttributes.Public,
  136. // CallingConventions.Standard,
  137. // new Type[0]);
  138. ConstructorBuilder constructor = typeBuilder.DefineConstructor(
  139. MethodAttributes.Public |
  140. MethodAttributes.SpecialName |
  141. MethodAttributes.RTSpecialName,
  142. CallingConventions.Standard,
  143. new Type[0]);
  144. //Define the reflection ConstructorInfor for System.Object
  145. ConstructorInfo conObj = typeof (BuiltIn_Commands_BaseClass).GetConstructor(new Type[0]);
  146. //call constructor of base object
  147. ILGenerator il = constructor.GetILGenerator();
  148. il.Emit(OpCodes.Ldarg_0);
  149. il.Emit(OpCodes.Call, conObj);
  150. //Common.SendToDebug("IL_CREATE_CONSTRUCTOR: Creating global: UInt32 State = 0;");
  151. //string FieldName;
  152. //// Create state object
  153. //FieldName = "State";
  154. //FieldBuilder State_fb = typeBuilder.DefineField(
  155. // FieldName,
  156. // typeof(UInt32),
  157. // FieldAttributes.Public);
  158. //il.Emit(OpCodes.Ldarg_0);
  159. //il.Emit(OpCodes.Ldc_I4, 0);
  160. //il.Emit(OpCodes.Stfld, State_fb);
  161. //Common.SendToDebug("IL_CREATE_CONSTRUCTOR: Creating global: LSL_BuiltIn_Commands_TestImplementation LSL_BuiltIns = New LSL_BuiltIn_Commands_TestImplementation();");
  162. ////Type objType1 = typeof(object);
  163. //Type objType1 = typeof(LSL_BuiltIn_Commands_TestImplementation);
  164. //FieldName = "LSL_BuiltIns";
  165. //FieldBuilder LSL_BuiltIns_fb = typeBuilder.DefineField(
  166. // FieldName,
  167. // objType1,
  168. // FieldAttributes.Public);
  169. ////LSL_BuiltIn_Commands_TestImplementation _ti = new LSL_BuiltIn_Commands_TestImplementation();
  170. //il.Emit(OpCodes.Ldarg_0);
  171. ////il.Emit(OpCodes.Ldstr, "Test 123");
  172. //il.Emit(OpCodes.Newobj, objType1.GetConstructor(new Type[] { }));
  173. //il.Emit(OpCodes.Stfld, LSL_BuiltIns_fb);
  174. foreach (UInt32 pos in LSOP.StaticBlocks.Keys)
  175. {
  176. LSO_Struct.StaticBlock sb;
  177. LSOP.StaticBlocks.TryGetValue(pos, out sb);
  178. if (sb.ObjectType > 0 && sb.ObjectType < 8)
  179. {
  180. // We don't want void or null's
  181. il.Emit(OpCodes.Ldarg_0);
  182. // Push position to stack
  183. il.Emit(OpCodes.Ldc_I4, pos);
  184. //il.Emit(OpCodes.Box, typeof(UInt32));
  185. Type datatype = null;
  186. // Push data to stack
  187. Common.SendToDebug("Adding to static (" + pos + ") type: " +
  188. ((LSO_Enums.Variable_Type_Codes) sb.ObjectType).ToString() + " (" + sb.ObjectType +
  189. ")");
  190. switch ((LSO_Enums.Variable_Type_Codes) sb.ObjectType)
  191. {
  192. case LSO_Enums.Variable_Type_Codes.Float:
  193. case LSO_Enums.Variable_Type_Codes.Integer:
  194. //UInt32
  195. il.Emit(OpCodes.Ldc_I4, BitConverter.ToUInt32(sb.BlockVariable, 0));
  196. datatype = typeof (UInt32);
  197. il.Emit(OpCodes.Box, datatype);
  198. break;
  199. case LSO_Enums.Variable_Type_Codes.String:
  200. case LSO_Enums.Variable_Type_Codes.Key:
  201. //String
  202. LSO_Struct.HeapBlock hb =
  203. LSOP.GetHeap(LSOP.myHeader.HR + BitConverter.ToUInt32(sb.BlockVariable, 0) - 1);
  204. il.Emit(OpCodes.Ldstr, Encoding.UTF8.GetString(hb.Data));
  205. datatype = typeof (string);
  206. break;
  207. case LSO_Enums.Variable_Type_Codes.Vector:
  208. datatype = typeof (LSO_Enums.Vector);
  209. //TODO: Not implemented
  210. break;
  211. case LSO_Enums.Variable_Type_Codes.Rotation:
  212. //Object
  213. //TODO: Not implemented
  214. datatype = typeof (LSO_Enums.Rotation);
  215. break;
  216. default:
  217. datatype = typeof (object);
  218. break;
  219. }
  220. // Make call
  221. il.Emit(OpCodes.Call,
  222. typeof (BuiltIn_Commands_BaseClass).GetMethod("AddToStatic", new Type[] {typeof (UInt32), datatype}));
  223. }
  224. }
  225. ////il.Emit(OpCodes.Newobj, typeof(UInt32));
  226. //il.Emit(OpCodes.Starg_0);
  227. //// Create LSL function library
  228. //FieldBuilder LSL_BuiltIns_fb = typeBuilder.DefineField("LSL_BuiltIns", typeof(LSL_BuiltIn_Commands_Interface), FieldAttributes.Public);
  229. //il.Emit(OpCodes.Newobj, typeof(LSL_BuiltIn_Commands_Interface));
  230. //il.Emit(OpCodes.Stloc_1);
  231. il.Emit(OpCodes.Ret);
  232. }
  233. // End of class
  234. }
  235. }