More fixes for scope
This commit is contained in:
parent
1f57eed3e7
commit
b3b26964cc
|
@ -8,31 +8,24 @@ namespace Upsilon.BaseTypes
|
|||
{
|
||||
internal class LuaTable : LuaType, IIndexable, IScopeOwner
|
||||
{
|
||||
private readonly Dictionary<string, VariableSymbol> _variableLookup;
|
||||
public EvaluationScope EvaluationScope { get; }
|
||||
|
||||
public LuaTable(EvaluationScope scope)
|
||||
{
|
||||
EvaluationScope = scope;
|
||||
_variableLookup = scope.Variables.ToDictionary(x => x.Key.Name, x => x.Key);
|
||||
}
|
||||
|
||||
|
||||
public override Type Type => Type.Table;
|
||||
public override object ToCSharpObject()
|
||||
{
|
||||
return EvaluationScope.Variables.Where(x => !x.Key.Local)
|
||||
.ToDictionary(x => x.Key.Name, x => x.Value.ToCSharpObject());
|
||||
return EvaluationScope.Variables.ToDictionary(x => x.Key, x => x.Value.ToCSharpObject());
|
||||
}
|
||||
|
||||
|
||||
public LuaType Get(string s, EvaluationScope scope)
|
||||
{
|
||||
if (!_variableLookup.TryGetValue(s, out var variableSymbol))
|
||||
return new LuaNull();
|
||||
if (variableSymbol.Local && scope != EvaluationScope)
|
||||
return new LuaNull();
|
||||
if (EvaluationScope.TryGet(variableSymbol, out var o))
|
||||
if (EvaluationScope.TryGet(s, out var o))
|
||||
{
|
||||
return o;
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ namespace Upsilon.Binder
|
|||
private readonly Diagnostics _diagnostics;
|
||||
public BoundScope Scope { get; private set; }
|
||||
|
||||
private Dictionary<FunctionVariableSymbol, UnboundFunctionExpression> _unboundFunctions =
|
||||
new Dictionary<FunctionVariableSymbol, UnboundFunctionExpression>();
|
||||
private Dictionary<string, UnboundFunctionExpression> _unboundFunctions =
|
||||
new Dictionary<string, UnboundFunctionExpression>();
|
||||
|
||||
public Binder(Diagnostics diagnostics, Dictionary<string, VariableSymbol> variables)
|
||||
{
|
||||
|
@ -35,9 +35,8 @@ namespace Upsilon.Binder
|
|||
unboundFunctionStatement.Value.Block =
|
||||
(BoundBlockStatement) BindBlockStatement(unboundFunctionStatement.Value.UnboundBlock);
|
||||
Scope = Scope.ParentScope;
|
||||
unboundFunctionStatement.Key.IsBound = true;
|
||||
}
|
||||
_unboundFunctions = new Dictionary<FunctionVariableSymbol, UnboundFunctionExpression>();
|
||||
_unboundFunctions = new Dictionary<string, UnboundFunctionExpression>();
|
||||
return new BoundScript((BoundBlockStatement) bound);
|
||||
}
|
||||
|
||||
|
@ -185,12 +184,12 @@ namespace Upsilon.Binder
|
|||
Scope.SetVariable(functionVariable);
|
||||
}
|
||||
|
||||
var unboundFunctionStatement = _unboundFunctions[function];
|
||||
var unboundFunctionStatement = _unboundFunctions[function.Name];
|
||||
unboundFunctionStatement.Block =
|
||||
(BoundBlockStatement) BindBlockStatement(unboundFunctionStatement.UnboundBlock);
|
||||
Scope = Scope.ParentScope;
|
||||
function.IsBound = true;
|
||||
_unboundFunctions.Remove(function);
|
||||
_unboundFunctions.Remove(function.Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,7 +306,7 @@ namespace Upsilon.Binder
|
|||
}
|
||||
}
|
||||
|
||||
private BoundExpression BindFunctionExpression(FunctionExpressionSyntax e)
|
||||
private BoundExpression BindFunctionExpression(FunctionExpressionSyntax e, string variableSymbol = null)
|
||||
{
|
||||
var innerScope = new BoundScope(Scope);
|
||||
var parameters = ImmutableArray.CreateBuilder<VariableSymbol>();
|
||||
|
@ -329,21 +328,27 @@ namespace Upsilon.Binder
|
|||
else
|
||||
{
|
||||
var unbound = new UnboundFunctionExpression(parameters.ToImmutable(), e.Block);
|
||||
_unboundFunctions.Add(
|
||||
new FunctionVariableSymbol(Guid.NewGuid().ToString(), Type.Unknown, true, parameters.ToImmutable()),
|
||||
unbound);
|
||||
if (variableSymbol == null)
|
||||
{
|
||||
_unboundFunctions.Add( Guid.NewGuid().ToString(), unbound);
|
||||
}
|
||||
else
|
||||
{
|
||||
_unboundFunctions.Add(variableSymbol, unbound);
|
||||
}
|
||||
return unbound;
|
||||
}
|
||||
}
|
||||
|
||||
private BoundStatement BindFunctionAssignmentStatement(FunctionAssignmentStatementSyntax e)
|
||||
{
|
||||
var func = (BoundFunctionExpression)BindFunctionExpression(e.FunctionExpression);
|
||||
var name = e.Identifier.Name;
|
||||
var isLocal = e.LocalToken != null;
|
||||
|
||||
var innerScope = new BoundScope(Scope);
|
||||
|
||||
var func = (BoundFunctionExpression)BindFunctionExpression(e.FunctionExpression, name);
|
||||
var parameters = ImmutableArray.CreateBuilder<VariableSymbol>();
|
||||
|
||||
foreach (var identifierToken in func.Parameters)
|
||||
{
|
||||
var vari = new VariableSymbol(identifierToken.Name, Type.Unknown, true);
|
||||
|
@ -351,9 +356,11 @@ namespace Upsilon.Binder
|
|||
innerScope.SetVariable(vari);
|
||||
}
|
||||
|
||||
|
||||
if (!Scope.TryGetVariable(name, !isLocal, out var variable))
|
||||
{
|
||||
variable = new FunctionVariableSymbol(name, Type.Function, isLocal, parameters.ToImmutable());
|
||||
((FunctionVariableSymbol) variable).IsBound = !(func is UnboundFunctionExpression);
|
||||
if (isLocal)
|
||||
Scope.SetVariable(variable);
|
||||
else
|
||||
|
@ -376,8 +383,6 @@ namespace Upsilon.Binder
|
|||
}
|
||||
}
|
||||
|
||||
((FunctionVariableSymbol) variable).IsBound = true;
|
||||
|
||||
return new BoundFunctionAssignmentStatement(variable, func);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,35 +9,53 @@ namespace Upsilon.Evaluator
|
|||
private readonly EvaluationScope _parentScope;
|
||||
private EvaluationScope _getOnlyParentScope;
|
||||
|
||||
internal readonly Dictionary<VariableSymbol, LuaType> Variables;
|
||||
internal readonly Dictionary<string, LuaType> Variables;
|
||||
internal readonly Dictionary<string, LuaType> LocalVariables;
|
||||
|
||||
|
||||
internal EvaluationScope(EvaluationScope parentScope)
|
||||
{
|
||||
_parentScope = parentScope;
|
||||
Variables = new Dictionary<VariableSymbol, LuaType>();
|
||||
Variables = new Dictionary<string, LuaType>();
|
||||
LocalVariables = new Dictionary<string, LuaType>();
|
||||
}
|
||||
|
||||
internal EvaluationScope(Dictionary<VariableSymbol, LuaType> vars)
|
||||
internal EvaluationScope(Dictionary<string, LuaType> vars)
|
||||
{
|
||||
Variables = vars;
|
||||
LocalVariables = new Dictionary<string, LuaType>();
|
||||
}
|
||||
|
||||
internal static EvaluationScope CreateWithGetOnlyParent(EvaluationScope parent)
|
||||
{
|
||||
var scope = new EvaluationScope(new Dictionary<VariableSymbol, LuaType>()) {_getOnlyParentScope = parent};
|
||||
var scope = new EvaluationScope(new Dictionary<string, LuaType>()) {_getOnlyParentScope = parent};
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void Set(VariableSymbol symbol, LuaType obj)
|
||||
{
|
||||
if (Variables.ContainsKey(symbol))
|
||||
if (symbol.Local)
|
||||
{
|
||||
Variables[symbol] = obj;
|
||||
if (LocalVariables.ContainsKey(symbol.Name))
|
||||
{
|
||||
LocalVariables[symbol.Name] = obj;
|
||||
}
|
||||
else
|
||||
{
|
||||
Variables.Add(symbol, obj);
|
||||
LocalVariables.Add(symbol.Name, obj);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Variables.ContainsKey(symbol.Name))
|
||||
{
|
||||
Variables[symbol.Name] = obj;
|
||||
}
|
||||
else
|
||||
{
|
||||
Variables.Add(symbol.Name, obj);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +71,9 @@ namespace Upsilon.Evaluator
|
|||
|
||||
public bool TryGet(VariableSymbol symbol, out LuaType obj)
|
||||
{
|
||||
if (Variables.TryGetValue(symbol, out obj))
|
||||
if (Variables.TryGetValue(symbol.Name, out obj))
|
||||
return true;
|
||||
if (LocalVariables.TryGetValue(symbol.Name, out obj))
|
||||
return true;
|
||||
if (_parentScope != null)
|
||||
if (_parentScope.TryGet(symbol, out obj))
|
||||
|
@ -66,18 +86,16 @@ namespace Upsilon.Evaluator
|
|||
|
||||
public bool TryGet(string variable, out LuaType obj)
|
||||
{
|
||||
foreach (var luaType in Variables)
|
||||
{
|
||||
if (luaType.Key.Name == variable)
|
||||
{
|
||||
obj = luaType.Value;
|
||||
if (Variables.TryGetValue(variable, out obj))
|
||||
return true;
|
||||
if (LocalVariables.TryGetValue(variable, out obj))
|
||||
return true;
|
||||
};
|
||||
}
|
||||
if (_parentScope != null)
|
||||
if (_parentScope.TryGet(variable, out obj))
|
||||
return true;
|
||||
obj = null;
|
||||
if (_getOnlyParentScope != null)
|
||||
if (_getOnlyParentScope.TryGet(variable, out obj))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Upsilon.Evaluator
|
|||
private bool HasReturned { get; set; }
|
||||
public int Identifier { get; }
|
||||
|
||||
internal Evaluator(Diagnostics diagnostics, Dictionary<VariableSymbol, LuaType> variables)
|
||||
internal Evaluator(Diagnostics diagnostics, Dictionary<string, LuaType> variables)
|
||||
{
|
||||
_diagnostics = diagnostics;
|
||||
Scope = new EvaluationScope(variables);
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace Upsilon.Evaluator
|
|||
Diagnostics = new Diagnostics(ScriptString);
|
||||
_parsed = Parser.Parser.Parse(scriptString, Diagnostics);
|
||||
Binder = new Binder.Binder(Diagnostics, new Dictionary<string, VariableSymbol>());
|
||||
Evaluator = new Evaluator( Diagnostics, new Dictionary<VariableSymbol, LuaType>());
|
||||
Evaluator = new Evaluator( Diagnostics, new Dictionary<string, LuaType>());
|
||||
Scope = Evaluator.Scope;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ testFunc(100)
|
|||
";
|
||||
var script = new Script(input);
|
||||
Assert.Empty(script.Diagnostics.Messages);
|
||||
var val = script.Evaluate();
|
||||
script.Evaluate();
|
||||
Assert.Single(script.Diagnostics.Messages);
|
||||
Assert.True(script.HasVariable("testFunc"));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue