diff --git a/.idea/.idea.PorygonSharp/.idea/projectSettingsUpdater.xml b/.idea/.idea.PorygonSharp/.idea/projectSettingsUpdater.xml new file mode 100644 index 0000000..7515e76 --- /dev/null +++ b/.idea/.idea.PorygonSharp/.idea/projectSettingsUpdater.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/PorygonSharp/Attributes/PorygonEnumAttribute.cs b/PorygonSharp/Attributes/PorygonEnumAttribute.cs new file mode 100644 index 0000000..b1a1725 --- /dev/null +++ b/PorygonSharp/Attributes/PorygonEnumAttribute.cs @@ -0,0 +1,14 @@ +using System; + +namespace PorygonSharp.Attributes +{ + public class PorygonEnumAttribute : Attribute + { + public string Name { get; } + + public PorygonEnumAttribute(string name) + { + Name = name; + } + } +} \ No newline at end of file diff --git a/PorygonSharp/Attributes/PorygonUserdataAttribute.cs b/PorygonSharp/Attributes/PorygonUserdataAttribute.cs new file mode 100644 index 0000000..29d896d --- /dev/null +++ b/PorygonSharp/Attributes/PorygonUserdataAttribute.cs @@ -0,0 +1,13 @@ +using System; + +namespace PorygonSharp.Attributes +{ + public class PorygonUserdataAttribute : Attribute + { + public string Identifier { get; } + public PorygonUserdataAttribute(string identifier) + { + Identifier = identifier; + } + } +} \ No newline at end of file diff --git a/PorygonSharp/EvalValues/EvalValueCreator.cs b/PorygonSharp/EvalValues/EvalValueCreator.cs index 559d9fd..43eb1d9 100644 --- a/PorygonSharp/EvalValues/EvalValueCreator.cs +++ b/PorygonSharp/EvalValues/EvalValueCreator.cs @@ -11,6 +11,12 @@ namespace PorygonSharp.EvalValues public static EvalValue CreateValue(object o) { var type = o.GetType(); + if (type.IsEnum) + { + var typeHash = UserDataHandler.GetTypeId(type); + var handle = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection); + return new EvalValue(CreateUserDataEvalValue(typeHash, GCHandle.ToIntPtr(handle))); + } var typeCode = Type.GetTypeCode(type); switch (typeCode) { @@ -57,7 +63,7 @@ namespace PorygonSharp.EvalValues } [DllImport("libPorygonLang", EntryPoint = "CreateIntegerEvalValue",CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr CreateIntegerEvalValue(long l); + internal static extern IntPtr CreateIntegerEvalValue(long l); [DllImport("libPorygonLang", EntryPoint = "CreateFloatEvalValue",CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr CreateFloatEvalValue(double d); [DllImport("libPorygonLang", EntryPoint = "CreateBoolEvalValue",CallingConvention = CallingConvention.Cdecl)] diff --git a/PorygonSharp/ScriptType/ScriptType.cs b/PorygonSharp/ScriptType/ScriptType.cs index f5dd1d8..cb83ac5 100644 --- a/PorygonSharp/ScriptType/ScriptType.cs +++ b/PorygonSharp/ScriptType/ScriptType.cs @@ -11,6 +11,10 @@ namespace PorygonSharp.ScriptType { internal static IntPtr GetScriptType(Type t) { + if (t.IsEnum) + { + return UserDataHandler.CreateUserDataType(t); + } var typeCode = Type.GetTypeCode(t); switch (typeCode) { @@ -95,7 +99,7 @@ namespace PorygonSharp.ScriptType private static extern IntPtr CreateScriptType(TypeClass t); [DllImport("libPorygonLang", EntryPoint = "CreateNumericScriptType", CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr CreateNumericScriptType(bool isAware, bool isFloat); + internal static extern IntPtr CreateNumericScriptType(bool isAware, bool isFloat); [DllImport("libPorygonLang", EntryPoint = "CreateStringScriptType", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr CreateStringScriptType(bool knownAtBind, uint hash); diff --git a/PorygonSharp/StaticScope.cs b/PorygonSharp/StaticScope.cs new file mode 100644 index 0000000..7a56698 --- /dev/null +++ b/PorygonSharp/StaticScope.cs @@ -0,0 +1,22 @@ +using System; +using System.Runtime.InteropServices; +using PorygonSharp.EvalValues; +using PorygonSharp.Utilities; + +namespace PorygonSharp +{ + public static class StaticScope + { + public static void RegisterStaticVariable(string name, object o) + { + var type = o.GetType(); + var scriptType = ScriptType.ScriptType.GetScriptType(type); + var hash = name.ScriptHash(); + var value = EvalValueCreator.CreateValue(o); + RegisterStaticVariable(hash, scriptType, value.GetPointer()); + } + + [DllImport("libPorygonLang", EntryPoint = "RegisterStaticVariable", CallingConvention = CallingConvention.Cdecl)] + private static extern void RegisterStaticVariable(uint hashId, IntPtr scriptType, IntPtr value); + } +} \ No newline at end of file diff --git a/PorygonSharp/UserData/UserDataHandler.cs b/PorygonSharp/UserData/UserDataHandler.cs index e0c7e3c..e032298 100644 --- a/PorygonSharp/UserData/UserDataHandler.cs +++ b/PorygonSharp/UserData/UserDataHandler.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; +using PorygonSharp.Attributes; using PorygonSharp.EvalValues; using PorygonSharp.Utilities; @@ -17,6 +18,25 @@ namespace PorygonSharp.UserData private delegate IntPtr CallerDelegate(IntPtr parent, IntPtr scriptOption, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)]IntPtr[] parameters, int size); + public static void RegisterAssembly(Assembly assembly) + { + foreach (var type in assembly.GetTypes()) + { + var attr = type.GetCustomAttribute(); + if (attr != null) + { + RegisterType(attr.Identifier, type); + } + + var enumAttr = type.GetCustomAttribute(); + if (enumAttr != null) + { + RegisterEnumType(enumAttr.Name, type); + StaticScope.RegisterStaticVariable(enumAttr.Name, Activator.CreateInstance(type)); + } + } + } + public static void RegisterType(string name, Type type) { var hash = name.ScriptHash(); @@ -46,6 +66,26 @@ namespace PorygonSharp.UserData } } + public static void RegisterEnumType(string name, Type type) + { + var hash = name.ScriptHash(); + RegisterUserDataType(hash); + if (UserDataLookup.ContainsKey(type)) + return; + UserDataLookup.Add(type, hash); + var values = Enum.GetValues(type); + foreach (var value in values) + { + var getter = new GetterDelegate(ptr => EvalValueCreator.CreateIntegerEvalValue(Convert.ToInt64(value))); + var valueName = Enum.GetName(type, value); + var fieldName = valueName.ScriptHash(); + var t = ScriptType.ScriptType.CreateNumericScriptType(true, false); + RegisterUserDataField(hash, fieldName, + CreateUserDataField(t, Marshal.GetFunctionPointerForDelegate(getter), IntPtr.Zero)); + } + + } + private static void RegisterField(FieldInfo field, uint typeHash) { var getter = new GetterDelegate(ptr => diff --git a/PorygonSharp/libPorygonLang.so b/PorygonSharp/libPorygonLang.so index e4471f5..d1bec0f 100755 Binary files a/PorygonSharp/libPorygonLang.so and b/PorygonSharp/libPorygonLang.so differ diff --git a/PorygonSharpTests/EnumUserdataTest.cs b/PorygonSharpTests/EnumUserdataTest.cs new file mode 100644 index 0000000..9b8fc35 --- /dev/null +++ b/PorygonSharpTests/EnumUserdataTest.cs @@ -0,0 +1,54 @@ +using System; +using NUnit.Framework; +using PorygonSharp; +using PorygonSharp.UserData; + +namespace PorygonSharpTests +{ + public class EnumUserdataTest + { + private enum testEnum + { + One, Two, Three, Foo, Bar + } + + [Test] + public void AbleToAccessStaticEnumVariable() + { + UserDataHandler.RegisterEnumType("testEnum", typeof(testEnum)); + StaticScope.RegisterStaticVariable("testEnum", testEnum.One); + using (var script = new Script(@" + return type(testEnum) +")) + { + var diags = script.Diagnostics.GetDiagnostics(); + foreach (var diag in diags) + { + throw new Exception(script.Diagnostics.GetFullDiagnosticMessage(diag)); + } + var result = script.Evaluate(); + Assert.AreEqual("userdata", result.EvaluateString()); + } + } + + [Test] + public void AbleToUseStaticEnumVariable() + { + UserDataHandler.RegisterEnumType("testEnum", typeof(testEnum)); + StaticScope.RegisterStaticVariable("testEnum", testEnum.One); + using (var script = new Script(@" + return testEnum.Three + 2 +")) + { + var diags = script.Diagnostics.GetDiagnostics(); + foreach (var diag in diags) + { + throw new Exception(script.Diagnostics.GetFullDiagnosticMessage(diag)); + } + var result = script.Evaluate(); + Assert.AreEqual(4, result.EvaluateInteger()); + } + } + + } +} \ No newline at end of file