diff --git a/ast/nodes.flow.cs b/ast/nodes.flow.cs index a7d6df7..6fd056e 100644 --- a/ast/nodes.flow.cs +++ b/ast/nodes.flow.cs @@ -114,7 +114,7 @@ namespace arookas public override void Compile(sunContext context) { - context.Scopes.Push(); + context.Scopes.Push(context.Scopes.Top.Type); context.Loops.Push(IsNamed ? NameLabel.Label.Value : null); TryCompile(Declaration, context); var bodyPrologue = context.Text.OpenPoint(); diff --git a/ast/nodes.statements.cs b/ast/nodes.statements.cs index 2a85f66..b144b10 100644 --- a/ast/nodes.statements.cs +++ b/ast/nodes.statements.cs @@ -10,7 +10,7 @@ public override void Compile(sunContext context) { - context.Scopes.Push(); + context.Scopes.Push(context.Scopes.Top.Type); base.Compile(context); context.Scopes.Pop(); } diff --git a/context.cs b/context.cs index b8b8fde..8830c40 100644 --- a/context.cs +++ b/context.cs @@ -159,10 +159,10 @@ namespace arookas { throw new sunRedeclaredVariableException(node); } - var variableInfo = Scopes.Top.DeclareVariable(node.Value, Scopes.Count > 1 ? 1 : 0); - if (Scopes.IsRoot) + var variableInfo = Scopes.DeclareVariable(node.Value); + 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); } return variableInfo; @@ -181,7 +181,7 @@ namespace arookas 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 public sunConstInfo DeclareConstant(sunIdentifier node, sunExpression expression) diff --git a/scope stack.cs b/scope stack.cs index 3011aae..d23992c 100644 --- a/scope stack.cs +++ b/scope stack.cs @@ -7,6 +7,8 @@ namespace arookas class sunScopeStack : IEnumerable { List stack = new List(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 bool IsRoot { get { return Count == 1; } } @@ -18,12 +20,12 @@ namespace arookas 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() { @@ -35,10 +37,37 @@ namespace arookas public void 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 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 GetEnumerator() { return stack.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } @@ -48,18 +77,24 @@ namespace arookas { List variables = new List(10); List constants = new List(10); + public sunScopeType Type { get; private set; } + + public sunScope(sunScopeType type) + { + Type = type; + } public int VariableCount { get { return variables.Count; } } public int ConstantCount { get { return constants.Count; } } 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)) { return null; } - var variableInfo = new sunVariableInfo(name, display, variables.Count); + var variableInfo = new sunVariableInfo(name, display, index); variables.Add(variableInfo); return variableInfo; } @@ -79,6 +114,12 @@ namespace arookas 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 { public string Name { get; private set; }