diff --git a/.gitignore b/.gitignore index 78f962ba..53e01c08 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ demo-webpage/html/runner.js package-lock.json auth-trial/html/src-noconflict /benchmarks +.vscode diff --git a/src/callcc/declVars.ts b/src/callcc/declVars.ts index 72cd4c8f..179a05fa 100644 --- a/src/callcc/declVars.ts +++ b/src/callcc/declVars.ts @@ -27,7 +27,7 @@ function declToAssign(decl: t.VariableDeclarator): t.AssignmentExpression | null function getFunctionArgs(path: NodePath): string[] { const node = path.node; - if (node.type === 'FunctionDeclaration' || + if (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') { return (node).params.map((x: t.Identifier) => x.name); } @@ -45,11 +45,41 @@ function getBlock(node: t.Node): t.Statement[] { } else if (t.isObjectMethod(node)) { return node.body.body; }else { + throw new Error(`Got ${node.type}`); } } +const func = { + enter(path: NodePath) { + (path.node).toDecl = [] + }, + exit(path: NodePath) { + const toDecl: t.Identifier[] | undefined = (path.node).toDecl + if(toDecl && toDecl.length > 0) { + path.node.body.body.unshift(lifted(t.variableDeclaration('var', + toDecl.map(d => t.variableDeclarator(d))))) + } + } +} + +const prog = { + enter(path: NodePath) { + (path.node).toDecl = [] + }, + exit(path: NodePath) { + const toDecl: t.Identifier[] | undefined = (path.node).toDecl + if(toDecl && toDecl.length > 0) { + path.node.body.unshift(lifted(t.variableDeclaration('var', + toDecl.map(d => t.variableDeclarator(d))))) + } + } +} + const lift: Visitor = { + Program: prog, + FunctionDeclaration: func, + FunctionExpression: func, VariableDeclaration(path: NodePath>) { if (path.node.lifted) { return; @@ -73,9 +103,22 @@ const lift: Visitor = { throw new Error(`Destructuring assignment not supported`); } const id = decl.id.name; - const newDecl = t.variableDeclaration(kind, - [t.variableDeclarator(decl.id)]); - getBlock(topScope.node).unshift(lifted(newDecl)); + // This checks for the following case: + // + // function(x) { var x = 10; } + // + // is the same as: + // + // function(x) { x = 10; } + // + // Therefore, we do not need to lift x. Instead, we eliminate the + // declaration and only turn it into an assignment. + if ((kind === 'var' && topArgs.includes(id)) === false) { + //const newDecl = t.variableDeclaration(kind, + //[t.variableDeclarator(decl.id)]); + //getBlock(topScope.node).unshift(lifted(newDecl)); + (topScope.node).toDecl.push(decl.id) + } if (decl.init !== null) { // If we call path.insertAfter here, we will add assignments in reverse // order. Fortunately, path.insertAfter can take an array of nodes.