-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpassenger.nim
61 lines (53 loc) · 1.43 KB
/
passenger.nim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import std/os
import std/strutils
import std/tables
import std/macros
import std/times
import std/hashes
import cps
import gram
type
Safe = uint
Vertex = object
fn: Safe
name: string
info: LineInfo
Link[T] = object
name: string
entry: float
cont: T
template saften(fn: typed): Safe = cast[uint](fn)
var traced: Table[Safe, (string, LineInfo)]
template trace*(c: typed; fun: string; info: LineInfo) =
if saften(c.fn) notin traced:
traced[saften(c.fn)] = (fun, info)
proc `$`*(v: Vertex): string =
## render the continuation leg
try:
if saften(v.fn) in traced:
var (name, info) = traced[saften(v.fn)]
name = name.split("_")[0]
let fn = info.filename.lastPathPart
result = "$# ($# : $#)" % [ name, fn, $info.line ]
else:
result = $(saften(v.fn))
except:
result = "?"
proc `$`*[T](l: Link[T]): string =
## render the link between two continuation legs
try:
result = " $# cpu" % [ $l.entry ]
except:
result = "?"
const F = defaultGraphFlags.toInt
proc passenger*[T: Continuation](c: T): (T, Graph[Vertex, Link[T], F]) =
var g: Graph[Vertex, Link[T], F] = newGraph[Vertex, Link[T]]()
var prior: Node[Vertex, Link[T]]
trampolineIt c:
let vertex = g.add Vertex(fn: saften(it.fn))
let link = Link[T](cont: c, entry: cpuTime())
g.incl vertex
if not prior.isNil:
discard g.edge(prior, link, vertex)
prior = vertex
result = (c.T, g)