using System;
using System.IO;
using Flee.CalcEngine.InternalTypes;
using Flee.CalcEngine.PublicTypes;
using Flee.ExpressionElements.Base;
using Flee.InternalTypes;
using Flee.Parsing;
namespace Flee.PublicTypes
{
///
/// 表达式上下文类,提供表达式编译和执行的环境
///
public sealed class ExpressionContext
{
#region "Fields"
private PropertyDictionary _myProperties;
private readonly object _mySyncRoot = new object();
private VariableCollection _myVariables;
#endregion
#region "Constructor"
public ExpressionContext() : this(DefaultExpressionOwner.Instance)
{
}
public ExpressionContext(object expressionOwner)
{
Utility.AssertNotNull(expressionOwner, "expressionOwner");
_myProperties = new PropertyDictionary();
_myProperties.SetValue("CalculationEngine", null);
_myProperties.SetValue("CalcEngineExpressionName", null);
_myProperties.SetValue("IdentifierParser", null);
_myProperties.SetValue("ExpressionOwner", expressionOwner);
_myProperties.SetValue("ParserOptions", new ExpressionParserOptions(this));
_myProperties.SetValue("Options", new ExpressionOptions(this));
_myProperties.SetValue("Imports", new ExpressionImports());
this.Imports.SetContext(this);
_myVariables = new VariableCollection(this);
_myProperties.SetToDefault("NoClone");
this.RecreateParser();
}
#endregion
#region "Methods - Private"
private void AssertTypeIsAccessibleInternal(Type t)
{
bool isPublic = t.IsPublic;
if (t.IsNested == true)
{
isPublic = t.IsNestedPublic;
}
bool isSameModuleAsOwner = object.ReferenceEquals(t.Module, this.ExpressionOwner.GetType().Module);
// Public types are always accessible. Otherwise they have to be in the same module as the owner
bool isAccessible = isPublic | isSameModuleAsOwner;
if (isAccessible == false)
{
string msg = Utility.GetGeneralErrorMessage("TypeNotAccessibleToExpression", t.Name);
throw new ArgumentException(msg);
}
}
private void AssertNestedTypeIsAccessible(Type t)
{
while ((t != null))
{
AssertTypeIsAccessibleInternal(t);
t = t.DeclaringType;
}
}
#endregion
#region "Methods - Internal"
internal ExpressionContext CloneInternal(bool cloneVariables)
{
ExpressionContext context = (ExpressionContext)this.MemberwiseClone();
context._myProperties = _myProperties.Clone();
context._myProperties.SetValue("Options", context.Options.Clone());
context._myProperties.SetValue("ParserOptions", context.ParserOptions.Clone());
context._myProperties.SetValue("Imports", context.Imports.Clone());
context.Imports.SetContext(context);
if (cloneVariables == true)
{
context._myVariables = new VariableCollection(context);
this.Variables.Copy(context._myVariables);
}
return context;
}
internal void AssertTypeIsAccessible(Type t)
{
if (t.IsNested == true)
{
AssertNestedTypeIsAccessible(t);
}
else
{
AssertTypeIsAccessibleInternal(t);
}
}
internal ExpressionElement Parse(string expression, IServiceProvider services)
{
lock (_mySyncRoot)
{
System.IO.StringReader sr = new System.IO.StringReader(expression);
ExpressionParser parser = this.Parser;
parser.Reset(sr);
parser.Tokenizer.Reset(sr);
FleeExpressionAnalyzer analyzer = (FleeExpressionAnalyzer)parser.Analyzer;
analyzer.SetServices(services);
Node rootNode = DoParse();
analyzer.Reset();
ExpressionElement topElement = (ExpressionElement)rootNode.Values[0];
return topElement;
}
}
internal void RecreateParser()
{
lock (_mySyncRoot)
{
FleeExpressionAnalyzer analyzer = new FleeExpressionAnalyzer();
ExpressionParser parser = new ExpressionParser(TextReader.Null, analyzer, this);
_myProperties.SetValue("ExpressionParser", parser);
}
}
internal Node DoParse()
{
try
{
return this.Parser.Parse();
}
catch (ParserLogException ex)
{
// Syntax error; wrap it in our exception and rethrow
throw new ExpressionCompileException(ex);
}
}
internal void SetCalcEngine(CalculationEngine engine, string calcEngineExpressionName)
{
_myProperties.SetValue("CalculationEngine", engine);
_myProperties.SetValue("CalcEngineExpressionName", calcEngineExpressionName);
}
internal IdentifierAnalyzer ParseIdentifiers(string expression)
{
ExpressionParser parser = this.IdentifierParser;
StringReader sr = new StringReader(expression);
parser.Reset(sr);
parser.Tokenizer.Reset(sr);
IdentifierAnalyzer analyzer = (IdentifierAnalyzer)parser.Analyzer;
analyzer.Reset();
parser.Parse();
return (IdentifierAnalyzer)parser.Analyzer;
}
#endregion
#region "Methods - Public"
public ExpressionContext Clone()
{
return this.CloneInternal(true);
}
///
/// 编译动态表达式,返回类型在运行时确定
///
/// 要编译的表达式字符串
/// 编译后的动态表达式
public IDynamicExpression CompileDynamic(string expression)
{
return new Flee.InternalTypes.Expression