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