Skip to content

Instantly share code, notes, and snippets.

@keeyip
Last active December 21, 2015 14:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save keeyip/6320579 to your computer and use it in GitHub Desktop.
Save keeyip/6320579 to your computer and use it in GitHub Desktop.
Visualizing code
Ast = {
isLoop: function(node) {
return /(?:For|While)Statement/.test(node.type)
}
}
pre[data-name] {
display:none
}
* {
box-sizing: border-box;
}
body {
background:hsl(0,0%,50%);
}
.block {
display:inline-block;
margin: 8px;
vertical-align:top;
}
.line {
font-family: menlo;
font-size: 12px;
line-height: 16px;
}
.indent {
background:hsl(0,0%,46%);
display:inline-block;
width: 30px;
height: 17px;
vertical-align:top;
}
.op {
margin-bottom: 1px;
box-shadow: 0 0 2px hsla(0,0%,0%,0.1);
border-radius:2px;
display:inline-block;
vertical-align:top;
height:16px;
width:30px;
overflow:hidden;
color: hsl(0,0%,50%);
text-align:center;
}
.op-if {
background:hsl(0,0%,60%);
}
.op-else {
background:hsl(0,0%,60%);
}
.op-loop {
background:hsl(300,30%,40%);
}
.op-call {
background:hsl(50,40%,50%);
}
.op-recurse {
background:hsl(0,50%,40%);
border: solid 1px hsl(50,50%,50%);
}
.op-return {
background:hsl(0,0%,35%);
}
EXAMPLE = {
quicksort: (function() {
var partition = function partition(a, low, high) {
var left = low;
var right = high;
var pivot = low;
var pivotElement = a[pivot];
while(left <= right){
if(a[left]<= a[pivot]){
left++;
}
if(a[right]>a[pivot]){
right--;
}
if(a[left] > a[pivot] && a[right] <a[pivot] && left < right){
var temp = a[left];
a[left] = a[right];
a[right] = temp;
}
}
//this is tricky part. if right has moved to left of left, then this will be useful!
a[low] = a[right]
a[right] = pivotElement;
return right;
}
var quicksort = function quicksort(a, low, high) {
var pivot = low;
if(high > low) {
pivot = partition(a, low, high);
quicksort(a, low, pivot-1);
quicksort(a, pivot +1, high);
}
}
return {
quicksort: quicksort,
partition: partition
}
})()
}
<!doctype html>
<body>
<link rel='stylesheet' href='default.css'/>
<pre data-name="merge-sort">
if
return
for
for
recurse
recurse
call merge
return
</pre>
<pre data-name="merge">
while
if
if
else
else if
else if
return
</pre>
<script src='https://rawgithub.com/ariya/esprima/1.0.3/esprima.js'></script>
<script src='https://rawgithub.com/Constellation/estraverse/1.3.0/estraverse.js'></script>
<script src='https://rawgithub.com/Constellation/escodegen/0.0.26/escodegen.browser.js'></script>
<script src='https://rawgithub.com/jashkenas/underscore/1.5.1/underscore-min.js'></script>
<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js'></script>
<script src='underscore.deepClone.js'></script>
<script src='example-algorithms.js'></script>
<script src='instrument.js'></script>
<script src='Ast.js'></script>
<script src='parse.js'></script>
<script src='main.js'></script>
</body>
function instrument(ast0) {
console.group('Instrument')
var ast1 = _.deepClone(ast0)
var astTrace = esprima.parse('traceIt("type", "do")').body[0].expression
var astDo = esprima.parse('(function () { 1; })();').body[0].expression
console.warn('astTrace', astTrace)
console.warn('astDo', astDo)
var ast2 = estraverse.replace(ast1, {
enter: function(node, parent) {
},
leave: function(node, parent) {
if (Ast.isLoop(node)) {
var traceIt = _.deepClone(astTrace)
traceIt.arguments[0].value = "loop"
var doIt = _.deepClone(astDo)
doIt.callee.body.body[0] = node
traceIt.arguments[1] = doIt
console.warn('traceIt', escode.generate(traceIt));
//return traceIt
} else {
console.log(node.type)
}
}
})
console.warn('TRANSFORMED', escodegen.generate(ast2))
console.groupEnd()
}
$('pre[data-name]').each(function(i, pre) {
var $pre = $(pre)
var lines = $.trim($pre.text()).split(/[\n\r]+/)
var $block = $('<div class="block">');
_.each(lines, function(line) {
var op = $.trim(line)
if (op.match(/for|while/))
op = 'loop'
var indent = line.match(/^\s*/)[0].replace(/ /g, '<span class="indent"></span>');
var tag = '<span class="op op-' + op + '">' + op + '</span>';
$block.append('<div class="line">' + indent + tag + '</div>')
})
$block.appendTo('body')
})
instrument(parse(EXAMPLE.quicksort.quicksort))
instrument(parse(EXAMPLE.quicksort.partition))
function parse(code0) {
if (_.isFunction(code0)) {
code0 = code0.toString()
}
var ast0 = esprima.parse(code0)
var code1 = escodegen.generate(ast0)
console.group('Parse')
console.warn('code0',code0)
console.warn('ast0',ast0)
console.warn('code1',code1)
console.groupEnd()
return ast0
}
_.deepClone = function(x) {
return $.extend(true, {}, x)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment