PorygonSharp/PorygonSharp/ScriptType/ScriptType.cs

113 lines
4.6 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using PorygonSharp.UserData;
namespace PorygonSharp.ScriptType
{
internal static class ScriptType
{
internal static IntPtr GetScriptType(Type t)
{
if (t.IsEnum)
{
return UserDataHandler.CreateUserDataType(t);
}
var typeCode = Type.GetTypeCode(t);
switch (typeCode)
{
case TypeCode.Boolean:
return CreateScriptType(TypeClass.Bool);
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
return CreateNumericScriptType(true, false);
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Single:
return CreateNumericScriptType(true, true);
case TypeCode.Char:
case TypeCode.String:
return CreateStringScriptType(false, 0);
case TypeCode.Object:
if (t == typeof(void))
{
return CreateScriptType(TypeClass.Nil);
}
if (UserDataHandler.IsTypeRegistered(t))
{
return UserDataHandler.CreateUserDataType(t);
}
if (typeof(IList).IsAssignableFrom(t))
{
return CreateUserDataListType(t);
}
if (typeof(IDictionary<,>).IsAssignableFrom(t))
{
return CreateUserDataDictionaryType(t);
}
goto default;
default:
throw new ArgumentOutOfRangeException(t.FullName);
}
}
internal static IntPtr GetFunctionScriptType(MethodInfo info)
{
try
{
var returnType = GetScriptType(info.ReturnType);
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);
}
return CreateUserDataFunctionScriptType(returnType, parameterFuncs, parameters.Length);
}
catch
{
return IntPtr.Zero;
}
}
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);
}
private static IntPtr CreateUserDataDictionaryType(Type t)
{
var keyType = GetScriptType(t.GenericTypeArguments[0]);
var valueType = GetScriptType(t.GenericTypeArguments[1]);
return CreateCollectionType(keyType, valueType);
}
[DllImport("libPorygonLang", EntryPoint = "CreateScriptType", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr CreateScriptType(TypeClass t);
[DllImport("libPorygonLang", EntryPoint = "CreateNumericScriptType", CallingConvention = CallingConvention.Cdecl)]
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);
[DllImport("libPorygonLang", EntryPoint = "CreateUserDataFunctionScriptType", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr CreateUserDataFunctionScriptType(IntPtr returnType, IntPtr[] parameters, int parameterCount);
[DllImport("libPorygonLang", EntryPoint = "CreateCollectionType", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr CreateCollectionType(IntPtr keyType, IntPtr valueType);
}
}