diff --git a/PorygonSharp/EvalValues/EvalValueCreator.cs b/PorygonSharp/EvalValues/EvalValueCreator.cs
index 43eb1d9..c585254 100644
--- a/PorygonSharp/EvalValues/EvalValueCreator.cs
+++ b/PorygonSharp/EvalValues/EvalValueCreator.cs
@@ -11,7 +11,7 @@ namespace PorygonSharp.EvalValues
public static EvalValue CreateValue(object o)
{
var type = o.GetType();
- if (type.IsEnum)
+ if (type.IsEnum && !type.IsGenericParameter)
{
var typeHash = UserDataHandler.GetTypeId(type);
var handle = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
@@ -41,6 +41,8 @@ namespace PorygonSharp.EvalValues
case TypeCode.Object:
if (typeof(IList).IsAssignableFrom(type))
return CreateListEvalValue((IList)o, type);
+ if (!UserDataHandler.IsTypeRegistered(type))
+ return null;
var typeHash = UserDataHandler.GetTypeId(type);
var handle = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
return new EvalValue(CreateUserDataEvalValue(typeHash, GCHandle.ToIntPtr(handle)));
diff --git a/PorygonSharp/PorygonSharp.csproj b/PorygonSharp/PorygonSharp.csproj
index e67c354..b529212 100644
--- a/PorygonSharp/PorygonSharp.csproj
+++ b/PorygonSharp/PorygonSharp.csproj
@@ -10,5 +10,4 @@
PreserveNewest
-
diff --git a/PorygonSharp/Script.cs b/PorygonSharp/Script.cs
index fd2cdc2..dcefbcb 100644
--- a/PorygonSharp/Script.cs
+++ b/PorygonSharp/Script.cs
@@ -43,23 +43,43 @@ namespace PorygonSharp
private Diagnostics _diagnostics;
public Diagnostics Diagnostics => _diagnostics ?? (_diagnostics = new Diagnostics(_internalScript.Diagnostics));
+ public bool HasErrors => Diagnostics.HasErrors();
private static readonly RuntimeTypeHandle SetupHandle = typeof(CoreSetup).TypeHandle;
- public Script(string s)
+ public Script(string s, ScriptOptions options = null)
{
// Ensure core setup has been called
RuntimeHelpers.RunClassConstructor(SetupHandle);
-
- _internalScriptHandle = Create(s);
+
+ var optionsPointer = options?.GetRawPointer() ?? IntPtr.Zero;
+ _internalScriptHandle = Create(s, optionsPointer);
_internalScript = Marshal.PtrToStructure(_internalScriptHandle);
}
+ private Script(IntPtr ptr)
+ {
+ _internalScriptHandle = ptr;
+ _internalScript = Marshal.PtrToStructure(_internalScriptHandle);
+ }
+
+ public static Script Clone(Script script)
+ {
+ // Ensure core setup has been called
+ RuntimeHelpers.RunClassConstructor(SetupHandle);
+ return new Script(CloneScript(script._internalScriptHandle));
+ }
+
public void Dispose()
{
Marshal.FreeHGlobal(_internalScriptHandle);
}
-
+
+ internal IntPtr GetRawPointer()
+ {
+ return _internalScriptHandle;
+ }
+
public EvalValue Evaluate()
{
var ptr = Evaluate(_internalScriptHandle);
@@ -108,7 +128,7 @@ namespace PorygonSharp
}
[DllImport("libPorygonLang", EntryPoint = "CreateScript", CallingConvention = CallingConvention.Cdecl)]
- private static extern IntPtr Create([MarshalAs(UnmanagedType.LPWStr)]string s);
+ private static extern IntPtr Create([MarshalAs(UnmanagedType.LPWStr)]string s, IntPtr options);
[DllImport("libPorygonLang", EntryPoint = "EvaluateScript", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr Evaluate(IntPtr script);
[DllImport("libPorygonLang", EntryPoint = "HasVariable", CallingConvention = CallingConvention.Cdecl)]
@@ -122,6 +142,10 @@ namespace PorygonSharp
[DllImport("libPorygonLang", EntryPoint = "CallFunction", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr CallFunction(IntPtr script, [MarshalAs(UnmanagedType.LPWStr)]string key,
IntPtr[] parameters, int parameterCount);
+
+ [DllImport("libPorygonLang", EntryPoint = "CloneScript", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr CloneScript(IntPtr script);
+
}
}
\ No newline at end of file
diff --git a/PorygonSharp/ScriptOptions.cs b/PorygonSharp/ScriptOptions.cs
new file mode 100644
index 0000000..280a0c8
--- /dev/null
+++ b/PorygonSharp/ScriptOptions.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+// ReSharper disable PrivateFieldCanBeConvertedToLocalVariable
+
+namespace PorygonSharp
+{
+ public abstract class ScriptOptions
+ {
+ private readonly IntPtr _ptr;
+ private delegate void PrintDelegate(string s);
+ private delegate bool ModuleExistsDelegate(IntPtr namePtr, int size);
+ private delegate IntPtr ResolveModuleDelegate(IntPtr namePtr, int size);
+
+ private readonly PrintDelegate _print;
+ private readonly ModuleExistsDelegate _moduleExists;
+ private readonly ResolveModuleDelegate _resolveModule;
+
+ protected ScriptOptions()
+ {
+ _ptr = Create();
+ _print = Print;
+ SetOptionPrintFunc(_ptr, Marshal.GetFunctionPointerForDelegate(_print));
+ _moduleExists = (namePtr, size) =>
+ {
+ var nameArr = new byte[size];
+ for (var i = 0; i < size; i++)
+ nameArr[i] = Marshal.ReadByte(namePtr, i);
+ var name = Encoding.UTF8.GetString(nameArr);
+ return ModuleExists(name);
+ };
+ SetOptionModuleExistsFunc(_ptr, Marshal.GetFunctionPointerForDelegate(_moduleExists));
+ _resolveModule = (namePtr, size) =>
+ {
+ var nameArr = new byte[size];
+ for (var i = 0; i < size; i++)
+ nameArr[i] = Marshal.ReadByte(namePtr, i);
+ var name = Encoding.UTF8.GetString(nameArr);
+ return ResolveModule(name).GetRawPointer();
+ };
+ SetOptionResolveModuleFunc(_ptr, Marshal.GetFunctionPointerForDelegate(_resolveModule));
+ }
+
+ protected abstract void Print(string s);
+ protected abstract bool ModuleExists(string s);
+ protected abstract Script ResolveModule(string s);
+
+ internal IntPtr GetRawPointer()
+ {
+ return _ptr;
+ }
+
+
+ [DllImport("libPorygonLang", EntryPoint = "CreateOptions", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr Create();
+
+ [DllImport("libPorygonLang", EntryPoint = "SetOptionPrintFunc", CallingConvention = CallingConvention.Cdecl)]
+ private static extern void SetOptionPrintFunc(IntPtr opt, IntPtr func);
+
+ [DllImport("libPorygonLang", EntryPoint = "SetOptionModuleExistsFunc", CallingConvention = CallingConvention.Cdecl)]
+ private static extern void SetOptionModuleExistsFunc(IntPtr opt, IntPtr func);
+
+ [DllImport("libPorygonLang", EntryPoint = "SetOptionResolveModuleFunc", CallingConvention = CallingConvention.Cdecl)]
+ private static extern void SetOptionResolveModuleFunc(IntPtr opt, IntPtr func);
+
+ }
+}
\ No newline at end of file
diff --git a/PorygonSharp/ScriptType/ScriptType.cs b/PorygonSharp/ScriptType/ScriptType.cs
index cb83ac5..f743e05 100644
--- a/PorygonSharp/ScriptType/ScriptType.cs
+++ b/PorygonSharp/ScriptType/ScriptType.cs
@@ -9,11 +9,13 @@ namespace PorygonSharp.ScriptType
{
internal static class ScriptType
{
- internal static IntPtr GetScriptType(Type t)
+ internal static IntPtr? GetScriptType(Type t)
{
- if (t.IsEnum)
+ if (t.IsEnum && !t.IsGenericParameter)
{
- return UserDataHandler.CreateUserDataType(t);
+ if (UserDataHandler.IsTypeRegistered(t))
+ return UserDataHandler.CreateUserDataType(t);
+ return CreateNumericScriptType(true, false);
}
var typeCode = Type.GetTypeCode(t);
switch (typeCode)
@@ -49,30 +51,44 @@ namespace PorygonSharp.ScriptType
{
return CreateUserDataListType(t);
}
- if (typeof(IDictionary<,>).IsAssignableFrom(t))
+ if (typeof(IDictionary).IsAssignableFrom(t))
{
return CreateUserDataDictionaryType(t);
}
- goto default;
+
+ var attr = t.GetCustomAttribute();
+ if (attr != null)
+ {
+ UserDataHandler.RegisterType(attr.Identifier, t);
+ return UserDataHandler.CreateUserDataType(t);
+ }
+ return null;
default:
- throw new ArgumentOutOfRangeException(t.FullName);
+ return null;
}
}
- internal static IntPtr GetFunctionScriptType(MethodInfo info)
+ internal static IntPtr? GetFunctionScriptType(MethodInfo info)
{
try
{
var returnType = GetScriptType(info.ReturnType);
+ if (!returnType.HasValue)
+ return null;
var parameters = info.GetParameters();
var parameterFuncs = new IntPtr[parameters.Length];
for (var index = 0; index < parameters.Length; index++)
{
var parameter = parameters[index];
- parameterFuncs[index] = GetScriptType(parameter.ParameterType);
+ var parameterType = GetScriptType(parameter.ParameterType);
+ if (!parameterType.HasValue)
+ {
+ return null;
+ }
+ parameterFuncs[index] = parameterType.Value;
}
- return CreateUserDataFunctionScriptType(returnType, parameterFuncs, parameters.Length);
+ return CreateUserDataFunctionScriptType(returnType.Value, parameterFuncs, parameters.Length);
}
catch
{
@@ -80,19 +96,23 @@ namespace PorygonSharp.ScriptType
}
}
- private static IntPtr CreateUserDataListType(Type t)
+ private static IntPtr? CreateUserDataListType(Type t)
{
var keyType = CreateNumericScriptType(true, false);
var valType = t.IsArray ? t.GetElementType() : t.GenericTypeArguments[0];
var valueType = GetScriptType(valType);
- return CreateCollectionType(keyType, valueType);
+ if (valueType.HasValue)
+ return CreateCollectionType(keyType, valueType.Value);
+ return null;
}
- private static IntPtr CreateUserDataDictionaryType(Type t)
+ private static IntPtr? CreateUserDataDictionaryType(Type t)
{
var keyType = GetScriptType(t.GenericTypeArguments[0]);
var valueType = GetScriptType(t.GenericTypeArguments[1]);
- return CreateCollectionType(keyType, valueType);
+ if (keyType.HasValue && valueType.HasValue)
+ return CreateCollectionType(keyType.Value, valueType.Value);
+ return null;
}
[DllImport("libPorygonLang", EntryPoint = "CreateScriptType", CallingConvention = CallingConvention.Cdecl)]
diff --git a/PorygonSharp/StaticScope.cs b/PorygonSharp/StaticScope.cs
index 7a56698..46e3f02 100644
--- a/PorygonSharp/StaticScope.cs
+++ b/PorygonSharp/StaticScope.cs
@@ -13,7 +13,9 @@ namespace PorygonSharp
var scriptType = ScriptType.ScriptType.GetScriptType(type);
var hash = name.ScriptHash();
var value = EvalValueCreator.CreateValue(o);
- RegisterStaticVariable(hash, scriptType, value.GetPointer());
+ if (!scriptType.HasValue)
+ return;
+ RegisterStaticVariable(hash, scriptType.Value, value.GetPointer());
}
[DllImport("libPorygonLang", EntryPoint = "RegisterStaticVariable", CallingConvention = CallingConvention.Cdecl)]
diff --git a/PorygonSharp/UserData/UserDataHandler.cs b/PorygonSharp/UserData/UserDataHandler.cs
index e032298..9e0e2c8 100644
--- a/PorygonSharp/UserData/UserDataHandler.cs
+++ b/PorygonSharp/UserData/UserDataHandler.cs
@@ -40,10 +40,13 @@ namespace PorygonSharp.UserData
public static void RegisterType(string name, Type type)
{
var hash = name.ScriptHash();
- RegisterUserDataType(hash);
- if (UserDataLookup.ContainsKey(type))
- return;
- UserDataLookup.Add(type, hash);
+ lock (UserDataLookup)
+ {
+ if (UserDataLookup.ContainsKey(type))
+ return;
+ RegisterUserDataType(hash);
+ UserDataLookup.Add(type, hash);
+ }
const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance |
BindingFlags.FlattenHierarchy | BindingFlags.Static;
@@ -69,9 +72,9 @@ namespace PorygonSharp.UserData
public static void RegisterEnumType(string name, Type type)
{
var hash = name.ScriptHash();
- RegisterUserDataType(hash);
if (UserDataLookup.ContainsKey(type))
return;
+ RegisterUserDataType(hash);
UserDataLookup.Add(type, hash);
var values = Enum.GetValues(type);
foreach (var value in values)
@@ -107,7 +110,9 @@ namespace PorygonSharp.UserData
setterPtr = Marshal.GetFunctionPointerForDelegate(setter);
}
var scriptType = ScriptType.ScriptType.GetScriptType(field.FieldType);
- var userDataField = CreateUserDataField(scriptType, Marshal.GetFunctionPointerForDelegate(getter),
+ if (!scriptType.HasValue)
+ return;
+ var userDataField = CreateUserDataField(scriptType.Value, Marshal.GetFunctionPointerForDelegate(getter),
setterPtr);
var fieldName = field.Name.ScriptHash();
@@ -139,7 +144,9 @@ namespace PorygonSharp.UserData
setterPtr = Marshal.GetFunctionPointerForDelegate(setter);
}
var scriptType = ScriptType.ScriptType.GetScriptType(property.PropertyType);
- var userDataField = CreateUserDataField(scriptType, getterPtr, setterPtr);
+ if (!scriptType.HasValue)
+ return;
+ var userDataField = CreateUserDataField(scriptType.Value, getterPtr, setterPtr);
var fieldName = property.Name.ScriptHash();
RegisterUserDataField(typeHash, fieldName, userDataField);
@@ -172,9 +179,9 @@ namespace PorygonSharp.UserData
});
var getterPtr = Marshal.GetFunctionPointerForDelegate(getter);
var type = ScriptType.ScriptType.GetFunctionScriptType(method);
- if (type == IntPtr.Zero)
+ if (type == IntPtr.Zero || !type.HasValue)
return;
- var userDataField = CreateUserDataField(type, getterPtr, IntPtr.Zero);
+ var userDataField = CreateUserDataField(type.Value, getterPtr, IntPtr.Zero);
var fieldName = method.Name.ScriptHash();
RegisterUserDataField(typeHash, fieldName, userDataField);
diff --git a/PorygonSharp/libPorygonLang.so b/PorygonSharp/libPorygonLang.so
index d1bec0f..5dde80c 100755
Binary files a/PorygonSharp/libPorygonLang.so and b/PorygonSharp/libPorygonLang.so differ