Reworked diagnostics, saves line positions in memory, instead of calculating later.

This commit is contained in:
Deukhoofd 2019-01-16 23:57:42 +01:00
parent b5bfb7997b
commit 1d6b5673d6
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
55 changed files with 322 additions and 351 deletions

View File

@ -107,11 +107,9 @@ namespace Upsilon.BaseTypes.ScriptFunction
// if we haven't found a method, we throw an exception
if (method == null)
{
var (i, pos) = diagnostics.ScriptString.GetLinePosition(span.Start);
var line = diagnostics.ScriptString.GetLine(i);
throw new ScriptRuntimeException(
$"Can't find method {_method.Name} with parameter types {string.Join(", ", convertedTypes.Select(x => x.Name))} on type {_object.GetType().Name}",
i, pos, line);
span, diagnostics.ScriptString.GetSpan(span));
}
// get the method parameters
var parameters = method.GetParameters();

View File

@ -51,11 +51,9 @@ namespace Upsilon.BaseTypes.UserData
}
else
{
var (i, pos) = diagnostics.ScriptString.GetLinePosition(span.Start);
var line = diagnostics.ScriptString.GetLine(i);
throw new ScriptRuntimeException(
$"Tried indexing a CSharp list with a value that's not an integer. Value: {scriptIndex.ToCSharpObject()}",
i, pos, line);
span, diagnostics.ScriptString.GetSpan(span));
}
index--;

View File

@ -17,18 +17,18 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundBinaryExpression;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int line, int character)
{
if (characterPosition >= LeftExpression.Span.Start && characterPosition <= LeftExpression.Span.End)
if (LeftExpression.Span.Contains(line, character))
{
foreach (var exp in LeftExpression.GetNodeAtPosition(characterPosition))
foreach (var exp in LeftExpression.GetNodeAtPosition(line, character))
{
yield return exp;
}
}
if (characterPosition >= RightExpression.Span.Start && characterPosition <= RightExpression.Span.End)
if (RightExpression.Span.Contains(line, character))
{
foreach (var exp in RightExpression.GetNodeAtPosition(characterPosition))
foreach (var exp in RightExpression.GetNodeAtPosition(line, character))
{
yield return exp;
}

View File

@ -19,20 +19,25 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundFunctionCallExpression;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int line, int character)
{
if (characterPosition >= Identifier.Span.Start && characterPosition <= Identifier.Span.End)
if (Identifier.Span.Contains(line, character))
{
foreach (var exp in Identifier.GetNodeAtPosition(characterPosition))
foreach (var exp in Identifier.GetNodeAtPosition(line, character))
{
yield return exp;
}
}
foreach (var parameter in Parameters)
{
if (characterPosition >= parameter.Span.Start && characterPosition <= parameter.Span.End)
if (parameter.Span.Contains(line, character))
{
foreach (var boundNode in parameter.GetNodeAtPosition(characterPosition)) yield return boundNode;
foreach (var exp in parameter.GetNodeAtPosition(line, character))
{
yield return exp;
}
}
}
yield return this;

View File

@ -20,17 +20,21 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundFunctionExpression;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
foreach (var parameter in Parameters)
{
if (characterPosition >= parameter.Span.Start && characterPosition <= parameter.Span.End)
foreach (var boundNode in parameter.GetNodeAtPosition(characterPosition))
if (parameter.Span.Contains(linePosition, characterPosition))
{
foreach (var boundNode in parameter.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
}
}
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
foreach (var boundNode in Block.GetNodeAtPosition(characterPosition))
if (Block.Span.Contains(linePosition, characterPosition))
{
foreach (var boundNode in Block.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
}
yield return this;
}

View File

@ -18,16 +18,18 @@ namespace Upsilon.Binder
public BoundExpression Index { get; }
public override BoundKind Kind => BoundKind.BoundIndexExpression;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
if (characterPosition >= Identifier.Span.Start && characterPosition <= Identifier.Span.End)
foreach (var boundNode in Identifier.GetNodeAtPosition(characterPosition))
if (Identifier.Span.Contains(linePosition, characterPosition))
{
foreach (var boundNode in Identifier.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
if (characterPosition >= Index.Span.Start && characterPosition <= Index.Span.End)
foreach (var boundNode in Index.GetNodeAtPosition(characterPosition))
}
if (Index.Span.Contains(linePosition, characterPosition))
{
foreach (var boundNode in Index.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
}
yield return this;
}
@ -47,12 +49,15 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundFullstopIndexExpression;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
if (characterPosition >= Expression.Span.Start && characterPosition <= Expression.Span.End)
foreach (var boundNode in Expression.GetNodeAtPosition(characterPosition))
if (Expression.Span.Contains(linePosition, characterPosition))
{
foreach (var boundNode in Expression.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
}
yield return this;
}

View File

@ -12,7 +12,7 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundLiteralExpression;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int line, int character)
{
yield return this;
}

View File

@ -17,16 +17,16 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundTableExpression;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
foreach (var statement in Statements)
{
if (characterPosition >= statement.Span.Start && characterPosition <= statement.Span.End)
foreach (var boundNode in statement.GetNodeAtPosition(characterPosition))
yield return boundNode;
if (statement.Span.Contains(linePosition, characterPosition))
{
yield return statement;
}
}
yield return this;
}
public override Type Type => Type.Table;

View File

@ -7,12 +7,13 @@ namespace Upsilon.Binder
public class BoundUnaryExpression : BoundExpression
{
public override BoundKind Kind => BoundKind.BoundUnaryExpression;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
if (characterPosition >= InExpression.Span.Start && characterPosition <= InExpression.Span.End)
foreach (var boundNode in InExpression.GetNodeAtPosition(characterPosition))
if (InExpression.Span.Contains(linePosition, characterPosition))
{
foreach (var boundNode in InExpression.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
}
yield return this;
}

View File

@ -14,7 +14,7 @@ namespace Upsilon.Binder
public BoundVariableSymbol Variable { get; }
public override BoundKind Kind => BoundKind.VariableExpression;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
yield return Variable;
}

View File

@ -13,6 +13,6 @@ namespace Upsilon.Binder
public abstract BoundKind Kind { get; }
public TextSpan Span { get; }
public abstract IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition);
public abstract IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition);
}
}

View File

@ -13,13 +13,17 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundBlockStatement;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
foreach (var statement in Statements)
{
if (characterPosition >= statement.Span.Start && characterPosition <= statement.Span.End)
foreach (var boundNode in statement.GetNodeAtPosition(characterPosition))
yield return boundNode;
if (statement.Span.Contains(linePosition, characterPosition))
{
foreach (var node in statement.GetNodeAtPosition(linePosition, characterPosition))
{
yield return node;
}
}
}
yield return this;
}

View File

@ -10,11 +10,9 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundBreakStatement;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
if (characterPosition >= Span.Start && characterPosition <= Span.End)
yield return this;
yield return null;
yield return this;
}
}
}

View File

@ -7,13 +7,11 @@ namespace Upsilon.Binder
{
public BoundExpression Expression { get; }
public override BoundKind Kind => BoundKind.BoundExpressionStatement;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
if (characterPosition >= Span.Start && characterPosition <= Span.End)
foreach (var boundNode in Expression.GetNodeAtPosition(characterPosition))
yield return boundNode;
foreach (var boundNode in Expression.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
yield return this;
}
public BoundExpressionStatement(BoundExpression expression, TextSpan span):base(span)

View File

@ -16,10 +16,10 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundFunctionAssignmentStatement;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
if (characterPosition >= Func.Span.Start && characterPosition <= Func.Span.End)
foreach (var boundNode in Func.GetNodeAtPosition(characterPosition))
if (Func.Span.Contains(linePosition, characterPosition))
foreach (var boundNode in Func.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
yield return this;

View File

@ -20,16 +20,18 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundGenericForStatement;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
if (characterPosition >= BoundEnumerableExpression.Span.Start && characterPosition <= BoundEnumerableExpression.Span.End)
foreach (var boundNode in BoundEnumerableExpression.GetNodeAtPosition(characterPosition))
if (BoundEnumerableExpression.Span.Contains(linePosition, characterPosition))
{
foreach (var boundNode in BoundEnumerableExpression.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
foreach (var boundNode in Block.GetNodeAtPosition(characterPosition))
}
if (Block.Span.Contains(linePosition, characterPosition))
{
foreach (var boundNode in Block.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
}
yield return this;
}
}

View File

@ -25,24 +25,28 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundIfStatement;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
if (characterPosition >= Condition.Span.Start && characterPosition <= Condition.Span.End)
foreach (var boundNode in Condition.GetNodeAtPosition(characterPosition))
if (Condition.Span.Contains(linePosition, characterPosition))
{
foreach (var boundNode in Condition.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
foreach (var boundNode in Block.GetNodeAtPosition(characterPosition))
}
if (Block.Span.Contains(linePosition, characterPosition))
{
foreach (var boundNode in Block.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
if (NextElseIf != null && characterPosition >= NextElseIf.Span.Start && characterPosition <= NextElseIf.Span.End)
foreach (var boundNode in NextElseIf.GetNodeAtPosition(characterPosition))
}
if (NextElseIf != null && NextElseIf.Span.Contains(linePosition, characterPosition))
{
foreach (var boundNode in NextElseIf.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
if (ElseStatement != null && characterPosition >= ElseStatement.Span.Start && characterPosition <= ElseStatement.Span.End)
foreach (var boundNode in ElseStatement.GetNodeAtPosition(characterPosition))
}
if (ElseStatement != null && ElseStatement.Span.Contains(linePosition, characterPosition))
{
foreach (var boundNode in ElseStatement.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
}
yield return this;
}
@ -62,12 +66,13 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundElseStatement;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
if (Block != null && characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
foreach (var boundNode in Block.GetNodeAtPosition(characterPosition))
if (Block.Span.Contains(linePosition, characterPosition))
{
foreach (var boundNode in Block.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
}
yield return this;
}
}

View File

@ -18,14 +18,13 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundMultiAssignmentStatement;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
if (characterPosition >= Assignment.Span.Start && characterPosition <= Assignment.Span.End)
foreach (var boundNode in Assignment.GetNodeAtPosition(characterPosition))
if (Assignment.Span.Contains(linePosition, characterPosition))
foreach (var boundNode in Assignment.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
yield return this;
}
}
}

View File

@ -23,26 +23,21 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundNumericForStatement;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
if (characterPosition >= BoundStart.Span.Start && characterPosition <= BoundStart.Span.End)
foreach (var boundNode in BoundStart.GetNodeAtPosition(characterPosition))
if (BoundStart.Span.Contains(linePosition, characterPosition))
foreach (var boundNode in BoundStart.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
if (characterPosition >= BoundStop.Span.Start && characterPosition <= BoundStop.Span.End)
foreach (var boundNode in BoundStop.GetNodeAtPosition(characterPosition))
if (BoundStop.Span.Contains(linePosition, characterPosition))
foreach (var boundNode in BoundStop.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
if (characterPosition >= BoundStep.Span.Start && characterPosition <= BoundStep.Span.End)
foreach (var boundNode in BoundStep.GetNodeAtPosition(characterPosition))
if (BoundStep.Span.Contains(linePosition, characterPosition))
foreach (var boundNode in BoundStep.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
foreach (var boundNode in Block.GetNodeAtPosition(characterPosition))
if (Block.Span.Contains(linePosition, characterPosition))
foreach (var boundNode in Block.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
yield return this;
}
}
}

View File

@ -12,12 +12,11 @@ namespace Upsilon.Binder
public BoundExpression Expression { get; }
public override BoundKind Kind => BoundKind.BoundReturnStatement;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
if (characterPosition >= Expression.Span.Start && characterPosition <= Expression.Span.End)
foreach (var boundNode in Expression.GetNodeAtPosition(characterPosition))
if (Expression.Span.Contains(linePosition, characterPosition))
foreach (var boundNode in Expression.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
yield return this;
}
}

View File

@ -7,7 +7,7 @@ namespace Upsilon.Binder
public class BoundScript : BoundStatement
{
public Script Script { get; }
public BoundScript(BoundBlockStatement statement, TextSpan span, BoundScope scope, string fileName, Script script) : base(span)
{
Statement = statement;
@ -18,9 +18,9 @@ namespace Upsilon.Binder
public string FileName { get; set; }
public override BoundKind Kind => BoundKind.BoundScript;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
foreach (var boundNode in Statement.GetNodeAtPosition(characterPosition)) yield return boundNode;
foreach (var boundNode in Statement.GetNodeAtPosition(linePosition, characterPosition)) yield return boundNode;
}
public BoundBlockStatement Statement { get; }

View File

@ -16,18 +16,15 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundTableAssigmentStatement;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
if (characterPosition >= TableIndexExpression.Span.Start && characterPosition <= TableIndexExpression.Span.End)
foreach (var boundNode in TableIndexExpression.GetNodeAtPosition(characterPosition))
if (TableIndexExpression.Span.Contains(linePosition, characterPosition))
foreach (var boundNode in TableIndexExpression.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
if (characterPosition >= Value.Span.Start && characterPosition <= Value.Span.End)
foreach (var boundNode in Value.GetNodeAtPosition(characterPosition))
if (Value.Span.Contains(linePosition, characterPosition))
foreach (var boundNode in Value.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
yield return this;
}
}
}

View File

@ -18,16 +18,15 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundAssignmentStatement;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
if (characterPosition >= Variable.Span.Start && characterPosition <= Variable.Span.End)
if (Variable.Span.Contains(linePosition, characterPosition))
yield return Variable;
if (characterPosition >= BoundExpression.Span.Start && characterPosition <= BoundExpression.Span.End)
foreach (var boundNode in BoundExpression.GetNodeAtPosition(characterPosition))
if (BoundExpression.Span.Contains(linePosition, characterPosition))
foreach (var boundNode in BoundExpression.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
yield return this;
}
}
}

View File

@ -17,16 +17,14 @@ namespace Upsilon.Binder
}
public override BoundKind Kind => BoundKind.BoundWhileStatement;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
if (characterPosition >= Condition.Span.Start && characterPosition <= Condition.Span.End)
foreach (var boundNode in Condition.GetNodeAtPosition(characterPosition))
if (Condition.Span.Contains(linePosition, characterPosition))
foreach (var boundNode in Condition.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
foreach (var boundNode in Block.GetNodeAtPosition(characterPosition))
if (Block.Span.Contains(linePosition, characterPosition))
foreach (var boundNode in Block.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
yield return this;
}
}

View File

@ -19,19 +19,19 @@ namespace Upsilon.Binder
public BlockStatementSyntax UnboundBlock { get; }
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int linePosition, int characterPosition)
{
foreach (var parameter in Parameters)
{
if (characterPosition >= parameter.Span.Start && characterPosition <= parameter.Span.End)
foreach (var boundNode in parameter.GetNodeAtPosition(characterPosition))
if (parameter.Span.Contains(linePosition, characterPosition))
foreach (var boundNode in parameter.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
}
if (Block != null)
{
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
foreach (var boundNode in Block.GetNodeAtPosition(characterPosition))
if (Block.Span.Contains(linePosition, characterPosition))
foreach (var boundNode in Block.GetNodeAtPosition(linePosition, characterPosition))
yield return boundNode;
}
yield return this;

View File

@ -17,7 +17,7 @@ namespace Upsilon.Binder
public bool IsCreation { get; }
public override BoundKind Kind => BoundKind.BoundVariableSymbol;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition, int i)
{
yield return this;
}

View File

@ -33,9 +33,8 @@ namespace Upsilon
{
if (ThrowsOnError)
{
var linePos = ScriptString.GetLinePosition(location.Start);
var line = ScriptString.GetLine(linePos.Line);
throw new ParseException(FileName, message, linePos.Line, linePos.Pos, line);
var text = ScriptString.GetSpan(location);
throw new ParseException(FileName, message, location.StartLine, location.StartPosition, text);
}
Log(DiagnosticLevel.Error, message, location);
}
@ -122,39 +121,24 @@ 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);
return $"{Message} at ({linePos.Line}, {linePos.Pos})\n{Diagnostics.ScriptString.GetSpan(Span)}";
return $"{Message} at ({Span.StartLine}, {Span.StartPosition})\n{Diagnostics.ScriptString.GetSpan(Span)}";
}
public string GetDiagnosticPosition()
{
var linePos = Diagnostics.ScriptString.GetLinePosition(Span.Start);
return $"({linePos.Line},{linePos.Pos})";
return $"({Span.StartLine},{Span.StartPosition})";
}
public string LineBeforeError()
{
var linePos = Diagnostics.ScriptString.GetLinePosition(Span.Start);
var lineIndex = Diagnostics.ScriptString.GetLineStartPos(linePos.Line);
return Diagnostics.ScriptString.GetSpan(lineIndex, linePos.Pos);
return Diagnostics.ScriptString.GetSpan(Span.StartLine, 0, Span.StartLine, Span.StartPosition);
}
public string BeforeError(int i = 5)
{
return Diagnostics.ScriptString.GetSpan(Span.Start - i, i);
return Diagnostics.ScriptString.GetSpan(Span.StartLine, Span.StartPosition - i, Span.StartLine, Span.StartPosition);
}
public string AtError()
@ -164,15 +148,12 @@ namespace Upsilon
public string LineAfterError()
{
var linePos = Diagnostics.ScriptString.GetLinePosition(Span.Start);
var lineInfo = Diagnostics.ScriptString.GetLineInfo(linePos.Line);
return Diagnostics.ScriptString.GetSpan(Span.End, lineInfo.End - Span.End);
return Diagnostics.ScriptString.GetSpan(Span.EndLine, Span.EndPosition, Span.EndLine, 10000);
}
public string AfterError(int i = 5)
{
return Diagnostics.ScriptString.GetSpan(Span.Start + Span.Length, i);
return Diagnostics.ScriptString.GetSpan(Span.EndLine, Span.EndPosition, Span.EndLine, Span.EndPosition + i);
}
}

