Bind indexing of userdata
This commit is contained in:
parent
c1f4c8fb37
commit
f983239b5a
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using Upsilon.BoundTypes;
|
||||
|
||||
namespace Upsilon.BaseTypes.UserData
|
||||
{
|
||||
|
@ -10,6 +11,7 @@ namespace Upsilon.BaseTypes.UserData
|
|||
{
|
||||
var info = new UserDataType(t);
|
||||
_types.Add(t, info);
|
||||
BoundTypeHandler.LoadUserDataTypeDefinition(new UserDataBoundTypeDefinition(t));
|
||||
}
|
||||
|
||||
public static void LoadType<T>()
|
||||
|
|
|
@ -47,6 +47,7 @@ namespace Upsilon.Binder
|
|||
foreach (var valueParameter in unboundFunctionStatement.Value.Parameters)
|
||||
{
|
||||
Scope.AssignToNearest(valueParameter.VariableSymbol);
|
||||
if (valueParameter.VariableSymbol.Type == Type.Unknown)
|
||||
_diagnostics.LogUnknownVariableType(valueParameter.VariableSymbol.Name, valueParameter.Span);
|
||||
}
|
||||
unboundFunctionStatement.Value.Block =
|
||||
|
@ -458,8 +459,16 @@ namespace Upsilon.Binder
|
|||
if (variable.TypeName != null)
|
||||
{
|
||||
var type = BoundTypeHandler.GetTypeDefinition(variable.TypeName.Name);
|
||||
if (type == null)
|
||||
{
|
||||
_diagnostics.LogError($"Unknown type name '{variable.TypeName.Name}'", variable.Span);
|
||||
variableSymbol = new FunctionParameterSymbol(variable.IdentifierName.Name, Type.Unknown);
|
||||
}
|
||||
else
|
||||
{
|
||||
variableSymbol = new FunctionParameterSymbol(variable.IdentifierName.Name, type);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
variableSymbol = new FunctionParameterSymbol(variable.IdentifierName.Name, Type.Unknown);
|
||||
|
@ -688,6 +697,23 @@ namespace Upsilon.Binder
|
|||
}
|
||||
return new BoundFullStopIndexExpression(expression, index, Type.Unknown, e.Span);
|
||||
case Type.UserData:
|
||||
if (isAssignment)
|
||||
{
|
||||
return new BoundFullStopIndexExpression(expression, index, Type.Unknown, e.Span);
|
||||
}
|
||||
|
||||
if (expression.Kind == BoundKind.VariableExpression)
|
||||
{
|
||||
var variableExpression = (BoundVariableExpression)expression;
|
||||
var obj = variableExpression.Variable;
|
||||
var functionParameter = (FunctionParameterSymbol) obj.VariableSymbol;
|
||||
var udBoundDef = (UserDataBoundTypeDefinition)functionParameter.BoundTypeDefinition;
|
||||
if (udBoundDef.Properties.TryGetValue(index, out var property))
|
||||
{
|
||||
return new BoundFullStopIndexExpression(expression, index, property.Type, e.Span);
|
||||
}
|
||||
}
|
||||
return new BoundFullStopIndexExpression(expression, index, Type.Unknown, e.Span);
|
||||
case Type.Unknown:
|
||||
return new BoundFullStopIndexExpression(expression, index, Type.Unknown, e.Span);
|
||||
case Type.String:
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Upsilon.Binder
|
|||
Name = name;
|
||||
}
|
||||
|
||||
public Type Type { get; set; }
|
||||
public virtual Type Type { get; set; }
|
||||
public bool Local { get; }
|
||||
public string Name { get; }
|
||||
public string[] CommentValue { get; set; }
|
||||
|
@ -51,6 +51,12 @@ namespace Upsilon.Binder
|
|||
BoundTypeDefinition = type;
|
||||
}
|
||||
|
||||
private Type _type;
|
||||
public override Type Type
|
||||
{
|
||||
get => BoundTypeDefinition?.ScriptType ?? _type;
|
||||
set => _type = Type;
|
||||
}
|
||||
}
|
||||
|
||||
public class TableVariableSymbol : VariableSymbol
|
||||
|
@ -63,16 +69,4 @@ namespace Upsilon.Binder
|
|||
Variables = variables;
|
||||
}
|
||||
}
|
||||
|
||||
public class UserDataVariableSymbol : VariableSymbol
|
||||
{
|
||||
public BoundTypeDefinition BoundTypeDefinition { get; }
|
||||
|
||||
public UserDataVariableSymbol(string name, bool local, BoundTypeDefinition boundTypeDefinition)
|
||||
:base (name, Type.UserData, local)
|
||||
{
|
||||
BoundTypeDefinition = boundTypeDefinition;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using Upsilon.BaseTypes;
|
||||
|
||||
namespace Upsilon.BoundTypes
|
||||
{
|
||||
public class BoundTypeDefinition
|
||||
{
|
||||
public BoundTypeDefinition(Type scriptType, System.Type[] validInternalTypes)
|
||||
{
|
||||
ScriptType = scriptType;
|
||||
ValidInternalTypes = validInternalTypes;
|
||||
}
|
||||
|
||||
public BoundTypeDefinition(Type scriptType, System.Type backingType)
|
||||
{
|
||||
ScriptType = scriptType;
|
||||
ValidInternalTypes = new []{backingType};
|
||||
}
|
||||
|
||||
public Type ScriptType { get; }
|
||||
public System.Type[] ValidInternalTypes { get; }
|
||||
}
|
||||
}
|
|
@ -6,7 +6,8 @@ namespace Upsilon.BoundTypes
|
|||
{
|
||||
public static class BoundTypeHandler
|
||||
{
|
||||
private static readonly Dictionary<string, BoundTypeDefinition> TypeDefinitions = new Dictionary<string, BoundTypeDefinition>
|
||||
private static readonly Dictionary<string, BoundTypeDefinition> DefaultTypeDefinitions =
|
||||
new Dictionary<string, BoundTypeDefinition>
|
||||
{
|
||||
{"string", new BoundTypeDefinition(Type.String, typeof(string))},
|
||||
{
|
||||
|
@ -19,27 +20,36 @@ namespace Upsilon.BoundTypes
|
|||
{"function", new BoundTypeDefinition(Type.Function, new System.Type[0])},
|
||||
};
|
||||
|
||||
private static Dictionary<string, BoundTypeDefinition> _typeDefinitions =
|
||||
new Dictionary<string, BoundTypeDefinition>(DefaultTypeDefinitions);
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
_typeDefinitions =
|
||||
new Dictionary<string, BoundTypeDefinition>(DefaultTypeDefinitions);
|
||||
}
|
||||
|
||||
public static BoundTypeDefinition GetTypeDefinition(string key)
|
||||
{
|
||||
return TypeDefinitions[key.ToLowerInvariant()];
|
||||
var normalizedName = key.ToLowerInvariant();
|
||||
if (_typeDefinitions.TryGetValue(normalizedName, out var bt))
|
||||
{
|
||||
return bt;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public class BoundTypeDefinition
|
||||
public static void LoadUserDataTypeDefinition(UserDataBoundTypeDefinition def)
|
||||
{
|
||||
public BoundTypeDefinition(Type scriptType, System.Type[] validInternalTypes)
|
||||
var key = def.Name.ToLowerInvariant();
|
||||
if (_typeDefinitions.ContainsKey(key))
|
||||
{
|
||||
ScriptType = scriptType;
|
||||
ValidInternalTypes = validInternalTypes;
|
||||
_typeDefinitions[key] = def;
|
||||
}
|
||||
|
||||
public BoundTypeDefinition(Type scriptType, System.Type validInternalType)
|
||||
else
|
||||
{
|
||||
ScriptType = scriptType;
|
||||
ValidInternalTypes = new []{validInternalType};
|
||||
}
|
||||
|
||||
public Type ScriptType { get; }
|
||||
public System.Type[] ValidInternalTypes { get; }
|
||||
_typeDefinitions.Add(key, def);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
using System.Collections.Generic;
|
||||
using Upsilon.BaseTypes;
|
||||
|
||||
namespace Upsilon.BoundTypes
|
||||
{
|
||||
public class UserDataBoundTypeDefinition : BoundTypeDefinition
|
||||
{
|
||||
public string Name { get; }
|
||||
public Dictionary<string, UserDataBoundProperty> Properties { get; }
|
||||
|
||||
public UserDataBoundTypeDefinition(System.Type backingType)
|
||||
: base(Type.UserData, backingType)
|
||||
{
|
||||
Name = backingType.Name;
|
||||
}
|
||||
|
||||
public UserDataBoundTypeDefinition(string name, Dictionary<string, UserDataBoundProperty> properties)
|
||||
: base(Type.UserData, new System.Type[0])
|
||||
{
|
||||
Name = name;
|
||||
Properties = properties;
|
||||
}
|
||||
}
|
||||
|
||||
public class UserDataBoundProperty
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public Type Type { get; set; }
|
||||
public string ActualType { get; set; }
|
||||
public string Comment { get; set; }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue