//----------------------------------------------------------------------------------------------------------------------------------------------------- public TryStatement FindOutermostTryStatementWithin(StatementScope homeScope) { TryStatement result = null; var scope = this; while (!ReferenceEquals(scope, homeScope)) { if (scope == null) { throw new Exception("Internal error: bad scope hierarchy."); } if (scope.ThisExceptionBlockType == ExceptionBlockType.Finally) { throw new InvalidOperationException("Leaving from withing FINALLY block is not allowed."); } if (scope.ThisExceptionBlockType != ExceptionBlockType.None) { result = scope.ThisExceptionStatement; } scope = scope.m_Previous; } return(result); }
//----------------------------------------------------------------------------------------------------------------------------------------------------- public StatementScope(StatementBlock statementBlock, RewriteMode rewriteMode) { m_Previous = s_Current; m_Root = (m_Previous != null ? m_Previous.Root : this); m_StatementBlock = statementBlock; m_Writer = statementBlock.OwnerMethod.TransparentWriter; m_OwnerMethod = statementBlock.OwnerMethod; m_OwnerClass = statementBlock.OwnerMethod.OwnerClass; m_Depth = 1; m_ThisExceptionBlockType = ExceptionBlockType.None; m_ThisExceptionStatement = null; if (m_Previous != null) { m_InheritedLoopStatement = m_Previous.InheritedLoopStatement; m_InheritedExceptionStatement = m_Previous.InheritedExceptionStatement; m_InheritedExceptionBlockType = m_Previous.InheritedExceptionBlockType; } m_StatementBlock = statementBlock; m_IsRewriteMode = true; m_RewriteInsertionIndex = 0; s_Current = this; }
//----------------------------------------------------------------------------------------------------------------------------------------------------- public static IDisposable Stash() { var stash = new StashScope(s_Current); s_Current = null; return(stash); }
//----------------------------------------------------------------------------------------------------------------------------------------------------- private StatementScope(StatementBlock statementBlock, bool attachStatementBlock) { m_Previous = s_Current; m_Root = m_Previous.Root; if (m_Previous == null) { throw new InvalidOperationException("Parent scope is not present."); } m_StatementBlock = statementBlock; m_Writer = m_Previous.m_Writer; m_OwnerMethod = m_Previous.m_OwnerMethod; m_OwnerClass = m_Previous.m_OwnerClass; m_Depth = m_Previous.Depth + 1; m_InheritedLoopStatement = m_Previous.InheritedLoopStatement; m_ThisExceptionBlockType = ExceptionBlockType.None; m_ThisExceptionStatement = null; m_InheritedExceptionStatement = m_Previous.InheritedExceptionStatement; m_InheritedExceptionBlockType = m_Previous.InheritedExceptionBlockType; m_StatementBlock = (attachStatementBlock ? AttachStatementBlock(statementBlock) : null); s_Current = this; }
//----------------------------------------------------------------------------------------------------------------------------------------------------- public void Attach(StatementScope scope) { m_OwnerMethod = scope.OwnerMethod; m_ParentBlock = (scope.Previous != null ? scope.Previous.StatementBlock : null); m_Depth = (m_ParentBlock != null ? m_ParentBlock.Depth + 1 : 0); m_EnclosingTryStatement = scope.InheritedExceptionStatement; m_EnclosingLoopStatement = scope.InheritedLoopStatement; }
//----------------------------------------------------------------------------------------------------------------------------------------------------- #region IHapilUsingSyntax Members public void Do(Action body) { using (var scope = new StatementScope(m_BodyBlock)) { var writer = scope.Writer; var disposable = writer.Local <IDisposable>(initialValue: m_Disposable.CastTo <IDisposable>()); writer.Try(() => { body(); }) .Finally(() => { writer.If(disposable != writer.Const <IDisposable>(null)).Then(() => { disposable.Void(x => x.Dispose); }); }); } }
//----------------------------------------------------------------------------------------------------------------------------------------------------- #region IHapilForeachDoSyntax<TItem> Members public void Do(Action <ILoopBody, Local <TElement> > body) { using (var scope = new StatementScope(m_BodyBlock, loopStatement: this)) { var writer = scope.Writer; var enumerator = writer.Local <IEnumerator <TElement> >(); enumerator.Assign(m_Collection.CastTo <IEnumerable <TElement> >().Func <IEnumerator <TElement> >(x => x.GetEnumerator)); writer.Using(enumerator).Do(() => { m_InnerWhile = (WhileStatement)writer.While(enumerator.Func <bool>(e => e.MoveNext)); m_InnerWhile.Do(loop => { m_Element.Assign(enumerator.Prop(e => e.Current)); body(this, m_Element); }); }); } }
//----------------------------------------------------------------------------------------------------------------------------------------------------- public ProceedStatement(MethodMember ownerMethod, MethodWriterBase[] decoratedWriters, IMutableOperand returnValueLocal) { m_OwnerMethod = ownerMethod; m_DecoratedStatements = new StatementBlock(); m_ReturnValueLocal = returnValueLocal; using (var scope = new StatementScope(m_DecoratedStatements /*, exceptionStatement: null, blockType: ExceptionBlockType.None*/)) { m_LeaveLabel = scope.DefineLabel(); foreach (var writer in decoratedWriters) { writer.SetupDecoratedMode(returnValueLocal, m_LeaveLabel); writer.Flush(); } m_LeaveLabel.MarkLabel(); } }
//----------------------------------------------------------------------------------------------------------------------------------------------------- #region IHapilLockSyntax Members public void Do(Action body) { var timeoutExceptionMessage = string.Format("Lock could not be acquired within allotted timeout ({0} ms).", m_MillisecondsTimeout); using (var scope = new StatementScope(m_BodyBlock)) { var w = scope.Writer; w.If(!Static.Func(Monitor.TryEnter, m_SyncRoot, w.Const(m_MillisecondsTimeout))).Then(() => w.Throw <TimeoutException>(timeoutExceptionMessage) ); w.Try(() => { body(); }) .Finally(() => { Static.Void(Monitor.Exit, m_SyncRoot); }); } }
//----------------------------------------------------------------------------------------------------------------------------------------------------- public StatementScope(ClassType ownerClass, MethodWriterBase writer, StatementBlock statementBlock) { if (s_Current != null) { throw new InvalidOperationException("Root scope already exists."); } m_Writer = writer; m_OwnerMethod = (writer != null ? writer.OwnerMethod : null); m_OwnerClass = ownerClass; m_Depth = 0; m_InheritedLoopStatement = null; m_ThisExceptionBlockType = ExceptionBlockType.None; m_ThisExceptionStatement = null; m_InheritedExceptionStatement = null; m_InheritedExceptionBlockType = ExceptionBlockType.None; m_Previous = null; m_Root = this; s_Current = this; m_StatementBlock = AttachStatementBlock(statementBlock); }
//----------------------------------------------------------------------------------------------------------------------------------------------------- public LabelStatement(MethodMember ownerMethod, StatementScope homeScope) { m_OwnerMethod = ownerMethod; m_Label = ownerMethod.MethodFactory.GetILGenerator().DefineLabel(); m_HomeScope = homeScope; }
//----------------------------------------------------------------------------------------------------------------------------------------------------- protected LoopStatementBase() { m_HomeScope = StatementScope.Current; }
//------------------------------------------------------------------------------------------------------------------------------------------------- public StashScope(StatementScope current) { m_SavedCurrent = current; }
//----------------------------------------------------------------------------------------------------------------------------------------------------- public static void Cleanup() { s_Current = null; }