Support for enums, and adding static variables

This commit is contained in:
Deukhoofd 2019-08-18 15:54:39 +02:00
parent d2cc82dc21
commit 6ecbfe2074
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
9 changed files with 161 additions and 2 deletions

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RiderProjectSettingsUpdater">
<option name="vcsConfiguration" value="1" />
</component>
</project>

View File

@ -0,0 +1,14 @@
using System;
namespace PorygonSharp.Attributes
{
public class PorygonEnumAttribute : Attribute
{
public string Name { get; }
public PorygonEnumAttribute(string name)
{
Name = name;
}
}
}

View File

@ -0,0 +1,13 @@
using System;
namespace PorygonSharp.Attributes
{
public class PorygonUserdataAttribute : Attribute
{
public string Identifier { get; }
public PorygonUserdataAttribute(string identifier)
{
Identifier = identifier;
}
}
}

View File

@ -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)]

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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<PorygonUserdataAttribute>();
if (attr != null)
{
RegisterType(attr.Identifier, type);
}
var enumAttr = type.GetCustomAttribute<PorygonEnumAttribute>();
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 =>

Binary file not shown.

View File

@ -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());
}
}
}
}