-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathwalker.js
125 lines (110 loc) · 3.59 KB
/
walker.js
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
var convert = require('cpsjs')
var esprima = require('esprima').parse
var escodegen = require('escodegen').generate
var Memory = require('memory-tree/memoryProxy')
var EventEmitter = require('events').EventEmitter
window.transform = function (str) {
var x = convert(esprima(str));
return [escodegen(x[0]), x[1]];
};
window.run = function run(str) {
var __undefined
var scopeInfoMap = new WeakMap()
var stackInfoMap = new WeakMap()
var ccnum = 0;
var globalScopeInfo = Memory.Scope({}, Memory({
callcc: function (val, ret) {
var saved_env = continList[continList.length - 1]
return val(eval('(function (v) { // ' + (ccnum++) + '\n' +
' saved_env.go();' +
' val(v, ret);' +
'})'), ret)
}
}))
var __globalScope = globalScopeInfo[0]
var __stack = null;
var currentContin = null;
var emitter = new EventEmitter()
var ast = convert(esprima(str, { loc: true }))
var code = escodegen(ast[0])
window.nodeList = ast[1];
window.code = code;
scopeInfoMap.set(__globalScope, globalScopeInfo)
function __pushStack(stack, scope, callSha) {
callInfo = callSha ? ast[1][callSha] : null
var scopeInfo = scopeInfoMap.get(scope)
var parentStackInfo = stack ? stackInfoMap.get(stack)
: null
var scopeIndex = ast[1][scopeInfo[1].index]
var stackInfo = Memory.Stack(parentStackInfo, scopeInfo, callInfo, scopeIndex)
__stack = stackInfo[0]
stackInfoMap.set(stackInfo[0], stackInfo)
}
function __popStack(stack) {
__stack = __stack.caller
}
function __createScopeObject(scopeDef, parentScope, scopeIndexSha) {
var parentScopeInfo = scopeInfoMap.get(parentScope)
var scopeInfo = Memory.Scope(scopeDef, parentScopeInfo)
scopeInfo[1].index = scopeIndexSha
scopeInfo[1].viewAll = true
scopeInfoMap.set(scopeInfo[0], scopeInfo)
return scopeInfo[0]
}
function __end(val) {
__popStack(__stack)
emitter.emit('tick', null)
emitter.emit('end', __stack)
}
function createCallState(stackInfo, stackSha, tokenSha, cb, valInfo) {
// Add callstate into sha list...
return { tokenSha: tokenSha, stack: stackInfo[0], go: setSha, func: cb, valInfo: valInfo }
function setSha() {
stackInfo[1].setSha(stackSha)
emitter.emit('tick', this, ast[1])
}
}
/* Temporarily hold off on this part.
* Cram it into the callstate instead....
function createContinuation(cc, cs, valInfo, next) {
// Add contin into sha list...
return { parentContin: cc, callState: cs, valInfo: valInfo, next: next }
}
*/
var continList = []
var continLoc = -1
function __continuation(curSha, val, cb) {
var valInfo = { hasVal: true, value: val }
if (arguments.length === 2) {
cb = val
valInfo.value = val = null
valInfo.hasVal = false
}
var stackInfo = stackInfoMap.get(__stack)
var stackSha = stackInfo[1].getSha()
var callState = createCallState(stackInfo, stackSha, curSha, cb, valInfo)
continList.push(callState)
continLoc++
//currentContin = createContinuation(currentContin, callState, valInfo, cb)
emitter.emit('tick', callState, ast[1])
//emitter.next = cb.bind(null, val)
}
emitter.next = function () {
var contin
if (continLoc === -1) return eval(code)
if (continLoc === continList.length - 1) {
contin = continList[continLoc]
return contin.func(contin.valInfo.value)
}
continLoc++
contin = continList[continLoc]
return contin.go()
}
emitter.prev = function () {
if (continLoc === 0) return
continLoc--
contin = continList[continLoc]
return contin.go()
}
return emitter
}