Reworked type handling to handle userdata more easily
This commit is contained in:
parent
6552e153d0
commit
96b0959bd6
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue