More work on binding table variables
This commit is contained in:
parent
a0861e090f
commit
16e1cde5c6
|
@ -2,7 +2,6 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
using Upsilon.BaseTypes.Number;
|
using Upsilon.BaseTypes.Number;
|
||||||
using Upsilon.Parser;
|
using Upsilon.Parser;
|
||||||
|
@ -253,8 +252,7 @@ namespace Upsilon.Binder
|
||||||
if (assignment.Type == Type.Table)
|
if (assignment.Type == Type.Table)
|
||||||
{
|
{
|
||||||
var tableExpression = (BoundTableExpression) assignment;
|
var tableExpression = (BoundTableExpression) assignment;
|
||||||
variable = new TableVariableSymbol(name, tableExpression.ValueType, isLocal,
|
variable = new TableVariableSymbol(name, isLocal, tableExpression.Expressions);
|
||||||
tableExpression.Expressions);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -470,23 +468,31 @@ namespace Upsilon.Binder
|
||||||
|
|
||||||
private BoundExpression BindTableExpression(TableExpressionSyntax e)
|
private BoundExpression BindTableExpression(TableExpressionSyntax e)
|
||||||
{
|
{
|
||||||
var keyType = Type.Unknown;
|
|
||||||
var valueType = Type.Unknown;
|
|
||||||
var statements = ImmutableArray.CreateBuilder<BoundStatement>();
|
var statements = ImmutableArray.CreateBuilder<BoundStatement>();
|
||||||
var s = Scope;
|
var s = Scope;
|
||||||
Scope = BoundScope.WithReadOnlyScope(s);
|
Scope = BoundScope.WithReadOnlyScope(s);
|
||||||
|
var innerVariables = new Dictionary<string, VariableSymbol>();
|
||||||
|
var current = 0;
|
||||||
|
|
||||||
foreach (var expressionSyntax in e.Expressions)
|
foreach (var expressionSyntax in e.Expressions)
|
||||||
{
|
{
|
||||||
var bound = BindStatement((StatementSyntax) expressionSyntax);
|
var bound = BindStatement((StatementSyntax) expressionSyntax);
|
||||||
|
if (bound.Kind == BoundKind.BoundExpressionStatement)
|
||||||
|
{
|
||||||
|
var boundExpression = (BoundExpressionStatement)bound;
|
||||||
|
current++;
|
||||||
|
innerVariables.Add(current.ToString(),
|
||||||
|
new VariableSymbol(current.ToString(), boundExpression.Expression.Type, false));
|
||||||
|
}
|
||||||
statements.Add(bound);
|
statements.Add(bound);
|
||||||
}
|
}
|
||||||
|
|
||||||
var innerVariables = Scope.Variables;
|
innerVariables = innerVariables.Union(Scope.Variables).ToDictionary(k => k.Key, v => v.Value);
|
||||||
Scope = s;
|
Scope = s;
|
||||||
return new BoundTableExpression(keyType, valueType, innerVariables, statements.ToImmutable(), e.Span);
|
return new BoundTableExpression(innerVariables, statements.ToImmutable(), e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExpression BindIndexExpression(IndexExpressionSyntax e)
|
private BoundExpression BindIndexExpression(IndexExpressionSyntax e, bool isAssignment = false)
|
||||||
{
|
{
|
||||||
var expression = BindExpression(e.Expression);
|
var expression = BindExpression(e.Expression);
|
||||||
|
|
||||||
|
@ -499,12 +505,37 @@ namespace Upsilon.Binder
|
||||||
switch (expression.Type)
|
switch (expression.Type)
|
||||||
{
|
{
|
||||||
case Type.Table:
|
case Type.Table:
|
||||||
|
if (isAssignment)
|
||||||
|
{
|
||||||
|
return new BoundIndexExpression(expression, index, Type.Unknown, e.Span);
|
||||||
|
}
|
||||||
if (expression.Kind == BoundKind.BoundTableExpression && index.Kind == BoundKind.BoundLiteralExpression)
|
if (expression.Kind == BoundKind.BoundTableExpression && index.Kind == BoundKind.BoundLiteralExpression)
|
||||||
{
|
{
|
||||||
var table = (BoundTableExpression)expression;
|
var table = (BoundTableExpression)expression;
|
||||||
|
var realIndex = (BoundLiteralExpression) index;
|
||||||
|
var variableDic = table.Expressions;
|
||||||
|
if (variableDic.TryGetValue(realIndex.Value.ToString(), out var variable))
|
||||||
|
{
|
||||||
|
return new BoundIndexExpression(expression, index, variable.Type, e.Span);
|
||||||
|
}
|
||||||
|
|
||||||
|
_diagnostics.LogError($"No variable '{realIndex.Value}' found in table.",
|
||||||
|
e.Span);
|
||||||
|
}
|
||||||
|
else if (expression.Kind == BoundKind.VariableExpression &&
|
||||||
|
index.Kind == BoundKind.BoundLiteralExpression)
|
||||||
|
{
|
||||||
|
var table = (BoundVariableExpression)expression;
|
||||||
|
var realTable = table.Variable;
|
||||||
var realIndex = (BoundLiteralExpression) index;
|
var realIndex = (BoundLiteralExpression) index;
|
||||||
var variable = table.Expressions[realIndex.Value.ToString()];
|
var variableDic = ((TableVariableSymbol) realTable.VariableSymbol).Variables;
|
||||||
return new BoundIndexExpression(expression, index, variable.Type, e.Span);
|
if (variableDic.TryGetValue(realIndex.Value.ToString(), out var variable))
|
||||||
|
{
|
||||||
|
return new BoundIndexExpression(expression, index, variable.Type, e.Span);
|
||||||
|
}
|
||||||
|
|
||||||
|
_diagnostics.LogError($"No variable '{realIndex.Value}' found in table '{realTable.VariableSymbol.Name}'.",
|
||||||
|
e.Span);
|
||||||
}
|
}
|
||||||
return new BoundIndexExpression(expression, index, Type.Unknown, e.Span);
|
return new BoundIndexExpression(expression, index, Type.Unknown, e.Span);
|
||||||
case Type.UserData:
|
case Type.UserData:
|
||||||
|
@ -518,13 +549,17 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExpression BindFullStopIndexExpression(FullStopIndexExpressionSyntax e)
|
private BoundExpression BindFullStopIndexExpression(FullStopIndexExpressionSyntax e, bool isAssignment = false)
|
||||||
{
|
{
|
||||||
var expression = BindExpression(e.Expression);
|
var expression = BindExpression(e.Expression);
|
||||||
var index = e.Index.Name;
|
var index = e.Index.Name;
|
||||||
switch (expression.Type)
|
switch (expression.Type)
|
||||||
{
|
{
|
||||||
case Type.Table:
|
case Type.Table:
|
||||||
|
if (isAssignment)
|
||||||
|
{
|
||||||
|
return new BoundFullStopIndexExpression(expression, index, Type.Unknown, e.Span);
|
||||||
|
}
|
||||||
if (expression.Kind == BoundKind.BoundTableExpression)
|
if (expression.Kind == BoundKind.BoundTableExpression)
|
||||||
{
|
{
|
||||||
var table = (BoundTableExpression)expression;
|
var table = (BoundTableExpression)expression;
|
||||||
|
@ -532,7 +567,7 @@ namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
return new BoundFullStopIndexExpression(expression, index, variable.Type, e.Span);
|
return new BoundFullStopIndexExpression(expression, index, variable.Type, e.Span);
|
||||||
}
|
}
|
||||||
_diagnostics.LogError($"No variable {index} found in table.", e.Span);
|
_diagnostics.LogError($"No variable '{index}' found in table.", e.Span);
|
||||||
}
|
}
|
||||||
if (expression.Kind == BoundKind.VariableExpression)
|
if (expression.Kind == BoundKind.VariableExpression)
|
||||||
{
|
{
|
||||||
|
@ -544,7 +579,7 @@ namespace Upsilon.Binder
|
||||||
return new BoundFullStopIndexExpression(expression, index, variable.Type, e.Span);
|
return new BoundFullStopIndexExpression(expression, index, variable.Type, e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
_diagnostics.LogError($"No variable {index} found in table {realTable.VariableSymbol.Name}.",
|
_diagnostics.LogError($"No variable '{index}' found in table '{realTable.VariableSymbol.Name}'.",
|
||||||
e.Span);
|
e.Span);
|
||||||
}
|
}
|
||||||
return new BoundFullStopIndexExpression(expression, index, Type.Unknown, e.Span);
|
return new BoundFullStopIndexExpression(expression, index, Type.Unknown, e.Span);
|
||||||
|
@ -562,12 +597,41 @@ namespace Upsilon.Binder
|
||||||
private BoundStatement BindTableAssignmentStatement(TableAssigmentStatementSyntax e)
|
private BoundStatement BindTableAssignmentStatement(TableAssigmentStatementSyntax e)
|
||||||
{
|
{
|
||||||
BoundExpression indexableExpression;
|
BoundExpression indexableExpression;
|
||||||
if (e.TableExpression.Kind == SyntaxKind.IndexExpression)
|
|
||||||
indexableExpression = (BoundIndexExpression)BindExpression(e.TableExpression);
|
|
||||||
else
|
|
||||||
indexableExpression = (BoundFullStopIndexExpression)BindExpression(e.TableExpression);
|
|
||||||
|
|
||||||
var value = BindExpression(e.Expression);
|
var value = BindExpression(e.Expression);
|
||||||
|
|
||||||
|
if (e.TableExpression.Kind == SyntaxKind.IndexExpression)
|
||||||
|
{
|
||||||
|
var indexable =
|
||||||
|
(BoundIndexExpression) BindIndexExpression((IndexExpressionSyntax) e.TableExpression, true);
|
||||||
|
|
||||||
|
if (indexable.Identifier.Kind == BoundKind.VariableExpression &&
|
||||||
|
indexable.Index.Kind == BoundKind.BoundLiteralExpression)
|
||||||
|
{
|
||||||
|
var variable = (BoundVariableExpression)indexable.Identifier;
|
||||||
|
var index = (BoundLiteralExpression)indexable.Index;
|
||||||
|
((TableVariableSymbol)variable.Variable.VariableSymbol).Variables.Add(index.Value.ToString(),
|
||||||
|
new VariableSymbol(index.Value.ToString(), value.Type, false));
|
||||||
|
}
|
||||||
|
indexableExpression = indexable;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var indexable =
|
||||||
|
(BoundFullStopIndexExpression) BindFullStopIndexExpression(
|
||||||
|
(FullStopIndexExpressionSyntax) e.TableExpression, true);
|
||||||
|
|
||||||
|
if (indexable.Expression.Kind == BoundKind.VariableExpression)
|
||||||
|
{
|
||||||
|
var variable = (BoundVariableExpression)indexable.Expression;
|
||||||
|
if (variable.Type == Type.Table)
|
||||||
|
{
|
||||||
|
((TableVariableSymbol)variable.Variable.VariableSymbol).Variables.Add(indexable.Index,
|
||||||
|
new VariableSymbol(indexable.Index, value.Type, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
indexableExpression = indexable;
|
||||||
|
}
|
||||||
|
|
||||||
return new BoundTableAssigmentStatement(indexableExpression, value, e.Span);
|
return new BoundTableAssigmentStatement(indexableExpression, value, e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,9 @@ namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundTableExpression : BoundExpression
|
public class BoundTableExpression : BoundExpression
|
||||||
{
|
{
|
||||||
public BoundTableExpression(Type keyType, Type valueType, Dictionary<string, VariableSymbol> expressions,
|
public BoundTableExpression(Dictionary<string, VariableSymbol> expressions,
|
||||||
ImmutableArray<BoundStatement> statements, TextSpan span) : base(span)
|
ImmutableArray<BoundStatement> statements, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
KeyType = keyType;
|
|
||||||
ValueType = valueType;
|
|
||||||
Expressions = expressions;
|
Expressions = expressions;
|
||||||
Statements = statements;
|
Statements = statements;
|
||||||
}
|
}
|
||||||
|
@ -30,8 +28,6 @@ namespace Upsilon.Binder
|
||||||
|
|
||||||
public override Type Type => Type.Table;
|
public override Type Type => Type.Table;
|
||||||
|
|
||||||
public Type KeyType { get; }
|
|
||||||
public Type ValueType { get; }
|
|
||||||
|
|
||||||
public Dictionary<string, VariableSymbol> Expressions { get; }
|
public Dictionary<string, VariableSymbol> Expressions { get; }
|
||||||
public ImmutableArray<BoundStatement> Statements { get; }
|
public ImmutableArray<BoundStatement> Statements { get; }
|
||||||
|
|
|
@ -34,13 +34,11 @@ namespace Upsilon.Binder
|
||||||
|
|
||||||
public class TableVariableSymbol : VariableSymbol
|
public class TableVariableSymbol : VariableSymbol
|
||||||
{
|
{
|
||||||
public Type OutType { get; }
|
|
||||||
public Dictionary<string, VariableSymbol> Variables { get; }
|
public Dictionary<string, VariableSymbol> Variables { get; }
|
||||||
|
|
||||||
public TableVariableSymbol(string name, Type outType, bool local, Dictionary<string, VariableSymbol> variables)
|
public TableVariableSymbol(string name, bool local, Dictionary<string, VariableSymbol> variables)
|
||||||
:base (name, Type.Table, local)
|
:base (name, Type.Table, local)
|
||||||
{
|
{
|
||||||
OutType = outType;
|
|
||||||
Variables = variables;
|
Variables = variables;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue