Lots of work for handling incomplete code and inspections better

This commit is contained in:
Deukhoofd 2018-11-25 19:30:18 +01:00
parent 0b6359f499
commit cae3d7fb53
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
50 changed files with 457 additions and 97 deletions

View File

@ -8,7 +8,7 @@ using Type = Upsilon.BaseTypes.Type;
namespace Upsilon.Binder
{
internal class Binder
internal class Binder : IDisposable
{
private Diagnostics _diagnostics;
public BoundScope Scope { get; private set; }
@ -29,6 +29,12 @@ namespace Upsilon.Binder
return new Binder {_diagnostics = diagnostics, Scope = scope};
}
public void Dispose()
{
Scope?.Dispose();
Scope = null;
_unboundFunctions.Clear();
}
public BoundScript BindScript(BlockStatementSyntax e)
{
@ -45,7 +51,7 @@ namespace Upsilon.Binder
Scope = Scope.ParentScope;
}
_unboundFunctions = new Dictionary<string, UnboundFunctionExpression>();
return new BoundScript((BoundBlockStatement) bound);
return new BoundScript((BoundBlockStatement) bound, e.Span);
}
private BoundStatement BindStatement(StatementSyntax s)
@ -74,7 +80,7 @@ namespace Upsilon.Binder
return BindGenericForStatement((GenericForStatementSyntax) s);
case SyntaxKind.BreakStatement:
return new BoundBreakStatement();
return new BoundBreakStatement(s.Span);
}
throw new NotImplementedException(s.Kind.ToString());
@ -124,7 +130,7 @@ namespace Upsilon.Binder
return inExp;
}
return new BoundUnaryExpression(op, inExp, op.OutType);
return new BoundUnaryExpression(op, inExp, op.OutType, e.Span);
}
private BoundExpression BindBinaryExpression(BinaryExpressionSyntax e)
@ -137,7 +143,7 @@ namespace Upsilon.Binder
_diagnostics.LogUnknownBinaryOperator(e.Span, e.Operator.Kind, left.Type, right.Type);
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)
@ -166,7 +172,7 @@ namespace Upsilon.Binder
_diagnostics.LogUnknownType(e.Span);
break;
}
return new BoundLiteralExpression(outValue);
return new BoundLiteralExpression(outValue, e.Span);
}
private BoundExpression BindParenthesizedExpression(ParenthesizedExpressionSyntax e)
@ -193,7 +199,7 @@ namespace Upsilon.Binder
if (expression.Kind == BoundKind.VariableExpression)
{
var variableExpression =(BoundVariableExpression) expression;
var function = (FunctionVariableSymbol)variableExpression.Variable;
var function = (FunctionVariableSymbol)variableExpression.Variable.VariableSymbol;
if (!function.IsBound)
{
Scope = new BoundScope(Scope);
@ -215,7 +221,7 @@ namespace Upsilon.Binder
}
//TODO: validate parameters
return new BoundFunctionCallExpression(expression, parameters.ToImmutable());
return new BoundFunctionCallExpression(expression, parameters.ToImmutable(), e.Span);
}
private BoundExpression BindVariableExpression(VariableExpressionSyntax e)
@ -224,16 +230,16 @@ namespace Upsilon.Binder
if (!Scope.TryGetVariable(name, true, out var variable))
{
_diagnostics.LogUnknownVariable(e.Identifier.Span, name);
return new BoundLiteralExpression(new ScriptNull());
return new BoundLiteralExpression(new ScriptNull(), e.Span);
}
return new BoundVariableExpression(variable);
var boundVariable = new BoundVariableSymbol(variable, e.Identifier.Span);
return new BoundVariableExpression(boundVariable, e.Span);
}
private BoundStatement BindExpressionStatement(ExpressionStatementSyntax s)
{
var exp = BindExpression(s.Expression);
return new BoundExpressionStatement(exp);
return new BoundExpressionStatement(exp, s.Span);
}
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)
{
v.Variable.Type = variable.Type;
v.Variable.VariableSymbol.Type = variable.Type;
}
else if (assignment.Type == Type.Unknown)
{
@ -299,12 +305,13 @@ namespace Upsilon.Binder
var boundVariable = TryBindVariable(name, isLocal, boundExpression);
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)
@ -318,7 +325,7 @@ namespace Upsilon.Binder
var boundVariable = TryBindVariable(identifierToken.Name, isLocal, assignment);
ls.Add(boundVariable);
}
return new BoundMultiAssignmentStatement(ls.ToImmutableArray(), assignment);
return new BoundMultiAssignmentStatement(ls.ToImmutableArray(), assignment, s.Span);
}
private BoundStatement BindBlockStatement(BlockStatementSyntax e)
@ -330,7 +337,7 @@ namespace Upsilon.Binder
arr.Add(bound);
}
return new BoundBlockStatement(arr.ToImmutable());
return new BoundBlockStatement(arr.ToImmutable(), e.Span);
}
private BoundStatement BindIfStatement(IfStatementSyntax e)
@ -343,21 +350,21 @@ namespace Upsilon.Binder
{
var nextElseIf = BindIfStatement(e.NextElseIfStatement);
return new BoundIfStatement((BoundExpressionStatement) condition, (BoundBlockStatement) block,
(BoundIfStatement) nextElseIf);
(BoundIfStatement) nextElseIf, e.Span);
}
if (e.ElseStatement == null)
{
return new BoundIfStatement((BoundExpressionStatement) condition, (BoundBlockStatement) block);
return new BoundIfStatement((BoundExpressionStatement) condition, (BoundBlockStatement) block, e.Span);
}
else
{
Scope = new BoundScope(Scope);
var elseBlock = BindBlockStatement(e.ElseStatement.Block);
var elseStatement = new BoundElseStatement((BoundBlockStatement) elseBlock);
var elseStatement = new BoundElseStatement((BoundBlockStatement) elseBlock, e.Span);
Scope = Scope.ParentScope;
return new BoundIfStatement((BoundExpressionStatement) condition, (BoundBlockStatement) block,
elseStatement);
elseStatement, e.Span);
}
}
@ -377,12 +384,12 @@ namespace Upsilon.Binder
Scope = innerScope;
var block = BindBlockStatement(e.Block);
Scope = Scope.ParentScope;
var func = new BoundFunctionExpression(parameters.ToImmutable(), (BoundBlockStatement) block);
var func = new BoundFunctionExpression(parameters.ToImmutable(), (BoundBlockStatement) block, e.Span);
return func;
}
else
{
var unbound = new UnboundFunctionExpression(parameters.ToImmutable(), e.Block);
var unbound = new UnboundFunctionExpression(parameters.ToImmutable(), e.Block, e.Span);
if (variableSymbol == null)
{
_unboundFunctions.Add( Guid.NewGuid().ToString(), unbound);
@ -433,18 +440,18 @@ namespace Upsilon.Binder
else
{
_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)
{
var expression = BindExpression(e.Expression);
return new BoundReturnStatement(expression);
return new BoundReturnStatement(expression, e.Span);
}
private BoundExpression BindTableExpression(TableExpressionSyntax e)
@ -466,7 +473,7 @@ namespace Upsilon.Binder
dictionary.Add(variable.Key, true);
}
Scope = s;
return new BoundTableExpression(keyType, valueType, dictionary, statements);
return new BoundTableExpression(keyType, valueType, dictionary, statements.ToImmutable(), e.Span);
}
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)
{
_diagnostics.LogInvalidIndexExpression(expression.Type, index.Type, e.Span);
return new BoundLiteralExpression(new ScriptNull());
return new BoundLiteralExpression(new ScriptNull(), e.Span);
}
switch (expression.Type)
{
case Type.Table:
case Type.UserData:
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:
return new BoundIndexExpression(expression, index, Type.String);
return new BoundIndexExpression(expression, index, Type.String, e.Span);
default:
_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.UserData:
case Type.Unknown:
return new BoundFullStopIndexExpression(expression, index);
return new BoundFullStopIndexExpression(expression, index, e.Span);
case Type.String:
return new BoundFullStopIndexExpression(expression, index);
return new BoundFullStopIndexExpression(expression, index, e.Span);
default:
_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);
var value = BindExpression(e.Expression);
return new BoundTableAssigmentStatement(indexableExpression, value);
return new BoundTableAssigmentStatement(indexableExpression, value, e.Span);
}
private BoundStatement BindNumericForStatement(NumericForStatementSyntax e)
@ -536,7 +543,8 @@ namespace Upsilon.Binder
boundStep = BindExpression(e.StepExpression);
var block = BindBlockStatement((BlockStatementSyntax) e.Block);
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)
@ -552,7 +560,7 @@ namespace Upsilon.Binder
var boundEnumerableExpression = BindExpression(e.EnumerableExpression);
var block = BindBlockStatement(e.Block);
return new BoundGenericForStatement(array.ToImmutable(), boundEnumerableExpression, block);
return new BoundGenericForStatement(array.ToImmutable(), boundEnumerableExpression, block, e.Span);
}
}
}

View File

@ -1,11 +1,12 @@
using Upsilon.BaseTypes;
using Upsilon.Parser;
using Upsilon.Text;
namespace Upsilon.Binder
{
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;
LeftExpression = leftExpression;
@ -14,6 +15,16 @@ namespace Upsilon.Binder
}
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 BoundBinaryOperator Operator { get; }

View File

@ -1,9 +1,14 @@
using Upsilon.BaseTypes;
using Upsilon.Text;
namespace Upsilon.Binder
{
public abstract class BoundExpression : BoundNode
{
protected BoundExpression(TextSpan span) : base(span)
{
}
public abstract Type Type { get; }
}
}

View File

@ -1,5 +1,6 @@
using System.Collections.Immutable;
using Upsilon.BaseTypes;
using Upsilon.Text;
namespace Upsilon.Binder
{
@ -8,13 +9,27 @@ namespace Upsilon.Binder
public BoundExpression Identifier { 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;
Parameters = parameters;
}
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;
}
}

View File

@ -1,5 +1,6 @@
using System.Collections.Immutable;
using Upsilon.BaseTypes;
using Upsilon.Text;
namespace Upsilon.Binder
{
@ -8,27 +9,20 @@ namespace Upsilon.Binder
public ImmutableArray<VariableSymbol> Parameters { get; }
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;
Block = block;
}
public override BoundKind Kind => BoundKind.BoundFunctionExpression;
public override Type Type => Type.Function;
}
public class BoundFunctionAssignmentStatement : BoundStatement
{
public VariableSymbol Variable { get; }
public BoundFunctionExpression Func { get; }
public BoundFunctionAssignmentStatement(VariableSymbol variable, BoundFunctionExpression func)
public override BoundNode GetNodeAtPosition(int characterPosition)
{
Variable = variable;
Func = func;
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
return Block.GetNodeAtPosition(characterPosition);
return this;
}
public override BoundKind Kind => BoundKind.BoundFunctionAssignmentStatement;
public override Type Type => Type.Function;
}
}

View File

@ -1,11 +1,12 @@
using Upsilon.BaseTypes;
using Upsilon.Parser;
using Upsilon.Text;
namespace Upsilon.Binder
{
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;
Index = index;
@ -16,6 +17,16 @@ namespace Upsilon.Binder
public BoundExpression Index { get; }
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; }
}
@ -24,13 +35,20 @@ namespace Upsilon.Binder
public BoundExpression Expression { get; }
public string Index { get; }
public BoundFullStopIndexExpression(BoundExpression expression, string index)
public BoundFullStopIndexExpression(BoundExpression expression, string index, TextSpan span) : base(span)
{
Expression = expression;
Index = index;
}
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;
}
}

View File

@ -1,15 +1,21 @@
using Upsilon.BaseTypes;
using Upsilon.Text;
namespace Upsilon.Binder
{
internal class BoundLiteralExpression : BoundExpression
{
public BoundLiteralExpression(ScriptType value)
public BoundLiteralExpression(ScriptType value, TextSpan span) : base(span)
{
Value = value;
}
public override BoundKind Kind => BoundKind.BoundLiteralExpression;
public override BoundNode GetNodeAtPosition(int characterPosition)
{
return this;
}
public override Type Type => Value.Type;
public ScriptType Value { get; }
}

View File

@ -1,13 +1,14 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using Upsilon.BaseTypes;
using Upsilon.Text;
namespace Upsilon.Binder
{
public class BoundTableExpression : BoundExpression
{
public BoundTableExpression(Type keyType, Type valueType, Dictionary<string, bool> expressions,
ImmutableArray<BoundStatement>.Builder statements)
ImmutableArray<BoundStatement> statements, TextSpan span) : base(span)
{
KeyType = keyType;
ValueType = valueType;
@ -16,12 +17,23 @@ namespace Upsilon.Binder
}
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 Type KeyType { get; }
public Type ValueType { get; }
public Dictionary<string, bool> Expressions { get; }
public ImmutableArray<BoundStatement>.Builder Statements { get; }
public ImmutableArray<BoundStatement> Statements { get; }
}
}

View File

@ -1,13 +1,21 @@
using Upsilon.BaseTypes;
using Upsilon.Text;
namespace Upsilon.Binder
{
public class BoundUnaryExpression : BoundExpression
{
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 BoundUnaryExpression(BoundUnaryOperator op, BoundExpression inExpression, Type type)
public BoundUnaryExpression(BoundUnaryOperator op, BoundExpression inExpression, Type type, TextSpan span) : base(span)
{
Operator = op;
InExpression = inExpression;

View File

@ -1,17 +1,23 @@
using System;
using Upsilon.Text;
using Type = Upsilon.BaseTypes.Type;
namespace Upsilon.Binder
{
public class BoundVariableExpression : BoundExpression
{
public BoundVariableExpression(VariableSymbol variable)
public BoundVariableExpression(BoundVariableSymbol variable, TextSpan span) : base(span)
{
Variable = variable;
}
public VariableSymbol Variable { get; }
public BoundVariableSymbol Variable { get; }
public override BoundKind Kind => BoundKind.VariableExpression;
public override BoundNode GetNodeAtPosition(int characterPosition)
{
return Variable;
}
public override Type Type => Variable.Type;
}
}

View File

@ -1,12 +1,13 @@
using System.Collections.Immutable;
using Upsilon.Parser;
using Upsilon.Text;
namespace Upsilon.Binder
{
public class UnboundFunctionExpression : BoundFunctionExpression
{
public UnboundFunctionExpression(ImmutableArray<VariableSymbol> parameters,
BlockStatementSyntax unboundBlock) : base(parameters, null)
BlockStatementSyntax unboundBlock, TextSpan span) : base(parameters, null, span)
{
UnboundBlock = unboundBlock;
}

View File

@ -2,6 +2,7 @@ namespace Upsilon.Binder
{
public enum BoundKind
{
BoundVariableSymbol,
BoundScript,
BoundLiteralExpression,
@ -28,5 +29,6 @@ namespace Upsilon.Binder
BoundNumericForStatement,
BoundGenericForStatement,
BoundBreakStatement,
}
}

View File

@ -4,7 +4,14 @@ namespace Upsilon.Binder
{
public abstract class BoundNode
{
protected BoundNode(TextSpan span)
{
Span = span;
}
public abstract BoundKind Kind { get; }
public TextSpan Span { get; protected set; }
public TextSpan Span { get; }
public abstract BoundNode GetNodeAtPosition(int characterPosition);
}
}

View File

@ -1,14 +1,14 @@
using System;
using System.Collections.Generic;
namespace Upsilon.Binder
{
public class BoundScope
public class BoundScope : IDisposable
{
public readonly BoundScope ParentScope;
private BoundScope _readOnlyScope;
public readonly Dictionary<string, VariableSymbol> Variables;
public BoundScope(BoundScope parentScope)
{
ParentScope = parentScope;
@ -26,6 +26,11 @@ namespace Upsilon.Binder
return scope;
}
public void Dispose()
{
Variables.Clear();
}
public void DefineLocalVariable(VariableSymbol var)
{
Variables.Add(var.Name, var);

View File

@ -1,15 +1,26 @@
using System.Collections.Immutable;
using System.Linq;
using Upsilon.Text;
namespace Upsilon.Binder
{
public class BoundBlockStatement : BoundStatement
{
public BoundBlockStatement(ImmutableArray<BoundStatement> statements)
public BoundBlockStatement(ImmutableArray<BoundStatement> statements, TextSpan span) : base(span)
{
Statements = statements;
}
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; }
}

View File

@ -1,7 +1,19 @@
using Upsilon.Text;
namespace Upsilon.Binder
{
public class BoundBreakStatement : BoundStatement
{
public BoundBreakStatement(TextSpan span) : base(span)
{
}
public override BoundKind Kind => BoundKind.BoundBreakStatement;
public override BoundNode GetNodeAtPosition(int characterPosition)
{
if (characterPosition >= Span.Start && characterPosition <= Span.End)
return this;
return null;
}
}
}

View File

@ -1,11 +1,19 @@
using Upsilon.Text;
namespace Upsilon.Binder
{
public class BoundExpressionStatement : BoundStatement
{
public BoundExpression Expression { get; }
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;
}

View File

@ -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;
}
}
}

View File

@ -1,4 +1,5 @@
using System.Collections.Immutable;
using Upsilon.Text;
namespace Upsilon.Binder
{
@ -9,7 +10,7 @@ namespace Upsilon.Binder
public BoundStatement Block { get; }
public BoundGenericForStatement(ImmutableArray<VariableSymbol> variables,
BoundExpression boundEnumerableExpression, BoundStatement block)
BoundExpression boundEnumerableExpression, BoundStatement block, TextSpan span) : base(span)
{
Variables = variables;
BoundEnumerableExpression = boundEnumerableExpression;
@ -17,5 +18,13 @@ namespace Upsilon.Binder
}
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;
}
}
}

View File

@ -1,20 +1,22 @@
using Upsilon.Text;
namespace Upsilon.Binder
{
public class BoundIfStatement : BoundStatement
{
public BoundIfStatement(BoundExpressionStatement condition, BoundBlockStatement block)
public BoundIfStatement(BoundExpressionStatement condition, BoundBlockStatement block, TextSpan span): base(span)
{
Condition = condition;
Block = block;
}
public BoundIfStatement(BoundExpressionStatement condition, BoundBlockStatement block, BoundElseStatement elseStatement)
public BoundIfStatement(BoundExpressionStatement condition, BoundBlockStatement block, BoundElseStatement elseStatement, TextSpan span) : base(span)
{
Condition = condition;
Block = block;
ElseStatement = elseStatement;
}
public BoundIfStatement(BoundExpressionStatement condition, BoundBlockStatement block, BoundIfStatement nextElseIf)
public BoundIfStatement(BoundExpressionStatement condition, BoundBlockStatement block, BoundIfStatement nextElseIf, TextSpan span) : base(span)
{
Condition = condition;
Block = block;
@ -22,6 +24,18 @@ namespace Upsilon.Binder
}
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 BoundBlockStatement Block { get; }
@ -33,11 +47,17 @@ namespace Upsilon.Binder
{
public BoundBlockStatement Block { get; }
public BoundElseStatement(BoundBlockStatement block)
public BoundElseStatement(BoundBlockStatement block, TextSpan span) : base(span)
{
Block = block;
}
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;
}
}
}

View File

@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using Upsilon.Text;
namespace Upsilon.Binder
{
@ -8,12 +9,20 @@ namespace Upsilon.Binder
public ImmutableArray<VariableSymbol> Variables { 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;
Assignment = assignment;
}
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;
}
}
}

View File

@ -1,3 +1,5 @@
using Upsilon.Text;
namespace Upsilon.Binder
{
public class BoundNumericForStatement : BoundStatement
@ -9,7 +11,7 @@ namespace Upsilon.Binder
public BoundBlockStatement Block { get; }
public BoundNumericForStatement(VariableSymbol variable, BoundExpression boundStart,
BoundExpression boundStop, BoundExpression boundStep, BoundBlockStatement block)
BoundExpression boundStop, BoundExpression boundStep, BoundBlockStatement block, TextSpan span) : base(span)
{
Variable = variable;
BoundStart = boundStart;
@ -19,5 +21,18 @@ namespace Upsilon.Binder
}
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;
}
}
}

View File

@ -1,13 +1,21 @@
using Upsilon.Text;
namespace Upsilon.Binder
{
public class BoundReturnStatement : BoundStatement
{
public BoundReturnStatement(BoundExpression expression)
public BoundReturnStatement(BoundExpression expression, TextSpan span) : base(span)
{
Expression = expression;
}
public BoundExpression Expression { get; }
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;
}
}
}

View File

@ -1,15 +1,20 @@
using System.Collections.Generic;
using Upsilon.Text;
namespace Upsilon.Binder
{
public class BoundScript : BoundStatement
{
public BoundScript(BoundBlockStatement statement)
public BoundScript(BoundBlockStatement statement, TextSpan span) : base(span)
{
Statement = statement;
}
public override BoundKind Kind => BoundKind.BoundScript;
public override BoundNode GetNodeAtPosition(int characterPosition)
{
return Statement.GetNodeAtPosition(characterPosition);
}
public BoundBlockStatement Statement { get; }
}

View File

@ -1,6 +1,11 @@
using Upsilon.Text;
namespace Upsilon.Binder
{
public abstract class BoundStatement : BoundNode
{
protected BoundStatement(TextSpan span) : base(span)
{
}
}
}

View File

@ -1,3 +1,5 @@
using Upsilon.Text;
namespace Upsilon.Binder
{
public class BoundTableAssigmentStatement : BoundStatement
@ -5,12 +7,22 @@ namespace Upsilon.Binder
public BoundExpression TableIndexExpression { get; }
public BoundExpression Value { get; }
public BoundTableAssigmentStatement(BoundExpression tableIndexExpression, BoundExpression value)
public BoundTableAssigmentStatement(BoundExpression tableIndexExpression, BoundExpression value,
TextSpan span) : base(span)
{
TableIndexExpression = tableIndexExpression;
Value = value;
}
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;
}
}
}

View File

@ -1,12 +1,15 @@
using Upsilon.Text;
namespace Upsilon.Binder
{
public class BoundVariableAssignment : BoundStatement
{
public VariableSymbol Variable { get; }
public BoundVariableSymbol Variable { get; }
public BoundExpression BoundExpression { 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;
BoundExpression = boundExpression;
@ -14,5 +17,14 @@ namespace Upsilon.Binder
}
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;
}
}
}

View File

@ -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; }
}
}

View File

@ -90,6 +90,17 @@ namespace Upsilon
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()
{
var linePos = Diagnostics.ScriptString.GetLinePosition(Span.Start);

View File

@ -1,12 +1,13 @@
using System;
using System.Collections.Generic;
using Upsilon.BaseTypes;
using Upsilon.Binder;
namespace Upsilon.Evaluator
{
public class EvaluationScope
public class EvaluationScope : IDisposable
{
private readonly EvaluationScope _parentScope;
private EvaluationScope _parentScope;
private EvaluationScope _getOnlyParentScope;
public readonly Dictionary<string, ScriptType> Variables;
@ -29,6 +30,13 @@ namespace Upsilon.Evaluator
return scope;
}
public void Dispose()
{
_parentScope?.Dispose();
_parentScope = null;
Variables.Clear();
}
public void AssignToNearest(VariableSymbol symbol, ScriptType value)
{
if (Variables.ContainsKey(symbol.Name))

View File

@ -10,7 +10,7 @@ using Type = Upsilon.BaseTypes.Type;
namespace Upsilon.Evaluator
{
internal class Evaluator
internal class Evaluator : IDisposable
{
private Diagnostics _diagnostics;
private ScriptType _lastValue;
@ -38,6 +38,13 @@ namespace Upsilon.Evaluator
return new Evaluator {_diagnostics = diagnostics, Scope = scope};
}
public void Dispose()
{
Scope.Dispose();
_lastValue = null;
_returnValue = null;
}
public ScriptType Evaluate(BoundScript e)
{
EvaluateNode(e.Statement);
@ -302,11 +309,11 @@ namespace Upsilon.Evaluator
var val = EvaluateExpression(e.BoundExpression);
if (e.IsLocalDefinition)
{
Scope.CreateLocal(e.Variable, val);
Scope.CreateLocal(e.Variable.VariableSymbol, val);
}
else
{
Scope.AssignToNearest(e.Variable, val);
Scope.AssignToNearest(e.Variable.VariableSymbol, val);
}
_lastValue = val;
}
@ -339,11 +346,11 @@ namespace Upsilon.Evaluator
private ScriptType EvaluateVariableExpression(BoundVariableExpression e)
{
if (Scope.TryGet(e.Variable, out var val))
if (Scope.TryGet(e.Variable.VariableSymbol, out var 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)

View File

@ -10,11 +10,11 @@ using Upsilon.Utilities;
namespace Upsilon.Evaluator
{
public class Script
public class Script : IDisposable
{
private SourceText ScriptString { get; }
public SourceText ScriptString { get; }
private Evaluator Evaluator { get; }
private readonly BlockStatementSyntax _parsed;
private BlockStatementSyntax _parsed;
private BoundScript _bound;
public Diagnostics Diagnostics { get; }
private Binder.Binder Binder { get; }
@ -128,5 +128,14 @@ namespace Upsilon.Evaluator
{
return _parsed.Print();
}
public void Dispose()
{
Binder?.Dispose();
Evaluator?.Dispose();
Scope?.Dispose();
_parsed = null;
_bound = null;
}
}
}

View File

@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using Upsilon.Text;
namespace Upsilon.Parser
{
@ -17,6 +18,7 @@ namespace Upsilon.Parser
OpenParenthesis = openParenthesis;
Parameters = parameters;
CloseParenthesis = closeParenthesis;
Span = new TextSpan(Identifier.Span.Start, CloseParenthesis.Span.End - Identifier.Span.End);
}
public override SyntaxKind Kind => SyntaxKind.FunctionCallExpression;

View File

@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using Upsilon.Text;
namespace Upsilon.Parser
{
@ -22,6 +23,7 @@ namespace Upsilon.Parser
CloseParenthesis = closeParenthesis;
Block = block;
EndToken = endToken;
Span = new TextSpan(FunctionToken.Span.Start, EndToken.Span.End - FunctionToken.Span.Start);
}
public override SyntaxKind Kind => SyntaxKind.FunctionExpression;

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using Upsilon.Text;
namespace Upsilon.Parser
{
@ -16,6 +17,7 @@ namespace Upsilon.Parser
OpenBracket = openBracket;
Index = index;
CloseBracket = closeBracket;
Span = new TextSpan(expression.Span.Start, CloseBracket.Span.End - expression.Span.Start);
}
public override SyntaxKind Kind => SyntaxKind.IndexExpression;
@ -39,6 +41,7 @@ namespace Upsilon.Parser
Expression = expression;
FullStop = fullStop;
Index = index;
Span = new TextSpan(expression.Span.Start, Index.Span.End - expression.Span.Start);
}
public override SyntaxKind Kind => SyntaxKind.FullStopIndexExpression;

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using Upsilon.Text;
namespace Upsilon.Parser
{
@ -9,6 +10,7 @@ namespace Upsilon.Parser
OpenParenthesis = openParenthesis;
Expression = expression;
CloseParenthesis = closeParenthesis;
Span = new TextSpan(OpenParenthesis.Span.Start, CloseParenthesis.Span.End - OpenParenthesis.Span.Start);
}
public override SyntaxKind Kind => SyntaxKind.ParenthesizedExpression;

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using Upsilon.Text;
namespace Upsilon.Parser
{
@ -8,6 +9,7 @@ namespace Upsilon.Parser
{
Operator = @operator;
Expression = expression;
Span = new TextSpan(Operator.Span.Start, expression.Span.End - Operator.Span.Start);
}
public override SyntaxKind Kind => SyntaxKind.UnaryExpression;

View File

@ -9,6 +9,7 @@ namespace Upsilon.Parser
public VariableExpressionSyntax(IdentifierToken identifier)
{
Identifier = identifier;
Span = Identifier.Span;
}
public override SyntaxKind Kind => SyntaxKind.VariableExpression;

View File

@ -218,13 +218,13 @@ namespace Upsilon.Parser
localToken = NextToken();
}
var functionToken = MatchToken(SyntaxKind.FunctionKeyword);
var identifier = (IdentifierToken)MatchToken(SyntaxKind.Identifier);
var identifier = MatchToken(SyntaxKind.Identifier);
var openParenthesis = MatchToken(SyntaxKind.OpenParenthesis);
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);
variableBuilder.Add(variableIdentifier);
var variableIdentifier = MatchToken(SyntaxKind.Identifier);
variableBuilder.Add((IdentifierToken) variableIdentifier);
if (Current.Kind == SyntaxKind.Comma)
NextToken();
}
@ -233,7 +233,7 @@ namespace Upsilon.Parser
var endToken = MatchToken(SyntaxKind.EndKeyword);
var functionExpression = new FunctionExpressionSyntax(functionToken, openParenthesis,
variableBuilder.ToImmutable(), closeParenthesis, (BlockStatementSyntax) block, endToken);
return new FunctionAssignmentStatementSyntax(localToken, identifier, functionExpression);
return new FunctionAssignmentStatementSyntax(localToken, (IdentifierToken) identifier, functionExpression);
}
private StatementSyntax ParseExpressionStatement()

View File

@ -8,6 +8,7 @@ namespace Upsilon.Parser
public BreakStatementSyntax(SyntaxToken breakKeyword)
{
BreakKeyword = breakKeyword;
Span = breakKeyword.Span;
}
public override SyntaxKind Kind => SyntaxKind.BreakStatement;

View File

@ -9,6 +9,7 @@ namespace Upsilon.Parser
public ExpressionStatementSyntax(ExpressionSyntax expression)
{
Expression = expression;
Span = expression.Span;
}
public override SyntaxKind Kind => SyntaxKind.ExpressionStatement;

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using Upsilon.Text;
namespace Upsilon.Parser
{
@ -9,6 +10,9 @@ namespace Upsilon.Parser
LocalToken = localToken;
Identifier = identifier;
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; }

View File

@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using Upsilon.Text;
namespace Upsilon.Parser
{
@ -23,6 +24,7 @@ namespace Upsilon.Parser
DoKeyword = doKeyword;
Block = block;
EndKeyword = endKeyword;
Span = new TextSpan(forKeyword.Span.Start, endKeyword.Span.End - forKeyword.Span.Start);
}
public override SyntaxKind Kind => SyntaxKind.GenericForStatement;

View File

@ -16,7 +16,7 @@ namespace Upsilon.Parser
ThenToken = thenToken;
Block = block;
EndToken = endToken;
Span = new TextSpan(IfToken.Span.Start, EndToken.Span.End - IfToken.Span.Start);
}
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
@ -27,7 +27,7 @@ namespace Upsilon.Parser
ThenToken = thenToken;
Block = block;
ElseStatement = elseStatement;
Span = new TextSpan(IfToken.Span.Start, EndToken.Span.End - IfToken.Span.Start);
}
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
@ -38,6 +38,7 @@ namespace Upsilon.Parser
ThenToken = thenToken;
Block = block;
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 ThenToken;
yield return Block;
Span = new TextSpan(ElseIfToken.Span.Start, Block.Span.End - ElseIfToken.Span.Start);
}
public ElseIfStatementSyntax(IfStatementSyntax s)
@ -115,6 +117,7 @@ namespace Upsilon.Parser
ElseToken = elseToken;
Block = block;
EndToken = endToken;
Span = new TextSpan(ElseToken.Span.Start, EndToken.Span.End - ElseToken.Span.Start);
}
public override SyntaxKind Kind => SyntaxKind.ElseStatement;

View File

@ -1,5 +1,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Upsilon.Text;
namespace Upsilon.Parser
{
@ -17,6 +19,9 @@ namespace Upsilon.Parser
Identifiers = identifiers.ToImmutableArray();
AssignmentToken = assignmentToken;
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;

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using Upsilon.Text;
namespace Upsilon.Parser
{
@ -31,6 +32,7 @@ namespace Upsilon.Parser
DoToken = doToken;
Block = block;
EndToken = endToken;
Span = new TextSpan(ForToken.Span.Start, EndToken.Span.End - ForToken.Span.Start);
}
public override SyntaxKind Kind => SyntaxKind.NumericForStatement;

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using Upsilon.Text;
namespace Upsilon.Parser
{
@ -8,6 +9,7 @@ namespace Upsilon.Parser
{
ReturnToken = returnToken;
Expression = expression;
Span = new TextSpan(returnToken.Span.Start, expression.Span.End - returnToken.Span.Start);
}
public SyntaxToken ReturnToken { get; }

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using Upsilon.Text;
namespace Upsilon.Parser
{
@ -14,6 +15,7 @@ namespace Upsilon.Parser
TableExpression = tableExpression;
AssignmentToken = assignmentToken;
Expression = expression;
Span = new TextSpan(tableExpression.Span.Start, expression.Span.End - tableExpression.Span.Start);
}
public override SyntaxKind Kind => SyntaxKind.TableAssignmentStatement;

View File

@ -41,6 +41,11 @@ namespace Upsilon.Text
while (min <= max)
{
var mid = (min + max) / 2 ;
if (mid >= _lines.Length)
{
max = _lines.Length - 1;
continue;
}
var midLine = _lines[mid];
if (midLine.Start <= spanPos && midLine.End > spanPos)
{
@ -56,6 +61,11 @@ namespace Upsilon.Text
max = mid - 1;
}
}
if (min >= _lines.Length)
{
min = _lines.Length - 1;
}
var newPos = spanPos - _lines[min].Start;
return (min, newPos);
}
@ -65,6 +75,16 @@ namespace Upsilon.Text
return _lines[lineIndex].Start;
}
public int GetLineCount()
{
return _lines.Length;
}
public int GetTextLength()
{
return _text.Length;
}
public SourceTextLine GetLineInfo(int lineIndex)
{
return _lines[lineIndex];

View File

@ -106,7 +106,7 @@ end
Assert.Empty(script.Diagnostics.Messages);
var result = script.EvaluateFunction<long>("test", new[] {obj});
Assert.Empty(script.Diagnostics.Messages);
Assert.Equal(result, 120);
Assert.Equal(120, result);
}
[Fact]