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