diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..159cd6d --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +**/bin/Debug/ +**/obj/Debug/ +Irony_All.2012.sln.DotSettings +Irony_All.2012.sln.DotSettings.user +Irony_All.2012.v11.suo +**/bin/Release/ +**/obj/Release/ diff --git a/Irony.GrammarExplorer/030.Irony.GrammarExplorer.2012.csproj b/Irony.GrammarExplorer/030.Irony.GrammarExplorer.2012.csproj new file mode 100644 index 0000000..5ea3300 --- /dev/null +++ b/Irony.GrammarExplorer/030.Irony.GrammarExplorer.2012.csproj @@ -0,0 +1,165 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {AE1C04A8-B03D-4144-98E9-BF66C50265E7} + WinExe + Properties + Irony.GrammarExplorer + Irony.GrammarExplorer + + + 3.5 + + + v4.0 + + + + + + + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + Client + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + + + 3.5 + + + + + + + + + + Form + + + fmGrammarExplorer.cs + + + Form + + + fmSelectGrammars.cs + + + + + + + + fmGrammarExplorer.cs + Designer + + + fmSelectGrammars.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + Designer + fmShowException.cs + + + True + Resources.resx + True + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + Form + + + fmShowException.cs + + + + + + + + + {D81F5C91-D7DB-46E5-BC99-49488FB6814C} + 010.Irony.2010 + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Irony.Samples.Console/025.Irony.Samples.Console.2012.csproj b/Irony.Samples.Console/025.Irony.Samples.Console.2012.csproj new file mode 100644 index 0000000..1941977 --- /dev/null +++ b/Irony.Samples.Console/025.Irony.Samples.Console.2012.csproj @@ -0,0 +1,121 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {5A31B964-CDFA-4406-9316-32A0F04CE149} + Exe + Properties + Irony.Samples.Console + Irony.Samples.Console + v4.0 + 512 + + + + + + + + + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + + + + {AD263C0B-99D3-40A9-9DBF-9086CC524A0B} + 020.Irony.Samples.2010 + + + {D81F5C91-D7DB-46E5-BC99-49488FB6814C} + 010.Irony.2010 + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + + \ No newline at end of file diff --git a/Irony.Samples/020.Irony.Samples.2012.csproj b/Irony.Samples/020.Irony.Samples.2012.csproj new file mode 100644 index 0000000..538a75a --- /dev/null +++ b/Irony.Samples/020.Irony.Samples.2012.csproj @@ -0,0 +1,164 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {AD263C0B-99D3-40A9-9DBF-9086CC524A0B} + Library + Properties + Irony.Samples + Irony.Samples + + + 3.5 + + + v4.0 + + + + + + + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + AllRules.ruleset + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {D81F5C91-D7DB-46E5-BC99-49488FB6814C} + 010.Irony.2010 + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Irony.Tests/040.Irony.Tests.VsTest.2012.csproj b/Irony.Tests/040.Irony.Tests.VsTest.2012.csproj new file mode 100644 index 0000000..98f2958 --- /dev/null +++ b/Irony.Tests/040.Irony.Tests.VsTest.2012.csproj @@ -0,0 +1,127 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {0CFA8CEE-0110-49C1-93E5-CB7BE3A5716B} + Library + Properties + Irony.Tests + Irony.Tests.VSTest + v4.0 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + + + + + + + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + + + + 3.5 + + + + + + + + + + + + + + + + + + + + {D81F5C91-D7DB-46E5-BC99-49488FB6814C} + 010.Irony.2010 + + + + + + + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Irony.Tests/050.Irony.Tests.NUnit.2012.csproj b/Irony.Tests/050.Irony.Tests.NUnit.2012.csproj new file mode 100644 index 0000000..0660695 --- /dev/null +++ b/Irony.Tests/050.Irony.Tests.NUnit.2012.csproj @@ -0,0 +1,132 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {1A98BEDA-DF53-49B7-A366-2ED7606036BD} + Library + Properties + Irony.Tests + Irony.Tests.NUnit + v4.0 + 512 + + + + + + + + + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + Client + + + true + full + false + bin\Debug\ + TRACE;DEBUG;USE_NUNIT + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + + False + ..\..\..\..\..\..\Temp\NUnit-2.5.8.10295\bin\net-2.0\framework\nunit.framework.dll + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + {D81F5C91-D7DB-46E5-BC99-49488FB6814C} + 010.Irony.2010 + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Irony.Tests/Ast/IdentifierNodeTests.cs b/Irony.Tests/Ast/IdentifierNodeTests.cs new file mode 100644 index 0000000..93340e5 --- /dev/null +++ b/Irony.Tests/Ast/IdentifierNodeTests.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Irony.Ast; +using Irony.Interpreter; +using Irony.Parsing; +using NUnit.Framework; + +namespace Irony.Tests.Ast +{ + [TestFixture] + public class IdentifierNodeTests + { + [Test] + public void EvaluateNodeReadsFromTopMostSymbolInFrameStack() { + // Create context + var context = CreateContext(); + var symbol = SymbolTable.Symbols.TextToSymbol("id"); + // Insert value in lower frame + context.SetLocalValue(symbol, 24); + context.PushFrame("x", null, context.CurrentFrame); + // Insert value in top frame + context.SetLocalValue(symbol, 42); + context.PushFrame("y", null, context.CurrentFrame); + + // Try evaluating + var sut = new IdentifierNode(); + var token = new TestToken(symbol); + sut.Init(null, new ParseTreeNode(token)); + sut.EvaluateNode(context, AstMode.Read); + + var actual = context.LastResult; + Assert.That(actual, Is.EqualTo(42)); + } + + [Test] + public void EvaluateNodeWritesToTopMostSymbolInFrameStack() { + // Create context + var context = CreateContext(); + var symbol = SymbolTable.Symbols.TextToSymbol("id"); + // Insert value in lower frame + context.SetLocalValue(symbol, 24); + context.PushFrame("x", null, context.CurrentFrame); + // Insert value in top frame + context.SetLocalValue(symbol, 42); + context.PushFrame("y", null, context.CurrentFrame); + + context.Data.Push(100); + + // Try evaluating + var sut = new IdentifierNode(); + var token = new TestToken(symbol); + sut.Init(null, new ParseTreeNode(token)); + sut.EvaluateNode(context, AstMode.Write); + + var actual = context.CurrentFrame.Parent.Values[symbol]; + Assert.That(actual, Is.EqualTo(100)); + } + + private static EvaluationContext CreateContext() { + return new EvaluationContext(new LanguageRuntime(new LanguageData(new Grammar()))); + } + + private class TestToken : Token { + public TestToken(Symbol symbol) : base(new Terminal("testTerminal"), new SourceLocation(), "token", "value") { + Symbol = symbol; + } + } + } +} diff --git a/Irony.Tests/Ast/LocalIdentifierNodeTests.cs b/Irony.Tests/Ast/LocalIdentifierNodeTests.cs new file mode 100644 index 0000000..f3d07cd --- /dev/null +++ b/Irony.Tests/Ast/LocalIdentifierNodeTests.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Irony.Ast; +using Irony.Interpreter; +using Irony.Parsing; +using NUnit.Framework; + +namespace Irony.Tests.Ast +{ + [TestFixture] + public class LocalIdentifierNodeTests + { + [Test] + public void EvaluateNodeReadsFromTopMostSymbolInFrameStack() { + // Create context + var context = CreateContext(); + var symbol = SymbolTable.Symbols.TextToSymbol("id"); + // Insert value in lower frame + context.SetLocalValue(symbol, 24); + context.PushFrame("x", null, context.CurrentFrame); + // Insert value in top frame + context.SetLocalValue(symbol, 42); + context.PushFrame("y", null, context.CurrentFrame); + + // Try evaluating + var sut = new LocalIdentifierNode(); + var token = new TestToken(symbol); + sut.Init(null, new ParseTreeNode(token)); + sut.EvaluateNode(context, AstMode.Read); + + var actual = context.LastResult; + Assert.That(actual, Is.EqualTo(42)); + } + + [Test] + public void EvaluateNodeWritesToTopFrameStack() { + // Create context + var context = CreateContext(); + var symbol = SymbolTable.Symbols.TextToSymbol("id"); + // Insert value in lower frame + context.SetLocalValue(symbol, 24); + context.PushFrame("x", null, context.CurrentFrame); + // Insert value in top frame + context.SetLocalValue(symbol, 42); + context.PushFrame("y", null, context.CurrentFrame); + + context.Data.Push(100); + + // Try evaluating + var sut = new LocalIdentifierNode(); + var token = new TestToken(symbol); + sut.Init(null, new ParseTreeNode(token)); + sut.EvaluateNode(context, AstMode.Write); + + var actual = context.CurrentFrame.Values[symbol]; + Assert.That(actual, Is.EqualTo(100)); + // Check that parent value is untouched. This is what differentiate LocalIdentifierNode from IdentifierNode + Assert.That(context.CurrentFrame.Parent.Values[symbol], Is.EqualTo(42)); + } + + private static EvaluationContext CreateContext() { + return new EvaluationContext(new LanguageRuntime(new LanguageData(new Grammar()))); + } + + private class TestToken : Token { + public TestToken(Symbol symbol) : base(new Terminal("testTerminal"), new SourceLocation(), "token", "value") { + Symbol = symbol; + } + } + } +} diff --git a/Irony.Tests/Interpreter/EvaluateAsyncTests.cs b/Irony.Tests/Interpreter/EvaluateAsyncTests.cs new file mode 100644 index 0000000..749d422 --- /dev/null +++ b/Irony.Tests/Interpreter/EvaluateAsyncTests.cs @@ -0,0 +1,213 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using Irony.Ast; +using Irony.Interpreter; +using Irony.Parsing; +using NUnit.Framework; + +namespace Irony.Tests.Interpreter +{ + public class MiniGrammar : Grammar + { + public MiniGrammar() + { + // 1. Terminals + var identifier = new IdentifierTerminal("id"); + var number = new NumberLiteral("number"); + + // 2. Non-terminals + var StmtList = new NonTerminal("StmtList", typeof(StatementListNode)); + var Stmt = new NonTerminal("Stmt"); + var Expr = new NonTerminal("Expr"); + var FunctionCall = new NonTerminal("FunctionCall", typeof (FunctionCallNode)); + + // 3. BNF rules + StmtList.Rule = MakePlusRule(StmtList, Stmt); + Stmt.Rule = Expr + ToTerm(";"); + Expr.Rule = FunctionCall | number; + FunctionCall.Rule = identifier + "(" + ")"; + + MarkPunctuation("(", ")", ";"); + RegisterBracePair("(", ")"); + MarkTransient(Stmt, Expr); + + Root = StmtList; + LanguageFlags = LanguageFlags.CreateAst; + } + } + + [TestFixture] + public class EvaluateAsyncTests + { + [Test] + public void MiniGrammarFunctionCall() + { + AssertAstTree(new MiniGrammar(), "func1();func2();", + NewNode(), + NewNode(), + NewNode("func1"), + NewNode(), + NewNode("func2")); + } + [Test] + public void ScriptCanBeCanceled() + { + var interpreter = new ScriptInterpreter(new MiniGrammar()); + bool func2IsCalled = false; + interpreter.EvaluationContext.SetValue(SymbolTable.Symbols.TextToSymbol("func1"), new ActionCallTarget(() => Thread.Sleep(500))); + interpreter.EvaluationContext.SetValue(SymbolTable.Symbols.TextToSymbol("func2"), new ActionCallTarget(() => func2IsCalled = true)); + interpreter.EvaluateAsync("func1();func2();"); + Thread.Sleep(100); // Give the parser time to finish and evaluation to start. + interpreter.Abort(TimeSpan.FromMilliseconds(1000)); + + Assert.That(interpreter.Status, Is.EqualTo(InterpreterStatus.Canceled)); + Assert.That(func2IsCalled, Is.False); + } + + [Test] + public void ScriptIsAbortedIfNotCanceledWithinTimeout() + { + var interpreter = new ScriptInterpreter(new MiniGrammar()); + bool func2IsCalled = false; + interpreter.EvaluationContext.SetValue(SymbolTable.Symbols.TextToSymbol("func1"), new ActionCallTarget(() => Thread.Sleep(500))); + interpreter.EvaluationContext.SetValue(SymbolTable.Symbols.TextToSymbol("func2"), new ActionCallTarget(() => func2IsCalled = true)); + interpreter.EvaluateAsync("func1();func2();"); + Thread.Sleep(100); // Give the parser time to finish and evaluation to start. + interpreter.Abort(TimeSpan.FromMilliseconds(1)); + + Assert.That(interpreter.Status, Is.EqualTo(InterpreterStatus.Aborted)); + Assert.That(func2IsCalled, Is.False); + } + + [Test] + public void WaitHandleWillBeSetWhenScriptCompletes() + { + var interpreter = new ScriptInterpreter(new MiniGrammar()); + bool func2IsCalled = false; + interpreter.EvaluationContext.SetValue(SymbolTable.Symbols.TextToSymbol("func1"), new ActionCallTarget(() => Thread.Sleep(0))); + interpreter.EvaluationContext.SetValue(SymbolTable.Symbols.TextToSymbol("func2"), new ActionCallTarget(() => func2IsCalled = true)); + interpreter.EvaluateAsync("func1();func2();"); + interpreter.WaitHandle.WaitOne(); + + Assert.That(interpreter.Status, Is.EqualTo(InterpreterStatus.Ready)); + Assert.That(func2IsCalled, Is.True); + } + + [Test] + public void LastResultContainsLastExpressionWhenScriptCompletes() + { + var interpreter = new ScriptInterpreter(new MiniGrammar()); + interpreter.EvaluateAsync("5;42;"); + interpreter.WaitHandle.WaitOne(); + + Assert.That(interpreter.Status, Is.EqualTo(InterpreterStatus.Ready)); + Assert.That(interpreter.EvaluationContext.LastResult, Is.EqualTo(42)); + } + + [Test] + public void StatusIsRunTimeErrorIfExecutionFails() + { + var interpreter = new ScriptInterpreter(new MiniGrammar()); + interpreter.EvaluationContext.SetValue(SymbolTable.Symbols.TextToSymbol("func1"), new ActionCallTarget(() => { throw new Exception(); })); + interpreter.EvaluateAsync("func1();"); + interpreter.WaitHandle.WaitOne(); + + Assert.That(interpreter.Status, Is.EqualTo(InterpreterStatus.RuntimeError)); + } + + + public class ActionCallTarget : ICallTarget + { + private readonly Action _action; + + public ActionCallTarget(Action action) + { + _action = action; + } + + public void Call(EvaluationContext context) + { + _action(); + } + } + + protected ParseTree AssertAstTree(Grammar grammar, string script, params ComparableAstNode[] nodes) + { + var parser = new Parser(grammar); + var parseTree = parser.Parse(script); + + Assert.That(parseTree.Status, Is.EqualTo(ParseTreeStatus.Parsed), FormatParseError(parseTree)); + var astNodes = UnfoldAstTree((AstNode)parseTree.Root.AstNode); + var comparableNodes = astNodes.Select(x => new ComparableAstNode(x.GetType(), x.AsString)).ToArray(); + Assert.That(comparableNodes, Is.EqualTo(nodes)); + return parseTree; + } + + protected IEnumerable UnfoldAstTree(AstNode node) + { + yield return node; + foreach (var childNode in node.ChildNodes) + { + var subNodes = UnfoldAstTree(childNode); + foreach (var subNode in subNodes) + { + yield return subNode; + } + } + } + + protected class ComparableAstNode : IEquatable + { + private readonly Type _astType; + private readonly string _value; + + public ComparableAstNode(Type astType, string value) + { + this._astType = astType; + this._value = value; + } + + public bool Equals(ComparableAstNode other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + if (_value != null) + return Equals(_astType, other._astType) && string.Equals(_value, other._value); + return Equals(_astType, other._astType); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj is ComparableAstNode) + return Equals((ComparableAstNode)obj); + if (obj is AstNode) + return Equals(new ComparableAstNode(obj.GetType(), ((AstNode)obj).AsString)); + return false; + } + + public override string ToString() + { + if (_value == null) + return _astType.FullName; + return string.Format("{0}:{1}", _astType.FullName, _value); + } + } + + protected ComparableAstNode NewNode(string value = null) + { + return new ComparableAstNode(typeof(T), value); + } + + protected string FormatParseError(ParseTree result) + { + if (!result.HasErrors()) return string.Empty; + return string.Join("\n", result.ParserMessages); + } + + } +} diff --git a/Irony.Tests/Interpreter/EvaluationContextTests.cs b/Irony.Tests/Interpreter/EvaluationContextTests.cs new file mode 100644 index 0000000..672c18c --- /dev/null +++ b/Irony.Tests/Interpreter/EvaluationContextTests.cs @@ -0,0 +1,153 @@ +using Irony.Interpreter; +using Irony.Parsing; +using NUnit.Framework; + +namespace Irony.Tests.Interpreter +{ + [TestFixture] + public class EvaluationContextTests + { + [Test] + public void SetValueCreatesGlobalValueIfFrameStackEmpty() { + var sut = CreateContext(); + var symbol = SymbolTable.Symbols.TextToSymbol("test"); + sut.SetValue(symbol, 42); + var actual = sut.Globals[symbol]; + Assert.That(actual, Is.EqualTo(42)); + } + + [Test] + public void SetValueOverwritesGlobalValueIfFrameStackEmpty() { + var sut = CreateContext(); + var symbol = SymbolTable.Symbols.TextToSymbol("test"); + sut.SetValue(symbol, 42); + sut.SetValue(symbol, 24); + var actual = sut.Globals[symbol]; + Assert.That(actual, Is.EqualTo(24)); + } + + [Test] + public void SetValueOverwritesGlobalValueIfStackNotEmpty() { + var sut = CreateContext(); + var symbol = SymbolTable.Symbols.TextToSymbol("test"); + sut.SetValue(symbol, 42); + sut.PushFrame("x", null, sut.CurrentFrame); + sut.SetValue(symbol, 24); + var actual = sut.Globals[symbol]; + Assert.That(actual, Is.EqualTo(24)); + Assert.That(sut.CurrentFrame.Values.ContainsKey(symbol), Is.False); + } + + [Test] + public void SetValueCreatesLocalValueIfNotFound() { + var sut = CreateContext(); + var symbol = SymbolTable.Symbols.TextToSymbol("test"); + sut.PushFrame("x", null, sut.CurrentFrame); + sut.SetValue(symbol, 42); + Assert.That(sut.Globals.ContainsKey(symbol), Is.False); + Assert.That(sut.CurrentFrame.Values[symbol], Is.EqualTo(42)); + } + + [Test] + public void SetValueOverwritesValueAtSameStackFrame() + { + var sut = CreateContext(); + var symbol = SymbolTable.Symbols.TextToSymbol("test"); + sut.PushFrame("x", null, sut.CurrentFrame); + sut.SetValue(symbol, 24); + sut.SetValue(symbol, 42); + Assert.That(sut.CurrentFrame.Values[symbol], Is.EqualTo(42)); + } + + [Test] + public void SetValueOverwritesValueAtLowerStackFrame() + { + var sut = CreateContext(); + var symbol = SymbolTable.Symbols.TextToSymbol("test"); + sut.PushFrame("x", null, sut.CurrentFrame); + sut.SetValue(symbol, 24); + sut.PushFrame("y", null, sut.CurrentFrame); + sut.SetValue(symbol, 42); + Assert.That(sut.CurrentFrame.Values.ContainsKey(symbol), Is.False); + Assert.That(sut.CurrentFrame.Parent.Values[symbol], Is.EqualTo(42)); + } + + [Test] + public void SetLocalValueCreatesLocalValueEvenIfSymbolExistsInLowerFrame() + { + var sut = CreateContext(); + var symbol = SymbolTable.Symbols.TextToSymbol("test"); + sut.PushFrame("x", null, sut.CurrentFrame); + sut.SetValue(symbol, 24); + sut.PushFrame("y", null, sut.CurrentFrame); + sut.SetLocalValue(symbol, 42); + Assert.That(sut.CurrentFrame.Values[symbol], Is.EqualTo(42)); + Assert.That(sut.CurrentFrame.Parent.Values[symbol], Is.EqualTo(24)); + } + + [Test] + public void SetLocalValueOverwritesValueAtSameStackFrame() + { + var sut = CreateContext(); + var symbol = SymbolTable.Symbols.TextToSymbol("test"); + sut.PushFrame("x", null, sut.CurrentFrame); + sut.SetLocalValue(symbol, 24); + sut.SetLocalValue(symbol, 42); + Assert.That(sut.CurrentFrame.Values[symbol], Is.EqualTo(42)); + } + + [Test] + public void TryGetValueReturnsTrueIfValueExistsInCurrentFrame() + { + var sut = CreateContext(); + var symbol = SymbolTable.Symbols.TextToSymbol("test"); + sut.SetLocalValue(symbol, 12); + object value; + var actual = sut.TryGetValue(symbol, out value); + Assert.That(actual, Is.True); + } + + [Test] + public void TryGetValueReturnsTrueIfValueExistsInLowerFrame() + { + var sut = CreateContext(); + var symbol = SymbolTable.Symbols.TextToSymbol("test"); + sut.SetLocalValue(symbol, 12); + sut.PushFrame("x", null, sut.CurrentFrame); + object value; + var actual = sut.TryGetValue(symbol, out value); + Assert.That(actual, Is.True); + } + + [Test] + public void TryGetValueReturnsFalseIfValueDoesNotExists() + { + var sut = CreateContext(); + var symbol = SymbolTable.Symbols.TextToSymbol("test"); + object value; + var actual = sut.TryGetValue(symbol, out value); + Assert.That(actual, Is.False); + } + + [Test] + public void TryGetValueReadsValueFromTopFrameWhereFound() + { + var sut = CreateContext(); + var symbol = SymbolTable.Symbols.TextToSymbol("test"); + sut.SetLocalValue(symbol, 12); + sut.PushFrame("x", null, sut.CurrentFrame); + sut.SetLocalValue(symbol, 24); + sut.PushFrame("y", null, sut.CurrentFrame); + sut.SetLocalValue(symbol, 42); + sut.PushFrame("z", null, sut.CurrentFrame); + object actual; + sut.TryGetValue(symbol, out actual); + Assert.That(actual, Is.EqualTo(42)); + } + + private static EvaluationContext CreateContext() + { + return new EvaluationContext(new LanguageRuntime(new LanguageData(new Grammar()))); + } + } +} diff --git a/Irony/010.Irony.2012.csproj b/Irony/010.Irony.2012.csproj new file mode 100644 index 0000000..62faf7e --- /dev/null +++ b/Irony/010.Irony.2012.csproj @@ -0,0 +1,230 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {D81F5C91-D7DB-46E5-BC99-49488FB6814C} + Library + Properties + Irony + Irony + + + 3.5 + + + v4.0 + + + + + + + + + true + irony.snk + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + false + + + pdbonly + true + bin\Release\ + + + prompt + 4 + AllRules.ruleset + + + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MathResources.resx + True + True + + + + + + + + True + True + Resources.resx + + + + + ResXFileCodeGenerator + MathResources.Designer.cs + Designer + Microsoft.Scripting.Math + + + PublicResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/Irony/100.IronySilverlight.2012.csproj b/Irony/100.IronySilverlight.2012.csproj new file mode 100644 index 0000000..4ae6514 --- /dev/null +++ b/Irony/100.IronySilverlight.2012.csproj @@ -0,0 +1,227 @@ + + + + v3.5 + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {B945A137-E4C4-4DD5-9598-261F466549FE} + {A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Irony + IronySL + v5.0 + false + true + true + true + irony.snk + + + + + + + + + Silverlight + $(TargetFrameworkVersion) + + + 4.0 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT + true + true + prompt + 4 + AllRules.ruleset + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT + true + true + prompt + 4 + AllRules.ruleset + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + + + + + + \ No newline at end of file diff --git a/Irony/Ast/Base/AstNode.cs b/Irony/Ast/Base/AstNode.cs index 6ed6158..a9e7f25 100644 --- a/Irony/Ast/Base/AstNode.cs +++ b/Irony/Ast/Base/AstNode.cs @@ -14,6 +14,7 @@ using System.Collections.Generic; using System.Text; using System.CodeDom; +using System.Threading; using System.Xml; using System.IO; using Irony.Parsing; @@ -61,9 +62,20 @@ public virtual void Init(ParsingContext context, ParseTreeNode treeNode) { // exception handling implementation in base method. Otherwise, put all derived functionality // in EvaluateNode, or create other method(s) and set reference to it in EvaluateRef public virtual void Evaluate(EvaluationContext context, AstMode mode) { - try { - EvaluateRef(context, mode); - } catch (RuntimeException) { + try + { + context.CancellationToken.ThrowIfCancellationRequested(); + EvaluateRef(context, mode); + } + catch (OperationCanceledException) + { + throw; + } + catch (ThreadAbortException) + { + throw; + } + catch (RuntimeException) { throw; } catch (Exception ex) { throw new RuntimeException(ex.Message, ex, this.GetErrorAnchor()); diff --git a/Irony/Ast/Functions/FunctionCallNode.cs b/Irony/Ast/Functions/FunctionCallNode.cs index 73dde86..b8d0572 100644 --- a/Irony/Ast/Functions/FunctionCallNode.cs +++ b/Irony/Ast/Functions/FunctionCallNode.cs @@ -29,7 +29,9 @@ public override void Init(ParsingContext context, ParseTreeNode treeNode) { base.Init(context, treeNode); TargetRef = AddChild("Target", treeNode.ChildNodes[0]); _targetName = treeNode.ChildNodes[0].FindTokenAndGetText(); - Arguments = AddChild("Args", treeNode.ChildNodes[1]); + // Arguments are optionally + if (treeNode.ChildNodes.Count > 1) + Arguments = AddChild("Args", treeNode.ChildNodes[1]); AsString = "Call " + _targetName; } @@ -38,7 +40,8 @@ public override void EvaluateNode(EvaluationContext context, AstMode mode) { var target = context.Data.Pop() as ICallTarget; if (target == null) context.ThrowError(Resources.ErrVarIsNotCallable, _targetName); - Arguments.Evaluate(context, AstMode.Read); + if (Arguments != null) + Arguments.Evaluate(context, AstMode.Read); target.Call(context); } diff --git a/Irony/Ast/PrimitiveNodes/LocalIdentifierNode.cs b/Irony/Ast/PrimitiveNodes/LocalIdentifierNode.cs new file mode 100644 index 0000000..7a99699 --- /dev/null +++ b/Irony/Ast/PrimitiveNodes/LocalIdentifierNode.cs @@ -0,0 +1,56 @@ +#region License +/* ********************************************************************************** + * Copyright (c) Roman Ivantsov + * This source code is subject to terms and conditions of the MIT License + * for Irony. A copy of the license can be found in the License.txt file + * at the root of this distribution. + * By using this source code in any fashion, you are agreeing to be bound by the terms of the + * MIT License. + * You must not remove this notice from this software. + * **********************************************************************************/ +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml; +using Irony.Parsing; +using Irony.Interpreter; + +namespace Irony.Ast +{ + + public class LocalIdentifierNode : AstNode + { + public Symbol Symbol; + + public LocalIdentifierNode() { } + + public override void Init(ParsingContext context, ParseTreeNode treeNode) + { + base.Init(context, treeNode); + Symbol = treeNode.Token.Symbol; + AsString = Symbol.Text; + } + + + public override void EvaluateNode(EvaluationContext context, AstMode mode) + { + switch (mode) + { + case AstMode.Read: + object value; + if (context.TryGetValue(Symbol, out value)) + context.Data.Push(value); + else + context.ThrowError(Resources.ErrVarNotDefined, Symbol); + break; + case AstMode.Write: + context.SetLocalValue(Symbol, context.Data.Pop()); + break; + } + } + + }//class +}//namespace diff --git a/Irony/Interpreter/EvaluationContext.cs b/Irony/Interpreter/EvaluationContext.cs index 8d33fbc..ad2499f 100644 --- a/Irony/Interpreter/EvaluationContext.cs +++ b/Irony/Interpreter/EvaluationContext.cs @@ -48,6 +48,7 @@ public partial class EvaluationContext { public StackFrame TopFrame, CurrentFrame; public StringBuilder OutputBuffer = new StringBuilder(); public int EvaluationTime; + public CancellationToken CancellationToken { get; set; } public EvaluationContext(LanguageRuntime runtime) { Runtime = runtime; @@ -72,7 +73,7 @@ public bool HasLastResult { get { return LastResult != Runtime.Unassigned; } } - public void PushFrame(string methodName, AstNode node, StackFrame parent) { + public void PushFrame(string methodName, AstNode node, StackFrame parent) { CurrentFrame = new StackFrame(this, methodName, CurrentFrame, parent); } public void PopFrame() { @@ -91,11 +92,36 @@ public bool TryGetValue(Symbol symbol, out object value) { return false; } + /// + /// Finds first occurrence of symbol in frame stack and overwrites the value. + /// If the symbol is not found, a new symbol will be created on the current frame. + /// public void SetValue(Symbol symbol, object value) { var keySymbol = LanguageCaseSensitive ? symbol : symbol.LowerSymbol; + + // Find topmost frame with symbol and assign value + var frame = CurrentFrame; + while (frame != null) { + if (frame.Values.ContainsKey(keySymbol)) { + frame.Values[keySymbol] = value; + return; + } + frame = frame.Parent; + } + // Value not found in frame stack, assign value as new local value CurrentFrame.Values[keySymbol] = value; } + /// + /// Sets value in current frame. If the symbol already exists it will be overwritten. + /// This method will not look for existing symbol down the frame stack. + /// + public void SetLocalValue(Symbol symbol, object value) { + var keySymbol = LanguageCaseSensitive ? symbol : symbol.LowerSymbol; + CurrentFrame.Values[keySymbol] = value; + } + + public void Write(string text) { OutputBuffer.Append(text); } diff --git a/Irony/Interpreter/ScriptInterpreter.cs b/Irony/Interpreter/ScriptInterpreter.cs index 9d64068..b23edcd 100644 --- a/Irony/Interpreter/ScriptInterpreter.cs +++ b/Irony/Interpreter/ScriptInterpreter.cs @@ -26,6 +26,7 @@ public enum InterpreterStatus { WaitingMoreInput, //command line only SyntaxError, RuntimeError, + Canceled, Aborted } @@ -42,7 +43,13 @@ public class ScriptInterpreter { public InterpreterStatus Status { get; private set; } public bool RethrowExceptions = true; - public bool PrintParseErrors = true; + public bool PrintParseErrors = true; + + private CancellationTokenSource _cancellationTokenSource; + + private readonly ManualResetEvent _waitHandle = new ManualResetEvent(true); + public WaitHandle WaitHandle { get { return _waitHandle; } } + public ParseMode ParseMode { get { return Parser.Context.Mode; } set { Parser.Context.Mode = value; } @@ -51,7 +58,7 @@ public ValuesTable Globals { get { return EvaluationContext.TopFrame.Values; } } //internal, real status of interpreter. The public Status field gets updated only on exit from public methods - // We want to make sure external code sees interpeter as BUSY until we actually completed operation internally + // We want to make sure external code sees interpreter as BUSY until we actually completed operation internally private InterpreterStatus _internalStatus; #endregion @@ -78,10 +85,12 @@ public void Evaluate(ParseTree parsedScript) { } public void Evaluate() { try { + _waitHandle.Reset(); _internalStatus = Status = InterpreterStatus.Evaluating; ParseAndEvaluate(); } finally { Status = _internalStatus; + _waitHandle.Set(); } } @@ -94,7 +103,8 @@ public void EvaluateAsync(ParseTree parsedScript) { EvaluateAsync(); } public void EvaluateAsync() { - CheckNotBusy(); + CheckNotBusy(); + _waitHandle.Reset(); Status = _internalStatus = InterpreterStatus.Evaluating; WorkerThread = new Thread(AsyncThreadStart); WorkerThread.Start(null); @@ -117,7 +127,9 @@ public ParseTree ParsedScript { _parsedScript = value; _script = (_parsedScript == null ? null : _parsedScript.SourceText); } - } ParseTree _parsedScript; + } + + ParseTree _parsedScript; public bool IsBusy() { return Status == InterpreterStatus.Evaluating; @@ -137,13 +149,27 @@ public ParserMessageList GetParserMessages() { return ParsedScript.ParserMessages; } - public void Abort() { + /// + /// Signals the interpreter to cancel at the next AstNode evaluation. + /// The script will be aborted if the is exceeded. + /// Use to determine if the script was canceled, aborted or terminated before abortion. + /// + public void Abort(TimeSpan cancelTimeout) { try { + if (_cancellationTokenSource != null) + _cancellationTokenSource.Cancel(); + _cancellationTokenSource = null; if (WorkerThread == null) return; - WorkerThread.Abort(); - WorkerThread.Join(50); + WorkerThread.Join((int) cancelTimeout.TotalMilliseconds); + if (WorkerThread.IsAlive) WorkerThread.Abort(); } catch { } WorkerThread = null; + WaitHandle.WaitOne(); + } + + public void Abort() + { + Abort(TimeSpan.FromSeconds(5)); } #endregion @@ -151,8 +177,14 @@ public void Abort() { private void AsyncThreadStart(object data) { try { ParseAndEvaluate(); - } finally { + } + catch { + // Eat rethrown runtime exceptions. Uncaught thread exceptions may bring the whole application down. + // The user should check Status and LastException instead. + } + finally { Status = _internalStatus; + _waitHandle.Set(); } } private void CheckNotBusy() { @@ -162,20 +194,32 @@ private void CheckNotBusy() { private void ParseAndEvaluate() { EvaluationContext.EvaluationTime = 0; - try { + try + { LastException = null; - if(ParsedScript == null) { + if (ParsedScript == null) + { //don't evaluate empty strings, just return if (Script == null || Script.Trim() == string.Empty && Status == InterpreterStatus.Ready) return; ParsedScript = this.Parser.Parse(Script, "source"); CheckParseStatus(); - if(_internalStatus != InterpreterStatus.Evaluating) return; + if (_internalStatus != InterpreterStatus.Evaluating) return; } - if(ParsedScript == null) + if (ParsedScript == null) return; EvaluateParsedScript(); _internalStatus = InterpreterStatus.Ready; - } catch (Exception ex) { + _cancellationTokenSource = null; + } + catch (OperationCanceledException) + { + _internalStatus = InterpreterStatus.Canceled; + } + catch (ThreadAbortException) + { + _internalStatus = InterpreterStatus.Aborted; + } + catch (Exception ex) { LastException = ex; _internalStatus = InterpreterStatus.RuntimeError; if (LastException != null && RethrowExceptions) @@ -187,6 +231,8 @@ private void EvaluateParsedScript() { var iRoot = GetAstInterface(); if (iRoot == null) return; EvaluationContext.ClearLastResult(); + _cancellationTokenSource = new CancellationTokenSource(); + EvaluationContext.CancellationToken = _cancellationTokenSource.Token; var start = Environment.TickCount; iRoot.Evaluate(EvaluationContext, AstMode.Read); EvaluationContext.EvaluationTime = Environment.TickCount - start; diff --git a/Irony/Interpreter/StackFrame.cs b/Irony/Interpreter/StackFrame.cs index f3ff64d..d6ff38e 100644 --- a/Irony/Interpreter/StackFrame.cs +++ b/Irony/Interpreter/StackFrame.cs @@ -23,7 +23,7 @@ public class StackFrame { public string MethodName; //for debugging purposes public StackFrame Parent; //Lexical parent - not the same as the caller public StackFrame Caller; - internal ValuesTable Values; //global values for top frame; parameters and local variables for method frame + public ValuesTable Values; //global values for top frame; parameters and local variables for method frame public StackFrame(EvaluationContext context, ValuesTable globals) { Context = context; diff --git a/Irony/Properties/AssemblyInfo.cs b/Irony/Properties/AssemblyInfo.cs index fb3d231..50948d1 100644 --- a/Irony/Properties/AssemblyInfo.cs +++ b/Irony/Properties/AssemblyInfo.cs @@ -55,5 +55,5 @@ // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("1.0.3.0")] +[assembly: AssemblyFileVersion("1.0.3.0")] diff --git a/Irony_All.2012.sln b/Irony_All.2012.sln new file mode 100644 index 0000000..27a82b9 --- /dev/null +++ b/Irony_All.2012.sln @@ -0,0 +1,119 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{05F0AC0D-AD43-45B4-8A98-00C54CF5280D}" + ProjectSection(SolutionItems) = preProject + License.txt = License.txt + ReadMe.txt = ReadMe.txt + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "010.Irony.2012", "Irony\010.Irony.2012.csproj", "{D81F5C91-D7DB-46E5-BC99-49488FB6814C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "020.Irony.Samples.2012", "Irony.Samples\020.Irony.Samples.2012.csproj", "{AD263C0B-99D3-40A9-9DBF-9086CC524A0B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "030.Irony.GrammarExplorer.2012", "Irony.GrammarExplorer\030.Irony.GrammarExplorer.2012.csproj", "{AE1C04A8-B03D-4144-98E9-BF66C50265E7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "040.Irony.Tests.VsTest.2012", "Irony.Tests\040.Irony.Tests.VsTest.2012.csproj", "{0CFA8CEE-0110-49C1-93E5-CB7BE3A5716B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "025.Irony.Samples.Console.2012", "Irony.Samples.Console\025.Irony.Samples.Console.2012.csproj", "{5A31B964-CDFA-4406-9316-32A0F04CE149}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "050.Irony.Tests.NUnit.2012", "Irony.Tests\050.Irony.Tests.NUnit.2012.csproj", "{1A98BEDA-DF53-49B7-A366-2ED7606036BD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "100.IronySilverlight.2012", "Irony\100.IronySilverlight.2012.csproj", "{B945A137-E4C4-4DD5-9598-261F466549FE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + FxCop|Any CPU = FxCop|Any CPU + Release|Any CPU = Release|Any CPU + Silverlight Debug|Any CPU = Silverlight Debug|Any CPU + Silverlight Release|Any CPU = Silverlight Release|Any CPU + SpecSharp|Any CPU = SpecSharp|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D81F5C91-D7DB-46E5-BC99-49488FB6814C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D81F5C91-D7DB-46E5-BC99-49488FB6814C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D81F5C91-D7DB-46E5-BC99-49488FB6814C}.FxCop|Any CPU.ActiveCfg = Release|Any CPU + {D81F5C91-D7DB-46E5-BC99-49488FB6814C}.FxCop|Any CPU.Build.0 = Release|Any CPU + {D81F5C91-D7DB-46E5-BC99-49488FB6814C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D81F5C91-D7DB-46E5-BC99-49488FB6814C}.Release|Any CPU.Build.0 = Release|Any CPU + {D81F5C91-D7DB-46E5-BC99-49488FB6814C}.Silverlight Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D81F5C91-D7DB-46E5-BC99-49488FB6814C}.Silverlight Debug|Any CPU.Build.0 = Debug|Any CPU + {D81F5C91-D7DB-46E5-BC99-49488FB6814C}.Silverlight Release|Any CPU.ActiveCfg = Release|Any CPU + {D81F5C91-D7DB-46E5-BC99-49488FB6814C}.Silverlight Release|Any CPU.Build.0 = Release|Any CPU + {D81F5C91-D7DB-46E5-BC99-49488FB6814C}.SpecSharp|Any CPU.ActiveCfg = Release|Any CPU + {D81F5C91-D7DB-46E5-BC99-49488FB6814C}.SpecSharp|Any CPU.Build.0 = Release|Any CPU + {AD263C0B-99D3-40A9-9DBF-9086CC524A0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AD263C0B-99D3-40A9-9DBF-9086CC524A0B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AD263C0B-99D3-40A9-9DBF-9086CC524A0B}.FxCop|Any CPU.ActiveCfg = Release|Any CPU + {AD263C0B-99D3-40A9-9DBF-9086CC524A0B}.FxCop|Any CPU.Build.0 = Release|Any CPU + {AD263C0B-99D3-40A9-9DBF-9086CC524A0B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AD263C0B-99D3-40A9-9DBF-9086CC524A0B}.Release|Any CPU.Build.0 = Release|Any CPU + {AD263C0B-99D3-40A9-9DBF-9086CC524A0B}.Silverlight Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AD263C0B-99D3-40A9-9DBF-9086CC524A0B}.Silverlight Debug|Any CPU.Build.0 = Debug|Any CPU + {AD263C0B-99D3-40A9-9DBF-9086CC524A0B}.Silverlight Release|Any CPU.ActiveCfg = Release|Any CPU + {AD263C0B-99D3-40A9-9DBF-9086CC524A0B}.Silverlight Release|Any CPU.Build.0 = Release|Any CPU + {AD263C0B-99D3-40A9-9DBF-9086CC524A0B}.SpecSharp|Any CPU.ActiveCfg = Release|Any CPU + {AD263C0B-99D3-40A9-9DBF-9086CC524A0B}.SpecSharp|Any CPU.Build.0 = Release|Any CPU + {AE1C04A8-B03D-4144-98E9-BF66C50265E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AE1C04A8-B03D-4144-98E9-BF66C50265E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AE1C04A8-B03D-4144-98E9-BF66C50265E7}.FxCop|Any CPU.ActiveCfg = Release|Any CPU + {AE1C04A8-B03D-4144-98E9-BF66C50265E7}.FxCop|Any CPU.Build.0 = Release|Any CPU + {AE1C04A8-B03D-4144-98E9-BF66C50265E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AE1C04A8-B03D-4144-98E9-BF66C50265E7}.Release|Any CPU.Build.0 = Release|Any CPU + {AE1C04A8-B03D-4144-98E9-BF66C50265E7}.Silverlight Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AE1C04A8-B03D-4144-98E9-BF66C50265E7}.Silverlight Debug|Any CPU.Build.0 = Debug|Any CPU + {AE1C04A8-B03D-4144-98E9-BF66C50265E7}.Silverlight Release|Any CPU.ActiveCfg = Release|Any CPU + {AE1C04A8-B03D-4144-98E9-BF66C50265E7}.Silverlight Release|Any CPU.Build.0 = Release|Any CPU + {AE1C04A8-B03D-4144-98E9-BF66C50265E7}.SpecSharp|Any CPU.ActiveCfg = Release|Any CPU + {AE1C04A8-B03D-4144-98E9-BF66C50265E7}.SpecSharp|Any CPU.Build.0 = Release|Any CPU + {0CFA8CEE-0110-49C1-93E5-CB7BE3A5716B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0CFA8CEE-0110-49C1-93E5-CB7BE3A5716B}.FxCop|Any CPU.ActiveCfg = Release|Any CPU + {0CFA8CEE-0110-49C1-93E5-CB7BE3A5716B}.FxCop|Any CPU.Build.0 = Release|Any CPU + {0CFA8CEE-0110-49C1-93E5-CB7BE3A5716B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0CFA8CEE-0110-49C1-93E5-CB7BE3A5716B}.Release|Any CPU.Build.0 = Release|Any CPU + {0CFA8CEE-0110-49C1-93E5-CB7BE3A5716B}.Silverlight Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0CFA8CEE-0110-49C1-93E5-CB7BE3A5716B}.Silverlight Debug|Any CPU.Build.0 = Debug|Any CPU + {0CFA8CEE-0110-49C1-93E5-CB7BE3A5716B}.Silverlight Release|Any CPU.ActiveCfg = Release|Any CPU + {0CFA8CEE-0110-49C1-93E5-CB7BE3A5716B}.Silverlight Release|Any CPU.Build.0 = Release|Any CPU + {0CFA8CEE-0110-49C1-93E5-CB7BE3A5716B}.SpecSharp|Any CPU.ActiveCfg = Release|Any CPU + {0CFA8CEE-0110-49C1-93E5-CB7BE3A5716B}.SpecSharp|Any CPU.Build.0 = Release|Any CPU + {5A31B964-CDFA-4406-9316-32A0F04CE149}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5A31B964-CDFA-4406-9316-32A0F04CE149}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5A31B964-CDFA-4406-9316-32A0F04CE149}.FxCop|Any CPU.ActiveCfg = Release|Any CPU + {5A31B964-CDFA-4406-9316-32A0F04CE149}.FxCop|Any CPU.Build.0 = Release|Any CPU + {5A31B964-CDFA-4406-9316-32A0F04CE149}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5A31B964-CDFA-4406-9316-32A0F04CE149}.Release|Any CPU.Build.0 = Release|Any CPU + {5A31B964-CDFA-4406-9316-32A0F04CE149}.Silverlight Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5A31B964-CDFA-4406-9316-32A0F04CE149}.Silverlight Debug|Any CPU.Build.0 = Debug|Any CPU + {5A31B964-CDFA-4406-9316-32A0F04CE149}.Silverlight Release|Any CPU.ActiveCfg = Release|Any CPU + {5A31B964-CDFA-4406-9316-32A0F04CE149}.Silverlight Release|Any CPU.Build.0 = Release|Any CPU + {5A31B964-CDFA-4406-9316-32A0F04CE149}.SpecSharp|Any CPU.ActiveCfg = Release|Any CPU + {5A31B964-CDFA-4406-9316-32A0F04CE149}.SpecSharp|Any CPU.Build.0 = Release|Any CPU + {1A98BEDA-DF53-49B7-A366-2ED7606036BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1A98BEDA-DF53-49B7-A366-2ED7606036BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1A98BEDA-DF53-49B7-A366-2ED7606036BD}.FxCop|Any CPU.ActiveCfg = Release|Any CPU + {1A98BEDA-DF53-49B7-A366-2ED7606036BD}.FxCop|Any CPU.Build.0 = Release|Any CPU + {1A98BEDA-DF53-49B7-A366-2ED7606036BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1A98BEDA-DF53-49B7-A366-2ED7606036BD}.Silverlight Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1A98BEDA-DF53-49B7-A366-2ED7606036BD}.Silverlight Debug|Any CPU.Build.0 = Debug|Any CPU + {1A98BEDA-DF53-49B7-A366-2ED7606036BD}.Silverlight Release|Any CPU.ActiveCfg = Release|Any CPU + {1A98BEDA-DF53-49B7-A366-2ED7606036BD}.Silverlight Release|Any CPU.Build.0 = Release|Any CPU + {1A98BEDA-DF53-49B7-A366-2ED7606036BD}.SpecSharp|Any CPU.ActiveCfg = Release|Any CPU + {1A98BEDA-DF53-49B7-A366-2ED7606036BD}.SpecSharp|Any CPU.Build.0 = Release|Any CPU + {B945A137-E4C4-4DD5-9598-261F466549FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B945A137-E4C4-4DD5-9598-261F466549FE}.FxCop|Any CPU.ActiveCfg = Release|Any CPU + {B945A137-E4C4-4DD5-9598-261F466549FE}.FxCop|Any CPU.Build.0 = Release|Any CPU + {B945A137-E4C4-4DD5-9598-261F466549FE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B945A137-E4C4-4DD5-9598-261F466549FE}.Release|Any CPU.Build.0 = Release|Any CPU + {B945A137-E4C4-4DD5-9598-261F466549FE}.Silverlight Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B945A137-E4C4-4DD5-9598-261F466549FE}.Silverlight Debug|Any CPU.Build.0 = Debug|Any CPU + {B945A137-E4C4-4DD5-9598-261F466549FE}.Silverlight Release|Any CPU.ActiveCfg = Release|Any CPU + {B945A137-E4C4-4DD5-9598-261F466549FE}.Silverlight Release|Any CPU.Build.0 = Release|Any CPU + {B945A137-E4C4-4DD5-9598-261F466549FE}.SpecSharp|Any CPU.ActiveCfg = Release|Any CPU + {B945A137-E4C4-4DD5-9598-261F466549FE}.SpecSharp|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal