Made indexable also work with full stop index

This commit is contained in:
Deukhoofd 2018-11-20 14:05:34 +01:00
parent 066af47b5b
commit df8c7b99c9
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
10 changed files with 130 additions and 15 deletions

View File

@ -4,6 +4,7 @@ using System.Collections.Immutable;
using Upsilon.BaseTypes; using Upsilon.BaseTypes;
using Upsilon.BaseTypes.Number; using Upsilon.BaseTypes.Number;
using Upsilon.Parser; using Upsilon.Parser;
using Upsilon.Text;
using Type = Upsilon.BaseTypes.Type; using Type = Upsilon.BaseTypes.Type;
namespace Upsilon.Binder namespace Upsilon.Binder
@ -83,6 +84,8 @@ namespace Upsilon.Binder
return BindTableExpression((TableExpressionSyntax) e); return BindTableExpression((TableExpressionSyntax) e);
case SyntaxKind.IndexExpression: case SyntaxKind.IndexExpression:
return BindIndexExpression((IndexExpressionSyntax) e); return BindIndexExpression((IndexExpressionSyntax) e);
case SyntaxKind.FullStopIndexExpression:
return BindFullStopIndexExpression((FullStopIndexExpressionSyntax) e);
case SyntaxKind.FunctionExpression: case SyntaxKind.FunctionExpression:
return BindFunctionExpression((FunctionExpressionSyntax) e); return BindFunctionExpression((FunctionExpressionSyntax) e);
case SyntaxKind.BadExpression: case SyntaxKind.BadExpression:
@ -452,11 +455,34 @@ namespace Upsilon.Binder
} }
} }
private BoundExpression BindFullStopIndexExpression(FullStopIndexExpressionSyntax e)
{
var expression = BindExpression(e.Expression);
var index = e.Index.Name;
switch (expression.Type)
{
case Type.Table:
case Type.UserData:
case Type.Unknown:
return new BoundFullStopIndexExpression(expression, index);
case Type.String:
return new BoundFullStopIndexExpression(expression, index);
default:
_diagnostics.LogInvalidIndexExpression(expression.Type, Type.String, e.Span);
return new BoundLiteralExpression(new LuaNull());
}
}
private BoundStatement BindTableAssignmentStatement(TableAssigmentStatementSyntax e) private BoundStatement BindTableAssignmentStatement(TableAssigmentStatementSyntax e)
{ {
var tableIndexExpression = (BoundIndexExpression)BindExpression(e.TableExpression); 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);
return new BoundTableAssigmentStatement(tableIndexExpression, value); return new BoundTableAssigmentStatement(indexableExpression, value);
} }
} }
} }

View File

@ -18,4 +18,19 @@ namespace Upsilon.Binder
public override BoundKind Kind => BoundKind.BoundIndexExpression; public override BoundKind Kind => BoundKind.BoundIndexExpression;
public override Type Type { get; } public override Type Type { get; }
} }
public class BoundFullStopIndexExpression : BoundExpression
{
public BoundExpression Expression { get; }
public string Index { get; }
public BoundFullStopIndexExpression(BoundExpression expression, string index)
{
Expression = expression;
Index = index;
}
public override BoundKind Kind => BoundKind.BoundFullstopIndexExpression;
public override Type Type => Type.Unknown;
}
} }

View File

@ -22,6 +22,7 @@ namespace Upsilon.Binder
BoundPromise, BoundPromise,
BoundReturnStatement, BoundReturnStatement,
BoundFunctionAssignmentStatement, BoundFunctionAssignmentStatement,
BoundTableAssigmentStatement BoundTableAssigmentStatement,
BoundFullstopIndexExpression
} }
} }

View File

@ -2,10 +2,10 @@ namespace Upsilon.Binder
{ {
public class BoundTableAssigmentStatement : BoundStatement public class BoundTableAssigmentStatement : BoundStatement
{ {
public BoundIndexExpression TableIndexExpression { get; } public BoundExpression TableIndexExpression { get; }
public BoundExpression Value { get; } public BoundExpression Value { get; }
public BoundTableAssigmentStatement(BoundIndexExpression tableIndexExpression, BoundExpression value) public BoundTableAssigmentStatement(BoundExpression tableIndexExpression, BoundExpression value)
{ {
TableIndexExpression = tableIndexExpression; TableIndexExpression = tableIndexExpression;
Value = value; Value = value;

View File

@ -71,6 +71,7 @@ namespace Upsilon.Evaluator
case BoundKind.BoundFunctionExpression: case BoundKind.BoundFunctionExpression:
case BoundKind.BoundTableExpression: case BoundKind.BoundTableExpression:
case BoundKind.BoundIndexExpression: case BoundKind.BoundIndexExpression:
case BoundKind.BoundFullstopIndexExpression:
_lastValue = EvaluateExpression((BoundExpression) b); _lastValue = EvaluateExpression((BoundExpression) b);
break; break;
case BoundKind.BoundAssignmentStatement: case BoundKind.BoundAssignmentStatement:
@ -148,6 +149,8 @@ namespace Upsilon.Evaluator
return EvaluateBoundFunctionStatement((BoundFunctionExpression) e); return EvaluateBoundFunctionStatement((BoundFunctionExpression) e);
case BoundKind.BoundPromise: case BoundKind.BoundPromise:
return EvaluateUnboundFunctionStatement((UnboundFunctionExpression) e); return EvaluateUnboundFunctionStatement((UnboundFunctionExpression) e);
case BoundKind.BoundFullstopIndexExpression:
return EvaluateFullStopIndexExpression((BoundFullStopIndexExpression) e);
default: default:
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -343,16 +346,41 @@ namespace Upsilon.Evaluator
{ {
scope = scopeOwner.EvaluationScope; scope = scopeOwner.EvaluationScope;
} }
var indexer = EvaluateExpression(e.Index);
var evaluator = new Evaluator(_diagnostics, scope);
var indexer = evaluator.EvaluateExpression(e.Index);
return indexable.Get(indexer.ToString(), scope); return indexable.Get(indexer.ToString(), scope);
} }
private LuaType EvaluateFullStopIndexExpression(BoundFullStopIndexExpression e)
{
var variable = EvaluateExpression(e.Expression);
if (!(variable is IIndexable indexable))
{
throw new Exception("Variable is not indexable.");
}
var scope = Scope;
if (variable is IScopeOwner scopeOwner)
{
scope = scopeOwner.EvaluationScope;
}
return indexable.Get(e.Index, scope);
}
private void EvaluateTableAssignmentStatement(BoundTableAssigmentStatement e) private void EvaluateTableAssignmentStatement(BoundTableAssigmentStatement e)
{ {
var table = EvaluateExpression(e.TableIndexExpression.Identifier); LuaType table;
var index = EvaluateExpression(e.TableIndexExpression.Index); LuaType index;
if (e.TableIndexExpression.Kind == BoundKind.BoundIndexExpression)
{
table = EvaluateExpression(((BoundIndexExpression)e.TableIndexExpression).Identifier);
index = EvaluateExpression(((BoundIndexExpression)e.TableIndexExpression).Index);
}
else
{
table = EvaluateExpression(((BoundFullStopIndexExpression)e.TableIndexExpression).Expression);
index = ((BoundFullStopIndexExpression) e.TableIndexExpression).Index.ToLuaType();
}
var value = EvaluateExpression(e.Value); var value = EvaluateExpression(e.Value);
if (!(table is IIndexable indexable)) if (!(table is IIndexable indexable))
{ {

View File

@ -27,4 +27,26 @@ namespace Upsilon.Parser
yield return CloseBracket; yield return CloseBracket;
} }
} }
public class FullStopIndexExpressionSyntax : ExpressionSyntax
{
public ExpressionSyntax Expression { get; }
public SyntaxToken FullStop { get; }
public IdentifierToken Index { get; }
public FullStopIndexExpressionSyntax(ExpressionSyntax expression, SyntaxToken fullStop, IdentifierToken index)
{
Expression = expression;
FullStop = fullStop;
Index = index;
}
public override SyntaxKind Kind => SyntaxKind.FullStopIndexExpression;
public override IEnumerable<SyntaxNode> ChildNodes()
{
yield return Expression;
yield return FullStop;
yield return Index;
}
}
} }

View File

@ -74,6 +74,8 @@ namespace Upsilon.Parser
return new SyntaxToken(SyntaxKind.OpenBracket, _position, "[", null); return new SyntaxToken(SyntaxKind.OpenBracket, _position, "[", null);
case ']': case ']':
return new SyntaxToken(SyntaxKind.CloseBracket, _position, "]", null); return new SyntaxToken(SyntaxKind.CloseBracket, _position, "]", null);
case '.':
return new SyntaxToken(SyntaxKind.FullStop, _position, ".", null);
case ',': case ',':
return new SyntaxToken(SyntaxKind.Comma, _position, ",", null); return new SyntaxToken(SyntaxKind.Comma, _position, ",", null);
case '"': case '"':

View File

@ -178,6 +178,10 @@ namespace Upsilon.Parser
{ {
return ParseTableAssignmentExpression(expression); return ParseTableAssignmentExpression(expression);
} }
if (expression.Kind == SyntaxKind.FullStopIndexExpression && Current.Kind == SyntaxKind.Equals)
{
return ParseTableAssignmentExpression(expression);
}
return new ExpressionStatementSyntax(expression); return new ExpressionStatementSyntax(expression);
} }
@ -199,12 +203,15 @@ namespace Upsilon.Parser
{ {
expression = ParseBinaryExpression(); expression = ParseBinaryExpression();
} }
while (Current.Kind == SyntaxKind.OpenBracket || Current.Kind == SyntaxKind.OpenParenthesis) while (Current.Kind == SyntaxKind.OpenBracket || Current.Kind == SyntaxKind.OpenParenthesis ||
Current.Kind == SyntaxKind.FullStop)
{ {
if (Current.Kind == SyntaxKind.OpenBracket) if (Current.Kind == SyntaxKind.OpenBracket)
expression = ParseIndexExpression(expression); expression = ParseIndexExpression(expression);
else if (Current.Kind == SyntaxKind.OpenParenthesis) else if (Current.Kind == SyntaxKind.OpenParenthesis)
expression = ParseFunctionCallExpression(expression); expression = ParseFunctionCallExpression(expression);
else if (Current.Kind == SyntaxKind.FullStop)
expression = ParseFullStopIndexExpression(expression);
} }
return expression; return expression;
} }
@ -317,12 +324,24 @@ namespace Upsilon.Parser
private ExpressionSyntax ParseIndexExpression(ExpressionSyntax expression) private ExpressionSyntax ParseIndexExpression(ExpressionSyntax expression)
{ {
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(expression, openBracket, index, closeBracket); return new IndexExpressionSyntax(expression, openBracket, index, closeBracket);
} }
private ExpressionSyntax ParseFullStopIndexExpression(ExpressionSyntax expression)
{
var fullStop = MatchToken(SyntaxKind.FullStop);
var index = MatchToken(SyntaxKind.Identifier);
if (index is IdentifierToken identifier)
{
return new FullStopIndexExpressionSyntax(expression, fullStop, identifier);
}
_diagnostics.LogBadCharacter(expression.Span, SyntaxKind.Identifier);
return new BadExpressionSyntax();
}
private ExpressionSyntax ParseParenthesizedExpression() private ExpressionSyntax ParseParenthesizedExpression()
{ {
var l = MatchToken(SyntaxKind.OpenParenthesis); var l = MatchToken(SyntaxKind.OpenParenthesis);

View File

@ -21,6 +21,7 @@ namespace Upsilon.Parser
Tilde, Tilde,
TildeEquals, TildeEquals,
Comma, Comma,
FullStop,
String, String,
OpenBrace, OpenBrace,
CloseBrace, CloseBrace,
@ -56,6 +57,7 @@ namespace Upsilon.Parser
BadExpression, BadExpression,
TableExpression, TableExpression,
IndexExpression, IndexExpression,
FullStopIndexExpression,
// script unit // script unit
ScriptUnit, ScriptUnit,
@ -69,6 +71,6 @@ namespace Upsilon.Parser
FunctionExpression, FunctionExpression,
ReturnStatement, ReturnStatement,
FunctionAssignmentStatement, FunctionAssignmentStatement,
TableAssignmentStatement TableAssignmentStatement,
} }
} }

View File

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