Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

孙源 homework-3 #48

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
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