View File

@ -10,5 +10,6 @@ namespace Upsilon.Evaluator.Debugging
public class Breakpoint
{
public int Line { get; set; }
public int Position { get; set; }
}
}

View File

@ -67,8 +67,7 @@ namespace Upsilon.Evaluator
{
foreach (var breakpoint in file.Breakpoints)
{
var lineStart = _script.ScriptString.GetLineInfo(breakpoint.Line).Start;
var debugStatement = e.GetBottomStatementAtPosition(lineStart);
var debugStatement = e.GetBottomStatementAtPosition(breakpoint.Line, breakpoint.Position);
debugStatement.HasBreakpoint = true;
}
}
@ -436,9 +435,7 @@ namespace Upsilon.Evaluator
private void ThrowException(string message, TextSpan location)
{
var (i, pos) = _script.ScriptString.GetLinePosition(location.Start);
var line = _script.ScriptString.GetLine(i);
throw new ScriptRuntimeException(message, i, pos, line);
throw new ScriptRuntimeException(message, location, _diagnostics.ScriptString.GetSpan(location));
}
private void EvaluateAssignmentStatement(BoundVariableAssignment e)

View File

@ -1,4 +1,5 @@
using System;
using Upsilon.Text;
namespace Upsilon.Exceptions
{
@ -9,11 +10,11 @@ namespace Upsilon.Exceptions
public int Character { get; }
public string ErrorLine { get; }
public ScriptRuntimeException(string errorMessage, int line, int character, string errorLine)
public ScriptRuntimeException(string errorMessage, TextSpan position, string errorLine)
{
ErrorMessage = errorMessage;
Line = line;
Character = character;
Line = position.StartLine;
Character = position.StartPosition;
ErrorLine = errorLine;
}

View File

@ -10,7 +10,7 @@ namespace Upsilon.Parser
Left = left;
Operator = @operator;
Right = right;
Span = new TextSpan(left.Span.Start, right.Span.End - left.Span.Start);
Span = TextSpan.Between(left.Span, right.Span);
}
public override SyntaxKind Kind => SyntaxKind.BinaryExpression;

