#region using using System; using System.Collections.Generic; #endregion namespace ScriptNET.Runtime { /// /// Script Scope represents a tree of local scopes. /// Scopes stores variables and types tables. /// /// Run-time queries ScriptScope through ScriptContext for: /// /// Resolving names of types and variables; /// Resolving names of functions; /// Adding new function into scope; /// Assigning values to variables. /// /// public class ScriptScope : IScriptScope { #region properties private IScriptScope parent; /// /// Parent Scope of the current scope. /// Null if this scope is a global (root). /// public IScriptScope Parent { get { return parent; } set { parent = value; } } Dictionary vars = new Dictionary (); #endregion #region constructors /// /// Default Constructor /// public ScriptScope(): this(null) { } public ScriptScope(IScriptScope parent) { Parent = parent; } #endregion #region IScriptScope /// /// Returns value of the variable. Throws ScriptIdNotFoundException /// /// Variable ID /// Value of the variable public virtual object GetItem(string id, bool throwException) { object result = GetVariableInternal(id, true); if (result == RuntimeHost.NoVariable && throwException) { throw new ScriptIdNotFoundException(id + " is not found"); } return result; } /// /// Returns true if excatly this scope has variable with given id /// /// /// public virtual bool HasVariable(string id) { return vars.ContainsKey(id); } /// /// Searches the scope hierarchy for the given id, /// should return NoVariable if it is not found /// /// /// protected virtual object GetVariableInternal(string id, bool searchHierarchy) { if (vars.ContainsKey(id)) { return vars[id]; } if (!searchHierarchy) return RuntimeHost.NoVariable; IScriptScope scope = Parent; while(scope != null) { if (scope.HasVariable(id)) return scope.GetItem(id, true); scope = scope.Parent; } return RuntimeHost.NoVariable; } /// /// Sets Item: variable or type /// /// item's id /// type of item /// value public virtual void SetItem(string id, object value) { if (vars.ContainsKey(id)) { vars[id] = value; } else { vars.Add(id, value); } } /// /// Cleans Scope (Removes items) /// /// Type of cleanup public virtual void Clean() { vars.Clear(); } #endregion #region Functions /// /// Gets Invokable object (Function) by a given name /// /// Name /// public virtual IInvokable GetFunctionDefinition(string name) { object result = GetVariableInternal(name, false); IInvokable function = result as IInvokable; if (function != null) return function; if (parent != null) return parent.GetFunctionDefinition(name); else throw new ScriptIdNotFoundException("Function " + name + " not found"); } #endregion } /// /// Default scope activator - used by framework to create ScriptScope by default /// may be overriden in xml configuration /// public class ScriptScopeActivator : IScopeActivator { #region IScopeActivator Members public IScriptScope Create(IScriptScope parent, params object[] args) { if (args == null || args.Length == 0) { ScriptScope result = new ScriptScope(parent); SetBaseItems(result); return result; } throw new NotSupportedException(); } private void SetBaseItems(ScriptScope result) { //Process only root scopes if (result.Parent != null) return; //Variables result.SetItem("Scope", this); result.SetItem("Compiler", ScriptdotnetGrammar.Compiler); ////Custom Functions //AppendAst result.SetItem(ScriptNET.CustomFunctions.AppendFunc.FunctionName, ScriptNET.CustomFunctions.AppendFunc.FunctionDefinition); //ReplaceAst result.SetItem(ScriptNET.CustomFunctions.ReplaceFunc.FunctionName, ScriptNET.CustomFunctions.ReplaceFunc.FunctionDefinition); //eval result.SetItem(ScriptNET.CustomFunctions.EvalFunc.FunctionName, ScriptNET.CustomFunctions.EvalFunc.FunctionDefinition); //About result.SetItem(ScriptNET.CustomFunctions.AboutFunc.FunctionName, ScriptNET.CustomFunctions.AboutFunc.FunctionDefinition); //Console result.SetItem(ScriptNET.CustomFunctions.RunConsole.FunctionName, ScriptNET.CustomFunctions.RunConsole.FunctionDefinition); //Array result.SetItem(ScriptNET.CustomFunctions.ArrayFunc.FunctionName, ScriptNET.CustomFunctions.ArrayFunc.FunctionDefinition); //Char result.SetItem(ScriptNET.CustomFunctions.CharFunc.FunctionName, ScriptNET.CustomFunctions.CharFunc.FunctionDefinition); } #endregion } }