public override void Generate(ScriptLoader owner) { LookaheadStack <INodeEnumerator> nodes = this.nodes; LookaheadStack <uint> states = this.states; int proc_state = 0; object proc_arg = null; INodeEnumerator ne = m_enumerator; IExceptionHandler ehnd = m_handler; loop: uint state = states.PopOrDefault(); while (ne.MoveNext()) { INode node = ne.Current; if (node.ChildCount == 0) { bool goNext; do { goNext = OnGenerate(node.GetToken(), state, ref proc_state, ref proc_arg); if (ehnd.FailCount > 0) { ne.Dispose(); while (nodes.Count > 0) { nodes.Pop().Dispose(); } return; } else if (proc_state != 0) { proc_arg = OnRequested(ref state, ref proc_state, proc_arg); } // 다음으로 넘어가지 않는다 // 반복 } while (!goNext); } else { nodes.Push(ne); ne = node.GetEnumerator(); } } ne.Dispose(); if (nodes.Count > 0) { ne = nodes.Pop(); goto loop; } // 끝내기 전에 마무리지어야 한다 }
// 핵심 // 1. Generate는 Interruptible하다는 점 // 2. ScriptLoader가 더 많은 일을 할 수 있게되었다는 점 (코드 생성 범위를 벗어난 일을 할 수 있게됨) // 3. 예를 들면 include // 4. state를 1로 잡고 argument에 string path인자를 넣어준 뒤 true를 반환 // 4-a. 반환 전 사용되고 있는 모든 값을 필드에 박아서 저장 // 5. 로더가 해당 스크립트를 로딩한 뒤 받은 type을 argument에 넣고 continue // 6. 나머지 작업을 처리한다 /// <summary> /// 해제 /// </summary> protected virtual void Dispose(bool disposing) { if (m_handler != null) { m_enumerator.Dispose(); m_enumerator = null; m_handler = null; } }
public bool MoveNext() { if (e1 == null) // ok { if (ne.MoveNext()) { current = ((TokNode)ne.Current).GetToken(); return(true); } else { return(false); } } loop: if (ne.MoveNext()) { if (ne.Current.ChildCount == 0) { current = ((TokNode)ne.Current).GetToken(); return(true); } else { stack.Push(ne); ne = ne.Current.GetEnumerator(); } goto loop; } if (stack.Count > 0) { ne.Dispose(); ne = stack.Pop(); goto loop; } if (save >= 0) { e1.index = save; } return(false); }