View File

@ -18,7 +18,7 @@ namespace Upsilon.Parser
OpenParenthesis = openParenthesis;
Parameters = parameters;
CloseParenthesis = closeParenthesis;
Span = new TextSpan(Identifier.Span.Start, CloseParenthesis.Span.End - Identifier.Span.Start);
Span = TextSpan.Between(Identifier.Span, CloseParenthesis.Span);
}
public override SyntaxKind Kind => SyntaxKind.FunctionCallExpression;

View File

@ -23,7 +23,7 @@ namespace Upsilon.Parser
CloseParenthesis = closeParenthesis;
Block = block;
EndToken = endToken;
Span = new TextSpan(FunctionToken.Span.Start, EndToken.Span.End - FunctionToken.Span.Start);
Span = TextSpan.Between(FunctionToken.Span, endToken.Span);
}
public override SyntaxKind Kind => SyntaxKind.FunctionExpression;

View File

@ -17,7 +17,7 @@ namespace Upsilon.Parser
OpenBracket = openBracket;
Index = index;
CloseBracket = closeBracket;
Span = new TextSpan(expression.Span.Start, CloseBracket.Span.End - expression.Span.Start);
Span = TextSpan.Between(expression.Span, closeBracket.Span);
}
public override SyntaxKind Kind => SyntaxKind.IndexExpression;
@ -41,7 +41,7 @@ namespace Upsilon.Parser
Expression = expression;
FullStop = fullStop;
Index = index;
Span = new TextSpan(expression.Span.Start, Index.Span.End - expression.Span.Start);
Span = TextSpan.Between(expression.Span, Index.Span);
}
public override SyntaxKind Kind => SyntaxKind.FullStopIndexExpression;

View File

