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; 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, e.Span); var func = new BoundFunctionExpression(parameters.ToImmutable(), (BoundBlockStatement) block, e.Span,
innerScope);
return func; return func;
} }
else 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) if (variableSymbol == null)
{ {
_unboundFunctions.Add( Guid.NewGuid().ToString(), unbound); _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); innerVariables = innerVariables.Union(Scope.Variables).ToDictionary(k => k.Key, v => v.Value);
var innerSCope = Scope;
Scope = s; 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) private BoundExpression BindIndexExpression(IndexExpressionSyntax e, bool isAssignment = false)

View File

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

View File

@ -5,13 +5,14 @@ using Upsilon.Text;
namespace Upsilon.Binder namespace Upsilon.Binder
{ {
public class BoundTableExpression : BoundExpression public class BoundTableExpression : BoundExpression, IBoundNodeScopeOwner
{ {
public BoundTableExpression(Dictionary<string, VariableSymbol> expressions, public BoundTableExpression(Dictionary<string, VariableSymbol> expressions,
ImmutableArray<BoundStatement> statements, TextSpan span) : base(span) ImmutableArray<BoundStatement> statements, TextSpan span, BoundScope scope) : base(span)
{ {
Expressions = expressions; Expressions = expressions;
Statements = statements; Statements = statements;
Scope = scope;
} }
public override BoundKind Kind => BoundKind.BoundTableExpression; public override BoundKind Kind => BoundKind.BoundTableExpression;
@ -32,5 +33,6 @@ namespace Upsilon.Binder
public Dictionary<string, VariableSymbol> Expressions { get; } public Dictionary<string, VariableSymbol> Expressions { get; }
public ImmutableArray<BoundStatement> Statements { 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 class BoundScope : IDisposable
{ {
public readonly BoundScope ParentScope; public readonly BoundScope ParentScope;
private BoundScope _readOnlyScope; public BoundScope ReadOnlyScope { get; private set; }
public readonly Dictionary<string, VariableSymbol> Variables; public readonly Dictionary<string, VariableSymbol> Variables;
public BoundScope(BoundScope parentScope) public BoundScope(BoundScope parentScope)
@ -22,13 +22,13 @@ namespace Upsilon.Binder
public static BoundScope WithReadOnlyScope(BoundScope readOnlyScope) public static BoundScope WithReadOnlyScope(BoundScope readOnlyScope)
{ {
var scope = new BoundScope(null) {_readOnlyScope = readOnlyScope}; var scope = new BoundScope(null) {ReadOnlyScope = readOnlyScope};
return scope; return scope;
} }
public void Dispose() public void Dispose()
{ {
Variables.Clear(); //Variables.Clear();
} }
public void DefineLocalVariable(VariableSymbol var) public void DefineLocalVariable(VariableSymbol var)
@ -62,9 +62,9 @@ namespace Upsilon.Binder
{ {
return ParentScope.TryGetVariable(key, true, out result); 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; return false;
} }

View File

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

View File

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

View File

@ -8,7 +8,7 @@ namespace Upsilon.Binder
public class UnboundFunctionExpression : BoundFunctionExpression public class UnboundFunctionExpression : BoundFunctionExpression
{ {
public UnboundFunctionExpression(ImmutableArray<BoundVariableSymbol> parameters, 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; 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 System.Linq;
using Upsilon.Binder; using Upsilon.Binder;
@ -7,17 +8,35 @@ namespace Upsilon.Utilities
{ {
public static BoundScope GetScopeAt(this BoundScript script, int characterPosition) public static BoundScope GetScopeAt(this BoundScript script, int characterPosition)
{ {
var scope = script.Scope;
foreach (var node in script.GetNodeAtPosition(characterPosition)) 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) public static BoundNode GetBottomNodeAtPosition(this BoundNode node, int characterPosition)
{ {
return node.GetNodeAtPosition(characterPosition).First(); 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);
}
} }
} }