Fixed: variable indices were incorrect in nested scopes.

This commit is contained in:
arookas 2015-12-12 12:40:37 -05:00
parent 84c4326c09
commit f506572894
4 changed files with 53 additions and 12 deletions

View file

@ -114,7 +114,7 @@ namespace arookas
public override void Compile(sunContext context) public override void Compile(sunContext context)
{ {
context.Scopes.Push(); context.Scopes.Push(context.Scopes.Top.Type);
context.Loops.Push(IsNamed ? NameLabel.Label.Value : null); context.Loops.Push(IsNamed ? NameLabel.Label.Value : null);
TryCompile(Declaration, context); TryCompile(Declaration, context);
var bodyPrologue = context.Text.OpenPoint(); var bodyPrologue = context.Text.OpenPoint();

View file

@ -10,7 +10,7 @@
public override void Compile(sunContext context) public override void Compile(sunContext context)
{ {
context.Scopes.Push(); context.Scopes.Push(context.Scopes.Top.Type);
base.Compile(context); base.Compile(context);
context.Scopes.Pop(); context.Scopes.Pop();
} }

View file

@ -159,10 +159,10 @@ namespace arookas
{ {
throw new sunRedeclaredVariableException(node); throw new sunRedeclaredVariableException(node);
} }
var variableInfo = Scopes.Top.DeclareVariable(node.Value, Scopes.Count > 1 ? 1 : 0); var variableInfo = Scopes.DeclareVariable(node.Value);
if (Scopes.IsRoot) if (Scopes.Top.Type == sunScopeType.Script)
{ {
// global-scope variables are added to the symbol table // script variables are added to the symbol table
SymbolTable.Add(variableInfo); SymbolTable.Add(variableInfo);
} }
return variableInfo; return variableInfo;
@ -181,7 +181,7 @@ namespace arookas
throw new sunUndeclaredVariableException(node); throw new sunUndeclaredVariableException(node);
} }
public sunVariableInfo DeclareParameter(string name) { return Scopes.Top.DeclareVariable(name, 1); } public sunVariableInfo DeclareParameter(string name) { return Scopes.DeclareVariable(name); }
// constants // constants
public sunConstInfo DeclareConstant(sunIdentifier node, sunExpression expression) public sunConstInfo DeclareConstant(sunIdentifier node, sunExpression expression)

View file

@ -7,6 +7,8 @@ namespace arookas
class sunScopeStack : IEnumerable<sunScope> class sunScopeStack : IEnumerable<sunScope>
{ {
List<sunScope> stack = new List<sunScope>(8); List<sunScope> stack = new List<sunScope>(8);
int GlobalCount { get { return stack.Where(i => i.Type == sunScopeType.Script).Sum(i => i.VariableCount); } }
int LocalCount { get { return stack.Where(i => i.Type == sunScopeType.Function).Sum(i => i.VariableCount); } }
public int Count { get { return stack.Count; } } public int Count { get { return stack.Count; } }
public bool IsRoot { get { return Count == 1; } } public bool IsRoot { get { return Count == 1; } }
@ -18,12 +20,12 @@ namespace arookas
public sunScopeStack() public sunScopeStack()
{ {
Push(); // push global scope Push(sunScopeType.Script); // push global scope
} }
public void Push() public void Push(sunScopeType type)
{ {
stack.Add(new sunScope()); stack.Add(new sunScope(type));
} }
public void Pop() public void Pop()
{ {
@ -35,10 +37,37 @@ namespace arookas
public void Clear() public void Clear()
{ {
stack.Clear(); stack.Clear();
Push(); // add global scope Push(sunScopeType.Script); // add global scope
} }
public bool GetIsVariableDeclared(string name) { return stack.Any(i => i.GetIsVariableDeclared(name)); } public bool GetIsVariableDeclared(string name) { return stack.Any(i => i.GetIsVariableDeclared(name)); }
public sunVariableInfo DeclareVariable(string name)
{
switch (Top.Type)
{
case sunScopeType.Script: return DeclareGlobal(name);
case sunScopeType.Function: return DeclareLocal(name);
}
return null;
}
sunVariableInfo DeclareGlobal(string name)
{
var variableInfo = Top.DeclareVariable(name, 0, GlobalCount);
if (variableInfo == null)
{
return null;
}
return variableInfo;
}
sunVariableInfo DeclareLocal(string name)
{
var variableInfo = Top.DeclareVariable(name, 1, LocalCount);
if (variableInfo == null)
{
return null;
}
return variableInfo;
}
public IEnumerator<sunScope> GetEnumerator() { return stack.GetEnumerator(); } public IEnumerator<sunScope> GetEnumerator() { return stack.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
@ -48,18 +77,24 @@ namespace arookas
{ {
List<sunVariableInfo> variables = new List<sunVariableInfo>(10); List<sunVariableInfo> variables = new List<sunVariableInfo>(10);
List<sunConstInfo> constants = new List<sunConstInfo>(10); List<sunConstInfo> constants = new List<sunConstInfo>(10);
public sunScopeType Type { get; private set; }
public sunScope(sunScopeType type)
{
Type = type;
}
public int VariableCount { get { return variables.Count; } } public int VariableCount { get { return variables.Count; } }
public int ConstantCount { get { return constants.Count; } } public int ConstantCount { get { return constants.Count; } }
public bool GetIsVariableDeclared(string name) { return variables.Any(v => v.Name == name); } public bool GetIsVariableDeclared(string name) { return variables.Any(v => v.Name == name); }
public sunVariableInfo DeclareVariable(string name, int display) public sunVariableInfo DeclareVariable(string name, int display, int index)
{ {
if (GetIsVariableDeclared(name) || GetIsConstantDeclared(name)) if (GetIsVariableDeclared(name) || GetIsConstantDeclared(name))
{ {
return null; return null;
} }
var variableInfo = new sunVariableInfo(name, display, variables.Count); var variableInfo = new sunVariableInfo(name, display, index);
variables.Add(variableInfo); variables.Add(variableInfo);
return variableInfo; return variableInfo;
} }
@ -79,6 +114,12 @@ namespace arookas
public sunConstInfo ResolveConstant(string name) { return constants.FirstOrDefault(c => c.Name == name); } public sunConstInfo ResolveConstant(string name) { return constants.FirstOrDefault(c => c.Name == name); }
} }
enum sunScopeType
{
Script, // outside of a function
Function, // inside of a function
}
class sunConstInfo class sunConstInfo
{ {
public string Name { get; private set; } public string Name { get; private set; }