1
1
const acorn = require ( 'acorn' ) ;
2
2
3
+ // 查找某变量所在的父级环境
4
+ function findEnv ( name , env ) {
5
+ return env [ name ] ? env : env . fa && findEnv ( name , env . fa ) ;
6
+ }
7
+
3
8
function evaluate ( node , env ) {
4
9
switch ( node . type ) {
5
10
// TODO: 补全作业代码
6
11
// 作为叶子节点的字面量和变量直接返回它们的值
7
12
case 'Literal' :
8
13
return node . value ;
9
14
case 'Identifier' :
10
- return env [ node . name ] ;
15
+ return findEnv ( node . name , env ) [ node . name ] ;
11
16
// 数组,对象
12
17
case 'ArrayExpression' :
13
18
return node . elements . map ( e => evaluate ( e , env ) ) ;
@@ -37,29 +42,30 @@ function evaluate(node, env) {
37
42
// 大概是要先去父级作用域查询,查询不到时再在本作用域新建这个变量?
38
43
case 'UpdateExpression' :
39
44
let value = evaluate ( node . argument , env ) ;
40
- if ( node . prefix ) { a
45
+ if ( node . prefix ) {
41
46
return node . operator === '++' ? ++ value : -- value ;
42
47
} else {
43
48
return node . operator === '++' ? value ++ : value -- ;
44
49
}
45
50
case 'AssignmentExpression' :
46
- return env [ node . left . name ] = evaluate ( node . right , env ) ;
51
+ let protoEnv = findEnv ( node . left . name , env ) ;
52
+ return protoEnv ? protoEnv [ node . left . name ] = evaluate ( node . right , env ) : env [ node . left . name ] = evaluate ( node . right , env ) ;
47
53
// 逗号都要算一遍,只返回最后一个值
48
54
case 'SequenceExpression' :
49
55
return node . expressions . reduce ( ( _ , expression ) =>
50
- evaluate ( expression , env ) , undefined ) ;
56
+ evaluate ( expression , env ) , undefined ) ;
51
57
// 函数及作用域相关
52
58
case 'FunctionExpression' :
53
59
return function ( ...args ) {
54
60
return evaluate ( node . body , {
55
- ... env ,
61
+ fa : env ,
56
62
...node . params . reduce ( ( params , param , index ) => ( { ...params , [ param . name ] : args [ index ] } ) , { } ) ,
57
63
} ) ;
58
64
} ;
59
65
case 'ArrowFunctionExpression' :
60
66
return function ( ...args ) {
61
67
return evaluate ( node . body , {
62
- ... env ,
68
+ fa : env ,
63
69
...node . params . reduce ( ( params , param , index ) => ( { ...params , [ param . name ] : args [ index ] } ) , { } ) ,
64
70
} ) ;
65
71
}
@@ -74,6 +80,7 @@ function customerEval(code, env = {}) {
74
80
const node = acorn . parseExpressionAt ( code , 0 , {
75
81
ecmaVersion : 6
76
82
} )
83
+ env . fa = null ;
77
84
return evaluate ( node , env )
78
85
}
79
86
0 commit comments