PageRenderTime 38ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/source/core/middle/Resolver.ooc

http://github.com/nddrylliog/oc
Unknown | 215 lines | 172 code | 43 blank | 0 comment | 0 complexity | 264a07dfe01e5f98ed055ca0d82ac6b6 MD5 | raw file
  1. import os/Coro, structs/[ArrayList, List, Stack, HashBag]
  2. import ast/[Node, Module]
  3. import ../backend/Backend
  4. import ../frontend/BuildParams
  5. Task: class {
  6. resolver: Resolver
  7. id: Int { get set }
  8. idSeed := static 0
  9. parent: Task
  10. parentCoro, coro: Coro
  11. oldStackBase: Pointer
  12. node: Node { get set }
  13. done?: Bool { get set }
  14. userdata: HashBag
  15. lastFree := static Stack<This> new()
  16. init: func ~real (=parent, .node, dummy: Bool) {
  17. init(parent resolver, parent coro, node)
  18. }
  19. init: func ~onlyCoro (=resolver, =parentCoro, =node) {
  20. idSeed += 1
  21. id = idSeed
  22. coro = Coro new()
  23. done? = false
  24. version(OOC_TASK_DEBUG) { "Creating new task %s" printfln(toString()) }
  25. }
  26. new: static func (.parent, .node) -> This {
  27. if(lastFree empty?()) {
  28. new~real(parent, node, false)
  29. } else {
  30. res := lastFree pop()
  31. version(OOC_TASK_DEBUG) { ("Re-using last free task " + res toString()) println() }
  32. res parent = parent
  33. res node = node
  34. res done? = false
  35. res
  36. }
  37. }
  38. /**
  39. * Set userdata to this task
  40. */
  41. set: func <T> (key: String, value: T) {
  42. if(!userdata) userdata = HashBag new()
  43. userdata put(key, value)
  44. }
  45. unset: func (key: String) {
  46. if(!userdata) return
  47. userdata remove(key)
  48. }
  49. has: func (key: String) -> Bool {
  50. if(!userdata) return false
  51. userdata contains?(key)
  52. }
  53. get: func <T> (key: String, T: Class) -> T {
  54. if(userdata) {
  55. return userdata get(key, T)
  56. } else null
  57. }
  58. start: func {
  59. version(OOC_TASK_DEBUG) { (toString() + " started") println() }
  60. // Adjust the stackbottom and add our Coro's stack as a root for the GC
  61. parentCoro startCoro(coro, ||
  62. // This allows us to reuse tasks
  63. while(this node != null) {
  64. version(OOC_TASK_DEBUG) { (toString() + " launching resolve of " + toString()) println() }
  65. this node resolve(this)
  66. version(OOC_TASK_DEBUG) { (toString() + " finished, yielding " + toString()) println() }
  67. this done? = true
  68. this node = null
  69. This lastFree push(this)
  70. yield()
  71. }
  72. )
  73. }
  74. yield: func {
  75. version(OOC_TASK_DEBUG) { (toString() + " yield") println() }
  76. coro switchTo(parentCoro)
  77. }
  78. queue: func (n: Node) {
  79. task := Task new(this, n)
  80. version(OOC_TASK_DEBUG) { (toString() + " queuing " + n toString() + " with " + task toString()) println() }
  81. task start()
  82. while(!task done?) {
  83. version(OOC_TASK_DEBUG) { (task toString() + " not done yet, looping") println() }
  84. switchTo(task)
  85. yield()
  86. }
  87. }
  88. queueList: func (l: Iterable<Node>) {
  89. pool := ArrayList<Node> new()
  90. l each(|n, i| spawn(n, i, pool))
  91. exhaust(pool)
  92. }
  93. queueAll: func (f: Func (Func (Node, Int))) {
  94. pool := ArrayList<Node> new()
  95. f(|n, i| spawn(n, i, pool))
  96. exhaust(pool)
  97. }
  98. spawn: func (n: Node, index: Int, pool: List<Task>) {
  99. version(OOC_TASK_DEBUG) { (toString() + " spawning for " + n toString()) }
  100. task := Task new(this, n)
  101. task set("index", index)
  102. task start()
  103. if(!task done?) pool add(task)
  104. }
  105. exhaust: func (pool: List<Task>) {
  106. version(OOC_TASK_DEBUG) { (toString() + " exhausting pool ") println() }
  107. while(!pool empty?()) {
  108. oldPool := pool
  109. pool = ArrayList<Task> new()
  110. oldPool each(|task|
  111. version(OOC_TASK_DEBUG) { (toString() + " switching to unfinished task " + task toString()) println() }
  112. switchTo(task)
  113. if(!task done?) pool add(task)
  114. )
  115. if(!pool empty?()) yield()
  116. }
  117. }
  118. need: func (f: Func -> Bool) {
  119. while(!f()) {
  120. yield()
  121. }
  122. }
  123. switchTo: func (task: Task) {
  124. coro switchTo(task coro)
  125. }
  126. toString: func -> String {
  127. "[#%d %s]" format(id, node ? node toString() : "<no node>")
  128. }
  129. walkBackward: func (f: Func (Node) -> Bool) {
  130. if(f(node)) return // true = break
  131. if(parent)
  132. parent walkBackward(f)
  133. }
  134. walkBackwardTasks: func ~withTask (f: Func (Task) -> Bool) {
  135. if(f(this)) return // true = break
  136. if(parent)
  137. parent walkBackwardTasks(f)
  138. }
  139. }
  140. ModuleTask: class extends Node {
  141. module: Module
  142. init: func (=module) {}
  143. resolve: func (task: Task) {
  144. task queue(module)
  145. "Finished resolving %s!" printfln(module fullName)
  146. task resolver params backend process(module, task resolver params)
  147. }
  148. }
  149. Resolver: class extends Node {
  150. modules: ArrayList<Module> { get set }
  151. params: BuildParams
  152. init: func (=params, mainModule: Module) {
  153. modules = ArrayList<Module> new()
  154. modules addAll(mainModule getDeps())
  155. }
  156. start: func {
  157. "Resolver started, with %d module(s)!" printfln(modules size)
  158. mainCoro := Coro new()
  159. mainCoro initializeMainCoro()
  160. mainTask := Task new(this, mainCoro, this)
  161. mainTask start()
  162. while(!mainTask done?) {
  163. "" println()
  164. "========================== Looping! ===============" println()
  165. "" println()
  166. mainCoro switchTo(mainTask coro)
  167. }
  168. }
  169. resolve: func (task: Task) {
  170. task queueList(modules map(|m| ModuleTask new(m)))
  171. }
  172. }