author | Alan Dipert
<alan@dipert.org> 2020-04-11 14:59:59 UTC |
committer | Alan Dipert
<alan@dipert.org> 2020-04-11 14:59:59 UTC |
parent | e7b5725c4fbc302529ff083e60ac1a242018b904 |
jacl.js | +26 | -13 |
diff --git a/jacl.js b/jacl.js index 75b705e..c64329d 100644 --- a/jacl.js +++ b/jacl.js @@ -1567,35 +1567,48 @@ const analyze = (env, parent, form) => { } }; -const findNodesByName = (root, op) => { +// TODO Consider turning this into an iterator function. +const findNodes = (root, pred) => { let found = []; - if (root.op === op) found.push(root); - for (const child of root.children) { - found = [...found, ...findNodesByName(child, op)]; + if (pred(root)) + found.push(root); + for (const x of root.children) { + found = [...found, ...findNodes(x, pred)]; } return found; }; -const optimizeTagbody = node => { - gos: for (const go of findNodesByName(node, 'go')) { +const optimizeGo = node => { + const gos = findNodes(node, x => { + return x.op === 'go' && x.context !== 'expr'; + }); + next: for (const go of gos) { let parent = go.parent; while (parent) { if (parent.op === 'tagbody' && go.tagbodyId === parent.id) { go.op = 'go-continue'; - continue gos; - } - if (parent.op === 'lambda') { - continue gos; + continue next; } + if (parent.op === 'lambda') + continue next; parent = parent.parent; } } }; +const optimizeTagbody = node => { + const tbs = findNodes(node, x => x.op === 'tagbody'); + next: for (const tb of tbs) { + const gos = findNodes(tb, x => x.op === 'go' && x.tagbodyId === tb.id); + // If gos is empty, tb has no GOs that will throw exceptions. + if (!gos.length) + tb.op = 'tagbody-static'; + } +}; + const optimize = node => { - optimizeTagbody(node); - // TODO Consider optimize TAGBODYs for size consisting only of local - // GOs + optimizeGo(node); + // TODO: optimizeTagbody(node); return node; };