Skip to content

Commit 94bb372

Browse files
committed
started implementing krazy kode for pre-computing stable layouts
1 parent f31edd9 commit 94bb372

File tree

1 file changed

+165
-0
lines changed

1 file changed

+165
-0
lines changed

PyTutorGAE/js/edu-python.js

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,171 @@ function isOutputLineVisible(lineNo) {
254254

255255

256256

257+
// Pre-compute the layout of top-level heap objects for ALL execution
258+
// points as soon as a trace is first loaded. The reason why we want to
259+
// do this is so that when the user steps through execution points, the
260+
// heap objects don't "jiggle around" (i.e., preserving positional
261+
// invariance). Also, if we set up the layout objects properly, then we
262+
// can take full advantage of d3 to perform rendering and transitions.
263+
264+
265+
// curTraceLayouts is a list of top-level heap layout "objects" with the
266+
// same length as curTrace after it's been fully initialized. Each
267+
// element of curTraceLayouts is computed from the contents of its
268+
// immediate predecessor, thus ensuring that objects don't "jiggle
269+
// around" between consecutive execution points.
270+
//
271+
// Each top-level heap layout "object" is itself a LIST of LISTS of
272+
// object IDs, where each element of the outer list represents a row,
273+
// and each element of the inner list represents columns within a
274+
// particular row. Each row can have a different number of columns. Most
275+
// rows have exactly ONE column (representing ONE object ID), but rows
276+
// containing 1-D linked data structures have multiple columns. Each
277+
// inner list element looks something like ['row1', 3, 2, 1] where the
278+
// first element is a unique row ID tag, which is used as a key for d3 to
279+
// preserve "object constancy" for updates, transitions, etc. The row ID
280+
// is derived from the FIRST object ID inserted into the row. Since all
281+
// object IDs are unique, all row IDs will also be unique.
282+
var curTraceLayouts = null;
283+
284+
/* This is a good, simple example to test whether objects "jiggle"
285+
286+
x = [1, [2, [3, None]]]
287+
y = [4, [5, [6, None]]]
288+
289+
x[1][1] = y[1]
290+
291+
*/
292+
293+
294+
function precomputeCurTraceLayouts() {
295+
curTraceLayouts = [];
296+
curTraceLayouts.push([]); // pre-seed with an empty sentinel to simplify the code
297+
298+
assert(curTrace.length > 0);
299+
300+
301+
$.each(curTrace, function(i, elt) {
302+
var prevLayout = curTraceLayouts[curTraceLayouts.length - 1];
303+
304+
// make a DEEP COPY of prevLayout to use as the basis for curLine
305+
var curLayout = $.extend(true /* deep copy */ , [], prevLayout);
306+
307+
// initialize with all IDs from curLayout
308+
var idsToRemove = d3.map();
309+
$.each(curLayout, function(i, row) {
310+
for (var j = 1 /* ignore row ID tag */; j < row.length; j++) {
311+
idsToRemove.set(row[j], 1);
312+
}
313+
});
314+
315+
316+
function curLayoutIndexOf(id) {
317+
for (var i = 0; i < curLayout.length; i++) {
318+
var row = curLayout[i];
319+
var index = row.indexOf(id);
320+
if (index > 0) { // index of 0 is impossible since it's the row ID tag
321+
return {row: row, index: index}
322+
}
323+
}
324+
return null;
325+
}
326+
327+
328+
// a krazy function!
329+
// id - the new object ID to be inserted somewhere in curLayout
330+
// (if it's not already in there)
331+
// curRow - a row within curLayout where new linked list
332+
// elements can be appended onto (might be null)
333+
// newRow - a new row that might be spliced into curRow or appended
334+
// as a new row in curLayout
335+
function updateCurLayout(id, curRow, newRow) {
336+
var curLayoutLoc = curLayoutIndexOf(id);
337+
338+
// if id is already in curLayout ...
339+
if (curLayoutLoc) {
340+
var foundRow = curLayoutLoc.row;
341+
var foundIndex = curLayoutLoc.index;
342+
343+
// splice the contents of newRow right BEFORE foundIndex.
344+
// (Think about when you're trying to insert in id=3 into ['row1', 2, 1]
345+
// to represent a linked list 3->2->1. You want to splice the 3
346+
// entry right before the 2 to form ['row1', 3, 2, 1])
347+
if (newRow.length > 1) {
348+
var args = [foundIndex - 1, 0];
349+
for (var i = 1; i < newRow.length; i++) { // ignore row ID tag
350+
args.push(newRow[i]);
351+
idsToRemove.remove(newRow[i]);
352+
}
353+
foundRow.splice.apply(args);
354+
355+
// remove ALL elements from newRow since they've all been accounted for
356+
// (but don't reassign it away to an empty list, since the
357+
// CALLER checks its value. TODO: get rid of this gross hack?!?)
358+
newRow.splice(0, newRow.length);
359+
}
360+
361+
// recurse to find more top-level linked entries to append onto curRow
362+
// updateCurLayout(child ID, foundRow, [])
363+
364+
}
365+
else {
366+
// push id into newRow ...
367+
if (newRow.length == 0) {
368+
newRow.push('row' + id); // unique row ID (since IDs are unique)
369+
}
370+
newRow.push(id);
371+
372+
// RECURSE to find possible top-level linked entries
373+
// updateCurLayout(child ID, curRow, newRow)
374+
375+
376+
// if newRow hasn't been spliced into an existing row yet during
377+
// a child recursive call ...
378+
if (newRow.length > 0) {
379+
if (curRow && curRow.length > 0) {
380+
// append onto the END of curRow if it exists
381+
for (var i = 1; i < newRow.length; i++) { // ignore row ID tag
382+
curRow.push(newRow[i]);
383+
}
384+
}
385+
else {
386+
// otherwise push to curLayout as a new row
387+
curLayout.push(newRow);
388+
}
389+
390+
// regardless, newRow is now accounted for, so clear it
391+
for (var i = 1; i < newRow.length; i++) { // ignore row ID tag
392+
idsToRemove.remove(newRow[i]);
393+
}
394+
newRow.splice(0, newRow.length);
395+
}
396+
397+
}
398+
}
399+
400+
401+
// iterate through all globals and ordered stack frames
402+
// and then call updateCurLayout(id, null, []);
403+
404+
405+
// iterate through remaining elements of idsToRemove and REMOVE them
406+
// from curLayout
407+
idsToRemove.forEach(function(id, xxx) {
408+
var ind = row.indexOf(id);
409+
if (ind > 0) { // remember that index 0 of the row is the row ID tag
410+
row.splice(ind, 1);
411+
}
412+
});
413+
414+
curTraceLayouts.push(curLayout);
415+
});
416+
417+
curTraceLayouts.splice(0, 1); // remove seeded empty sentinel element
418+
assert (curTrace.length == curTraceLayouts.length);
419+
}
420+
421+
257422
// relies on curTrace and curInstr globals
258423
function updateOutput() {
259424
if (!curTrace) {

0 commit comments

Comments
 (0)