Bind indexing of userdata
This commit is contained in:
parent
c1f4c8fb37
commit
f983239b5a
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Upsilon.BoundTypes;
|
||||||
|
|
||||||
namespace Upsilon.BaseTypes.UserData
|
namespace Upsilon.BaseTypes.UserData
|
||||||
{
|
{
|
||||||
|
@ -10,6 +11,7 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
{
|
{
|
||||||
var info = new UserDataType(t);
|
var info = new UserDataType(t);
|
||||||
_types.Add(t, info);
|
_types.Add(t, info);
|
||||||
|
BoundTypeHandler.LoadUserDataTypeDefinition(new UserDataBoundTypeDefinition(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void LoadType<T>()
|
public static void LoadType<T>()
|
||||||
|
|
|
@ -47,7 +47,8 @@ namespace Upsilon.Binder
|
||||||
foreach (var valueParameter in unboundFunctionStatement.Value.Parameters)
|
foreach (var valueParameter in unboundFunctionStatement.Value.Parameters)
|
||||||
{
|
{
|
||||||
Scope.AssignToNearest(valueParameter.VariableSymbol);
|
Scope.AssignToNearest(valueParameter.VariableSymbol);
|
||||||
_diagnostics.LogUnknownVariableType(valueParameter.VariableSymbol.Name, valueParameter.Span);
|
if (valueParameter.VariableSymbol.Type == Type.Unknown)
|
||||||
|
_diagnostics.LogUnknownVariableType(valueParameter.VariableSymbol.Name, valueParameter.Span);
|
||||||
}
|
}
|
||||||
unboundFunctionStatement.Value.Block =
|
unboundFunctionStatement.Value.Block =
|
||||||
(BoundBlockStatement) BindBlockStatement(unboundFunctionStatement.Value.UnboundBlock);
|
(BoundBlockStatement) BindBlockStatement(unboundFunctionStatement.Value.UnboundBlock);
|
||||||
|
@ -458,7 +459,15 @@ namespace Upsilon.Binder
|
||||||
if (variable.TypeName != null)
|
if (variable.TypeName != null)
|
||||||
{
|
{
|
||||||
var type = BoundTypeHandler.GetTypeDefinition(variable.TypeName.Name);
|
var type = BoundTypeHandler.GetTypeDefinition(variable.TypeName.Name);
|
||||||
variableSymbol = new FunctionParameterSymbol(variable.IdentifierName.Name, type);
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -688,6 +697,23 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
return new BoundFullStopIndexExpression(expression, index, Type.Unknown, e.Span);
|
return new BoundFullStopIndexExpression(expression, index, Type.Unknown, e.Span);
|
||||||
case Type.UserData:
|
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:
|
case Type.Unknown:
|
||||||
return new BoundFullStopIndexExpression(expression, index, Type.Unknown, e.Span);
|
return new BoundFullStopIndexExpression(expression, index, Type.Unknown, e.Span);
|
||||||
case Type.String:
|
case Type.String:
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace Upsilon.Binder
|
||||||
Name = name;
|
Name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type Type { get; set; }
|
public virtual Type Type { get; set; }
|
||||||
public bool Local { get; }
|
public bool Local { get; }
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
public string[] CommentValue { get; set; }
|
public string[] CommentValue { get; set; }
|
||||||
|
@ -51,6 +51,12 @@ namespace Upsilon.Binder
|
||||||
BoundTypeDefinition = type;
|
BoundTypeDefinition = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Type _type;
|
||||||
|
public override Type Type
|
||||||
|
{
|
||||||
|
get => BoundTypeDefinition?.ScriptType ?? _type;
|
||||||
|
set => _type = Type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TableVariableSymbol : VariableSymbol
|
public class TableVariableSymbol : VariableSymbol
|
||||||
|
@ -63,16 +69,4 @@ namespace Upsilon.Binder
|
||||||
Variables = variables;
|
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
|
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))},
|
{"string", new BoundTypeDefinition(Type.String, typeof(string))},
|
||||||
{
|
{
|
||||||
|
@ -19,27 +20,36 @@ namespace Upsilon.BoundTypes
|
||||||
{"function", new BoundTypeDefinition(Type.Function, new System.Type[0])},
|
{"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)
|
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)
|
|
||||||
{
|
{
|
||||||
ScriptType = scriptType;
|
var key = def.Name.ToLowerInvariant();
|
||||||
ValidInternalTypes = validInternalTypes;
|
if (_typeDefinitions.ContainsKey(key))
|
||||||
|
{
|
||||||
|
_typeDefinitions[key] = def;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_typeDefinitions.Add(key, def);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundTypeDefinition(Type scriptType, System.Type validInternalType)
|
|
||||||
{
|
|
||||||
ScriptType = scriptType;
|
|
||||||
ValidInternalTypes = new []{validInternalType};
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type ScriptType { get; }
|
|
||||||
public System.Type[] ValidInternalTypes { get; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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