Created
February 5, 2017 03:26
-
-
Save nhz-io/a79ba3bb42793e2e32d81d0ea237dc9d to your computer and use it in GitHub Desktop.
AST Histograms created by nhz-io - https://repl.it/F71R/12
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pre, code { | |
display: none; | |
} | |
body { | |
background: #EEE; | |
} | |
.container { | |
font-size: 0; | |
} | |
canvas { | |
padding: 2px; | |
margin: 2px; | |
border: solid rgba(0,0,0,0.2) 1px; | |
background: white; | |
} | |
.histogram { | |
display: inline-block; | |
vertical-align: top; | |
padding: 0; | |
margin: 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width"> | |
<title>AST Histograms</title> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.js"></script> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/esprima/2.7.3/esprima.js"></script> | |
<script src="//rawgit.com/nhz-io/gen-utils/master/src/common/index.js"></script> | |
<script src="//rawgit.com/nhz-io/gen-utils/master/src/ast/index.js"></script> | |
<link href="index.css" rel="stylesheet" type="text/css" /> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="histogram"> | |
<pre class="code"> | |
function name() { | |
/* ... */ | |
} | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
function name(arg) { | |
/* ... */ | |
} | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
function name(arg1, arg2) { | |
/* ... */ | |
} | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
function name(...args) { | |
/* ... */ | |
} | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
function name(arg1, arg2, ...args) { | |
/* ... */ | |
} | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
(function () { | |
/* ... */ | |
})() | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
(function (arg) { | |
/* ... */ | |
})() | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
(function (arg1, arg2) { | |
/* ... */ | |
})() | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
(function (...args) { | |
/* ... */ | |
})() | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
(function (arg1, arg2, ...args) { | |
/* ... */ | |
})() | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
(function name() { | |
/* ... */ | |
})() | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
(function name(arg) { | |
/* ... */ | |
})() | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
(function name(arg1, arg2) { | |
/* ... */ | |
})() | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
(function name(...args) { | |
/* ... */ | |
})() | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
(function name(arg1, arg2, ...args) { | |
/* ... */ | |
})() | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
(() => { | |
/* ... */ | |
})() | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
(arg => { | |
/* ... */ | |
})() | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
((arg1, arg2) => { | |
/* ... */ | |
})() | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
((...args) => { | |
/* ... */ | |
})() | |
</pre> | |
</div> | |
<div class="histogram"> | |
<pre class="code"> | |
((arg1, arg2, ...args) => { | |
/* ... */ | |
})() | |
</pre> | |
</div> | |
</div> | |
<script src="index.js"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fontSize = 12 | |
const fontFamily = 'Monospace' | |
const font = `${fontSize}px ${fontFamily}` | |
const textFill = '#555' | |
const chartFill = 'rgba(100,100,0,0.25)' | |
const chartHeight = 20 | |
const margin = 2 | |
const separatorMargin = margin | |
const typeMargin = margin * 3 | |
const chartMargin = margin * 2 | |
const slotHeight = ( | |
typeMargin + | |
fontSize + | |
chartMargin + | |
separatorMargin + | |
chartHeight | |
) | |
const canvasWidth = 400 | |
const data = [] | |
d3.selectAll('.histogram .code').each(function() { | |
const indent = new RegExp(`^${this.innerText.match(/^\s*/)[0]}`, 'gmi') | |
const code = this.innerText.replace(indent, '') | |
const ast = esprima.parse(code, {range: true}) | |
const list = Array.from(astNodes(ast)).sort((a, b) => | |
a.range[0] - b.range[0] | |
) | |
const types = [] | |
const nodes = {} | |
const min = list.map(i => i.range[0]).sort((a, b) => a - b)[0] | |
const max = list.map(i => i.range[1]).sort((a, b) => b - a)[0] | |
for (const item of list) { | |
const type = item.type | |
if (type !== 'Program') { | |
if (types.indexOf(type) === -1) { | |
types.push(type) | |
} | |
nodes[type] = nodes[type] || [] | |
nodes[type].push(item) | |
} | |
} | |
data.push({ | |
types, | |
nodes, | |
code, | |
min, | |
max, | |
data: Array.from( | |
map(types, type => ({type, nodes: nodes[type]})) | |
), | |
}) | |
}) | |
d3.selectAll('.histogram').data(data) | |
.append('canvas') | |
.attr('width', canvasWidth) | |
.each(function (d, i) { | |
const {types, data, min, max, nodes, code} = d | |
const lines = code.split(/\n/) | |
const codeHeight = (fontSize + margin) * lines.length | |
const canvasHeight = ( | |
codeHeight + | |
typeMargin + | |
slotHeight * types.length + | |
chartMargin * 2 + | |
chartHeight + | |
margin | |
) | |
d3.select(this).attr('height', canvasHeight) | |
const ctx = this.getContext('2d') | |
ctx.font = font | |
const s = d3.scaleLinear().domain([min, max]).range([1, canvasWidth]) | |
ctx.fillStyle = 'white' | |
ctx.fillRect(0, 0, canvasWidth, canvasHeight) | |
ctx.fillStyle = textFill | |
let y = 0 | |
lines.forEach((line, i) => { | |
y += fontSize + margin | |
ctx.fillText(line, margin, y) | |
}) | |
ctx.fillStyle = chartFill | |
ctx.fillRect(0, y - margin * 2, canvasWidth, 1) | |
types.forEach((type, i) => { | |
let y = ( | |
codeHeight + | |
typeMargin + | |
slotHeight * i + | |
fontSize + | |
typeMargin + | |
chartMargin * 2 + | |
chartHeight | |
) | |
ctx.fillStyle = textFill | |
ctx.fillText(`${type} (${nodes[type].length})`, margin, y) | |
y += chartMargin | |
ctx.fillStyle = chartFill | |
ctx.fillRect(0, y, canvasWidth, 1) | |
y += separatorMargin | |
ctx.fillStyle = chartFill | |
nodes[type].forEach(node => { | |
const width = s(node.range[1] - node.range[0]) - 1 | |
ctx.fillRect( | |
s(node.range[0]), | |
codeHeight + chartMargin, | |
width < 1 ? 1 : width, | |
chartHeight | |
) | |
ctx.fillRect( | |
s(node.range[0]), | |
y, | |
width < 1 ? 1 : width, | |
chartHeight | |
) | |
}) | |
}) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment