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)
{
var name = e.Identifier.Name;
if (!Scope.TryGetVariable(name, true, out var variable))
var expression = BindExpression(e.Expression);
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());
}
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);
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 BoundIndexExpression(TableVariableSymbol identifier, BoundExpression index, Type type)
public BoundIndexExpression(BoundExpression identifier, BoundExpression index, Type type)
{
Identifier = identifier;
Index = index;
Type = type;
}
public TableVariableSymbol Identifier { get; }
public BoundExpression Identifier { get; }
public BoundExpression Index { get; }
public override BoundKind Kind => BoundKind.BoundIndexExpression;

View File

@ -333,20 +333,36 @@ namespace Upsilon.Evaluator
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))
{
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();
}
if (!(val is IIndexable indexable))
{
throw new Exception("Variable is not indexable.");
}
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 IdentifierToken Identifier { get; }
public ExpressionSyntax Expression { get; }
public SyntaxToken OpenBracket { get; }
public ExpressionSyntax Index { get; }
public SyntaxToken CloseBracket { get; }
public IndexExpressionSyntax(IdentifierToken identifier, SyntaxToken openBracket, ExpressionSyntax index,
public IndexExpressionSyntax(ExpressionSyntax expression, SyntaxToken openBracket, ExpressionSyntax index,
SyntaxToken closeBracket)
{
Identifier = identifier;
Expression = expression;
OpenBracket = openBracket;
Index = index;
CloseBracket = closeBracket;
@ -21,7 +21,7 @@ namespace Upsilon.Parser
public override SyntaxKind Kind => SyntaxKind.IndexExpression;
public override IEnumerable<SyntaxNode> ChildNodes()
{
yield return Identifier;
yield return Expression;
yield return OpenBracket;
yield return Index;
yield return CloseBracket;

View File

@ -4,7 +4,8 @@ namespace Upsilon.Parser
{
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;
}

View File

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

View File

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

View File

@ -57,6 +57,27 @@ return table[""test""]
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]
public void FunctionsInTable()
{

View File

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