From 14e30d0855f24fcd52cdb209465494e8eb29293f Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Tue, 27 Nov 2018 19:04:58 +0100 Subject: [PATCH] Support for getting a bound scope at a specific character position --- Upsilon/Binder/Binder.cs | 8 +++--- .../BoundFunctionExpression.cs | 7 ++++-- .../BoundExpressions/BoundTableExpression.cs | 6 +++-- Upsilon/Binder/BoundScope.cs | 10 ++++---- .../BoundStatements/BoundBlockStatement.cs | 2 +- .../BoundExpressionStatement.cs | 2 +- .../UnboundFunctionExpression.cs | 2 +- Upsilon/Binder/IBoundNodeScopeOwner.cs | 7 ++++++ Upsilon/Utilities/SearchHelper.cs | 25 ++++++++++++++++--- 9 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 Upsilon/Binder/IBoundNodeScopeOwner.cs diff --git a/Upsilon/Binder/Binder.cs b/Upsilon/Binder/Binder.cs index 7af1f08..ea3cb3e 100644 --- a/Upsilon/Binder/Binder.cs +++ b/Upsilon/Binder/Binder.cs @@ -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) diff --git a/Upsilon/Binder/BoundExpressions/BoundFunctionExpression.cs b/Upsilon/Binder/BoundExpressions/BoundFunctionExpression.cs index 4f2c1d7..49819ec 100644 --- a/Upsilon/Binder/BoundExpressions/BoundFunctionExpression.cs +++ b/Upsilon/Binder/BoundExpressions/BoundFunctionExpression.cs @@ -5,15 +5,17 @@ using Upsilon.Text; namespace Upsilon.Binder { - public class BoundFunctionExpression : BoundExpression + public class BoundFunctionExpression : BoundExpression, IBoundNodeScopeOwner { public ImmutableArray Parameters { get; } public BoundBlockStatement Block { get; set; } - public BoundFunctionExpression(ImmutableArray parameters, BoundBlockStatement block, TextSpan span) : base(span) + public BoundFunctionExpression(ImmutableArray 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; } } } \ No newline at end of file diff --git a/Upsilon/Binder/BoundExpressions/BoundTableExpression.cs b/Upsilon/Binder/BoundExpressions/BoundTableExpression.cs index 3f94a2c..3e15137 100644 --- a/Upsilon/Binder/BoundExpressions/BoundTableExpression.cs +++ b/Upsilon/Binder/BoundExpressions/BoundTableExpression.cs @@ -5,13 +5,14 @@ using Upsilon.Text; namespace Upsilon.Binder { - public class BoundTableExpression : BoundExpression + public class BoundTableExpression : BoundExpression, IBoundNodeScopeOwner { public BoundTableExpression(Dictionary expressions, - ImmutableArray statements, TextSpan span) : base(span) + ImmutableArray 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 Expressions { get; } public ImmutableArray Statements { get; } + public BoundScope Scope { get; set; } } } \ No newline at end of file diff --git a/Upsilon/Binder/BoundScope.cs b/Upsilon/Binder/BoundScope.cs index 411c81f..dce4b43 100644 --- a/Upsilon/Binder/BoundScope.cs +++ b/Upsilon/Binder/BoundScope.cs @@ -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 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; } diff --git a/Upsilon/Binder/BoundStatements/BoundBlockStatement.cs b/Upsilon/Binder/BoundStatements/BoundBlockStatement.cs index eddfaf7..8d54dfc 100644 --- a/Upsilon/Binder/BoundStatements/BoundBlockStatement.cs +++ b/Upsilon/Binder/BoundStatements/BoundBlockStatement.cs @@ -15,13 +15,13 @@ namespace Upsilon.Binder public override BoundKind Kind => BoundKind.BoundBlockStatement; public override IEnumerable 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 Statements { get; } diff --git a/Upsilon/Binder/BoundStatements/BoundExpressionStatement.cs b/Upsilon/Binder/BoundStatements/BoundExpressionStatement.cs index 569cb15..a0dec05 100644 --- a/Upsilon/Binder/BoundStatements/BoundExpressionStatement.cs +++ b/Upsilon/Binder/BoundStatements/BoundExpressionStatement.cs @@ -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) diff --git a/Upsilon/Binder/BoundStatements/UnboundFunctionExpression.cs b/Upsilon/Binder/BoundStatements/UnboundFunctionExpression.cs index 66ae2a8..e563951 100644 --- a/Upsilon/Binder/BoundStatements/UnboundFunctionExpression.cs +++ b/Upsilon/Binder/BoundStatements/UnboundFunctionExpression.cs @@ -8,7 +8,7 @@ namespace Upsilon.Binder public class UnboundFunctionExpression : BoundFunctionExpression { public UnboundFunctionExpression(ImmutableArray parameters, - BlockStatementSyntax unboundBlock, TextSpan span) : base(parameters, null, span) + BlockStatementSyntax unboundBlock, TextSpan span, BoundScope scope) : base(parameters, null, span, scope) { UnboundBlock = unboundBlock; } diff --git a/Upsilon/Binder/IBoundNodeScopeOwner.cs b/Upsilon/Binder/IBoundNodeScopeOwner.cs new file mode 100644 index 0000000..8ea854a --- /dev/null +++ b/Upsilon/Binder/IBoundNodeScopeOwner.cs @@ -0,0 +1,7 @@ +namespace Upsilon.Binder +{ + public interface IBoundNodeScopeOwner + { + BoundScope Scope { get; set; } + } +} \ No newline at end of file diff --git a/Upsilon/Utilities/SearchHelper.cs b/Upsilon/Utilities/SearchHelper.cs index 49f9e56..3243118 100644 --- a/Upsilon/Utilities/SearchHelper.cs +++ b/Upsilon/Utilities/SearchHelper.cs @@ -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 GetBoundScopeVisibleVariables(this BoundScope scope) + { + IEnumerable> 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); + } } } \ No newline at end of file