#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
}
}