125 lines
4 KiB
C#
125 lines
4 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace arookas {
|
|
class sunScopeStack : IEnumerable<sunScope> {
|
|
List<sunScope> Stack { get; set; }
|
|
|
|
public int Count { get { return Stack.Count; } }
|
|
#if SSC_PACK_VARS
|
|
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); } }
|
|
#else
|
|
int GlobalCount { get; set; }
|
|
int LocalCount { get; set; }
|
|
#endif
|
|
|
|
public sunScope Root { get { return this.FirstOrDefault(i => i.Type == Top.Type); } }
|
|
public sunScope Script { get { return this.FirstOrDefault(i => i.Type == sunScopeType.Script); } }
|
|
public sunScope Function { get { return this.FirstOrDefault(i => i.Type == sunScopeType.Function); } }
|
|
public sunScope Top { get { return this[Count - 1]; } }
|
|
|
|
public sunScope this[int index] { get { return Stack[index]; } }
|
|
|
|
public sunScopeStack() {
|
|
Stack = new List<sunScope>(8);
|
|
Push(sunScopeType.Script); // push global scope
|
|
}
|
|
|
|
public void Push() { Push(Top.Type); }
|
|
public void Push(sunScopeType type) {
|
|
Stack.Add(new sunScope(type));
|
|
}
|
|
public void Pop() {
|
|
if (Count > 1) {
|
|
Stack.RemoveAt(Count - 1);
|
|
}
|
|
}
|
|
public void Clear() {
|
|
Stack.Clear();
|
|
Push(sunScopeType.Script); // add global scope
|
|
}
|
|
|
|
#if !SSC_PACK_VARS
|
|
public void ResetGlobalCount() { GlobalCount = 0; }
|
|
public void ResetLocalCount() { LocalCount = 0; }
|
|
#endif
|
|
|
|
public sunVariableSymbol DeclareVariable(string name) {
|
|
switch (Top.Type) {
|
|
case sunScopeType.Script: return DeclareGlobal(name);
|
|
case sunScopeType.Function: return DeclareLocal(name);
|
|
}
|
|
return null;
|
|
}
|
|
public sunConstantSymbol DeclareConstant(string name, sunExpression expression) {
|
|
return Top.DeclareConstant(name, expression);
|
|
}
|
|
sunVariableSymbol DeclareGlobal(string name) {
|
|
var symbol = Top.DeclareVariable(name, 0, GlobalCount);
|
|
#if !SSC_PACK_VARS
|
|
if (symbol != null) {
|
|
++GlobalCount;
|
|
}
|
|
#endif
|
|
return symbol;
|
|
}
|
|
sunVariableSymbol DeclareLocal(string name) {
|
|
var symbol = Top.DeclareVariable(name, 1, LocalCount);
|
|
#if !SSC_PACK_VARS
|
|
if (symbol != null) {
|
|
++LocalCount;
|
|
}
|
|
#endif
|
|
return symbol;
|
|
}
|
|
|
|
public IEnumerator<sunScope> GetEnumerator() { return Stack.GetEnumerator(); }
|
|
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
|
|
}
|
|
|
|
class sunScope {
|
|
List<sunStorableSymbol> Storables { get; set; }
|
|
IEnumerable<sunVariableSymbol> Variables { get { return Storables.OfType<sunVariableSymbol>(); } }
|
|
IEnumerable<sunConstantSymbol> Constants { get { return Storables.OfType<sunConstantSymbol>(); } }
|
|
public sunScopeType Type { get; private set; }
|
|
|
|
public sunScope(sunScopeType type) {
|
|
Storables = new List<sunStorableSymbol>(10);
|
|
Type = type;
|
|
}
|
|
|
|
public int StorableCount { get { return Storables.Count; } }
|
|
public int VariableCount { get { return Variables.Count(); } }
|
|
public int ConstantCount { get { return Constants.Count(); } }
|
|
|
|
public bool GetIsDeclared(string name) { return Storables.Any(v => v.Name == name); }
|
|
|
|
public sunVariableSymbol DeclareVariable(string name, int display, int index) {
|
|
if (GetIsDeclared(name)) {
|
|
return null;
|
|
}
|
|
var symbol = new sunVariableSymbol(name, display, index);
|
|
Storables.Add(symbol);
|
|
return symbol;
|
|
}
|
|
public sunConstantSymbol DeclareConstant(string name, sunExpression expression) {
|
|
if (GetIsDeclared(name)) {
|
|
return null;
|
|
}
|
|
var symbol = new sunConstantSymbol(name, expression);
|
|
Storables.Add(symbol);
|
|
return symbol;
|
|
}
|
|
|
|
public sunStorableSymbol ResolveStorable(string name) { return Storables.FirstOrDefault(i => i.Name == name); }
|
|
public sunVariableSymbol ResolveVariable(string name) { return Variables.FirstOrDefault(i => i.Name == name); }
|
|
public sunConstantSymbol ResolveConstant(string name) { return Constants.FirstOrDefault(i => i.Name == name); }
|
|
}
|
|
|
|
enum sunScopeType {
|
|
Script, // outside of a function
|
|
Function, // inside of a function
|
|
}
|
|
}
|