OpenSimMirror/OpenSim/Region/ScriptEngine/LSOEngine/LSO/Engine.cs

293 lines
12 KiB
C#

/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* Original code: Tedd Hansen */
using System;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading;
using OpenSim.Region.ScriptEngine.Common;
using OpenSim.Region.ScriptEngine.LSOEngine.LSO;
namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO
{
public class Engine
{
//private string LSO_FileName = @"LSO\AdditionTest.lso";
private string LSO_FileName; // = @"LSO\CloseToDefault.lso";
private AppDomain appDomain;
public string Compile(string LSOFileName)
{
LSO_FileName = LSOFileName;
//appDomain = AppDomain.CreateDomain("AlternateAppDomain");
appDomain = Thread.GetDomain();
// Create Assembly Name
AssemblyName asmName = new AssemblyName();
asmName.Name = Path.GetFileNameWithoutExtension(LSO_FileName);
//asmName.Name = "TestAssembly";
string DLL_FileName = asmName.Name + ".dll";
string DLL_FileName_WithPath = Path.GetDirectoryName(LSO_FileName) + @"\" + DLL_FileName;
LSOEngine.LSO.Common.SendToLog("LSO File Name: " + Path.GetFileName(LSO_FileName));
LSOEngine.LSO.Common.SendToLog("Assembly name: " + asmName.Name);
LSOEngine.LSO.Common.SendToLog("Assembly File Name: " + asmName.Name + ".dll");
LSOEngine.LSO.Common.SendToLog("Starting processing of LSL ByteCode...");
LSOEngine.LSO.Common.SendToLog(String.Empty);
// Create Assembly
AssemblyBuilder asmBuilder = appDomain.DefineDynamicAssembly(
asmName,
AssemblyBuilderAccess.RunAndSave
);
//// Create Assembly
//AssemblyBuilder asmBuilder =
// Thread.GetDomain().DefineDynamicAssembly
//(asmName, AssemblyBuilderAccess.RunAndSave);
// Create a module (and save to disk)
ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule
(asmName.Name,
DLL_FileName);
//Common.SendToDebug("asmName.Name is still \String.Empty + asmName.Name + "\String.Empty);
// Create a Class (/Type)
TypeBuilder typeBuilder = modBuilder.DefineType(
"LSL_ScriptObject",
TypeAttributes.Public | TypeAttributes.BeforeFieldInit,
typeof (LSL_BaseClass));
//,
// typeof());
//, typeof(LSL_BuiltIn_Commands_Interface));
//,
// typeof(object),
// new Type[] { typeof(LSL_CLRInterface.LSLScript) });
/*
* Generate the IL itself
*/
LSO_Parser LSOP = new LSO_Parser(LSO_FileName, typeBuilder);
LSOP.OpenFile();
LSOP.Parse();
// Constructor has to be created AFTER LSO_Parser because of accumulated variables
if (LSOEngine.LSO.Common.IL_CreateConstructor)
IL_CREATE_CONSTRUCTOR(typeBuilder, LSOP);
LSOP.CloseFile();
/*
* Done generating. Create a type and run it.
*/
LSOEngine.LSO.Common.SendToLog("Attempting to compile assembly...");
// Compile it
Type type = typeBuilder.CreateType();
LSOEngine.LSO.Common.SendToLog("Compilation successful!");
LSOEngine.LSO.Common.SendToLog("Saving assembly: " + DLL_FileName);
asmBuilder.Save(DLL_FileName);
LSOEngine.LSO.Common.SendToLog("Returning assembly filename: " + DLL_FileName);
return DLL_FileName;
//Common.SendToLog("Creating an instance of new assembly...");
//// Create an instance we can play with
////LSLScript hello = (LSLScript)Activator.CreateInstance(type);
////LSL_CLRInterface.LSLScript MyScript = (LSL_CLRInterface.LSLScript)Activator.CreateInstance(type);
//object MyScript = (object)Activator.CreateInstance(type);
//System.Reflection.MemberInfo[] Members = type.GetMembers();
//Common.SendToLog("Members of assembly " + type.ToString() + ":");
//foreach (MemberInfo member in Members)
// Common.SendToLog(member.ToString());
//// Play with it
////MyScript.event_state_entry("Test");
//object[] args = { null };
////System.Collections.Generic.List<string> Functions = (System.Collections.Generic.List<string>)type.InvokeMember("GetFunctions", BindingFlags.InvokeMethod, null, MyScript, null);
//string[] ret = { };
//if (Common.IL_CreateFunctionList)
// ret = (string[])type.InvokeMember("GetFunctions", BindingFlags.InvokeMethod, null, MyScript, null);
//foreach (string s in ret)
//{
// Common.SendToLog(String.Empty);
// Common.SendToLog("*** Executing LSL Server Event: " + s);
// //object test = type.GetMember(s);
// //object runner = type.InvokeMember(s, BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, MyScript, args);
// //runner();
// //objBooks_Late = type.InvokeMember(s, BindingFlags.CreateInstance, null, objApp_Late, null);
// type.InvokeMember(s, BindingFlags.InvokeMethod, null, MyScript, new object[] { "Test" });
//}
}
private static void IL_CREATE_CONSTRUCTOR(TypeBuilder typeBuilder, LSO_Parser LSOP)
{
LSOEngine.LSO.Common.SendToDebug("IL_CREATE_CONSTRUCTOR()");
//ConstructorBuilder constructor = typeBuilder.DefineConstructor(
// MethodAttributes.Public,
// CallingConventions.Standard,
// new Type[0]);
ConstructorBuilder constructor = typeBuilder.DefineConstructor(
MethodAttributes.Public |
MethodAttributes.SpecialName |
MethodAttributes.RTSpecialName,
CallingConventions.Standard,
new Type[0]);
//Define the reflection ConstructorInfor for System.Object
ConstructorInfo conObj = typeof (LSL_BaseClass).GetConstructor(new Type[0]);
//call constructor of base object
ILGenerator il = constructor.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, conObj);
//Common.SendToDebug("IL_CREATE_CONSTRUCTOR: Creating global: UInt32 State = 0;");
//string FieldName;
//// Create state object
//FieldName = "State";
//FieldBuilder State_fb = typeBuilder.DefineField(
// FieldName,
// typeof(UInt32),
// FieldAttributes.Public);
//il.Emit(OpCodes.Ldarg_0);
//il.Emit(OpCodes.Ldc_I4, 0);
//il.Emit(OpCodes.Stfld, State_fb);
//Common.SendToDebug("IL_CREATE_CONSTRUCTOR: Creating global: LSL_BuiltIn_Commands_TestImplementation LSL_BuiltIns = New LSL_BuiltIn_Commands_TestImplementation();");
////Type objType1 = typeof(object);
//Type objType1 = typeof(LSL_BuiltIn_Commands_TestImplementation);
//FieldName = "LSL_BuiltIns";
//FieldBuilder LSL_BuiltIns_fb = typeBuilder.DefineField(
// FieldName,
// objType1,
// FieldAttributes.Public);
////LSL_BuiltIn_Commands_TestImplementation _ti = new LSL_BuiltIn_Commands_TestImplementation();
//il.Emit(OpCodes.Ldarg_0);
////il.Emit(OpCodes.Ldstr, "Test 123");
//il.Emit(OpCodes.Newobj, objType1.GetConstructor(new Type[] { }));
//il.Emit(OpCodes.Stfld, LSL_BuiltIns_fb);
foreach (UInt32 pos in LSOP.StaticBlocks.Keys)
{
LSO_Struct.StaticBlock sb;
LSOP.StaticBlocks.TryGetValue(pos, out sb);
if (sb.ObjectType > 0 && sb.ObjectType < 8)
{
// We don't want void or null's
il.Emit(OpCodes.Ldarg_0);
// Push position to stack
il.Emit(OpCodes.Ldc_I4, pos);
//il.Emit(OpCodes.Box, typeof(UInt32));
Type datatype = null;
// Push data to stack
LSOEngine.LSO.Common.SendToDebug("Adding to static (" + pos + ") type: " +
((LSO_Enums.Variable_Type_Codes) sb.ObjectType).ToString() + " (" + sb.ObjectType +
")");
switch ((LSO_Enums.Variable_Type_Codes) sb.ObjectType)
{
case LSO_Enums.Variable_Type_Codes.Float:
case LSO_Enums.Variable_Type_Codes.Integer:
//UInt32
il.Emit(OpCodes.Ldc_I4, BitConverter.ToUInt32(sb.BlockVariable, 0));
datatype = typeof (UInt32);
il.Emit(OpCodes.Box, datatype);
break;
case LSO_Enums.Variable_Type_Codes.String:
case LSO_Enums.Variable_Type_Codes.Key:
//String
LSO_Struct.HeapBlock hb =
LSOP.GetHeap(LSOP.myHeader.HR + BitConverter.ToUInt32(sb.BlockVariable, 0) - 1);
il.Emit(OpCodes.Ldstr, Encoding.UTF8.GetString(hb.Data));
datatype = typeof (string);
break;
case LSO_Enums.Variable_Type_Codes.Vector:
datatype = typeof (LSO_Enums.Vector);
//TODO: Not implemented
break;
case LSO_Enums.Variable_Type_Codes.Rotation:
//Object
//TODO: Not implemented
datatype = typeof (LSO_Enums.Rotation);
break;
default:
datatype = typeof (object);
break;
}
// Make call
il.Emit(OpCodes.Call,
typeof (LSL_BaseClass).GetMethod("AddToStatic", new Type[] {typeof (UInt32), datatype}));
}
}
////il.Emit(OpCodes.Newobj, typeof(UInt32));
//il.Emit(OpCodes.Starg_0);
//// Create LSL function library
//FieldBuilder LSL_BuiltIns_fb = typeBuilder.DefineField("LSL_BuiltIns", typeof(LSL_BuiltIn_Commands_Interface), FieldAttributes.Public);
//il.Emit(OpCodes.Newobj, typeof(LSL_BuiltIn_Commands_Interface));
//il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ret);
}
// End of class
}
}