Made indexable also work with full stop index
This commit is contained in:
parent
066af47b5b
commit
df8c7b99c9
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -22,6 +22,7 @@ namespace Upsilon.Binder
|
||||||
BoundPromise,
|
BoundPromise,
|
||||||
BoundReturnStatement,
|
BoundReturnStatement,
|
||||||
BoundFunctionAssignmentStatement,
|
BoundFunctionAssignmentStatement,
|
||||||
BoundTableAssigmentStatement
|
BoundTableAssigmentStatement,
|
||||||
|
BoundFullstopIndexExpression
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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 '"':
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue