Reworked type handling to handle userdata more easily

This commit is contained in:
Deukhoofd 2019-01-19 16:38:33 +01:00
parent 6552e153d0
commit 96b0959bd6
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
8 changed files with 51 additions and 23 deletions

View File

@ -1,3 +1,4 @@
using System;
using System.Collections.Immutable; using System.Collections.Immutable;
namespace Upsilon.BaseTypes namespace Upsilon.BaseTypes
@ -5,12 +6,24 @@ namespace Upsilon.BaseTypes
public class TypeContainer public class TypeContainer
{ {
public Type Type { get; } public Type Type { get; }
public string UserData { get; }
protected TypeContainer(Type t) protected TypeContainer(Type t)
{ {
if (t == Type.UserData)
{
throw new Exception(
"Instantiating a userdata type without specifying type. Use constructor with string instead.");
}
Type = t; Type = t;
} }
public TypeContainer(string userData)
{
Type = Type.UserData;
UserData = userData;
}
public static implicit operator TypeContainer (Type type) public static implicit operator TypeContainer (Type type)
{ {
return new TypeContainer(type); return new TypeContainer(type);
@ -61,7 +74,7 @@ namespace Upsilon.BaseTypes
public class CompositeTypeContainer : TypeContainer public class CompositeTypeContainer : TypeContainer
{ {
public ImmutableArray<Type> Types { get; set; } public ImmutableArray<TypeContainer> Types { get; set; }
public CompositeTypeContainer() : base(Type.Table) public CompositeTypeContainer() : base(Type.Table)
{ {

View File

@ -6,6 +6,7 @@ using Upsilon.BaseTypes.Number;
using Upsilon.BaseTypes.ScriptFunction; using Upsilon.BaseTypes.ScriptFunction;
using Upsilon.BaseTypes.ScriptTypeInterfaces; using Upsilon.BaseTypes.ScriptTypeInterfaces;
using Upsilon.BaseTypes.UserData; using Upsilon.BaseTypes.UserData;
using Upsilon.BoundTypes;
using Upsilon.Text; using Upsilon.Text;
namespace Upsilon.BaseTypes namespace Upsilon.BaseTypes
@ -108,7 +109,7 @@ namespace Upsilon.BaseTypes
} }
} }
public static Type GetScriptType(this System.Type t) public static TypeContainer GetScriptType(this System.Type t)
{ {
if (t == typeof(bool)) if (t == typeof(bool))
return Type.Boolean; return Type.Boolean;
@ -144,7 +145,7 @@ namespace Upsilon.BaseTypes
if (t == typeof(ScriptType)) if (t == typeof(ScriptType))
return Type.Unknown; return Type.Unknown;
return Type.UserData; return new TypeContainer(BoundTypeHandler.GetTypeName(t));
} }
} }

View File

@ -954,7 +954,16 @@ namespace Upsilon.Binder
VariableSymbol valueVariable; VariableSymbol valueVariable;
if (boundEnumerableExpression.Type is CompositeTypeContainer composite && composite.Types.Length == 2) if (boundEnumerableExpression.Type is CompositeTypeContainer composite && composite.Types.Length == 2)
{ {
valueVariable = new VariableSymbol(valueVar.Name, composite.Types[1], true); var type = composite.Types[1];
if (type == Type.UserData)
{
valueVariable = new UserDataVariableSymbol(valueVar.Name,
BoundTypeHandler.GetTypeDefinition(type.UserData));
}
else
{
valueVariable = new VariableSymbol(valueVar.Name, composite.Types[1], true);
}
} }
else else
{ {

View File

@ -33,7 +33,7 @@ namespace Upsilon.Binder
public BoundExpression Expression { get; } public BoundExpression Expression { get; }
public string Index { get; } public string Index { get; }
public BoundFullStopIndexExpression(BoundExpression expression, string index, Type type, TextSpan span) : base(span) public BoundFullStopIndexExpression(BoundExpression expression, string index, TypeContainer type, TextSpan span) : base(span)
{ {
Expression = expression; Expression = expression;
Index = index; Index = index;

View File

@ -50,7 +50,7 @@ namespace Upsilon.Binder
if (valueType.HasValue) if (valueType.HasValue)
valueRealType = valueType.Value; valueRealType = valueType.Value;
var arr = new[] {BaseTypes.Type.String, valueRealType}; var arr = new TypeContainer[] {BaseTypes.Type.String, valueRealType};
return new CompositeTypeContainer() return new CompositeTypeContainer()
{ {
Types = arr.ToImmutableArray() Types = arr.ToImmutableArray()

View File

@ -4,19 +4,19 @@ namespace Upsilon.BoundTypes
{ {
public class BoundTypeDefinition public class BoundTypeDefinition
{ {
public BoundTypeDefinition(Type scriptType, System.Type[] validInternalTypes) public BoundTypeDefinition(TypeContainer scriptType, System.Type[] validInternalTypes)
{ {
ScriptType = scriptType; ScriptType = scriptType;
ValidInternalTypes = validInternalTypes; ValidInternalTypes = validInternalTypes;
} }
public BoundTypeDefinition(Type scriptType, System.Type backingType) public BoundTypeDefinition(TypeContainer scriptType, System.Type backingType)
{ {
ScriptType = scriptType; ScriptType = scriptType;
ValidInternalTypes = new []{backingType}; ValidInternalTypes = new []{backingType};
} }
public Type ScriptType { get; } public TypeContainer ScriptType { get; }
public System.Type[] ValidInternalTypes { get; } public System.Type[] ValidInternalTypes { get; }
} }
} }

View File

@ -41,6 +41,11 @@ namespace Upsilon.BoundTypes
return TypeDefinitions.Values.FirstOrDefault(x => x.ValidInternalTypes.Contains(type)); return TypeDefinitions.Values.FirstOrDefault(x => x.ValidInternalTypes.Contains(type));
} }
public static string GetTypeName(System.Type type)
{
return TypeDefinitions.FirstOrDefault(x => x.Value.ValidInternalTypes.Contains(type)).Key;
}
public static void LoadUserDataTypeDefinition(UserDataBoundTypeDefinition def) public static void LoadUserDataTypeDefinition(UserDataBoundTypeDefinition def)
{ {
var key = def.Name.ToLowerInvariant(); var key = def.Name.ToLowerInvariant();

View File

@ -16,14 +16,14 @@ namespace Upsilon.BoundTypes
public string Name { get; protected set; } public string Name { get; protected set; }
public Dictionary<string, UserDataBoundProperty> Properties { get; protected set; } public Dictionary<string, UserDataBoundProperty> Properties { get; protected set; }
internal UserDataBoundTypeDefinition(System.Type backingType) internal UserDataBoundTypeDefinition(System.Type backingType, string name)
: base(Type.UserData, backingType) : base(new TypeContainer(name), backingType)
{ {
Name = backingType.Name; Name = backingType.Name;
} }
public UserDataBoundTypeDefinition(string name, Dictionary<string, UserDataBoundProperty> backingType) public UserDataBoundTypeDefinition(string name, Dictionary<string, UserDataBoundProperty> backingType)
: base(Type.UserData, typeof(void)) : base(new TypeContainer(name), typeof(void))
{ {
Name = name; Name = name;
Properties = backingType; Properties = backingType;
@ -33,7 +33,7 @@ namespace Upsilon.BoundTypes
public static UserDataBoundTypeDefinition Create(System.Type backingType, string name) public static UserDataBoundTypeDefinition Create(System.Type backingType, string name)
{ {
var obj = new UserDataBoundTypeDefinition(backingType) var obj = new UserDataBoundTypeDefinition(backingType, name)
{ {
Properties = new Dictionary<string, UserDataBoundProperty>(), Properties = new Dictionary<string, UserDataBoundProperty>(),
Name = name Name = name
@ -101,7 +101,7 @@ namespace Upsilon.BoundTypes
public class UserDataBoundEnumDefinition : UserDataBoundTypeDefinition public class UserDataBoundEnumDefinition : UserDataBoundTypeDefinition
{ {
public UserDataBoundEnumDefinition(System.Type enumType, string name) : base(enumType) public UserDataBoundEnumDefinition(System.Type enumType, string name) : base(enumType, name)
{ {
if (!enumType.IsEnum) if (!enumType.IsEnum)
throw new Exception("Trying to bind an enum with a type that's not an enum"); throw new Exception("Trying to bind an enum with a type that's not an enum");
@ -120,7 +120,7 @@ namespace Upsilon.BoundTypes
{ {
Name = valueName, Name = valueName,
ActualType = enumType.ToString(), ActualType = enumType.ToString(),
Type = Type.UserData Type = new TypeContainer(name)
}); });
} }
} }
@ -136,7 +136,7 @@ namespace Upsilon.BoundTypes
Properties.Add(valueName, new UserDataBoundProperty() Properties.Add(valueName, new UserDataBoundProperty()
{ {
Name = valueName, Name = valueName,
Type = Type.UserData, Type = new TypeContainer(name),
ActualType = name ActualType = name
}); });
} }
@ -146,7 +146,7 @@ namespace Upsilon.BoundTypes
public class UserDataBoundProperty public class UserDataBoundProperty
{ {
public string Name { get; set; } public string Name { get; set; }
public Type Type { get; set; } public TypeContainer Type { get; set; }
public virtual string ActualType { get; set; } public virtual string ActualType { get; set; }
public string Comment { get; set; } public string Comment { get; set; }
} }
@ -159,7 +159,7 @@ namespace Upsilon.BoundTypes
public class UserDataBoundMethod: UserDataBoundProperty public class UserDataBoundMethod: UserDataBoundProperty
{ {
public override string ActualType => "Function"; public override string ActualType => "Function";
public Type ResultType { get; set; } public TypeContainer ResultType { get; set; }
public UserDataBoundFunctionParameter[] Parameters { get; set; } public UserDataBoundFunctionParameter[] Parameters { get; set; }
public (bool IsValid, string Error, public (bool IsValid, string Error,
@ -177,21 +177,21 @@ namespace Upsilon.BoundTypes
{ {
var functionParameter = Parameters[i]; var functionParameter = Parameters[i];
var callingParameter = callingParameters[i]; var callingParameter = callingParameters[i];
if (callingParameter.Type == Type.Unknown || callingParameter.Type == Type.Nil) if (callingParameter.Type == BaseTypes.Type.Unknown || callingParameter.Type == BaseTypes.Type.Nil)
continue; continue;
if (!functionParameter.Type.HasFlag(callingParameter.Type)) if (!functionParameter.Type.Type.HasFlag(callingParameter.Type))
{ {
return (false, return (false,
$"Unexpected variable passed to internal function at variable {i + 1}. " + $"Unexpected variable passed to internal function at variable {i + 1}. " +
$"Expected one of the following: {functionParameter.Type.ToString()}, got: '{callingParameter.Type}'", $"Expected one of the following: {functionParameter.Type}, got: '{callingParameter.Type}'",
callingParameter); callingParameter);
} }
if (functionParameter.Type.HasFlag(Type.UserData)) if (functionParameter.Type.Type.HasFlag(BaseTypes.Type.UserData))
{ {
var variable = Binder.Binder.ResolveVariable(callingParameter, null); var variable = Binder.Binder.ResolveVariable(callingParameter, null);
if (variable != null && variable.TypeContainer == Type.UserData) if (variable != null && variable.TypeContainer == BaseTypes.Type.UserData)
{ {
var parent = var parent =
(UserDataBoundTypeDefinition) ((UserDataVariableSymbol) variable).BoundTypeDefinition; (UserDataBoundTypeDefinition) ((UserDataVariableSymbol) variable).BoundTypeDefinition;