diff --git a/homework/1/rename.js b/homework/1/rename.js index 0bbd947..91a9ea4 100644 --- a/homework/1/rename.js +++ b/homework/1/rename.js @@ -5,12 +5,46 @@ const traverse = require('../../common/traverse'); function transform(root, originName, targetName) { // 遍历所有节点 return traverse((node, ctx, next) => { - - // TODO: 作业代码写在这里 - if (node.type === 'xxx') { + switch(node.type) + { + case 'VariableDeclaration': + { + let variableDeclarator = node.declarations[0]; + if (variableDeclarator.id.name === originName) { + variableDeclarator.id.name = targetName; + } + } + break; + case 'FunctionDeclaration': + { + if (node.id.name === originName) { + node.id.name = targetName; + } + } + break; + // case 'ObjectExpression': + // if (node.properties[0].key.name === originName) { + // node.properties[0].key.name = targetName; + // } + // break; + case 'BinaryExpression': + { + if (node.left.name === originName) { + node.left.name = targetName; + } + if (node.right.name === originName) { + node.right.name = targetName; + } + } + break; + case 'MemberExpression': + { + if (!node.object.object && node.object.name === originName) { + node.object.name = targetName; + } + } + break; } - - // 继续往下遍历 return next(node, ctx) })(root); } diff --git a/homework/1/sourceCode.js b/homework/1/sourceCode.js new file mode 100644 index 0000000..a18dd66 --- /dev/null +++ b/homework/1/sourceCode.js @@ -0,0 +1,10 @@ +function foo() { + foo: while(true) { + var foo = { + foo: foo.foo.foo[foo + foo] + }; + break foo; + } +} + +module.exports = foo; \ No newline at end of file diff --git a/homework/1/test.js b/homework/1/test.js new file mode 100644 index 0000000..0f2b659 --- /dev/null +++ b/homework/1/test.js @@ -0,0 +1,7 @@ +const rename = require('./rename') +const sourceCode = require('./sourceCode') + + +let result = rename(sourceCode, 'foo', 'bar'); + +console.log(result); \ No newline at end of file diff --git a/homework/2/eval.js b/homework/2/eval.js index be527f5..b31f3f6 100644 --- a/homework/2/eval.js +++ b/homework/2/eval.js @@ -1,9 +1,129 @@ const acorn = require('acorn'); function evaluate(node, env) { - switch (node.type) { + switch (node.type) + { case 'Literal': - // TODO: 补全作业代码 + return node.value; + case 'Identifier': + return env[node.name]; + case 'BinaryExpression': + { + switch(node.operator) + { + case '+': + return evaluate(node.left, env) + evaluate(node.right, env); + case '-': + return evaluate(node.left, env) - evaluate(node.right, env); + case '*': + return evaluate(node.left, env) * evaluate(node.right, env); + case '/': + return evaluate(node.left, env) / evaluate(node.right, env); + case '**': + return evaluate(node.left, env) ** evaluate(node.right, env); + case '%': + return evaluate(node.left, env) % evaluate(node.right, env); + case '>': + return evaluate(node.left, env) > evaluate(node.right, env); + case '<': + return evaluate(node.left, env) < evaluate(node.right, env); + case '>=': + return evaluate(node.left, env) >= evaluate(node.right, env); + case '<=': + return evaluate(node.left, env) <= evaluate(node.right, env); + case '==': + return evaluate(node.left, env) == evaluate(node.right, env); + case '===': + return evaluate(node.left, env) === evaluate(node.right, env); + case '!==': + return evaluate(node.left, env) !== evaluate(node.right, env); + case '&': + return evaluate(node.left, env) & evaluate(node.right, env); + case '|': + return evaluate(node.left, env) | evaluate(node.right, env); + case '^': + return evaluate(node.left, env) ^ evaluate(node.right, env); + case '<<': + return evaluate(node.left, env) << evaluate(node.right, env); + case '>>': + return evaluate(node.left, env) >> evaluate(node.right, env); + case '>>>': + return evaluate(node.left, env) >>> evaluate(node.right, env); + case 'instanceof': + return evaluate(node.left, env) instanceof evaluate(node.right, env); + } + } + case 'LogicalExpression': + { + switch(node.operator) + { + case '&&': + return evaluate(node.left, env) && evaluate(node.right, env); + case '||': + return evaluate(node.left, env) || evaluate(node.right, env); + } + } + case 'UnaryExpression': { + switch(node.operator) + { + case '!': + return !evaluate(node.argument, env); + case '~': + return ~evaluate(node.argument, env); + case 'typeof': + return typeof evaluate(node.argument, env); + } + } + case 'UpdateExpression': { + const flag = node.prefix; + const argument = node.argument; + switch(node.operator) + { + case '++': + { + if (flag) { + return ++evaluate(argument, env); + } else { + return evaluate(argument, env)++; + } + } + case '--': + { + if (flag) { + return --evaluate(argument, env); + } else { + return evaluate(argument, env)--; + } + } + } + } + case 'ConditionalExpression': + { + if (evaluate(node.test, env)) { + return evaluate(node.consequent, env); + } else { + return evaluate(node.alternate, env); + } + } + case 'CallExpression': { + const c = evaluate(node.callee, env); + const args = node.arguments.map(arg => evaluate(arg, env)); + return c(...args); + } + case 'ObjectExpression': + return node.properties.reduce((preProperty, curProperty) => ( + {...preProperty, [curProperty.key.name] : evaluate(curProperty.value, env)}), {}); + case 'ArrayExpression': + return node.elements.map((element) => evaluate(element, env)); + case 'BlockStatement': + return node.body.reduce((preStatement, curStatement) => evaluate(curStatement, env), undefined); + case 'ArrowFunctionStatement': + return (...args) => { + return evaluate(node.body, { + ...env, + ...node.params.reduce((preParam, curParam, curIdx)=>({...preParam, [curParam.name]: args[curIdx]}), {}) + }) + } } throw new Error(`Unsupported Syntax ${node.type} at Location ${node.start}:${node.end}`); diff --git a/homework/2/sourceCode.js b/homework/2/sourceCode.js new file mode 100644 index 0000000..e834f2c --- /dev/null +++ b/homework/2/sourceCode.js @@ -0,0 +1,3 @@ +const foo = '({ a: 1 + 2 + 3, b: 4 + 5, c: [1, 2, 3] })'; + +module.exports = foo; \ No newline at end of file diff --git a/homework/2/test.js b/homework/2/test.js new file mode 100644 index 0000000..fdde79d --- /dev/null +++ b/homework/2/test.js @@ -0,0 +1,6 @@ +const customerEval = require('./eval') + + +const result = customerEval('((x,y)=>x+y)(2,3)'); + +console.log(result); \ No newline at end of file