work on nested tables, will need some cleanup later

This commit is contained in:
Deukhoofd 2018-11-18 16:08:20 +01:00
parent 3d4e6380ea
commit d8f7651de7
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
9 changed files with 93 additions and 47 deletions

View File

@ -387,24 +387,16 @@ namespace Upsilon.Binder
private BoundExpression BindIndexExpression(IndexExpressionSyntax e) private BoundExpression BindIndexExpression(IndexExpressionSyntax e)
{ {
var name = e.Identifier.Name; var expression = BindExpression(e.Expression);
if (!Scope.TryGetVariable(name, true, out var variable)) if (expression.Type != Type.Table && expression.Type != Type.Unknown)
{ {
_diagnostics.LogUnknownVariable(e.Identifier.Span, name); //TODO: wrong type diagnostic
throw new Exception(expression.Type.ToString());
return new BoundLiteralExpression(new LuaNull()); return new BoundLiteralExpression(new LuaNull());
} }
if (variable.Type != Type.Table)
{
//TODO better error message
_diagnostics.LogUnknownVariable(e.Identifier.Span, name);
return new BoundLiteralExpression(new LuaNull());
}
var tableVariable = (TableVariableSymbol) variable;
var outType = tableVariable.OutType;
var index = BindExpression(e.Index); var index = BindExpression(e.Index);
return new BoundIndexExpression(tableVariable, index, outType); return new BoundIndexExpression(expression, index, Type.Unknown);
} }
} }
} }

View File

@ -5,14 +5,14 @@ namespace Upsilon.Binder
{ {
public class BoundIndexExpression : BoundExpression public class BoundIndexExpression : BoundExpression
{ {
public BoundIndexExpression(TableVariableSymbol identifier, BoundExpression index, Type type) public BoundIndexExpression(BoundExpression identifier, BoundExpression index, Type type)
{ {
Identifier = identifier; Identifier = identifier;
Index = index; Index = index;
Type = type; Type = type;
} }
public TableVariableSymbol Identifier { get; } public BoundExpression Identifier { get; }
public BoundExpression Index { get; } public BoundExpression Index { get; }
public override BoundKind Kind => BoundKind.BoundIndexExpression; public override BoundKind Kind => BoundKind.BoundIndexExpression;

View File

@ -333,20 +333,36 @@ namespace Upsilon.Evaluator
private LuaType EvaluateIndexExpression(BoundIndexExpression e) private LuaType EvaluateIndexExpression(BoundIndexExpression e)
{ {
if (!Scope.TryGet(e.Identifier, out var val)) IIndexable index;
if (e.Identifier.Kind == BoundKind.VariableExpression)
{ {
throw new Exception($"Cannot find variable: '{e.Identifier.Name}'"); var variableExpression = (BoundVariableExpression) e.Identifier;
var variable = variableExpression.Variable;
if (!Scope.TryGet(variable, out var val))
{
throw new Exception($"Cannot find variable: '{variable.Name}'");
} }
if (!(val is IIndexable indexable)) if (!(val is IIndexable indexable))
{ {
throw new Exception("Variable is not indexable."); throw new Exception("Variable is not indexable.");
} }
index = indexable;
}
else if (e.Identifier.Kind == BoundKind.BoundIndexExpression)
{
var indexExpression = (BoundIndexExpression)e.Identifier;
index = (IIndexable) EvaluateIndexExpression(indexExpression);
}
else
{
throw new Exception();
}
var innerEvaluator = new Evaluator(_diagnostics, Scope, indexable.EvaluatorIdentifier);
var indexer = EvaluateExpression(e.Index);
return indexable.Get(indexer.ToString(), Identifier); var innerEvaluator = new Evaluator(_diagnostics, Scope, index.EvaluatorIdentifier);
var indexer = innerEvaluator.EvaluateExpression(e.Index);
return index.Get(indexer.ToString(), Identifier);
} }
} }
} }

View File

@ -4,15 +4,15 @@ namespace Upsilon.Parser
{ {
public class IndexExpressionSyntax : ExpressionSyntax public class IndexExpressionSyntax : ExpressionSyntax
{ {
public IdentifierToken Identifier { get; } public ExpressionSyntax Expression { get; }
public SyntaxToken OpenBracket { get; } public SyntaxToken OpenBracket { get; }
public ExpressionSyntax Index { get; } public ExpressionSyntax Index { get; }
public SyntaxToken CloseBracket { get; } public SyntaxToken CloseBracket { get; }
public IndexExpressionSyntax(IdentifierToken identifier, SyntaxToken openBracket, ExpressionSyntax index, public IndexExpressionSyntax(ExpressionSyntax expression, SyntaxToken openBracket, ExpressionSyntax index,
SyntaxToken closeBracket) SyntaxToken closeBracket)
{ {
Identifier = identifier; Expression = expression;
OpenBracket = openBracket; OpenBracket = openBracket;
Index = index; Index = index;
CloseBracket = closeBracket; CloseBracket = closeBracket;
@ -21,7 +21,7 @@ namespace Upsilon.Parser
public override SyntaxKind Kind => SyntaxKind.IndexExpression; public override SyntaxKind Kind => SyntaxKind.IndexExpression;
public override IEnumerable<SyntaxNode> ChildNodes() public override IEnumerable<SyntaxNode> ChildNodes()
{ {
yield return Identifier; yield return Expression;
yield return OpenBracket; yield return OpenBracket;
yield return Index; yield return Index;
yield return CloseBracket; yield return CloseBracket;

View File

@ -4,7 +4,8 @@ namespace Upsilon.Parser
{ {
public class IdentifierToken : SyntaxToken public class IdentifierToken : SyntaxToken
{ {
public IdentifierToken(string name, int position, int length) : base(SyntaxKind.Identifier, position, name, null) public IdentifierToken(string name, int position)
: base(SyntaxKind.Identifier, position, name, null)
{ {
Name = name; Name = name;
} }

View File

@ -166,7 +166,7 @@ namespace Upsilon.Parser
var str = stringBuilder.ToString(); var str = stringBuilder.ToString();
if (kind == SyntaxKind.Identifier) if (kind == SyntaxKind.Identifier)
{ {
return new IdentifierToken(str, start, str.Length); return new IdentifierToken(str, start);
} }
return new SyntaxToken(kind, start, str, null); return new SyntaxToken(kind, start, str, null);
} }

View File

@ -167,7 +167,12 @@ namespace Upsilon.Parser
private ExpressionSyntax ParseExpression() private ExpressionSyntax ParseExpression()
{ {
return ParseBinaryExpression(); var expression = ParseBinaryExpression();
while (Current.Kind == SyntaxKind.OpenBracket)
{
expression = ParseIndexExpression(expression);
}
return expression;
} }
private AssignmentExpressionSyntax ParseAssignmentExpression() private AssignmentExpressionSyntax ParseAssignmentExpression()
@ -214,34 +219,45 @@ namespace Upsilon.Parser
private ExpressionSyntax ParsePrimaryExpression() private ExpressionSyntax ParsePrimaryExpression()
{ {
ExpressionSyntax expression;
switch (Current.Kind) switch (Current.Kind)
{ {
case SyntaxKind.OpenParenthesis: case SyntaxKind.OpenParenthesis:
return ParseParenthesizedExpression(); expression = ParseParenthesizedExpression();
break;
case SyntaxKind.Number: case SyntaxKind.Number:
return ParseNumber(); expression = ParseNumber();
break;
case SyntaxKind.TrueKeyword: case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword: case SyntaxKind.FalseKeyword:
return ParseBoolean(); expression = ParseBoolean();
break;
case SyntaxKind.String: case SyntaxKind.String:
return ParseString(); expression = ParseString();
break;
case SyntaxKind.Identifier: case SyntaxKind.Identifier:
if (Next.Kind == SyntaxKind.OpenParenthesis) if (Next.Kind == SyntaxKind.OpenParenthesis)
return ParseFunctionCallExpression(); expression = ParseFunctionCallExpression();
if (Next.Kind == SyntaxKind.OpenBracket) else
return ParseIndexExpression(); {
var token = MatchToken(SyntaxKind.Identifier); var token = MatchToken(SyntaxKind.Identifier);
return new VariableExpressionSyntax((IdentifierToken) token); expression = new VariableExpressionSyntax((IdentifierToken) token);
}
break;
case SyntaxKind.OpenBrace: case SyntaxKind.OpenBrace:
return ParseTable(); expression = ParseTable();
break;
case SyntaxKind.NilKeyword: case SyntaxKind.NilKeyword:
var nilToken = MatchToken(SyntaxKind.NilKeyword); var nilToken = MatchToken(SyntaxKind.NilKeyword);
return new LiteralExpressionSyntax(nilToken, null); expression = new LiteralExpressionSyntax(nilToken, null);
break;
default: default:
_diagnostics.LogBadCharacter(new TextSpan(_position, 1), SyntaxKind.Identifier); _diagnostics.LogBadCharacter(new TextSpan(_position, 1), SyntaxKind.Identifier);
NextToken(); NextToken();
return new BadExpressionSyntax(); expression = new BadExpressionSyntax();
break;
} }
return expression;
} }
private ExpressionSyntax ParseFunctionCallExpression() private ExpressionSyntax ParseFunctionCallExpression()
@ -262,13 +278,12 @@ namespace Upsilon.Parser
parameters.ToImmutable(), closeParenthesis); parameters.ToImmutable(), closeParenthesis);
} }
private ExpressionSyntax ParseIndexExpression() private ExpressionSyntax ParseIndexExpression(ExpressionSyntax expression)
{ {
var identifier = (IdentifierToken)MatchToken(SyntaxKind.Identifier);
var openBracket = MatchToken(SyntaxKind.OpenBracket); var openBracket = MatchToken(SyntaxKind.OpenBracket);
var index = ParseExpression(); var index = ParseExpression();
var closeBracket = MatchToken(SyntaxKind.CloseBracket); var closeBracket = MatchToken(SyntaxKind.CloseBracket);
return new IndexExpressionSyntax(identifier, openBracket, index, closeBracket); return new IndexExpressionSyntax(expression, openBracket, index, closeBracket);
} }
private ExpressionSyntax ParseParenthesizedExpression() private ExpressionSyntax ParseParenthesizedExpression()

View File

@ -57,6 +57,27 @@ return table[""test""]
Assert.Null(evaluated); Assert.Null(evaluated);
} }
[Fact]
public void NestedTables()
{
const string input = @"
table = {
{
{
100, 600, 900
},
{}
}
}
return table[1][1][2]
";
var script = new Script(input);
Assert.Empty(script.Diagnostics.Messages);
var evaluated = script.Evaluate<long>();
Assert.Empty(script.Diagnostics.Messages);
Assert.Equal(600, evaluated);
}
[Fact] [Fact]
public void FunctionsInTable() public void FunctionsInTable()
{ {

View File

@ -31,6 +31,7 @@ namespace Ycicle
Console.ResetColor(); Console.ResetColor();
continue; continue;
} }
//Console.WriteLine(script.PrettyPrintSyntaxTree());
var evaluate = script.Evaluate(); var evaluate = script.Evaluate();
if (script.Diagnostics.Messages.Count > 0) if (script.Diagnostics.Messages.Count > 0)