ssc/scope stack.cs

133 lines
3.4 KiB
C#
Raw Normal View History

2015-12-07 13:15:02 +09:00
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace arookas
{
class sunScopeStack : IEnumerable<sunScope>
{
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); } }
2015-12-07 13:15:02 +09:00
public int Count { get { return stack.Count; } }
public sunScope Root { get { return this[0]; } }
public sunScope Top { get { return this[Count - 1]; } }
public sunScope this[int index] { get { return stack[index]; } }
public sunScopeStack()
{
Push(sunScopeType.Script); // push global scope
2015-12-07 13:15:02 +09:00
}
public void Push(sunScopeType type)
2015-12-07 13:15:02 +09:00
{
stack.Add(new sunScope(type));
2015-12-07 13:15:02 +09:00
}
public void Pop()
{
if (Count > 1)
2015-12-07 13:15:02 +09:00
{
stack.RemoveAt(Count - 1);
}
}
public void Clear()
{
stack.Clear();
Push(sunScopeType.Script); // add global scope
2015-12-07 13:15:02 +09:00
}
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;
}
2015-12-07 13:15:02 +09:00
public IEnumerator<sunScope> GetEnumerator() { return stack.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
class sunScope
{
List<sunVariableInfo> variables = new List<sunVariableInfo>(10);
List<sunConstInfo> constants = new List<sunConstInfo>(10);
public sunScopeType Type { get; private set; }
public sunScope(sunScopeType type)
{
Type = type;
}
2015-12-07 13:15:02 +09:00
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, int index)
2015-12-07 13:15:02 +09:00
{
if (GetIsVariableDeclared(name) || GetIsConstantDeclared(name))
{
return null;
}
var variableInfo = new sunVariableInfo(name, display, index);
2015-12-07 13:15:02 +09:00
variables.Add(variableInfo);
return variableInfo;
}
public sunVariableInfo ResolveVariable(string name) { return variables.FirstOrDefault(v => v.Name == name); }
public bool GetIsConstantDeclared(string name) { return constants.Any(c => c.Name == name); }
public sunConstInfo DeclareConstant(string name, sunExpression expression)
{
if (GetIsVariableDeclared(name) || GetIsConstantDeclared(name))
{
return null;
}
var constInfo = new sunConstInfo(name, expression);
constants.Add(constInfo);
return constInfo;
}
public sunConstInfo ResolveConstant(string name) { return constants.FirstOrDefault(c => c.Name == name); }
}
enum sunScopeType
{
Script, // outside of a function
Function, // inside of a function
}
2015-12-07 13:15:02 +09:00
class sunConstInfo
{
public string Name { get; private set; }
public sunExpression Expression { get; private set; }
public sunConstInfo(string name, sunExpression expression)
{
Name = name;
Expression = expression;
}
}
}