Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,23 @@ clone 本项目后根据 homework 目录下的 README.md 文件查看具体要
4. 进入 issue 中找到对应的作业提交安装模板提交作业

5. 提交后等待 code review 就好了

## 与brambles同步更新

1. fork过后添加原项目地址

git remote add upstream git@github.com:bramblex/jsjs-homework.git

2. `git remote -v` 就可以看到一个origin是你的,另外一个upstream是原作者的。

3. 执行`git fetch upstream`命令,检出upstream分支以及各自的更新;

4. 切换到你的本地分支主干:`git checkout master`;

5. 合并`upsteram/master`分支和`master`分支,将原项目中的更改更新到本地分支,这样就能使你的本地的fork分支与原项目保持同步,命令:`git merge upstream/master`;

6. 执行`git push`将本地分支的修改推送到远端fork的项目;

7. **另一种方式同步更新**

![image-20220115151418927](image-20220115151418927.png)
4 changes: 2 additions & 2 deletions homework/1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
## 作业要求:
1. `npm install` 安装依赖;
3. 补全 `rename.js` 里面的代码中的 `transform(code, originName, targetName)` 函数,使其能将 `code` 中所有变量名从 `originName` 改成 `targetName`;
4. `yarn test-homework-1` 可以执行本作业的测试用例,是作业通过 `rename.test.js` 中的测试用例 (运算表达式只需要实现 + 即可通过测试);
4. `yarn test-homework-1` 可以执行本作业的测试用例,是作业通过 `rename.test2.js` 中的测试用例 (运算表达式只需要实现 + 即可通过测试);

## 提示:
1. 所有的变量名都是 type 为 `Identifier`,但不是所有 `Identifier` 都是变量名;
2. 所有 Node 的定义 [https://github.com/estree/estree/blob/master/es5.md](https://github.com/estree/estree/blob/master/es5.md);
3. 可以将测试用例中的代码复制进 [https://astexplorer.net/](https://astexplorer.net/) 中查看其生成 AST;
3. 可以将测试用例中的代码复制进 [https://astexplorer.net/](https://astexplorer.net/) 中查看其生成 AST;
28 changes: 25 additions & 3 deletions homework/1/rename.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,32 @@ const traverse = require('../../common/traverse');
function transform(root, originName, targetName) {
// 遍历所有节点
return traverse((node, ctx, next) => {

// TODO: 作业代码写在这里
if (node.type === 'xxx') {
/*
* 真的尝试了不想一个个匹配
* 但是没找到解决方法
* 于是就这样了ε=(´ο`*)))唉
* */
if (node.type === 'FunctionDeclaration') {
if(node.id.name === originName){
node.id.name = targetName
}
}
if (node.type === 'VariableDeclaration') {
for(i of node.declarations){
i.id.name = targetName
}
}
if (node.type === 'MemberExpression') {
if(node.object.name === originName){
node.object.name = targetName
}
}
if (node.type === 'BinaryExpression') {
node.left.name = targetName;
node.right.name = targetName;
}


// 继续往下遍历
return next(node, ctx)
Expand All @@ -22,4 +44,4 @@ function rename(code, originName, targetName) {
return astring.generate(transform(ast, originName, targetName))
}

module.exports = rename
module.exports = rename
4 changes: 2 additions & 2 deletions homework/2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
## 作业要求:
1. `npm install` 安装依赖;
2. 补全 `eval.js` 里面的代码中的 `evaluate(node, env)` 函数,使其能将传入的表达式 AST 节点运算出结果;
3. `yarn test-homework-2` 可以执行本作业的测试用例,是作业通过 `eval.test.js` 中的测试用例 ;
3. `yarn test-homework-2` 可以执行本作业的测试用例,是作业通过 `eval.test2.js` 中的测试用例 ;

## 思考题:
1. 平时说的作用域,闭包在计算机眼里都是什么?
2. 我们作业的代码非常有限甚至非常简单,但是我们实现的程序却能执行无限复杂的表达式,思考这是为什么?
2. 我们作业的代码非常有限甚至非常简单,但是我们实现的程序却能执行无限复杂的表达式,思考这是为什么?
77 changes: 75 additions & 2 deletions homework/2/eval.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,90 @@ const acorn = require('acorn');
function evaluate(node, env) {
switch (node.type) {
case 'Literal':
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 'in': return evaluate(node.left, env) in evaluate(node.right, env);
case 'instanceof': return evaluate(node.left, env) instanceof evaluate(node.right, env);
}
}
case 'LogicalExpression':
if(node.operator === '&&') {
return evaluate(node.left,env) && evaluate(node.right, env)
}else if (node.operator === '||') {
return evaluate(node.left,env) || evaluate(node.right, env)
}else return ;
case 'CallExpression':
// if(node.callee.name === 'throwError')return env['throwError']();
// else
return evaluate(node.callee, env)(...node.arguments.map(arg => evaluate(arg, env)));

case 'ArrowFunctionExpression': {
// const args = node.params.map(e => e.name);
return function (...args) {
let argsEnv = {}
node.params.map( (item,index) => {
argsEnv[item.name] = args[index]
})
// const argsEnv = node.params.reduce((argsEnv, param, idx) => ({ ...argsEnv, [param.name]: args[idx] }), { ...env });

return evaluate(node.body,{...env, ...argsEnv});
};
}

case 'ConditionalExpression':
if(evaluate(node.test,env)) {
return evaluate(node.consequent, env)
}else {
return evaluate(node.alternate, env)
}
case 'ObjectExpression':
let tmpDict = {};
for (item of node.properties){
tmpDict[item.key.name] = evaluate(item.value)
}
return tmpDict
case 'ArrayExpression':
return node.elements.map((item, index) => {
return evaluate(item)
})
case 'SequenceExpression':
return node.expressions.forEach(item => evaluate(item, env))
case 'AssignmentExpression':{
return env[evaluate(node.left,env)] = env[evaluate(node.right,env)]
}
// TODO: 补全作业代码
}

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
})
// console.log(node)
return evaluate(node, env)
}

module.exports = customerEval
module.exports = customerEval
Binary file added image-20220115151156630.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-20220115151418927.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading