182 lines
6.2 KiB
C#
182 lines
6.2 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Immutable;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using Upsilon.BaseTypes.Number;
|
|
using Upsilon.BaseTypes.ScriptFunction;
|
|
using Upsilon.BaseTypes.ScriptTypeInterfaces;
|
|
using Upsilon.BaseTypes.UserData;
|
|
|
|
namespace Upsilon.BaseTypes
|
|
{
|
|
internal static class TypeConversion
|
|
{
|
|
public static ScriptType ToScriptType(this object o)
|
|
{
|
|
if (o is ScriptType type) return type;
|
|
switch (o)
|
|
{
|
|
case bool b:
|
|
return new ScriptBoolean(b);
|
|
case int i:
|
|
return new ScriptNumberLong(i);
|
|
case short s:
|
|
return new ScriptNumberLong(s);
|
|
case sbyte s:
|
|
return new ScriptNumberLong(s);
|
|
case byte s:
|
|
return new ScriptNumberLong(s);
|
|
case long i:
|
|
return new ScriptNumberLong(i);
|
|
case float f:
|
|
return new ScriptNumberDouble(f);
|
|
case double f:
|
|
return new ScriptNumberDouble(f);
|
|
case string s:
|
|
return new ScriptString(s);
|
|
case null:
|
|
return new ScriptNull();
|
|
default:
|
|
return ConvertUserData(o);
|
|
}
|
|
}
|
|
|
|
private static ScriptType ConvertUserData(object o)
|
|
{
|
|
if (o is IList ls)
|
|
{
|
|
return new ListUserData(ls);
|
|
}
|
|
if (o is IDictionary dic)
|
|
{
|
|
return new DictionaryUserData(dic);
|
|
}
|
|
if (o.GetType().IsGenericType)
|
|
{
|
|
var generic = o.GetType().GetGenericTypeDefinition();
|
|
if (generic.FullName != null && generic.FullName.Contains("System.Func"))
|
|
{
|
|
var function = (Delegate)o;
|
|
var method = new UserDataMethod(function.GetMethodInfo());
|
|
return new ScriptMethodInfoFunction(method, null, false,
|
|
false, false);
|
|
}
|
|
|
|
if (generic.FullName != null && generic.FullName.Contains("System.Action"))
|
|
{
|
|
var function = (Delegate)o;
|
|
var method = new UserDataMethod(function.GetMethodInfo());
|
|
return new ScriptMethodInfoFunction(method, null, false,
|
|
false, false);
|
|
}
|
|
}
|
|
|
|
if (o is IEnumerable enumerable)
|
|
{
|
|
return new ListUserData(enumerable.Cast<object>().ToList());
|
|
}
|
|
|
|
return new GenericUserData(o);
|
|
}
|
|
|
|
public static Type GetScriptType(object o)
|
|
{
|
|
if (o is ScriptType t)
|
|
{
|
|
return t.Type;
|
|
}
|
|
|
|
switch (o)
|
|
{
|
|
case bool _:
|
|
return Type.Boolean;
|
|
case int _:
|
|
return Type.Number;
|
|
case long _:
|
|
return Type.Number;
|
|
case float _:
|
|
return Type.Number;
|
|
case double _:
|
|
return Type.Number;
|
|
case string _:
|
|
return Type.String;
|
|
case null:
|
|
return Type.Nil;
|
|
default:
|
|
return Type.UserData;
|
|
}
|
|
}
|
|
|
|
public static TypeContainer GetScriptType(this System.Type t)
|
|
{
|
|
var typeCode = System.Type.GetTypeCode(t);
|
|
switch (typeCode)
|
|
{
|
|
case TypeCode.Boolean:
|
|
return Type.Boolean;
|
|
case TypeCode.Char:
|
|
case TypeCode.String:
|
|
return Type.String;
|
|
case TypeCode.Byte:
|
|
case TypeCode.Decimal:
|
|
case TypeCode.Double:
|
|
case TypeCode.Int16:
|
|
case TypeCode.Int32:
|
|
case TypeCode.Int64:
|
|
case TypeCode.SByte:
|
|
case TypeCode.Single:
|
|
case TypeCode.UInt16:
|
|
case TypeCode.UInt32:
|
|
case TypeCode.UInt64:
|
|
return Type.Number;
|
|
case TypeCode.Empty:
|
|
return Type.Nil;
|
|
}
|
|
if (t == typeof(void))
|
|
return Type.Nil;
|
|
|
|
if (t == typeof(ScriptString))
|
|
return Type.String;
|
|
if (t == typeof(ScriptBoolean))
|
|
return Type.Boolean;
|
|
if (typeof(ScriptNumber).IsAssignableFrom(t))
|
|
return Type.Number;
|
|
if (typeof(ScriptFunction.ScriptFunction).IsAssignableFrom(t))
|
|
return Type.Function;
|
|
if (typeof(ScriptTable.ScriptTable).IsAssignableFrom(t))
|
|
return Type.Table;
|
|
if (t == typeof(IIterable))
|
|
return Type.Nil;
|
|
if (t == typeof(SimpleScriptTable))
|
|
return Type.Table;
|
|
if (t.IsArray)
|
|
{
|
|
var elementType = t.GetElementType();
|
|
return new CompositeTypeContainer(new TypeContainer[] {Type.Number, GetScriptType(elementType)}
|
|
.ToImmutableArray());
|
|
}
|
|
if (typeof(IList).IsAssignableFrom(t))
|
|
{
|
|
var generic = t.GetGenericArguments()[0];
|
|
return new CompositeTypeContainer(new TypeContainer[] {Type.Number, GetScriptType(generic)}
|
|
.ToImmutableArray());
|
|
}
|
|
if (typeof(IDictionary).IsAssignableFrom(t))
|
|
{
|
|
var key = t.GetGenericArguments()[0];
|
|
var value = t.GetGenericArguments()[1];
|
|
return new CompositeTypeContainer(new[] {GetScriptType(key), GetScriptType(value)}.ToImmutableArray());
|
|
}
|
|
if (typeof(IEnumerable).IsAssignableFrom(t))
|
|
return Type.Table;
|
|
if (typeof(IIndexable).IsAssignableFrom(t))
|
|
return Type.Table;
|
|
|
|
if (t == typeof(ScriptType))
|
|
return Type.Unknown;
|
|
return new UndefinedUserDataTypeContainer(t);
|
|
}
|
|
|
|
}
|
|
} |