Fix Binder not allowing setting variables due to parent scope

This commit is contained in:
Deukhoofd 2018-11-19 14:45:20 +01:00
parent c4962ac24c
commit f4ae57c550
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
3 changed files with 39 additions and 12 deletions

View File

@ -398,7 +398,8 @@ namespace Upsilon.Binder
var valueType = Type.Unknown; var valueType = Type.Unknown;
var dictionary = new Dictionary<string, bool>(); var dictionary = new Dictionary<string, bool>();
var statements = ImmutableArray.CreateBuilder<BoundStatement>(); var statements = ImmutableArray.CreateBuilder<BoundStatement>();
Scope = new BoundScope(Scope); var s = Scope;
Scope = BoundScope.WithReadOnlyScope(s);
foreach (var expressionSyntax in e.Expressions) foreach (var expressionSyntax in e.Expressions)
{ {
var bound = BindStatement((StatementSyntax) expressionSyntax); var bound = BindStatement((StatementSyntax) expressionSyntax);
@ -409,7 +410,7 @@ namespace Upsilon.Binder
{ {
dictionary.Add(variable.Key, true); dictionary.Add(variable.Key, true);
} }
Scope = Scope.ParentScope; Scope = s;
return new BoundTableExpression(keyType, valueType, dictionary, statements); return new BoundTableExpression(keyType, valueType, dictionary, statements);
} }

View File

@ -1,33 +1,51 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Upsilon.BaseTypes;
namespace Upsilon.Binder namespace Upsilon.Binder
{ {
internal class BoundScope internal class BoundScope
{ {
public readonly BoundScope ParentScope; public readonly BoundScope ParentScope;
private BoundScope _readOnlyScope;
internal readonly Dictionary<string, VariableSymbol> Variables; internal readonly Dictionary<string, VariableSymbol> Variables;
internal readonly Dictionary<string, VariableSymbol> LocalVariables;
public BoundScope(BoundScope parentScope) public BoundScope(BoundScope parentScope)
{ {
ParentScope = parentScope; ParentScope = parentScope;
Variables = new Dictionary<string, VariableSymbol>(); Variables = new Dictionary<string, VariableSymbol>();
LocalVariables = new Dictionary<string, VariableSymbol>();
} }
public BoundScope(Dictionary<string, VariableSymbol> variables, BoundScope parentScope) public BoundScope(Dictionary<string, VariableSymbol> variables, BoundScope parentScope)
{ {
ParentScope = parentScope; ParentScope = parentScope;
Variables = variables; Variables = variables;
LocalVariables = new Dictionary<string, VariableSymbol>();
}
public static BoundScope WithReadOnlyScope(BoundScope readOnlyScope)
{
var scope = new BoundScope(null) {_readOnlyScope = readOnlyScope};
return scope;
} }
public void SetVariable(VariableSymbol var) public void SetVariable(VariableSymbol var)
{
if (var.Local)
{
if (LocalVariables.ContainsKey(var.Name))
LocalVariables[var.Name] = var;
else
LocalVariables.Add(var.Name, var);
}
else
{ {
if (Variables.ContainsKey(var.Name)) if (Variables.ContainsKey(var.Name))
Variables[var.Name] = var; Variables[var.Name] = var;
else else
Variables.Add(var.Name, var); Variables.Add(var.Name, var);
} }
}
public void SetGlobalVariable(VariableSymbol var) public void SetGlobalVariable(VariableSymbol var)
{ {
@ -44,6 +62,10 @@ namespace Upsilon.Binder
public bool TryGetVariable(string key, bool allowUpperScopes, out VariableSymbol result) public bool TryGetVariable(string key, bool allowUpperScopes, out VariableSymbol result)
{ {
if (LocalVariables.TryGetValue(key, out result))
{
return true;
}
if (Variables.TryGetValue(key, out result)) if (Variables.TryGetValue(key, out result))
{ {
return true; return true;
@ -52,6 +74,10 @@ namespace Upsilon.Binder
{ {
return ParentScope.TryGetVariable(key, true, out result); return ParentScope.TryGetVariable(key, true, out result);
} }
if (_readOnlyScope != null && allowUpperScopes)
{
return _readOnlyScope.TryGetVariable(key, true, out result);
}
return false; return false;
} }

View File

@ -71,10 +71,10 @@ namespace Upsilon.Evaluator
public bool TryGet(VariableSymbol symbol, out LuaType obj) public bool TryGet(VariableSymbol symbol, out LuaType obj)
{ {
if (Variables.TryGetValue(symbol.Name, out obj))
return true;
if (LocalVariables.TryGetValue(symbol.Name, out obj)) if (LocalVariables.TryGetValue(symbol.Name, out obj))
return true; return true;
if (Variables.TryGetValue(symbol.Name, out obj))
return true;
if (_parentScope != null) if (_parentScope != null)
if (_parentScope.TryGet(symbol, out obj)) if (_parentScope.TryGet(symbol, out obj))
return true; return true;
@ -86,10 +86,10 @@ namespace Upsilon.Evaluator
public bool TryGet(string variable, out LuaType obj) public bool TryGet(string variable, out LuaType obj)
{ {
if (Variables.TryGetValue(variable, out obj))
return true;
if (LocalVariables.TryGetValue(variable, out obj)) if (LocalVariables.TryGetValue(variable, out obj))
return true; return true;
if (Variables.TryGetValue(variable, out obj))
return true;
if (_parentScope != null) if (_parentScope != null)
if (_parentScope.TryGet(variable, out obj)) if (_parentScope.TryGet(variable, out obj))
return true; return true;