Skip to content
42 changes: 30 additions & 12 deletions homework/1/rename.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,41 @@ const astring = require('astring');
const traverse = require('../../common/traverse');

function transform(root, originName, targetName) {
// 遍历所有节点
return traverse((node, ctx, next) => {
// 遍历所有节点
return traverse((node, ctx, next) => {

// TODO: 作业代码写在这里
if (node.type === 'xxx') {
}
// TODO: 作业代码写在这里

// 继续往下遍历
return next(node, ctx)
})(root);
const nodeTypeArray = [
'FunctionDeclaration',
'VariableDeclarator',
'MemberExpression',
'BinaryExpression'
]
const keyTypeArray = [
'property',
'label',
'key'
]
if (nodeTypeArray.includes(node.type)) {
for (const key in node) {
if (keyTypeArray.includes(key)) continue
if (node[key].type === 'Identifier' && node[key].name === originName) {
node[key].name = targetName;
}
}
}

// 继续往下遍历
return next(node, ctx)
})(root);
}

function rename(code, originName, targetName) {
const ast = acorn.parse(code, {
ecmaVersion: 5,
})
return astring.generate(transform(ast, originName, targetName))
const ast = acorn.parse(code, {
ecmaVersion: 5,
})
return astring.generate(transform(ast, originName, targetName))
}

module.exports = rename
110 changes: 101 additions & 9 deletions homework/2/eval.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,111 @@
const acorn = require('acorn');

function evaluate(node, env) {
switch (node.type) {
case 'Literal':
// TODO: 补全作业代码
}
switch (node.type) {
case 'Literal':
// TODO: 补全作业代码
return node.value;
case 'Program':
evaluate(node.body, env);
case 'ExpressionStatement':
evaluate(node.expression, env);
case 'BinaryExpression':
case 'LogicalExpression':
//BinaryOperator {
// "==" | "!=" | "===" | "!=="
// | "<" | "<=" | ">" | ">="
// | "<<" | ">>" | ">>>"
// | "+" | "-" | "*" | "/" | "%"
// | "**" | "||" | "^" | "&&" | "in"
// | "instanceof"
// | "|>"
// }
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 '&&':
return evaluate(node.left, env) && evaluate(node.right, env);
case 'in':
return evaluate(node.left, env) in evaluate(node.right, env);
case 'instanceof':
return evaluate(node.left, env) instanceof evaluate(node.right, env);
// case '|>':
// return evaluate(node.left, env) | > evaluate(node.right, env);
}
case 'ConditionalExpression':
return evaluate(node.test, env) ? evaluate(node.consequent, env) : evaluate(node.alternate, env);
case 'ObjectExpression':
let obj = {};
for (let i in node.properties) {
obj[node.properties[i].key.name] = evaluate(node.properties[i].value, env)
}
return obj;
case 'Identifier':
return env[node.name];
case 'ArrayExpression':
let arr = []
for (i in node.elements) {
arr[i] = evaluate(node.elements[i], env)
}
return arr;
case 'CallExpression':
let callee = evaluate(node.callee, env);
let args = node.arguments.map(arg => evaluate(arg, env));
return callee(...args);
case 'ArrowFunctionExpression':
return (...args) => {
let argEnv = {};
for (let i in node.params) {
argEnv[node.params[i].name] = args[i];
}
return evaluate(node.body, {...env, ...argEnv })
}
}

throw new Error(`Unsupported Syntax ${node.type} at Location ${node.start}:${node.end}`);
throw new Error(`Unsupported Syntax ${node.type} at Location ${node.start}:${node.end}`);
}

function customerEval(code, env = {}) {
const node = acorn.parseExpressionAt(code, 0, {
ecmaVersion: 6
})
return evaluate(node, env)
const node = acorn.parseExpressionAt(code, 0, {
ecmaVersion: 6
})
return evaluate(node, env)
}

module.exports = customerEval
Loading