-
Notifications
You must be signed in to change notification settings - Fork 4
/
kyulrun
executable file
·128 lines (116 loc) · 3.34 KB
/
kyulrun
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
126
127
#!/usr/bin/env node
const {docopt} = require("docopt");
const path = require("path");
const fs = require('fs');
const {execFileSync} = require('child_process');
const K_RELEASE=process.env.K_RELEASE || './deps/k/k-distribution/target/release/k'
const usage = `
Usage:
kyulrun [options] <file>
Options:
--getTrace
`
const cmd = docopt(usage, {});
const pgmPath = cmd['<file>']
const getTrace = cmd['--getTrace']
const get = (term, path) => {
let p = path
.split(".")
.map(s => `<${s}>`)
let o = getKJSONPath(term.args, p)[0]
return o;
}
const getKJSONPath = (termList, pathComponents) => {
if (termList == undefined) return {}
if (pathComponents.length == 0) return termList
let pathComponent = pathComponents[0]
let subTerm = termList.find( term => term.node == "KApply" && term.label == pathComponent ) || []
return getKJSONPath(subTerm.args, pathComponents.slice(1))
}
const bigToHex = o => {
//stupid javascript
let a = execFileSync('./hex', [o])
return a.toString().trim()
}
const div = (n,d) => {
let a = execFileSync('bc <<<"obase=16; $1 / $2"', [n,d])
}
const toHex = o => {
let h = o.toString(16)
if (h.length == 1) return '0'+h
else return h
}
const formatMem = o => {
//mem entries as a list with entries [loc, value]
let entries;
if (o.label == '_|->_') {
entries = [o.args.map(g => g.token)]
}
else if (o.label == '.Map') {return false}
else if (o.label == '_Map_') {
entries = o.args.map(f => f.args.map(g => g.token))
}
let keys = new Set(entries.map(s => Math.floor(Number(s[0]) / 32)))
let prettyMem = '';
keys.forEach(key => {
let entry = Array(32).fill('00')
entries.filter(s => Math.floor(Number(s[0]) / 32) == key && !(s[1] == '0'))
.forEach(val => {
entry[(Number(val[0]) % 32)] = toHex(Number(val[1]))
})
if (!(entry.join('') == '00'.repeat(32))) {
prettyMem +=' '+(key*2).toString(16)+'0' + ': ' + entry.join('') + '\n'
}
})
return prettyMem
}
const formatStorage = o => {
let entries;
if (o.label == '_|->_') {
entries = [o.args.map(g => g.token)]
}
else if (o.label == '.Map') {return false}
else if (o.label == '_Map_') {
entries = o.args.map(f => f.args.map(g => g.token))
}
let prettyStorage = ''
for (let i=0; i<entries.length; i++) {
if (!entries[i][1] == '0') {
prettyStorage += ` ${bigToHex(entries[i][0]).padStart(64,'0')}: ${bigToHex(entries[i][1]).padStart(64,'0')}\n`
}
}
return prettyStorage
}
const getTraceFromTest = testPath => {
return fs.readFileSync(testPath)
.toString()
.split('----\n')[1]
.replace(/\/\/ /g,'').trim();
}
if (getTrace) {
console.log(getTraceFromTest(pgmPath))
process.exit()
}
try {
let krun = execFileSync('./kyul',
['run',
pgmPath]
)
let term;
try {
term = JSON.parse(krun.toString()).term
} catch(e) { console.log("Malformed output: " + e.toString())
process.exit(1)
}
let formatedMem = formatMem(get(term, 'callState.memory'))
let formatedStorage = formatStorage(get(term,'storage'))
let trace = 'Trace:\nMemory dump:\n'
if (formatedMem) trace+=formatedMem
trace+='Storage dump:'
if (formatedStorage) trace+='\n' + formatedStorage
console.log(trace)
process.exit()
} catch(e) {
console.log(e.toString())
process.exit(1)
}