Bind indexing of userdata

This commit is contained in:
Deukhoofd 2018-11-29 18:09:08 +01:00
parent c1f4c8fb37
commit f983239b5a
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
6 changed files with 118 additions and 32 deletions

View File

@ -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>()

View File

@ -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:

View File

@ -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;
}
}
}

View File

@ -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; }
}
}

View File

@ -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);
}
}
}
}

View File

@ -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; }
}
}