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);
|
2015-12-13 02:40:37 +09:00
|
|
|
|
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()
|
|
|
|
|
{
|
2015-12-13 02:40:37 +09:00
|
|
|
|
Push(sunScopeType.Script); // push global scope
|
2015-12-07 13:15:02 +09:00
|
|
|
|
}
|
|
|
|
|
|
2015-12-13 02:40:37 +09:00
|
|
|
|
public void Push(sunScopeType type)
|
2015-12-07 13:15:02 +09:00
|
|
|
|
{
|
2015-12-13 02:40:37 +09:00
|
|
|
|
stack.Add(new sunScope(type));
|
2015-12-07 13:15:02 +09:00
|
|
|
|
}
|
|
|
|
|
public void Pop()
|
|
|
|
|
{
|
2015-12-13 02:44:39 +09:00
|
|
|
|
if (Count > 1)
|
2015-12-07 13:15:02 +09:00
|
|
|
|
{
|
|
|
|
|
stack.RemoveAt(Count - 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public void Clear()
|
|
|
|
|
{
|
|
|
|
|
stack.Clear();
|
2015-12-13 02:40:37 +09:00
|
|
|
|
Push(sunScopeType.Script); // add global scope
|
2015-12-07 13:15:02 +09:00
|
|
|
|
}
|
|
|
|
|
|
2015-12-13 02:40:37 +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);
|
2015-12-13 02:40:37 +09:00
|
|
|
|
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); }
|
2015-12-13 02:40:37 +09:00
|
|
|
|
public sunVariableInfo DeclareVariable(string name, int display, int index)
|
2015-12-07 13:15:02 +09:00
|
|
|
|
{
|
|
|
|
|
if (GetIsVariableDeclared(name) || GetIsConstantDeclared(name))
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2015-12-13 02:40:37 +09:00
|
|
|
|
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); }
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-13 02:40:37 +09:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|