Skip to content

Commit 0888b5d

Browse files
commit homework2
1 parent bde46ae commit 0888b5d

File tree

1 file changed

+65
-2
lines changed

1 file changed

+65
-2
lines changed

homework/2/eval.js

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,69 @@ const acorn = require('acorn');
22

33
function evaluate(node, env) {
44
switch (node.type) {
5-
case 'Literal':
65
// TODO: 补全作业代码
6+
// 作为叶子节点的字面量和变量直接返回它们的值
7+
case 'Literal':
8+
return node.value;
9+
case 'Identifier':
10+
return env[node.name];
11+
// 数组,对象
12+
case 'ArrayExpression':
13+
return node.elements.map(e => evaluate(e, env));
14+
case 'ObjectExpression':
15+
return node.properties.reduce((obj, prop) => ({
16+
...obj,
17+
[prop.key.name]: evaluate(prop.value, env),
18+
}), {});
19+
// 一些运算相关的表达式((懒得枚举运算符所以直接用eval了嘤~
20+
case 'BinaryExpression':
21+
return eval(evaluate(node.left, env) + node.operator + evaluate(node.right, env));
22+
case 'UnaryExpression':
23+
return eval(node.operator + evaluate(node.argument, env));
24+
// 这里有个短路
25+
case 'LogicalExpression':
26+
return node.operator === '&&' ?
27+
evaluate(node.left, env) && evaluate(node.right, env) :
28+
evaluate(node.left, env) || evaluate(node.right, env);
29+
case 'ConditionalExpression':
30+
return evaluate(node.test, env) ?
31+
evaluate(node.consequent, env) :
32+
evaluate(node.alternate, env);
33+
// 取对象成员
34+
case 'MemberExpression':
35+
return evaluate(node.object, env)[node.computed ? evaluate(node.property, env) : node.property.name];
36+
// mark,赋值相关的好像不能在环境里直接取变量的值?比如`a = 5, a++, a++`
37+
// 大概是要先去父级作用域查询,查询不到时再在本作用域新建这个变量?
38+
case 'UpdateExpression':
39+
let value = evaluate(node.argument, env);
40+
if (node.prefix) {a
41+
return node.operator === '++' ? ++value : --value;
42+
} else {
43+
return node.operator === '++' ? value++ : value--;
44+
}
45+
case 'AssignmentExpression':
46+
return env[node.left.name] = evaluate(node.right, env);
47+
// 逗号都要算一遍,只返回最后一个值
48+
case 'SequenceExpression':
49+
return node.expressions.reduce((_, expression) =>
50+
evaluate(expression, env), undefined);
51+
// 函数及作用域相关
52+
case 'FunctionExpression':
53+
return function (...args) {
54+
return evaluate(node.body, {
55+
...env,
56+
...node.params.reduce((params, param, index) => ({...params, [param.name]: args[index]}), {}),
57+
});
58+
};
59+
case 'ArrowFunctionExpression':
60+
return function (...args) {
61+
return evaluate(node.body, {
62+
...env,
63+
...node.params.reduce((params, param, index) => ({...params, [param.name]: args[index]}), {}),
64+
});
65+
}
66+
case 'CallExpression':
67+
return evaluate(node.callee, env)(...node.arguments.map(arg => evaluate(arg, env)));
768
}
869

970
throw new Error(`Unsupported Syntax ${node.type} at Location ${node.start}:${node.end}`);
@@ -16,4 +77,6 @@ function customerEval(code, env = {}) {
1677
return evaluate(node, env)
1778
}
1879

19-
module.exports = customerEval
80+
module.exports = customerEval
81+
82+
customerEval("(n => ((x => n = x)(n + 2), (y => n + y)(3)))(1)");

0 commit comments

Comments
 (0)