Lots of work for handling incomplete code and inspections better
This commit is contained in:
parent
0b6359f499
commit
cae3d7fb53
|
@ -8,7 +8,7 @@ using Type = Upsilon.BaseTypes.Type;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
internal class Binder
|
internal class Binder : IDisposable
|
||||||
{
|
{
|
||||||
private Diagnostics _diagnostics;
|
private Diagnostics _diagnostics;
|
||||||
public BoundScope Scope { get; private set; }
|
public BoundScope Scope { get; private set; }
|
||||||
|
@ -29,6 +29,12 @@ namespace Upsilon.Binder
|
||||||
return new Binder {_diagnostics = diagnostics, Scope = scope};
|
return new Binder {_diagnostics = diagnostics, Scope = scope};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Scope?.Dispose();
|
||||||
|
Scope = null;
|
||||||
|
_unboundFunctions.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
public BoundScript BindScript(BlockStatementSyntax e)
|
public BoundScript BindScript(BlockStatementSyntax e)
|
||||||
{
|
{
|
||||||
|
@ -45,7 +51,7 @@ namespace Upsilon.Binder
|
||||||
Scope = Scope.ParentScope;
|
Scope = Scope.ParentScope;
|
||||||
}
|
}
|
||||||
_unboundFunctions = new Dictionary<string, UnboundFunctionExpression>();
|
_unboundFunctions = new Dictionary<string, UnboundFunctionExpression>();
|
||||||
return new BoundScript((BoundBlockStatement) bound);
|
return new BoundScript((BoundBlockStatement) bound, e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundStatement BindStatement(StatementSyntax s)
|
private BoundStatement BindStatement(StatementSyntax s)
|
||||||
|
@ -74,7 +80,7 @@ namespace Upsilon.Binder
|
||||||
return BindGenericForStatement((GenericForStatementSyntax) s);
|
return BindGenericForStatement((GenericForStatementSyntax) s);
|
||||||
|
|
||||||
case SyntaxKind.BreakStatement:
|
case SyntaxKind.BreakStatement:
|
||||||
return new BoundBreakStatement();
|
return new BoundBreakStatement(s.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NotImplementedException(s.Kind.ToString());
|
throw new NotImplementedException(s.Kind.ToString());
|
||||||
|
@ -124,7 +130,7 @@ namespace Upsilon.Binder
|
||||||
return inExp;
|
return inExp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundUnaryExpression(op, inExp, op.OutType);
|
return new BoundUnaryExpression(op, inExp, op.OutType, e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExpression BindBinaryExpression(BinaryExpressionSyntax e)
|
private BoundExpression BindBinaryExpression(BinaryExpressionSyntax e)
|
||||||
|
@ -137,7 +143,7 @@ namespace Upsilon.Binder
|
||||||
_diagnostics.LogUnknownBinaryOperator(e.Span, e.Operator.Kind, left.Type, right.Type);
|
_diagnostics.LogUnknownBinaryOperator(e.Span, e.Operator.Kind, left.Type, right.Type);
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
return new BoundBinaryExpression(op, left, right, op.OutType);
|
return new BoundBinaryExpression(op, left, right, op.OutType, e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExpression BindLiteralExpression(LiteralExpressionSyntax e)
|
private BoundExpression BindLiteralExpression(LiteralExpressionSyntax e)
|
||||||
|
@ -166,7 +172,7 @@ namespace Upsilon.Binder
|
||||||
_diagnostics.LogUnknownType(e.Span);
|
_diagnostics.LogUnknownType(e.Span);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return new BoundLiteralExpression(outValue);
|
return new BoundLiteralExpression(outValue, e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExpression BindParenthesizedExpression(ParenthesizedExpressionSyntax e)
|
private BoundExpression BindParenthesizedExpression(ParenthesizedExpressionSyntax e)
|
||||||
|
@ -193,7 +199,7 @@ namespace Upsilon.Binder
|
||||||
if (expression.Kind == BoundKind.VariableExpression)
|
if (expression.Kind == BoundKind.VariableExpression)
|
||||||
{
|
{
|
||||||
var variableExpression =(BoundVariableExpression) expression;
|
var variableExpression =(BoundVariableExpression) expression;
|
||||||
var function = (FunctionVariableSymbol)variableExpression.Variable;
|
var function = (FunctionVariableSymbol)variableExpression.Variable.VariableSymbol;
|
||||||
if (!function.IsBound)
|
if (!function.IsBound)
|
||||||
{
|
{
|
||||||
Scope = new BoundScope(Scope);
|
Scope = new BoundScope(Scope);
|
||||||
|
@ -215,7 +221,7 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: validate parameters
|
//TODO: validate parameters
|
||||||
return new BoundFunctionCallExpression(expression, parameters.ToImmutable());
|
return new BoundFunctionCallExpression(expression, parameters.ToImmutable(), e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExpression BindVariableExpression(VariableExpressionSyntax e)
|
private BoundExpression BindVariableExpression(VariableExpressionSyntax e)
|
||||||
|
@ -224,16 +230,16 @@ namespace Upsilon.Binder
|
||||||
if (!Scope.TryGetVariable(name, true, out var variable))
|
if (!Scope.TryGetVariable(name, true, out var variable))
|
||||||
{
|
{
|
||||||
_diagnostics.LogUnknownVariable(e.Identifier.Span, name);
|
_diagnostics.LogUnknownVariable(e.Identifier.Span, name);
|
||||||
return new BoundLiteralExpression(new ScriptNull());
|
return new BoundLiteralExpression(new ScriptNull(), e.Span);
|
||||||
}
|
}
|
||||||
|
var boundVariable = new BoundVariableSymbol(variable, e.Identifier.Span);
|
||||||
return new BoundVariableExpression(variable);
|
return new BoundVariableExpression(boundVariable, e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundStatement BindExpressionStatement(ExpressionStatementSyntax s)
|
private BoundStatement BindExpressionStatement(ExpressionStatementSyntax s)
|
||||||
{
|
{
|
||||||
var exp = BindExpression(s.Expression);
|
var exp = BindExpression(s.Expression);
|
||||||
return new BoundExpressionStatement(exp);
|
return new BoundExpressionStatement(exp, s.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private VariableSymbol TryBindVariable(string name, bool isLocal, BoundExpression assignment)
|
private VariableSymbol TryBindVariable(string name, bool isLocal, BoundExpression assignment)
|
||||||
|
@ -272,7 +278,7 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
else if (assignment.Type == Type.Unknown && assignment is BoundVariableExpression v)
|
else if (assignment.Type == Type.Unknown && assignment is BoundVariableExpression v)
|
||||||
{
|
{
|
||||||
v.Variable.Type = variable.Type;
|
v.Variable.VariableSymbol.Type = variable.Type;
|
||||||
}
|
}
|
||||||
else if (assignment.Type == Type.Unknown)
|
else if (assignment.Type == Type.Unknown)
|
||||||
{
|
{
|
||||||
|
@ -299,12 +305,13 @@ namespace Upsilon.Binder
|
||||||
var boundVariable = TryBindVariable(name, isLocal, boundExpression);
|
var boundVariable = TryBindVariable(name, isLocal, boundExpression);
|
||||||
if (boundVariable != null)
|
if (boundVariable != null)
|
||||||
{
|
{
|
||||||
return new BoundVariableAssignment(boundVariable, boundExpression, isLocal);
|
var variable = new BoundVariableSymbol(boundVariable, variableExpression.Span);
|
||||||
|
return new BoundVariableAssignment(variable, boundExpression, isLocal, e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundExpressionStatement(new BoundLiteralExpression(new ScriptNull()));
|
return new BoundExpressionStatement(new BoundLiteralExpression(new ScriptNull(), e.Span), e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundStatement BindMultiAssignmentStatement(MultiAssignmentStatementSyntax s)
|
private BoundStatement BindMultiAssignmentStatement(MultiAssignmentStatementSyntax s)
|
||||||
|
@ -318,7 +325,7 @@ namespace Upsilon.Binder
|
||||||
var boundVariable = TryBindVariable(identifierToken.Name, isLocal, assignment);
|
var boundVariable = TryBindVariable(identifierToken.Name, isLocal, assignment);
|
||||||
ls.Add(boundVariable);
|
ls.Add(boundVariable);
|
||||||
}
|
}
|
||||||
return new BoundMultiAssignmentStatement(ls.ToImmutableArray(), assignment);
|
return new BoundMultiAssignmentStatement(ls.ToImmutableArray(), assignment, s.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundStatement BindBlockStatement(BlockStatementSyntax e)
|
private BoundStatement BindBlockStatement(BlockStatementSyntax e)
|
||||||
|
@ -330,7 +337,7 @@ namespace Upsilon.Binder
|
||||||
arr.Add(bound);
|
arr.Add(bound);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundBlockStatement(arr.ToImmutable());
|
return new BoundBlockStatement(arr.ToImmutable(), e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundStatement BindIfStatement(IfStatementSyntax e)
|
private BoundStatement BindIfStatement(IfStatementSyntax e)
|
||||||
|
@ -343,21 +350,21 @@ namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
var nextElseIf = BindIfStatement(e.NextElseIfStatement);
|
var nextElseIf = BindIfStatement(e.NextElseIfStatement);
|
||||||
return new BoundIfStatement((BoundExpressionStatement) condition, (BoundBlockStatement) block,
|
return new BoundIfStatement((BoundExpressionStatement) condition, (BoundBlockStatement) block,
|
||||||
(BoundIfStatement) nextElseIf);
|
(BoundIfStatement) nextElseIf, e.Span);
|
||||||
}
|
}
|
||||||
if (e.ElseStatement == null)
|
if (e.ElseStatement == null)
|
||||||
{
|
{
|
||||||
return new BoundIfStatement((BoundExpressionStatement) condition, (BoundBlockStatement) block);
|
return new BoundIfStatement((BoundExpressionStatement) condition, (BoundBlockStatement) block, e.Span);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Scope = new BoundScope(Scope);
|
Scope = new BoundScope(Scope);
|
||||||
var elseBlock = BindBlockStatement(e.ElseStatement.Block);
|
var elseBlock = BindBlockStatement(e.ElseStatement.Block);
|
||||||
var elseStatement = new BoundElseStatement((BoundBlockStatement) elseBlock);
|
var elseStatement = new BoundElseStatement((BoundBlockStatement) elseBlock, e.Span);
|
||||||
Scope = Scope.ParentScope;
|
Scope = Scope.ParentScope;
|
||||||
|
|
||||||
return new BoundIfStatement((BoundExpressionStatement) condition, (BoundBlockStatement) block,
|
return new BoundIfStatement((BoundExpressionStatement) condition, (BoundBlockStatement) block,
|
||||||
elseStatement);
|
elseStatement, e.Span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,12 +384,12 @@ namespace Upsilon.Binder
|
||||||
Scope = innerScope;
|
Scope = innerScope;
|
||||||
var block = BindBlockStatement(e.Block);
|
var block = BindBlockStatement(e.Block);
|
||||||
Scope = Scope.ParentScope;
|
Scope = Scope.ParentScope;
|
||||||
var func = new BoundFunctionExpression(parameters.ToImmutable(), (BoundBlockStatement) block);
|
var func = new BoundFunctionExpression(parameters.ToImmutable(), (BoundBlockStatement) block, e.Span);
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var unbound = new UnboundFunctionExpression(parameters.ToImmutable(), e.Block);
|
var unbound = new UnboundFunctionExpression(parameters.ToImmutable(), e.Block, e.Span);
|
||||||
if (variableSymbol == null)
|
if (variableSymbol == null)
|
||||||
{
|
{
|
||||||
_unboundFunctions.Add( Guid.NewGuid().ToString(), unbound);
|
_unboundFunctions.Add( Guid.NewGuid().ToString(), unbound);
|
||||||
|
@ -433,18 +440,18 @@ namespace Upsilon.Binder
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_diagnostics.LogCannotConvert(Type.Function, variable.Type, e.Span);
|
_diagnostics.LogCannotConvert(Type.Function, variable.Type, e.Span);
|
||||||
return new BoundExpressionStatement(new BoundLiteralExpression(new ScriptNull()));
|
return new BoundExpressionStatement(new BoundLiteralExpression(new ScriptNull(), e.Span), e.Span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundFunctionAssignmentStatement(variable, func);
|
return new BoundFunctionAssignmentStatement(variable, func, e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundStatement BindReturnStatement(ReturnStatementSyntax e)
|
private BoundStatement BindReturnStatement(ReturnStatementSyntax e)
|
||||||
{
|
{
|
||||||
var expression = BindExpression(e.Expression);
|
var expression = BindExpression(e.Expression);
|
||||||
return new BoundReturnStatement(expression);
|
return new BoundReturnStatement(expression, e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExpression BindTableExpression(TableExpressionSyntax e)
|
private BoundExpression BindTableExpression(TableExpressionSyntax e)
|
||||||
|
@ -466,7 +473,7 @@ namespace Upsilon.Binder
|
||||||
dictionary.Add(variable.Key, true);
|
dictionary.Add(variable.Key, true);
|
||||||
}
|
}
|
||||||
Scope = s;
|
Scope = s;
|
||||||
return new BoundTableExpression(keyType, valueType, dictionary, statements);
|
return new BoundTableExpression(keyType, valueType, dictionary, statements.ToImmutable(), e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExpression BindIndexExpression(IndexExpressionSyntax e)
|
private BoundExpression BindIndexExpression(IndexExpressionSyntax e)
|
||||||
|
@ -477,19 +484,19 @@ namespace Upsilon.Binder
|
||||||
if (index.Type != Type.Number && index.Type != Type.String && index.Type != Type.Unknown)
|
if (index.Type != Type.Number && index.Type != Type.String && index.Type != Type.Unknown)
|
||||||
{
|
{
|
||||||
_diagnostics.LogInvalidIndexExpression(expression.Type, index.Type, e.Span);
|
_diagnostics.LogInvalidIndexExpression(expression.Type, index.Type, e.Span);
|
||||||
return new BoundLiteralExpression(new ScriptNull());
|
return new BoundLiteralExpression(new ScriptNull(), e.Span);
|
||||||
}
|
}
|
||||||
switch (expression.Type)
|
switch (expression.Type)
|
||||||
{
|
{
|
||||||
case Type.Table:
|
case Type.Table:
|
||||||
case Type.UserData:
|
case Type.UserData:
|
||||||
case Type.Unknown:
|
case Type.Unknown:
|
||||||
return new BoundIndexExpression(expression, index, Type.Unknown);
|
return new BoundIndexExpression(expression, index, Type.Unknown, e.Span);
|
||||||
case Type.String when index.Type == Type.Number:
|
case Type.String when index.Type == Type.Number:
|
||||||
return new BoundIndexExpression(expression, index, Type.String);
|
return new BoundIndexExpression(expression, index, Type.String, e.Span);
|
||||||
default:
|
default:
|
||||||
_diagnostics.LogInvalidIndexExpression(expression.Type, index.Type, e.Span);
|
_diagnostics.LogInvalidIndexExpression(expression.Type, index.Type, e.Span);
|
||||||
return new BoundLiteralExpression(new ScriptNull());
|
return new BoundLiteralExpression(new ScriptNull(), e.Span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,12 +509,12 @@ namespace Upsilon.Binder
|
||||||
case Type.Table:
|
case Type.Table:
|
||||||
case Type.UserData:
|
case Type.UserData:
|
||||||
case Type.Unknown:
|
case Type.Unknown:
|
||||||
return new BoundFullStopIndexExpression(expression, index);
|
return new BoundFullStopIndexExpression(expression, index, e.Span);
|
||||||
case Type.String:
|
case Type.String:
|
||||||
return new BoundFullStopIndexExpression(expression, index);
|
return new BoundFullStopIndexExpression(expression, index, e.Span);
|
||||||
default:
|
default:
|
||||||
_diagnostics.LogInvalidIndexExpression(expression.Type, Type.String, e.Span);
|
_diagnostics.LogInvalidIndexExpression(expression.Type, Type.String, e.Span);
|
||||||
return new BoundLiteralExpression(new ScriptNull());
|
return new BoundLiteralExpression(new ScriptNull(), e.Span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,7 +527,7 @@ namespace Upsilon.Binder
|
||||||
indexableExpression = (BoundFullStopIndexExpression)BindExpression(e.TableExpression);
|
indexableExpression = (BoundFullStopIndexExpression)BindExpression(e.TableExpression);
|
||||||
|
|
||||||
var value = BindExpression(e.Expression);
|
var value = BindExpression(e.Expression);
|
||||||
return new BoundTableAssigmentStatement(indexableExpression, value);
|
return new BoundTableAssigmentStatement(indexableExpression, value, e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundStatement BindNumericForStatement(NumericForStatementSyntax e)
|
private BoundStatement BindNumericForStatement(NumericForStatementSyntax e)
|
||||||
|
@ -536,7 +543,8 @@ namespace Upsilon.Binder
|
||||||
boundStep = BindExpression(e.StepExpression);
|
boundStep = BindExpression(e.StepExpression);
|
||||||
var block = BindBlockStatement((BlockStatementSyntax) e.Block);
|
var block = BindBlockStatement((BlockStatementSyntax) e.Block);
|
||||||
Scope = Scope.ParentScope;
|
Scope = Scope.ParentScope;
|
||||||
return new BoundNumericForStatement(variable, boundStart, boundStop, boundStep, (BoundBlockStatement) block);
|
return new BoundNumericForStatement(variable, boundStart, boundStop, boundStep, (BoundBlockStatement) block,
|
||||||
|
e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundStatement BindGenericForStatement(GenericForStatementSyntax e)
|
private BoundStatement BindGenericForStatement(GenericForStatementSyntax e)
|
||||||
|
@ -552,7 +560,7 @@ namespace Upsilon.Binder
|
||||||
var boundEnumerableExpression = BindExpression(e.EnumerableExpression);
|
var boundEnumerableExpression = BindExpression(e.EnumerableExpression);
|
||||||
var block = BindBlockStatement(e.Block);
|
var block = BindBlockStatement(e.Block);
|
||||||
|
|
||||||
return new BoundGenericForStatement(array.ToImmutable(), boundEnumerableExpression, block);
|
return new BoundGenericForStatement(array.ToImmutable(), boundEnumerableExpression, block, e.Span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,11 +1,12 @@
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
using Upsilon.Parser;
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundBinaryExpression : BoundExpression
|
public class BoundBinaryExpression : BoundExpression
|
||||||
{
|
{
|
||||||
public BoundBinaryExpression(BoundBinaryOperator op, BoundExpression leftExpression, BoundExpression rightExpression, Type type)
|
public BoundBinaryExpression(BoundBinaryOperator op, BoundExpression leftExpression,
|
||||||
|
BoundExpression rightExpression, Type type, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Operator = op;
|
Operator = op;
|
||||||
LeftExpression = leftExpression;
|
LeftExpression = leftExpression;
|
||||||
|
@ -14,6 +15,16 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundBinaryExpression;
|
public override BoundKind Kind => BoundKind.BoundBinaryExpression;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (characterPosition >= LeftExpression.Span.Start && characterPosition <= LeftExpression.Span.End)
|
||||||
|
return LeftExpression.GetNodeAtPosition(characterPosition);
|
||||||
|
if (characterPosition >= RightExpression.Span.Start && characterPosition <= RightExpression.Span.End)
|
||||||
|
return RightExpression.GetNodeAtPosition(characterPosition);
|
||||||
|
return this;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public override Type Type { get; }
|
public override Type Type { get; }
|
||||||
|
|
||||||
public BoundBinaryOperator Operator { get; }
|
public BoundBinaryOperator Operator { get; }
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public abstract class BoundExpression : BoundNode
|
public abstract class BoundExpression : BoundNode
|
||||||
{
|
{
|
||||||
|
protected BoundExpression(TextSpan span) : base(span)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public abstract Type Type { get; }
|
public abstract Type Type { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
|
@ -8,13 +9,27 @@ namespace Upsilon.Binder
|
||||||
public BoundExpression Identifier { get; }
|
public BoundExpression Identifier { get; }
|
||||||
public ImmutableArray<BoundExpression> Parameters { get; }
|
public ImmutableArray<BoundExpression> Parameters { get; }
|
||||||
|
|
||||||
public BoundFunctionCallExpression(BoundExpression identifier, ImmutableArray<BoundExpression> parameters)
|
public BoundFunctionCallExpression(BoundExpression identifier, ImmutableArray<BoundExpression> parameters,
|
||||||
|
TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Identifier = identifier;
|
Identifier = identifier;
|
||||||
Parameters = parameters;
|
Parameters = parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundFunctionCallExpression;
|
public override BoundKind Kind => BoundKind.BoundFunctionCallExpression;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (characterPosition >= Identifier.Span.Start && characterPosition <= Identifier.Span.End)
|
||||||
|
return Identifier.GetNodeAtPosition(characterPosition);
|
||||||
|
foreach (var parameter in Parameters)
|
||||||
|
{
|
||||||
|
if (characterPosition >= parameter.Span.Start && characterPosition <= parameter.Span.End)
|
||||||
|
return parameter.GetNodeAtPosition(characterPosition);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public override Type Type => Type.Unknown;
|
public override Type Type => Type.Unknown;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
|
@ -8,27 +9,20 @@ namespace Upsilon.Binder
|
||||||
public ImmutableArray<VariableSymbol> Parameters { get; }
|
public ImmutableArray<VariableSymbol> Parameters { get; }
|
||||||
public BoundBlockStatement Block { get; set; }
|
public BoundBlockStatement Block { get; set; }
|
||||||
|
|
||||||
public BoundFunctionExpression(ImmutableArray<VariableSymbol> parameters, BoundBlockStatement block)
|
public BoundFunctionExpression(ImmutableArray<VariableSymbol> parameters, BoundBlockStatement block, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Parameters = parameters;
|
Parameters = parameters;
|
||||||
Block = block;
|
Block = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundFunctionExpression;
|
public override BoundKind Kind => BoundKind.BoundFunctionExpression;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
|
||||||
|
return Block.GetNodeAtPosition(characterPosition);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public override Type Type => Type.Function;
|
public override Type Type => Type.Function;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundFunctionAssignmentStatement : BoundStatement
|
|
||||||
{
|
|
||||||
public VariableSymbol Variable { get; }
|
|
||||||
public BoundFunctionExpression Func { get; }
|
|
||||||
|
|
||||||
public BoundFunctionAssignmentStatement(VariableSymbol variable, BoundFunctionExpression func)
|
|
||||||
{
|
|
||||||
Variable = variable;
|
|
||||||
Func = func;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundFunctionAssignmentStatement;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,11 +1,12 @@
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
using Upsilon.Parser;
|
using Upsilon.Parser;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundIndexExpression : BoundExpression
|
public class BoundIndexExpression : BoundExpression
|
||||||
{
|
{
|
||||||
public BoundIndexExpression(BoundExpression identifier, BoundExpression index, Type type)
|
public BoundIndexExpression(BoundExpression identifier, BoundExpression index, Type type, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Identifier = identifier;
|
Identifier = identifier;
|
||||||
Index = index;
|
Index = index;
|
||||||
|
@ -16,6 +17,16 @@ namespace Upsilon.Binder
|
||||||
public BoundExpression Index { get; }
|
public BoundExpression Index { get; }
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundIndexExpression;
|
public override BoundKind Kind => BoundKind.BoundIndexExpression;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (characterPosition >= Identifier.Span.Start && characterPosition <= Identifier.Span.End)
|
||||||
|
return Identifier.GetNodeAtPosition(characterPosition);
|
||||||
|
if (characterPosition >= Index.Span.Start && characterPosition <= Index.Span.End)
|
||||||
|
return Index.GetNodeAtPosition(characterPosition);
|
||||||
|
return this;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public override Type Type { get; }
|
public override Type Type { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,13 +35,20 @@ namespace Upsilon.Binder
|
||||||
public BoundExpression Expression { get; }
|
public BoundExpression Expression { get; }
|
||||||
public string Index { get; }
|
public string Index { get; }
|
||||||
|
|
||||||
public BoundFullStopIndexExpression(BoundExpression expression, string index)
|
public BoundFullStopIndexExpression(BoundExpression expression, string index, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
Index = index;
|
Index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundFullstopIndexExpression;
|
public override BoundKind Kind => BoundKind.BoundFullstopIndexExpression;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (characterPosition >= Expression.Span.Start && characterPosition <= Expression.Span.End)
|
||||||
|
return Expression.GetNodeAtPosition(characterPosition);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public override Type Type => Type.Unknown;
|
public override Type Type => Type.Unknown;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,15 +1,21 @@
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
internal class BoundLiteralExpression : BoundExpression
|
internal class BoundLiteralExpression : BoundExpression
|
||||||
{
|
{
|
||||||
public BoundLiteralExpression(ScriptType value)
|
public BoundLiteralExpression(ScriptType value, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Value = value;
|
Value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundLiteralExpression;
|
public override BoundKind Kind => BoundKind.BoundLiteralExpression;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public override Type Type => Value.Type;
|
public override Type Type => Value.Type;
|
||||||
public ScriptType Value { get; }
|
public ScriptType Value { get; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundTableExpression : BoundExpression
|
public class BoundTableExpression : BoundExpression
|
||||||
{
|
{
|
||||||
public BoundTableExpression(Type keyType, Type valueType, Dictionary<string, bool> expressions,
|
public BoundTableExpression(Type keyType, Type valueType, Dictionary<string, bool> expressions,
|
||||||
ImmutableArray<BoundStatement>.Builder statements)
|
ImmutableArray<BoundStatement> statements, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
KeyType = keyType;
|
KeyType = keyType;
|
||||||
ValueType = valueType;
|
ValueType = valueType;
|
||||||
|
@ -16,12 +17,23 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundTableExpression;
|
public override BoundKind Kind => BoundKind.BoundTableExpression;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
foreach (var statement in Statements)
|
||||||
|
{
|
||||||
|
if (characterPosition >= statement.Span.Start && characterPosition <= statement.Span.End)
|
||||||
|
return statement.GetNodeAtPosition(characterPosition);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public override Type Type => Type.Table;
|
public override Type Type => Type.Table;
|
||||||
|
|
||||||
public Type KeyType { get; }
|
public Type KeyType { get; }
|
||||||
public Type ValueType { get; }
|
public Type ValueType { get; }
|
||||||
|
|
||||||
public Dictionary<string, bool> Expressions { get; }
|
public Dictionary<string, bool> Expressions { get; }
|
||||||
public ImmutableArray<BoundStatement>.Builder Statements { get; }
|
public ImmutableArray<BoundStatement> Statements { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,13 +1,21 @@
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundUnaryExpression : BoundExpression
|
public class BoundUnaryExpression : BoundExpression
|
||||||
{
|
{
|
||||||
public override BoundKind Kind => BoundKind.BoundUnaryExpression;
|
public override BoundKind Kind => BoundKind.BoundUnaryExpression;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (characterPosition >= InExpression.Span.Start && characterPosition <= InExpression.Span.End)
|
||||||
|
return InExpression.GetNodeAtPosition(characterPosition);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public override Type Type { get; }
|
public override Type Type { get; }
|
||||||
|
|
||||||
public BoundUnaryExpression(BoundUnaryOperator op, BoundExpression inExpression, Type type)
|
public BoundUnaryExpression(BoundUnaryOperator op, BoundExpression inExpression, Type type, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Operator = op;
|
Operator = op;
|
||||||
InExpression = inExpression;
|
InExpression = inExpression;
|
||||||
|
|
|
@ -1,17 +1,23 @@
|
||||||
using System;
|
using System;
|
||||||
|
using Upsilon.Text;
|
||||||
using Type = Upsilon.BaseTypes.Type;
|
using Type = Upsilon.BaseTypes.Type;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundVariableExpression : BoundExpression
|
public class BoundVariableExpression : BoundExpression
|
||||||
{
|
{
|
||||||
public BoundVariableExpression(VariableSymbol variable)
|
public BoundVariableExpression(BoundVariableSymbol variable, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Variable = variable;
|
Variable = variable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public VariableSymbol Variable { get; }
|
public BoundVariableSymbol Variable { get; }
|
||||||
public override BoundKind Kind => BoundKind.VariableExpression;
|
public override BoundKind Kind => BoundKind.VariableExpression;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
return Variable;
|
||||||
|
}
|
||||||
|
|
||||||
public override Type Type => Variable.Type;
|
public override Type Type => Variable.Type;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,13 @@
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using Upsilon.Parser;
|
using Upsilon.Parser;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class UnboundFunctionExpression : BoundFunctionExpression
|
public class UnboundFunctionExpression : BoundFunctionExpression
|
||||||
{
|
{
|
||||||
public UnboundFunctionExpression(ImmutableArray<VariableSymbol> parameters,
|
public UnboundFunctionExpression(ImmutableArray<VariableSymbol> parameters,
|
||||||
BlockStatementSyntax unboundBlock) : base(parameters, null)
|
BlockStatementSyntax unboundBlock, TextSpan span) : base(parameters, null, span)
|
||||||
{
|
{
|
||||||
UnboundBlock = unboundBlock;
|
UnboundBlock = unboundBlock;
|
||||||
}
|
}
|
|
@ -2,6 +2,7 @@ namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public enum BoundKind
|
public enum BoundKind
|
||||||
{
|
{
|
||||||
|
BoundVariableSymbol,
|
||||||
BoundScript,
|
BoundScript,
|
||||||
|
|
||||||
BoundLiteralExpression,
|
BoundLiteralExpression,
|
||||||
|
@ -28,5 +29,6 @@ namespace Upsilon.Binder
|
||||||
BoundNumericForStatement,
|
BoundNumericForStatement,
|
||||||
BoundGenericForStatement,
|
BoundGenericForStatement,
|
||||||
BoundBreakStatement,
|
BoundBreakStatement,
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,7 +4,14 @@ namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public abstract class BoundNode
|
public abstract class BoundNode
|
||||||
{
|
{
|
||||||
|
protected BoundNode(TextSpan span)
|
||||||
|
{
|
||||||
|
Span = span;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract BoundKind Kind { get; }
|
public abstract BoundKind Kind { get; }
|
||||||
public TextSpan Span { get; protected set; }
|
public TextSpan Span { get; }
|
||||||
|
|
||||||
|
public abstract BoundNode GetNodeAtPosition(int characterPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,14 +1,14 @@
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundScope
|
public class BoundScope : IDisposable
|
||||||
{
|
{
|
||||||
public readonly BoundScope ParentScope;
|
public readonly BoundScope ParentScope;
|
||||||
private BoundScope _readOnlyScope;
|
private BoundScope _readOnlyScope;
|
||||||
public readonly Dictionary<string, VariableSymbol> Variables;
|
public readonly Dictionary<string, VariableSymbol> Variables;
|
||||||
|
|
||||||
|
|
||||||
public BoundScope(BoundScope parentScope)
|
public BoundScope(BoundScope parentScope)
|
||||||
{
|
{
|
||||||
ParentScope = parentScope;
|
ParentScope = parentScope;
|
||||||
|
@ -26,6 +26,11 @@ namespace Upsilon.Binder
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Variables.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
public void DefineLocalVariable(VariableSymbol var)
|
public void DefineLocalVariable(VariableSymbol var)
|
||||||
{
|
{
|
||||||
Variables.Add(var.Name, var);
|
Variables.Add(var.Name, var);
|
||||||
|
|
|
@ -1,15 +1,26 @@
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
|
using System.Linq;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundBlockStatement : BoundStatement
|
public class BoundBlockStatement : BoundStatement
|
||||||
{
|
{
|
||||||
public BoundBlockStatement(ImmutableArray<BoundStatement> statements)
|
public BoundBlockStatement(ImmutableArray<BoundStatement> statements, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Statements = statements;
|
Statements = statements;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundBlockStatement;
|
public override BoundKind Kind => BoundKind.BoundBlockStatement;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
foreach (var statement in Statements)
|
||||||
|
{
|
||||||
|
if (characterPosition >= statement.Span.Start && characterPosition <= statement.Span.End)
|
||||||
|
return statement.GetNodeAtPosition(characterPosition);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public ImmutableArray<BoundStatement> Statements { get; }
|
public ImmutableArray<BoundStatement> Statements { get; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,19 @@
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundBreakStatement : BoundStatement
|
public class BoundBreakStatement : BoundStatement
|
||||||
{
|
{
|
||||||
|
public BoundBreakStatement(TextSpan span) : base(span)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundBreakStatement;
|
public override BoundKind Kind => BoundKind.BoundBreakStatement;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (characterPosition >= Span.Start && characterPosition <= Span.End)
|
||||||
|
return this;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,11 +1,19 @@
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundExpressionStatement : BoundStatement
|
public class BoundExpressionStatement : BoundStatement
|
||||||
{
|
{
|
||||||
public BoundExpression Expression { get; }
|
public BoundExpression Expression { get; }
|
||||||
public override BoundKind Kind => BoundKind.BoundExpressionStatement;
|
public override BoundKind Kind => BoundKind.BoundExpressionStatement;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (characterPosition >= Span.Start && characterPosition <= Span.End)
|
||||||
|
return Expression.GetNodeAtPosition(characterPosition);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public BoundExpressionStatement(BoundExpression expression)
|
public BoundExpressionStatement(BoundExpression expression, TextSpan span):base(span)
|
||||||
{
|
{
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
|
namespace Upsilon.Binder
|
||||||
|
{
|
||||||
|
public class BoundFunctionAssignmentStatement : BoundStatement
|
||||||
|
{
|
||||||
|
public VariableSymbol Variable { get; }
|
||||||
|
public BoundFunctionExpression Func { get; }
|
||||||
|
|
||||||
|
public BoundFunctionAssignmentStatement(VariableSymbol variable, BoundFunctionExpression func, TextSpan span): base(span)
|
||||||
|
{
|
||||||
|
Variable = variable;
|
||||||
|
Func = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BoundKind Kind => BoundKind.BoundFunctionAssignmentStatement;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (characterPosition >= Func.Span.Start && characterPosition <= Func.Span.End)
|
||||||
|
return Func.GetNodeAtPosition(characterPosition);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
|
@ -9,7 +10,7 @@ namespace Upsilon.Binder
|
||||||
public BoundStatement Block { get; }
|
public BoundStatement Block { get; }
|
||||||
|
|
||||||
public BoundGenericForStatement(ImmutableArray<VariableSymbol> variables,
|
public BoundGenericForStatement(ImmutableArray<VariableSymbol> variables,
|
||||||
BoundExpression boundEnumerableExpression, BoundStatement block)
|
BoundExpression boundEnumerableExpression, BoundStatement block, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Variables = variables;
|
Variables = variables;
|
||||||
BoundEnumerableExpression = boundEnumerableExpression;
|
BoundEnumerableExpression = boundEnumerableExpression;
|
||||||
|
@ -17,5 +18,13 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundGenericForStatement;
|
public override BoundKind Kind => BoundKind.BoundGenericForStatement;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (characterPosition >= BoundEnumerableExpression.Span.Start && characterPosition <= BoundEnumerableExpression.Span.End)
|
||||||
|
return BoundEnumerableExpression.GetNodeAtPosition(characterPosition);
|
||||||
|
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
|
||||||
|
return Block.GetNodeAtPosition(characterPosition);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,20 +1,22 @@
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundIfStatement : BoundStatement
|
public class BoundIfStatement : BoundStatement
|
||||||
{
|
{
|
||||||
public BoundIfStatement(BoundExpressionStatement condition, BoundBlockStatement block)
|
public BoundIfStatement(BoundExpressionStatement condition, BoundBlockStatement block, TextSpan span): base(span)
|
||||||
{
|
{
|
||||||
Condition = condition;
|
Condition = condition;
|
||||||
Block = block;
|
Block = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundIfStatement(BoundExpressionStatement condition, BoundBlockStatement block, BoundElseStatement elseStatement)
|
public BoundIfStatement(BoundExpressionStatement condition, BoundBlockStatement block, BoundElseStatement elseStatement, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Condition = condition;
|
Condition = condition;
|
||||||
Block = block;
|
Block = block;
|
||||||
ElseStatement = elseStatement;
|
ElseStatement = elseStatement;
|
||||||
}
|
}
|
||||||
public BoundIfStatement(BoundExpressionStatement condition, BoundBlockStatement block, BoundIfStatement nextElseIf)
|
public BoundIfStatement(BoundExpressionStatement condition, BoundBlockStatement block, BoundIfStatement nextElseIf, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Condition = condition;
|
Condition = condition;
|
||||||
Block = block;
|
Block = block;
|
||||||
|
@ -22,6 +24,18 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundIfStatement;
|
public override BoundKind Kind => BoundKind.BoundIfStatement;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (characterPosition >= Condition.Span.Start && characterPosition <= Condition.Span.End)
|
||||||
|
return Condition.GetNodeAtPosition(characterPosition);
|
||||||
|
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
|
||||||
|
return Block.GetNodeAtPosition(characterPosition);
|
||||||
|
if (NextElseIf != null && characterPosition >= NextElseIf.Span.Start && characterPosition <= NextElseIf.Span.End)
|
||||||
|
return NextElseIf.GetNodeAtPosition(characterPosition);
|
||||||
|
if (ElseStatement != null && characterPosition >= ElseStatement.Span.Start && characterPosition <= ElseStatement.Span.End)
|
||||||
|
return ElseStatement.GetNodeAtPosition(characterPosition);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public BoundExpressionStatement Condition { get; }
|
public BoundExpressionStatement Condition { get; }
|
||||||
public BoundBlockStatement Block { get; }
|
public BoundBlockStatement Block { get; }
|
||||||
|
@ -33,11 +47,17 @@ namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public BoundBlockStatement Block { get; }
|
public BoundBlockStatement Block { get; }
|
||||||
|
|
||||||
public BoundElseStatement(BoundBlockStatement block)
|
public BoundElseStatement(BoundBlockStatement block, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Block = block;
|
Block = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundElseStatement;
|
public override BoundKind Kind => BoundKind.BoundElseStatement;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (Block != null && characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
|
||||||
|
return Block.GetNodeAtPosition(characterPosition);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
|
@ -8,12 +9,20 @@ namespace Upsilon.Binder
|
||||||
public ImmutableArray<VariableSymbol> Variables { get; }
|
public ImmutableArray<VariableSymbol> Variables { get; }
|
||||||
public BoundExpression Assignment { get; }
|
public BoundExpression Assignment { get; }
|
||||||
|
|
||||||
public BoundMultiAssignmentStatement(ImmutableArray<VariableSymbol> variables, BoundExpression assignment)
|
public BoundMultiAssignmentStatement(ImmutableArray<VariableSymbol> variables, BoundExpression assignment,
|
||||||
|
TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Variables = variables;
|
Variables = variables;
|
||||||
Assignment = assignment;
|
Assignment = assignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundMultiAssignmentStatement;
|
public override BoundKind Kind => BoundKind.BoundMultiAssignmentStatement;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (characterPosition >= Assignment.Span.Start && characterPosition <= Assignment.Span.End)
|
||||||
|
return Assignment.GetNodeAtPosition(characterPosition);
|
||||||
|
return this;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundNumericForStatement : BoundStatement
|
public class BoundNumericForStatement : BoundStatement
|
||||||
|
@ -9,7 +11,7 @@ namespace Upsilon.Binder
|
||||||
public BoundBlockStatement Block { get; }
|
public BoundBlockStatement Block { get; }
|
||||||
|
|
||||||
public BoundNumericForStatement(VariableSymbol variable, BoundExpression boundStart,
|
public BoundNumericForStatement(VariableSymbol variable, BoundExpression boundStart,
|
||||||
BoundExpression boundStop, BoundExpression boundStep, BoundBlockStatement block)
|
BoundExpression boundStop, BoundExpression boundStep, BoundBlockStatement block, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Variable = variable;
|
Variable = variable;
|
||||||
BoundStart = boundStart;
|
BoundStart = boundStart;
|
||||||
|
@ -19,5 +21,18 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundNumericForStatement;
|
public override BoundKind Kind => BoundKind.BoundNumericForStatement;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (characterPosition >= BoundStart.Span.Start && characterPosition <= BoundStart.Span.End)
|
||||||
|
return BoundStart.GetNodeAtPosition(characterPosition);
|
||||||
|
if (characterPosition >= BoundStop.Span.Start && characterPosition <= BoundStop.Span.End)
|
||||||
|
return BoundStop.GetNodeAtPosition(characterPosition);
|
||||||
|
if (characterPosition >= BoundStep.Span.Start && characterPosition <= BoundStep.Span.End)
|
||||||
|
return BoundStep.GetNodeAtPosition(characterPosition);
|
||||||
|
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
|
||||||
|
return Block.GetNodeAtPosition(characterPosition);
|
||||||
|
return this;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,13 +1,21 @@
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundReturnStatement : BoundStatement
|
public class BoundReturnStatement : BoundStatement
|
||||||
{
|
{
|
||||||
public BoundReturnStatement(BoundExpression expression)
|
public BoundReturnStatement(BoundExpression expression, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundExpression Expression { get; }
|
public BoundExpression Expression { get; }
|
||||||
public override BoundKind Kind => BoundKind.BoundReturnStatement;
|
public override BoundKind Kind => BoundKind.BoundReturnStatement;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (characterPosition >= Expression.Span.Start && characterPosition <= Expression.Span.End)
|
||||||
|
return Expression.GetNodeAtPosition(characterPosition);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,15 +1,20 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundScript : BoundStatement
|
public class BoundScript : BoundStatement
|
||||||
{
|
{
|
||||||
public BoundScript(BoundBlockStatement statement)
|
public BoundScript(BoundBlockStatement statement, TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Statement = statement;
|
Statement = statement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundScript;
|
public override BoundKind Kind => BoundKind.BoundScript;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
return Statement.GetNodeAtPosition(characterPosition);
|
||||||
|
}
|
||||||
|
|
||||||
public BoundBlockStatement Statement { get; }
|
public BoundBlockStatement Statement { get; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public abstract class BoundStatement : BoundNode
|
public abstract class BoundStatement : BoundNode
|
||||||
{
|
{
|
||||||
|
protected BoundStatement(TextSpan span) : base(span)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundTableAssigmentStatement : BoundStatement
|
public class BoundTableAssigmentStatement : BoundStatement
|
||||||
|
@ -5,12 +7,22 @@ namespace Upsilon.Binder
|
||||||
public BoundExpression TableIndexExpression { get; }
|
public BoundExpression TableIndexExpression { get; }
|
||||||
public BoundExpression Value { get; }
|
public BoundExpression Value { get; }
|
||||||
|
|
||||||
public BoundTableAssigmentStatement(BoundExpression tableIndexExpression, BoundExpression value)
|
public BoundTableAssigmentStatement(BoundExpression tableIndexExpression, BoundExpression value,
|
||||||
|
TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
TableIndexExpression = tableIndexExpression;
|
TableIndexExpression = tableIndexExpression;
|
||||||
Value = value;
|
Value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundTableAssigmentStatement;
|
public override BoundKind Kind => BoundKind.BoundTableAssigmentStatement;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (characterPosition >= TableIndexExpression.Span.Start && characterPosition <= TableIndexExpression.Span.End)
|
||||||
|
return TableIndexExpression.GetNodeAtPosition(characterPosition);
|
||||||
|
if (characterPosition >= Value.Span.Start && characterPosition <= Value.Span.End)
|
||||||
|
return Value.GetNodeAtPosition(characterPosition);
|
||||||
|
return this;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,15 @@
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
public class BoundVariableAssignment : BoundStatement
|
public class BoundVariableAssignment : BoundStatement
|
||||||
{
|
{
|
||||||
public VariableSymbol Variable { get; }
|
public BoundVariableSymbol Variable { get; }
|
||||||
public BoundExpression BoundExpression { get; }
|
public BoundExpression BoundExpression { get; }
|
||||||
public bool IsLocalDefinition { get; }
|
public bool IsLocalDefinition { get; }
|
||||||
|
|
||||||
public BoundVariableAssignment(VariableSymbol variable, BoundExpression boundExpression, bool isLocalDefinition)
|
public BoundVariableAssignment(BoundVariableSymbol variable, BoundExpression boundExpression, bool isLocalDefinition,
|
||||||
|
TextSpan span) : base(span)
|
||||||
{
|
{
|
||||||
Variable = variable;
|
Variable = variable;
|
||||||
BoundExpression = boundExpression;
|
BoundExpression = boundExpression;
|
||||||
|
@ -14,5 +17,14 @@ namespace Upsilon.Binder
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundAssignmentStatement;
|
public override BoundKind Kind => BoundKind.BoundAssignmentStatement;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
if (characterPosition >= Variable.Span.Start && characterPosition <= Variable.Span.End)
|
||||||
|
return Variable;
|
||||||
|
if (characterPosition >= BoundExpression.Span.Start && characterPosition <= BoundExpression.Span.End)
|
||||||
|
return BoundExpression.GetNodeAtPosition(characterPosition);
|
||||||
|
return this;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
using Upsilon.BaseTypes;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
|
namespace Upsilon.Binder
|
||||||
|
{
|
||||||
|
public class BoundVariableSymbol : BoundExpression
|
||||||
|
{
|
||||||
|
public BoundVariableSymbol(VariableSymbol variableSymbol, TextSpan span) : base(span)
|
||||||
|
{
|
||||||
|
VariableSymbol = variableSymbol;
|
||||||
|
Type = variableSymbol.Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VariableSymbol VariableSymbol { get; }
|
||||||
|
public override BoundKind Kind => BoundKind.BoundVariableSymbol;
|
||||||
|
public override BoundNode GetNodeAtPosition(int characterPosition)
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Type Type { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -90,6 +90,17 @@ namespace Upsilon
|
||||||
Span = span;
|
Span = span;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public (int Position, int PositionOnLine) GetStartLine()
|
||||||
|
{
|
||||||
|
return Diagnostics.ScriptString.GetLinePosition(Span.Start);
|
||||||
|
}
|
||||||
|
|
||||||
|
public (int Position, int PositionOnLine) GetEndLine()
|
||||||
|
{
|
||||||
|
return Diagnostics.ScriptString.GetLinePosition(Span.End);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
var linePos = Diagnostics.ScriptString.GetLinePosition(Span.Start);
|
var linePos = Diagnostics.ScriptString.GetLinePosition(Span.Start);
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
using Upsilon.Binder;
|
using Upsilon.Binder;
|
||||||
|
|
||||||
namespace Upsilon.Evaluator
|
namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
public class EvaluationScope
|
public class EvaluationScope : IDisposable
|
||||||
{
|
{
|
||||||
private readonly EvaluationScope _parentScope;
|
private EvaluationScope _parentScope;
|
||||||
private EvaluationScope _getOnlyParentScope;
|
private EvaluationScope _getOnlyParentScope;
|
||||||
|
|
||||||
public readonly Dictionary<string, ScriptType> Variables;
|
public readonly Dictionary<string, ScriptType> Variables;
|
||||||
|
@ -29,6 +30,13 @@ namespace Upsilon.Evaluator
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_parentScope?.Dispose();
|
||||||
|
_parentScope = null;
|
||||||
|
Variables.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
public void AssignToNearest(VariableSymbol symbol, ScriptType value)
|
public void AssignToNearest(VariableSymbol symbol, ScriptType value)
|
||||||
{
|
{
|
||||||
if (Variables.ContainsKey(symbol.Name))
|
if (Variables.ContainsKey(symbol.Name))
|
||||||
|
|
|
@ -10,7 +10,7 @@ using Type = Upsilon.BaseTypes.Type;
|
||||||
|
|
||||||
namespace Upsilon.Evaluator
|
namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
internal class Evaluator
|
internal class Evaluator : IDisposable
|
||||||
{
|
{
|
||||||
private Diagnostics _diagnostics;
|
private Diagnostics _diagnostics;
|
||||||
private ScriptType _lastValue;
|
private ScriptType _lastValue;
|
||||||
|
@ -38,6 +38,13 @@ namespace Upsilon.Evaluator
|
||||||
return new Evaluator {_diagnostics = diagnostics, Scope = scope};
|
return new Evaluator {_diagnostics = diagnostics, Scope = scope};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Scope.Dispose();
|
||||||
|
_lastValue = null;
|
||||||
|
_returnValue = null;
|
||||||
|
}
|
||||||
|
|
||||||
public ScriptType Evaluate(BoundScript e)
|
public ScriptType Evaluate(BoundScript e)
|
||||||
{
|
{
|
||||||
EvaluateNode(e.Statement);
|
EvaluateNode(e.Statement);
|
||||||
|
@ -302,11 +309,11 @@ namespace Upsilon.Evaluator
|
||||||
var val = EvaluateExpression(e.BoundExpression);
|
var val = EvaluateExpression(e.BoundExpression);
|
||||||
if (e.IsLocalDefinition)
|
if (e.IsLocalDefinition)
|
||||||
{
|
{
|
||||||
Scope.CreateLocal(e.Variable, val);
|
Scope.CreateLocal(e.Variable.VariableSymbol, val);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Scope.AssignToNearest(e.Variable, val);
|
Scope.AssignToNearest(e.Variable.VariableSymbol, val);
|
||||||
}
|
}
|
||||||
_lastValue = val;
|
_lastValue = val;
|
||||||
}
|
}
|
||||||
|
@ -339,11 +346,11 @@ namespace Upsilon.Evaluator
|
||||||
|
|
||||||
private ScriptType EvaluateVariableExpression(BoundVariableExpression e)
|
private ScriptType EvaluateVariableExpression(BoundVariableExpression e)
|
||||||
{
|
{
|
||||||
if (Scope.TryGet(e.Variable, out var val))
|
if (Scope.TryGet(e.Variable.VariableSymbol, out var val))
|
||||||
{
|
{
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
throw new Exception($"Cannot find variable: '{e.Variable.Name}'");
|
throw new Exception($"Cannot find variable: '{e.Variable.VariableSymbol.Name}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EvaluateBoundBlockStatement(BoundBlockStatement boundBlockStatement)
|
private void EvaluateBoundBlockStatement(BoundBlockStatement boundBlockStatement)
|
||||||
|
|
|
@ -10,11 +10,11 @@ using Upsilon.Utilities;
|
||||||
|
|
||||||
namespace Upsilon.Evaluator
|
namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
public class Script
|
public class Script : IDisposable
|
||||||
{
|
{
|
||||||
private SourceText ScriptString { get; }
|
public SourceText ScriptString { get; }
|
||||||
private Evaluator Evaluator { get; }
|
private Evaluator Evaluator { get; }
|
||||||
private readonly BlockStatementSyntax _parsed;
|
private BlockStatementSyntax _parsed;
|
||||||
private BoundScript _bound;
|
private BoundScript _bound;
|
||||||
public Diagnostics Diagnostics { get; }
|
public Diagnostics Diagnostics { get; }
|
||||||
private Binder.Binder Binder { get; }
|
private Binder.Binder Binder { get; }
|
||||||
|
@ -128,5 +128,14 @@ namespace Upsilon.Evaluator
|
||||||
{
|
{
|
||||||
return _parsed.Print();
|
return _parsed.Print();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Binder?.Dispose();
|
||||||
|
Evaluator?.Dispose();
|
||||||
|
Scope?.Dispose();
|
||||||
|
_parsed = null;
|
||||||
|
_bound = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Parser
|
namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
|
@ -17,6 +18,7 @@ namespace Upsilon.Parser
|
||||||
OpenParenthesis = openParenthesis;
|
OpenParenthesis = openParenthesis;
|
||||||
Parameters = parameters;
|
Parameters = parameters;
|
||||||
CloseParenthesis = closeParenthesis;
|
CloseParenthesis = closeParenthesis;
|
||||||
|
Span = new TextSpan(Identifier.Span.Start, CloseParenthesis.Span.End - Identifier.Span.End);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.FunctionCallExpression;
|
public override SyntaxKind Kind => SyntaxKind.FunctionCallExpression;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Parser
|
namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
|
@ -22,6 +23,7 @@ namespace Upsilon.Parser
|
||||||
CloseParenthesis = closeParenthesis;
|
CloseParenthesis = closeParenthesis;
|
||||||
Block = block;
|
Block = block;
|
||||||
EndToken = endToken;
|
EndToken = endToken;
|
||||||
|
Span = new TextSpan(FunctionToken.Span.Start, EndToken.Span.End - FunctionToken.Span.Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.FunctionExpression;
|
public override SyntaxKind Kind => SyntaxKind.FunctionExpression;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Parser
|
namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
|
@ -16,6 +17,7 @@ namespace Upsilon.Parser
|
||||||
OpenBracket = openBracket;
|
OpenBracket = openBracket;
|
||||||
Index = index;
|
Index = index;
|
||||||
CloseBracket = closeBracket;
|
CloseBracket = closeBracket;
|
||||||
|
Span = new TextSpan(expression.Span.Start, CloseBracket.Span.End - expression.Span.Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.IndexExpression;
|
public override SyntaxKind Kind => SyntaxKind.IndexExpression;
|
||||||
|
@ -39,6 +41,7 @@ namespace Upsilon.Parser
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
FullStop = fullStop;
|
FullStop = fullStop;
|
||||||
Index = index;
|
Index = index;
|
||||||
|
Span = new TextSpan(expression.Span.Start, Index.Span.End - expression.Span.Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.FullStopIndexExpression;
|
public override SyntaxKind Kind => SyntaxKind.FullStopIndexExpression;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Parser
|
namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
|
@ -9,6 +10,7 @@ namespace Upsilon.Parser
|
||||||
OpenParenthesis = openParenthesis;
|
OpenParenthesis = openParenthesis;
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
CloseParenthesis = closeParenthesis;
|
CloseParenthesis = closeParenthesis;
|
||||||
|
Span = new TextSpan(OpenParenthesis.Span.Start, CloseParenthesis.Span.End - OpenParenthesis.Span.Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.ParenthesizedExpression;
|
public override SyntaxKind Kind => SyntaxKind.ParenthesizedExpression;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Parser
|
namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
|
@ -8,6 +9,7 @@ namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
Operator = @operator;
|
Operator = @operator;
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
|
Span = new TextSpan(Operator.Span.Start, expression.Span.End - Operator.Span.Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.UnaryExpression;
|
public override SyntaxKind Kind => SyntaxKind.UnaryExpression;
|
||||||
|
|
|
@ -9,6 +9,7 @@ namespace Upsilon.Parser
|
||||||
public VariableExpressionSyntax(IdentifierToken identifier)
|
public VariableExpressionSyntax(IdentifierToken identifier)
|
||||||
{
|
{
|
||||||
Identifier = identifier;
|
Identifier = identifier;
|
||||||
|
Span = Identifier.Span;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.VariableExpression;
|
public override SyntaxKind Kind => SyntaxKind.VariableExpression;
|
||||||
|
|
|
@ -218,13 +218,13 @@ namespace Upsilon.Parser
|
||||||
localToken = NextToken();
|
localToken = NextToken();
|
||||||
}
|
}
|
||||||
var functionToken = MatchToken(SyntaxKind.FunctionKeyword);
|
var functionToken = MatchToken(SyntaxKind.FunctionKeyword);
|
||||||
var identifier = (IdentifierToken)MatchToken(SyntaxKind.Identifier);
|
var identifier = MatchToken(SyntaxKind.Identifier);
|
||||||
var openParenthesis = MatchToken(SyntaxKind.OpenParenthesis);
|
var openParenthesis = MatchToken(SyntaxKind.OpenParenthesis);
|
||||||
var variableBuilder = ImmutableArray.CreateBuilder<IdentifierToken>();
|
var variableBuilder = ImmutableArray.CreateBuilder<IdentifierToken>();
|
||||||
while (Current.Kind != SyntaxKind.CloseParenthesis)
|
while (Current.Kind != SyntaxKind.CloseParenthesis || Current.Kind == SyntaxKind.EndOfFile)
|
||||||
{
|
{
|
||||||
var variableIdentifier = (IdentifierToken)MatchToken(SyntaxKind.Identifier);
|
var variableIdentifier = MatchToken(SyntaxKind.Identifier);
|
||||||
variableBuilder.Add(variableIdentifier);
|
variableBuilder.Add((IdentifierToken) variableIdentifier);
|
||||||
if (Current.Kind == SyntaxKind.Comma)
|
if (Current.Kind == SyntaxKind.Comma)
|
||||||
NextToken();
|
NextToken();
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,7 @@ namespace Upsilon.Parser
|
||||||
var endToken = MatchToken(SyntaxKind.EndKeyword);
|
var endToken = MatchToken(SyntaxKind.EndKeyword);
|
||||||
var functionExpression = new FunctionExpressionSyntax(functionToken, openParenthesis,
|
var functionExpression = new FunctionExpressionSyntax(functionToken, openParenthesis,
|
||||||
variableBuilder.ToImmutable(), closeParenthesis, (BlockStatementSyntax) block, endToken);
|
variableBuilder.ToImmutable(), closeParenthesis, (BlockStatementSyntax) block, endToken);
|
||||||
return new FunctionAssignmentStatementSyntax(localToken, identifier, functionExpression);
|
return new FunctionAssignmentStatementSyntax(localToken, (IdentifierToken) identifier, functionExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
private StatementSyntax ParseExpressionStatement()
|
private StatementSyntax ParseExpressionStatement()
|
||||||
|
|
|
@ -8,6 +8,7 @@ namespace Upsilon.Parser
|
||||||
public BreakStatementSyntax(SyntaxToken breakKeyword)
|
public BreakStatementSyntax(SyntaxToken breakKeyword)
|
||||||
{
|
{
|
||||||
BreakKeyword = breakKeyword;
|
BreakKeyword = breakKeyword;
|
||||||
|
Span = breakKeyword.Span;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.BreakStatement;
|
public override SyntaxKind Kind => SyntaxKind.BreakStatement;
|
||||||
|
|
|
@ -9,6 +9,7 @@ namespace Upsilon.Parser
|
||||||
public ExpressionStatementSyntax(ExpressionSyntax expression)
|
public ExpressionStatementSyntax(ExpressionSyntax expression)
|
||||||
{
|
{
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
|
Span = expression.Span;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.ExpressionStatement;
|
public override SyntaxKind Kind => SyntaxKind.ExpressionStatement;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Parser
|
namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
|
@ -9,6 +10,9 @@ namespace Upsilon.Parser
|
||||||
LocalToken = localToken;
|
LocalToken = localToken;
|
||||||
Identifier = identifier;
|
Identifier = identifier;
|
||||||
FunctionExpression = functionExpression;
|
FunctionExpression = functionExpression;
|
||||||
|
var start = Identifier.Span.Start;
|
||||||
|
if (localToken != null) start = localToken.Span.Start;
|
||||||
|
Span = new TextSpan(start, FunctionExpression.Span.End - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SyntaxToken LocalToken { get; }
|
public SyntaxToken LocalToken { get; }
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Parser
|
namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
|
@ -23,6 +24,7 @@ namespace Upsilon.Parser
|
||||||
DoKeyword = doKeyword;
|
DoKeyword = doKeyword;
|
||||||
Block = block;
|
Block = block;
|
||||||
EndKeyword = endKeyword;
|
EndKeyword = endKeyword;
|
||||||
|
Span = new TextSpan(forKeyword.Span.Start, endKeyword.Span.End - forKeyword.Span.Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.GenericForStatement;
|
public override SyntaxKind Kind => SyntaxKind.GenericForStatement;
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Upsilon.Parser
|
||||||
ThenToken = thenToken;
|
ThenToken = thenToken;
|
||||||
Block = block;
|
Block = block;
|
||||||
EndToken = endToken;
|
EndToken = endToken;
|
||||||
|
Span = new TextSpan(IfToken.Span.Start, EndToken.Span.End - IfToken.Span.Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
|
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
|
||||||
|
@ -27,7 +27,7 @@ namespace Upsilon.Parser
|
||||||
ThenToken = thenToken;
|
ThenToken = thenToken;
|
||||||
Block = block;
|
Block = block;
|
||||||
ElseStatement = elseStatement;
|
ElseStatement = elseStatement;
|
||||||
|
Span = new TextSpan(IfToken.Span.Start, EndToken.Span.End - IfToken.Span.Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
|
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
|
||||||
|
@ -38,6 +38,7 @@ namespace Upsilon.Parser
|
||||||
ThenToken = thenToken;
|
ThenToken = thenToken;
|
||||||
Block = block;
|
Block = block;
|
||||||
NextElseIfStatement = nextElseIfStatement;
|
NextElseIfStatement = nextElseIfStatement;
|
||||||
|
Span = new TextSpan(IfToken.Span.Start, NextElseIfStatement.Span.End - IfToken.Span.Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,6 +77,7 @@ namespace Upsilon.Parser
|
||||||
yield return Condition;
|
yield return Condition;
|
||||||
yield return ThenToken;
|
yield return ThenToken;
|
||||||
yield return Block;
|
yield return Block;
|
||||||
|
Span = new TextSpan(ElseIfToken.Span.Start, Block.Span.End - ElseIfToken.Span.Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ElseIfStatementSyntax(IfStatementSyntax s)
|
public ElseIfStatementSyntax(IfStatementSyntax s)
|
||||||
|
@ -115,6 +117,7 @@ namespace Upsilon.Parser
|
||||||
ElseToken = elseToken;
|
ElseToken = elseToken;
|
||||||
Block = block;
|
Block = block;
|
||||||
EndToken = endToken;
|
EndToken = endToken;
|
||||||
|
Span = new TextSpan(ElseToken.Span.Start, EndToken.Span.End - ElseToken.Span.Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.ElseStatement;
|
public override SyntaxKind Kind => SyntaxKind.ElseStatement;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
|
using System.Linq;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Parser
|
namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
|
@ -17,6 +19,9 @@ namespace Upsilon.Parser
|
||||||
Identifiers = identifiers.ToImmutableArray();
|
Identifiers = identifiers.ToImmutableArray();
|
||||||
AssignmentToken = assignmentToken;
|
AssignmentToken = assignmentToken;
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
|
var start = Identifiers.First().Span.Start;
|
||||||
|
if (localKeyword != null) start = localKeyword.Span.Start;
|
||||||
|
Span = new TextSpan(start, expression.Span.End - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.MultiAssignmentStatement;
|
public override SyntaxKind Kind => SyntaxKind.MultiAssignmentStatement;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Parser
|
namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
|
@ -31,6 +32,7 @@ namespace Upsilon.Parser
|
||||||
DoToken = doToken;
|
DoToken = doToken;
|
||||||
Block = block;
|
Block = block;
|
||||||
EndToken = endToken;
|
EndToken = endToken;
|
||||||
|
Span = new TextSpan(ForToken.Span.Start, EndToken.Span.End - ForToken.Span.Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.NumericForStatement;
|
public override SyntaxKind Kind => SyntaxKind.NumericForStatement;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Parser
|
namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
|
@ -8,6 +9,7 @@ namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
ReturnToken = returnToken;
|
ReturnToken = returnToken;
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
|
Span = new TextSpan(returnToken.Span.Start, expression.Span.End - returnToken.Span.Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SyntaxToken ReturnToken { get; }
|
public SyntaxToken ReturnToken { get; }
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
namespace Upsilon.Parser
|
namespace Upsilon.Parser
|
||||||
{
|
{
|
||||||
|
@ -14,6 +15,7 @@ namespace Upsilon.Parser
|
||||||
TableExpression = tableExpression;
|
TableExpression = tableExpression;
|
||||||
AssignmentToken = assignmentToken;
|
AssignmentToken = assignmentToken;
|
||||||
Expression = expression;
|
Expression = expression;
|
||||||
|
Span = new TextSpan(tableExpression.Span.Start, expression.Span.End - tableExpression.Span.Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SyntaxKind Kind => SyntaxKind.TableAssignmentStatement;
|
public override SyntaxKind Kind => SyntaxKind.TableAssignmentStatement;
|
||||||
|
|
|
@ -41,6 +41,11 @@ namespace Upsilon.Text
|
||||||
while (min <= max)
|
while (min <= max)
|
||||||
{
|
{
|
||||||
var mid = (min + max) / 2 ;
|
var mid = (min + max) / 2 ;
|
||||||
|
if (mid >= _lines.Length)
|
||||||
|
{
|
||||||
|
max = _lines.Length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
var midLine = _lines[mid];
|
var midLine = _lines[mid];
|
||||||
if (midLine.Start <= spanPos && midLine.End > spanPos)
|
if (midLine.Start <= spanPos && midLine.End > spanPos)
|
||||||
{
|
{
|
||||||
|
@ -56,6 +61,11 @@ namespace Upsilon.Text
|
||||||
max = mid - 1;
|
max = mid - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (min >= _lines.Length)
|
||||||
|
{
|
||||||
|
min = _lines.Length - 1;
|
||||||
|
}
|
||||||
var newPos = spanPos - _lines[min].Start;
|
var newPos = spanPos - _lines[min].Start;
|
||||||
return (min, newPos);
|
return (min, newPos);
|
||||||
}
|
}
|
||||||
|
@ -65,6 +75,16 @@ namespace Upsilon.Text
|
||||||
return _lines[lineIndex].Start;
|
return _lines[lineIndex].Start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int GetLineCount()
|
||||||
|
{
|
||||||
|
return _lines.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetTextLength()
|
||||||
|
{
|
||||||
|
return _text.Length;
|
||||||
|
}
|
||||||
|
|
||||||
public SourceTextLine GetLineInfo(int lineIndex)
|
public SourceTextLine GetLineInfo(int lineIndex)
|
||||||
{
|
{
|
||||||
return _lines[lineIndex];
|
return _lines[lineIndex];
|
||||||
|
|
|
@ -106,7 +106,7 @@ end
|
||||||
Assert.Empty(script.Diagnostics.Messages);
|
Assert.Empty(script.Diagnostics.Messages);
|
||||||
var result = script.EvaluateFunction<long>("test", new[] {obj});
|
var result = script.EvaluateFunction<long>("test", new[] {obj});
|
||||||
Assert.Empty(script.Diagnostics.Messages);
|
Assert.Empty(script.Diagnostics.Messages);
|
||||||
Assert.Equal(result, 120);
|
Assert.Equal(120, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
Loading…
Reference in New Issue