using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; namespace tlang { public interface IScopeEnvironment : IEnumerable> { bool VariableExists(string name); void SetVariable(string name,TObject obj); TObject GetVariable(string names); IScopeEnvironment SubEnv {get;} IScopeEnvironment RootEnv {get;} TObject this[string variable] {get;set;} } public class SubEnvironment : IScopeEnvironment { Dictionary items = new Dictionary(); IScopeEnvironment root; IScopeEnvironment parent; public SubEnvironment(IScopeEnvironment root,IScopeEnvironment parent) { this.root=root; this.parent = parent; } public TObject this[string variable] { get => GetVariable(variable); set => SetVariable(variable,value); } public IScopeEnvironment SubEnv => new SubEnvironment(root,this); public IScopeEnvironment RootEnv => root; public IEnumerator> GetEnumerator() { return getVars().GetEnumerator(); } private IEnumerable> getVars() { foreach(var v in parent) { yield return v; } foreach(var item in items) { yield return item; } } public TObject GetVariable(string name) { if(name == "last_ittr" && items.ContainsKey("last_ittr")) { return items["last_ittr"]; } if(parent.VariableExists(name)) { return parent[name]; } if(items.ContainsKey(name)) { return items[name]; } return TObject.Uninit; } public void SetVariable(string name, TObject obj) { if(parent.VariableExists(name) && name != "last_ittr") { parent.SetVariable(name,obj); }else if(items.ContainsKey(name)) { items[name] = obj; }else{ items.Add(name,obj); } } public bool VariableExists(string name) { if(parent.VariableExists(name)) return true; return items.ContainsKey(name); } IEnumerator IEnumerable.GetEnumerator() { return getVars().GetEnumerator(); } } public class RootEnvironment : IScopeEnvironment { Dictionary items = new Dictionary(); public IScopeEnvironment SubEnv => new SubEnvironment(this,this); public IScopeEnvironment RootEnv => this; public IEnumerator> GetEnumerator() { return items.GetEnumerator(); } public TObject GetVariable(string name) { if(items.ContainsKey(name)) { return items[name]; }else{ return TObject.Uninit; } } public void SetVariable(string name, TObject obj) { if(items.ContainsKey(name)) { items[name] = obj; } else { items.Add(name,obj); } } public bool VariableExists(string name) { return items.ContainsKey(name); } IEnumerator IEnumerable.GetEnumerator() { return items.GetEnumerator(); } public TObject this[string variable] { get => GetVariable(variable); set => SetVariable(variable,value); } } }