diff --git a/Source/ReferenceTests/Language/TryCatchFinallyTests.cs b/Source/ReferenceTests/Language/TryCatchFinallyTests.cs new file mode 100644 index 00000000..c74d5ca4 --- /dev/null +++ b/Source/ReferenceTests/Language/TryCatchFinallyTests.cs @@ -0,0 +1,40 @@ +using System; +using NUnit.Framework; + +namespace ReferenceTests.Language +{ + [TestFixture] + public class TryCatchFinallyTests : ReferenceTestBase + { + [Test] + public void TryFinallyWithoutCatch() + { + ExecuteAndCompareTypedResult( + "try { 2 + 2 } finally { 0 }", + 4, + 0 + ); + } + + [Test] + public void TryCatchFinally() + { + ExecuteAndCompareTypedResult( + "try { 2 + 2 } catch { -1 } finally { 0 }", + 4, + 0 + ); + } + + [Test] + public void TryCatchFinallyWithException() + { + ExecuteAndCompareTypedResult( + "try { 2 / 0 } catch { -1 } finally { 3 }", + -1, + 3 + ); + } + } +} + diff --git a/Source/ReferenceTests/ReferenceTests.csproj b/Source/ReferenceTests/ReferenceTests.csproj index 200087fc..6d59f245 100644 --- a/Source/ReferenceTests/ReferenceTests.csproj +++ b/Source/ReferenceTests/ReferenceTests.csproj @@ -132,6 +132,7 @@ + diff --git a/Source/System.Management/Pash/Implementation/ExecutionVisitor.cs b/Source/System.Management/Pash/Implementation/ExecutionVisitor.cs index 337f0f74..e64c11ba 100644 --- a/Source/System.Management/Pash/Implementation/ExecutionVisitor.cs +++ b/Source/System.Management/Pash/Implementation/ExecutionVisitor.cs @@ -1322,8 +1322,16 @@ public override AstVisitAction VisitTryStatement(TryStatementAst tryStatementAst { SetUnderscoreVariable(ex); + // not yet considered: no catches, special catches! tryStatementAst.CatchClauses.Last().Body.Visit(this); } + finally + { + if (tryStatementAst.Finally != null) + { + tryStatementAst.Finally.Visit(this); + } + } return AstVisitAction.SkipChildren; } diff --git a/Source/System.Management/Pash/ParserIntrinsics/AstBuilder.cs b/Source/System.Management/Pash/ParserIntrinsics/AstBuilder.cs index dafa2bdb..b3b37552 100644 --- a/Source/System.Management/Pash/ParserIntrinsics/AstBuilder.cs +++ b/Source/System.Management/Pash/ParserIntrinsics/AstBuilder.cs @@ -424,11 +424,20 @@ private StatementAst BuildBreakStatementAst(ParseTreeNode parseTreeNode) StatementAst BuildTryStatementAst(ParseTreeNode parseTreeNode) { + var subClauses = parseTreeNode.ChildNodes[0].ChildNodes; + var catchClauses = subClauses[2]; + var finallyClause = subClauses.Count > 3 ? subClauses[3] : null; + // there might be no catch clauses, then a finally clause could follow directly + if (catchClauses.Term == this._grammar.finally_clause) + { + finallyClause = catchClauses; + catchClauses = null; + } return new TryStatementAst( new ScriptExtent(parseTreeNode), - BuildStatementBlockAst(parseTreeNode.ChildNodes[0].ChildNodes[1]), - BuildCatchClausesAst(parseTreeNode.ChildNodes[0].ChildNodes[2]), - null + BuildStatementBlockAst(subClauses[1]), + catchClauses == null ? Enumerable.Empty() : BuildCatchClausesAst(catchClauses), + finallyClause == null ? null : BuildFinallyClauseAst(finallyClause) ); } @@ -452,6 +461,13 @@ private CatchClauseAst BuildCatchClauseAst(ParseTreeNode parseTreeNode) ); } + StatementBlockAst BuildFinallyClauseAst(ParseTreeNode finallyClause) + { + VerifyTerm(finallyClause, this._grammar.finally_clause); + + return BuildStatementBlockAst(finallyClause.ChildNodes[1]); + } + StatementAst BuildDataStatementAst(ParseTreeNode parseTreeNode) { throw new NotImplementedException();