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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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)
{ {
} }
} }
}

View File

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

View File

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

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; 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);

View File

@ -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))

View File

@ -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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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]