@ -10,7 +10,7 @@ namespace Upsilon.Parser
OpenParenthesis = openParenthesis;
Expression = expression;
CloseParenthesis = closeParenthesis;
Span = new TextSpan(OpenParenthesis.Span.Start, CloseParenthesis.Span.End - OpenParenthesis.Span.Start);
Span = TextSpan.Between(OpenParenthesis.Span, CloseParenthesis.Span);
}
public override SyntaxKind Kind => SyntaxKind.ParenthesizedExpression;

View File

@ -11,7 +11,7 @@ namespace Upsilon.Parser
Expressions = expressions;
OpenBrace = openBrace;
CloseBrace = closeBrace;
Span = new TextSpan(OpenBrace.Span.Start, CloseBrace.Span.End - OpenBrace.Span.Start);
Span = TextSpan.Between(OpenBrace.Span, CloseBrace.Span);
}
public override SyntaxKind Kind => SyntaxKind.TableExpression;

View File

@ -9,7 +9,7 @@ namespace Upsilon.Parser
{
Operator = @operator;
Expression = expression;
Span = new TextSpan(Operator.Span.Start, expression.Span.End - Operator.Span.Start);
Span = TextSpan.Between(Operator.Span, expression.Span);
}
public override SyntaxKind Kind => SyntaxKind.UnaryExpression;

View File

@ -1,10 +1,11 @@
using System.Collections.Generic;
using Upsilon.Text;
namespace Upsilon.Parser
{
public class IdentifierToken : SyntaxToken
{
public IdentifierToken(string name, int position)
public IdentifierToken(string name, TextSpan position)
: base(SyntaxKind.Identifier, position, name, null)
{
Name = name;

View File

@ -9,14 +9,15 @@ namespace Upsilon.Parser
public class Lexer
{
private bool SaveComments { get; }
private readonly string _text;
private readonly string[] _text;
private readonly Diagnostics _diagnostics;
private int _linePosition;
private int _position;
private Lexer(string text, Diagnostics diagnostics, bool saveComments)
{
SaveComments = saveComments;
_text = text;
_text = text.Split('\n');
_diagnostics = diagnostics;
}
@ -26,8 +27,29 @@ namespace Upsilon.Parser
return lexer.Lex();
}
private char Current => _position >= _text.Length ? '\0' : _text[_position];
private char Next => _position + 1 >= _text.Length ? '\0' : _text[_position + 1];
private char Current
{
get
{
var linePos = _linePosition;
var pos = _position;
if (linePos >= _text.Length) return '\0';
if (pos >= _text[linePos].Length) return '\n';
return _text[linePos][pos];
}
}
private char Next
{
get
{
var linePos = _linePosition;
var pos = _position + 1;
if (linePos >= _text.Length) return '\0';
if (pos >= _text[linePos].Length) return '\n';
return _text[linePos][pos];
}
}
private readonly List<string> _activeComments = new List<string>();
private ImmutableArray<SyntaxToken> Lex()
@ -66,46 +88,53 @@ namespace Upsilon.Parser
switch (Current)
{
case '\0':
return new SyntaxToken(SyntaxKind.EndOfFile, _position, "\0", null);
case ' ': case '\t': case '\r': case '\n':
return new SyntaxToken(SyntaxKind.WhiteSpace, _position, Current.ToString(), null);
return new SyntaxToken(SyntaxKind.EndOfFile, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "\0", null);
case ' ': case '\t': case '\r':
return new SyntaxToken(SyntaxKind.WhiteSpace, new TextSpan(_linePosition, _position, _linePosition, _position + 1), Current.ToString(), null);
case '\n':
{
_linePosition++;
var pos = _position;
_position = -1;
return new SyntaxToken(SyntaxKind.WhiteSpace, new TextSpan(_linePosition, pos, _linePosition, pos + 1), "\n", null);
}
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
return LexNumber();
case '+':
return new SyntaxToken(SyntaxKind.Plus, _position, "+", null);
return new SyntaxToken(SyntaxKind.Plus, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "+", null);
case '-':
if (Next == '-')
{
_position++;
return LexComments();
}
return new SyntaxToken(SyntaxKind.Minus, _position, "-", null);
return new SyntaxToken(SyntaxKind.Minus, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "-", null);
case '*':
return new SyntaxToken(SyntaxKind.Star, _position, "*", null);
return new SyntaxToken(SyntaxKind.Star, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "*", null);
case '/':
return new SyntaxToken(SyntaxKind.Slash, _position, "/", null);
return new SyntaxToken(SyntaxKind.Slash, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "/", null);
case '(':
return new SyntaxToken(SyntaxKind.OpenParenthesis, _position, "(", null);
return new SyntaxToken(SyntaxKind.OpenParenthesis, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "(", null);
case ')':
return new SyntaxToken(SyntaxKind.CloseParenthesis, _position, ")", null);
return new SyntaxToken(SyntaxKind.CloseParenthesis, new TextSpan(_linePosition, _position, _linePosition, _position + 1), ")", null);
case '{':
return new SyntaxToken(SyntaxKind.OpenBrace, _position, "{", null);
return new SyntaxToken(SyntaxKind.OpenBrace, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "{", null);
case '}':
return new SyntaxToken(SyntaxKind.CloseBrace, _position, "}", null);
return new SyntaxToken(SyntaxKind.CloseBrace, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "}", null);
case '[':
return new SyntaxToken(SyntaxKind.OpenBracket, _position, "[", null);
return new SyntaxToken(SyntaxKind.OpenBracket, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "[", null);
case ']':
return new SyntaxToken(SyntaxKind.CloseBracket, _position, "]", null);
return new SyntaxToken(SyntaxKind.CloseBracket, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "]", null);
case '.':
return new SyntaxToken(SyntaxKind.FullStop, _position, ".", null);
return new SyntaxToken(SyntaxKind.FullStop, new TextSpan(_linePosition, _position, _linePosition, _position + 1), ".", null);
case ',':
return new SyntaxToken(SyntaxKind.Comma, _position, ",", null);
return new SyntaxToken(SyntaxKind.Comma, new TextSpan(_linePosition, _position, _linePosition, _position + 1), ",", null);
case '#':
return new SyntaxToken(SyntaxKind.PoundSign, _position, "#", null);
return new SyntaxToken(SyntaxKind.PoundSign, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "#", null);
case '%':
return new SyntaxToken(SyntaxKind.PercentSign, _position, "%", null);
return new SyntaxToken(SyntaxKind.PercentSign, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "%", null);
case '^':
return new SyntaxToken(SyntaxKind.RoofSign, _position, "^", null);
return new SyntaxToken(SyntaxKind.RoofSign, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "^", null);
case '"':
case '\'':
return LexString(Current);
@ -113,35 +142,35 @@ namespace Upsilon.Parser
if (Next == '=')
{
_position++;
return new SyntaxToken(SyntaxKind.EqualsEquals, _position - 1, "==", null);
return new SyntaxToken(SyntaxKind.EqualsEquals, new TextSpan(_linePosition, _position - 1, _linePosition, _position + 1), "==", null);
}
return new SyntaxToken(SyntaxKind.Equals, _position, "=", null);
return new SyntaxToken(SyntaxKind.Equals, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "=", null);
case '~':
if (Next == '=')
{
_position++;
return new SyntaxToken(SyntaxKind.TildeEquals, _position - 1, "~=", null);
return new SyntaxToken(SyntaxKind.TildeEquals, new TextSpan(_linePosition, _position - 1, _linePosition, _position + 1), "~=", null);
}
return new SyntaxToken(SyntaxKind.Tilde, _position, "~", null);
return new SyntaxToken(SyntaxKind.Tilde, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "~", null);
case '<':
if (Next == '=')
{
_position++;
return new SyntaxToken(SyntaxKind.LessEquals, _position - 1, "<=", null);
return new SyntaxToken(SyntaxKind.LessEquals, new TextSpan(_linePosition, _position - 1, _linePosition, _position + 1), "<=", null);
}
return new SyntaxToken(SyntaxKind.Less, _position, "<", null);
return new SyntaxToken(SyntaxKind.Less, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "<", null);
case '>':
if (Next == '=')
{
_position++;
return new SyntaxToken(SyntaxKind.GreaterEquals, _position - 1, ">=", null);
return new SyntaxToken(SyntaxKind.GreaterEquals, new TextSpan(_linePosition, _position - 1, _linePosition, _position + 1), ">=", null);
}
return new SyntaxToken(SyntaxKind.Greater, _position, ">", null);
return new SyntaxToken(SyntaxKind.Greater, new TextSpan(_linePosition, _position, _linePosition, _position + 1), ">", null);
default:
if (char.IsLetter(Current) || Current == '_')
return LexIdentifierOrKeyword();
_diagnostics.LogBadCharacter(new TextSpan(_position, 1), SyntaxKind.Identifier);
return new SyntaxToken(SyntaxKind.BadToken, _position, "", null);
_diagnostics.LogBadCharacter(new TextSpan(_linePosition, _position, _linePosition, _position + 1), SyntaxKind.Identifier);
return new SyntaxToken(SyntaxKind.BadToken, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "", null);
}
}
@ -157,8 +186,8 @@ namespace Upsilon.Parser
{
if (hasDecimalPoint)
{
_diagnostics.LogBadCharacter(new TextSpan(_position, 1), SyntaxKind.Number);
return new SyntaxToken(SyntaxKind.BadToken, _position, "", null);
_diagnostics.LogBadCharacter(new TextSpan(_linePosition, _position, _linePosition, _position + 1), SyntaxKind.Number);
return new SyntaxToken(SyntaxKind.BadToken, new TextSpan(_linePosition, _position, _linePosition, _position + 1), "", null);
}
hasDecimalPoint = true;
}
@ -172,16 +201,18 @@ namespace Upsilon.Parser
o = double.Parse(numStr.ToString());
else
o = long.Parse(numStr.ToString());
return new SyntaxToken(SyntaxKind.Number, start, numStr.ToString(), o);
return new SyntaxToken(SyntaxKind.Number, new TextSpan(_linePosition, start, _linePosition, _position + 1), numStr.ToString(), o);
}
private SyntaxToken LexString(char current)
{
var start = _position;
var sb = new StringBuilder();
while (_position < _text.Length)
while (true)
{
_position++;
if (Current == '\0')
break;
if (Current == '\\' && Next == current)
{
sb.Append(current);
@ -194,15 +225,18 @@ namespace Upsilon.Parser
if (Current != current)
{
_diagnostics.LogBadCharacter(new TextSpan(_position, 1), current, Current);
_diagnostics.LogBadCharacter(new TextSpan(_linePosition, _position, _linePosition, _position + 1),
current, Current);
}
var res = sb.ToString();
return new SyntaxToken(SyntaxKind.String, start, $"\"{res}\"", res);
return new SyntaxToken(SyntaxKind.String, new TextSpan(_linePosition, start, _linePosition, _position + 1),
$"\"{res}\"", res);
}
private SyntaxToken LexIdentifierOrKeyword()
{
var startLine = _linePosition;
var start = _position;
var stringBuilder = new StringBuilder();
stringBuilder.Append(Current);
@ -216,19 +250,20 @@ namespace Upsilon.Parser
var str = stringBuilder.ToString();
if (kind == SyntaxKind.Identifier)
{
return new IdentifierToken(str, start);
return new IdentifierToken(str, new TextSpan(startLine, start, _linePosition, _position));
}
if (kind == SyntaxKind.ReturnKeyword)
{
return new ReturnSyntaxToken(start, Next == Environment.NewLine[0]);
return new ReturnSyntaxToken(new TextSpan(_linePosition, start, _linePosition, _position + 1), Next == Environment.NewLine[0]);
}
return new SyntaxToken(kind, start, str, null);
return new SyntaxToken(kind, new TextSpan(_linePosition, start, _linePosition, _position + 1), str, null);
}
private SyntaxToken LexComments()
{
_position++;
var startLine = _linePosition;
var start = _position;
StringBuilder stringBuilder = null;
if (SaveComments)
@ -244,7 +279,7 @@ namespace Upsilon.Parser
}
var str = stringBuilder?.ToString();
_position++;
return new SyntaxToken(SyntaxKind.Comment, start, _position - start, str);
return new SyntaxToken(SyntaxKind.Comment, new TextSpan(startLine, start, _linePosition, _position + 1), _position - start, str);
}
}
}

View File

@ -9,9 +9,9 @@ namespace Upsilon.Parser
{
TypeName = typeName;
IdentifierName = identifierName;
var start = identifierName.Span.Start;
if (typeName != null) start = typeName.Span.Start;
Span = new TextSpan(start, identifierName.Span.End - start);
var start = identifierName.Span;
if (typeName != null) start = typeName.Span;
Span = TextSpan.Between(start, identifierName.Span);
}
public IdentifierToken TypeName { get; }

View File

@ -29,7 +29,7 @@ namespace Upsilon.Parser
private SyntaxToken Get(int offset)
{
if (_position + offset >= _tokens.Length)
return new SyntaxToken(SyntaxKind.EndOfFile, _position + offset, "\0", null);
return new SyntaxToken