Support for getting a bound scope at a specific character position

This commit is contained in:
Deukhoofd 2018-11-27 19:04:58 +01:00
parent 8ece53db5b
commit 14e30d0855
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
9 changed files with 51 additions and 18 deletions

View File

@ -395,12 +395,13 @@ namespace Upsilon.Binder
Scope = innerScope;
var block = BindBlockStatement(e.Block);
Scope = Scope.ParentScope;
var func = new BoundFunctionExpression(parameters.ToImmutable(), (BoundBlockStatement) block, e.Span);
var func = new BoundFunctionExpression(parameters.ToImmutable(), (BoundBlockStatement) block, e.Span,
innerScope);
return func;
}
else
{
var unbound = new UnboundFunctionExpression(parameters.ToImmutable(), e.Block, e.Span);
var unbound = new UnboundFunctionExpression(parameters.ToImmutable(), e.Block, e.Span, innerScope);
if (variableSymbol == null)
{
_unboundFunctions.Add( Guid.NewGuid().ToString(), unbound);
@ -496,8 +497,9 @@ namespace Upsilon.Binder
}
innerVariables = innerVariables.Union(Scope.Variables).ToDictionary(k => k.Key, v => v.Value);
var innerSCope = Scope;
Scope = s;
return new BoundTableExpression(innerVariables, statements.ToImmutable(), e.Span);
return new BoundTableExpression(innerVariables, statements.ToImmutable(), e.Span, innerSCope);
}
private BoundExpression BindIndexExpression(IndexExpressionSyntax e, bool isAssignment = false)

View File

@ -5,15 +5,17 @@ using Upsilon.Text;
namespace Upsilon.Binder
{
public class BoundFunctionExpression : BoundExpression
public class BoundFunctionExpression : BoundExpression, IBoundNodeScopeOwner
{
public ImmutableArray<BoundVariableSymbol> Parameters { get; }
public BoundBlockStatement Block { get; set; }
public BoundFunctionExpression(ImmutableArray<BoundVariableSymbol> parameters, BoundBlockStatement block, TextSpan span) : base(span)
public BoundFunctionExpression(ImmutableArray<BoundVariableSymbol> parameters, BoundBlockStatement block, TextSpan span,
BoundScope scope) : base(span)
{
Parameters = parameters;
Block = block;
Scope = scope;
}
public override BoundKind Kind => BoundKind.BoundFunctionExpression;
@ -32,5 +34,6 @@ namespace Upsilon.Binder
}
public override Type Type => Type.Function;
public BoundScope Scope { get; set; }
}
}

View File

@ -5,13 +5,14 @@ using Upsilon.Text;
namespace Upsilon.Binder
{
public class BoundTableExpression : BoundExpression
public class BoundTableExpression : BoundExpression, IBoundNodeScopeOwner
{
public BoundTableExpression(Dictionary<string, VariableSymbol> expressions,
ImmutableArray<BoundStatement> statements, TextSpan span) : base(span)
ImmutableArray<BoundStatement> statements, TextSpan span, BoundScope scope) : base(span)
{
Expressions = expressions;
Statements = statements;
Scope = scope;
}
public override BoundKind Kind => BoundKind.BoundTableExpression;
@ -32,5 +33,6 @@ namespace Upsilon.Binder
public Dictionary<string, VariableSymbol> Expressions { get; }
public ImmutableArray<BoundStatement> Statements { get; }
public BoundScope Scope { get; set; }
}
}

View File

@ -6,7 +6,7 @@ namespace Upsilon.Binder
public class BoundScope : IDisposable
{
public readonly BoundScope ParentScope;
private BoundScope _readOnlyScope;
public BoundScope ReadOnlyScope { get; private set; }
public readonly Dictionary<string, VariableSymbol> Variables;
public BoundScope(BoundScope parentScope)
@ -22,13 +22,13 @@ namespace Upsilon.Binder
public static BoundScope WithReadOnlyScope(BoundScope readOnlyScope)
{
var scope = new BoundScope(null) {_readOnlyScope = readOnlyScope};
var scope = new BoundScope(null) {ReadOnlyScope = readOnlyScope};
return scope;
}
public void Dispose()
{
Variables.Clear();
//Variables.Clear();
}
public void DefineLocalVariable(VariableSymbol var)
@ -62,9 +62,9 @@ namespace Upsilon.Binder
{
return ParentScope.TryGetVariable(key, true, out result);
}
if (_readOnlyScope != null && allowUpperScopes)
if (ReadOnlyScope != null && allowUpperScopes)
{
return _readOnlyScope.TryGetVariable(key, true, out result);
return ReadOnlyScope.TryGetVariable(key, true, out result);
}
return false;
}

View File

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

View File

@ -13,7 +13,7 @@ namespace Upsilon.Binder
foreach (var boundNode in Expression.GetNodeAtPosition(characterPosition))
yield return boundNode;
yield return null;
yield return this;
}
public BoundExpressionStatement(BoundExpression expression, TextSpan span):base(span)

View File

@ -8,7 +8,7 @@ namespace Upsilon.Binder
public class UnboundFunctionExpression : BoundFunctionExpression
{
public UnboundFunctionExpression(ImmutableArray<BoundVariableSymbol> parameters,
BlockStatementSyntax unboundBlock, TextSpan span) : base(parameters, null, span)
BlockStatementSyntax unboundBlock, TextSpan span, BoundScope scope) : base(parameters, null, span, scope)
{
UnboundBlock = unboundBlock;
}

View File

@ -0,0 +1,7 @@
namespace Upsilon.Binder
{
public interface IBoundNodeScopeOwner
{
BoundScope Scope { get; set; }
}
}

View File

@ -1,3 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using Upsilon.Binder;
@ -7,17 +8,35 @@ namespace Upsilon.Utilities
{
public static BoundScope GetScopeAt(this BoundScript script, int characterPosition)
{
var scope = script.Scope;
foreach (var node in script.GetNodeAtPosition(characterPosition))
{
if (node is IBoundNodeScopeOwner scopeOwner && scopeOwner.Scope != null)
{
return scopeOwner.Scope;
}
}
return scope;
return script.Scope;
}
public static BoundNode GetBottomNodeAtPosition(this BoundNode node, int characterPosition)
{
return node.GetNodeAtPosition(characterPosition).First();
}
public static Dictionary<string, VariableSymbol> GetBoundScopeVisibleVariables(this BoundScope scope)
{
IEnumerable<KeyValuePair<string, VariableSymbol>> dictionary = scope.Variables;
if (scope.ParentScope != null)
{
dictionary= dictionary.Union(scope.ParentScope.GetBoundScopeVisibleVariables());
}
if (scope.ReadOnlyScope != null)
{
dictionary = dictionary.Union(scope.ReadOnlyScope.GetBoundScopeVisibleVariables());
}
return dictionary.ToDictionary(k => k.Key, v => v.Value);
}
}
}