diff --git a/es2panda/binder/binder.cpp b/es2panda/binder/binder.cpp index 1a56f6cdc0bbce6209c0a9fd80bb441c54173c46..418ed1275ac4be1a51dcae5852c4227e6d6e7793 100644 --- a/es2panda/binder/binder.cpp +++ b/es2panda/binder/binder.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -518,9 +519,13 @@ void Binder::ResolveReference(const ir::AstNode *parent, ir::AstNode *childNode) break; } case ir::AstNodeType::SWITCH_STATEMENT: { - auto scopeCtx = LexicalScope::Enter(this, childNode->AsSwitchStatement()->Scope()); + auto *switchStatement = childNode->AsSwitchStatement(); + ResolveReference(switchStatement, switchStatement->Discriminant()); - ResolveReferences(childNode); + auto scopeCtx = LexicalScope::Enter(this, childNode->AsSwitchStatement()->Scope()); + for (auto *it : switchStatement->Cases()) { + ResolveReference(switchStatement, it); + } break; } case ir::AstNodeType::DO_WHILE_STATEMENT: { diff --git a/es2panda/ir/statements/switchStatement.cpp b/es2panda/ir/statements/switchStatement.cpp index 94b97de649145b29bf47462967afdd856f4e31b1..acf81a4b29eddf7dcd7d84a4e49cb06d00c3e028 100644 --- a/es2panda/ir/statements/switchStatement.cpp +++ b/es2panda/ir/statements/switchStatement.cpp @@ -43,11 +43,12 @@ void SwitchStatement::Dump(ir::AstDumper *dumper) const void SwitchStatement::Compile(compiler::PandaGen *pg) const { - compiler::LocalRegScope lrs(pg, scope_); compiler::SwitchBuilder builder(pg, this); compiler::VReg tag = pg->AllocReg(); builder.CompileTagOfSwitch(tag); + + compiler::LocalRegScope lrs(pg, scope_); uint32_t defaultIndex = 0; for (size_t i = 0; i < cases_.size(); i++) { diff --git a/es2panda/ir/statements/switchStatement.h b/es2panda/ir/statements/switchStatement.h index 3e2148fd76c725b0736fe99247befc42c0ef5898..748414161f8d4d1136ea5ff3f5026f7f11c0acf6 100644 --- a/es2panda/ir/statements/switchStatement.h +++ b/es2panda/ir/statements/switchStatement.h @@ -49,11 +49,21 @@ public: return discriminant_; } + Expression *Discriminant() + { + return discriminant_; + } + const ArenaVector &Cases() const { return cases_; } + ArenaVector &Cases() + { + return cases_; + } + binder::LocalScope *Scope() const { return scope_; diff --git a/es2panda/test/compiler/js/language/statements/switch/discriminant-scope-expected.txt b/es2panda/test/compiler/js/language/statements/switch/discriminant-scope-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..a965a70ed4edf261c693c1467610cc44af853c53 --- /dev/null +++ b/es2panda/test/compiler/js/language/statements/switch/discriminant-scope-expected.txt @@ -0,0 +1 @@ +Done diff --git a/es2panda/test/compiler/js/language/statements/switch/discriminant-scope.js b/es2panda/test/compiler/js/language/statements/switch/discriminant-scope.js new file mode 100644 index 0000000000000000000000000000000000000000..390abba7384174927296b57651352529a472702b --- /dev/null +++ b/es2panda/test/compiler/js/language/statements/switch/discriminant-scope.js @@ -0,0 +1,12 @@ +function test() { + let a = 0; + switch (a) { + case 0: + const a = 0; + break; + } + + print("Done"); +} + +test(); \ No newline at end of file diff --git a/ts2panda/src/statement/switchStatement.ts b/ts2panda/src/statement/switchStatement.ts index f964b12928a1b4e5d61c9bee8a1f86e9deeea4b9..180587a66bded2228c2a8d47aec5bccab386a50f 100644 --- a/ts2panda/src/statement/switchStatement.ts +++ b/ts2panda/src/statement/switchStatement.ts @@ -92,7 +92,6 @@ export class SwitchBase { } export function compileSwitchStatement(stmt: ts.SwitchStatement, compiler: Compiler) { - compiler.pushScope(stmt); let pandaGen = compiler.getPandaGen(); let caseNums = stmt.caseBlock.clauses.length; let switchEndLabel = new Label(); @@ -100,6 +99,7 @@ export function compileSwitchStatement(stmt: ts.SwitchStatement, compiler: Compi let tagReg = pandaGen.getTemp(); switchBuilder.compileTagOfSwitch(tagReg); + compiler.pushScope(stmt); let caseTargets = stmt.caseBlock.clauses; let defaultIndex = 0; let defaultCnt = 0; diff --git a/ts2panda/tests/statements/switch.test.ts b/ts2panda/tests/statements/switch.test.ts index f3b908c218d727db534b42894362753de2805264..f09bb9bce2bebcd1c7f1ad893ea777ef02a173ac 100644 --- a/ts2panda/tests/statements/switch.test.ts +++ b/ts2panda/tests/statements/switch.test.ts @@ -27,12 +27,13 @@ import { Jmp, Jnez, Label, + Lda, Ldai, Sta, VReg, IRNode } from "../../src/irnodes"; -import { checkInstructions, compileMainSnippet } from "../utils/base"; +import { checkInstructions, compileMainSnippet, SnippetCompiler } from "../utils/base"; import { creatAstFromSnippet } from "../utils/asthelper" import { PandaGen } from '../../src/pandagen'; @@ -210,4 +211,47 @@ describe("switchTest", function () { ]; expect(checkInstructions(insns, expected)).to.be.true; }); + + it("discriminant's scope", function () { + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile( + `function test() { + let a = 0; + switch (a) { + case 0: + const a = 0; + break; + } + }`); + IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); + + let a = new VReg(); + let discriminant_a = new VReg(); + let body_a = new VReg(); + let caseLabel_0 = new Label(); + let switchEndLabel = new Label(); + let expected = [ + new Ldai(new Imm(0)), + new Sta(a), + // switch discriminant + new Lda(a), + new Sta(discriminant_a), + // switch body + new Ldai(new Imm(0)), + new Strictnoteq(new Imm(1), discriminant_a), + new Jeqz(caseLabel_0), + new Jmp(switchEndLabel), + // switch cases + caseLabel_0, + new Ldai(new Imm(0)), + new Sta(body_a), + new Jmp(switchEndLabel), + switchEndLabel, + new Returnundefined() + ]; + let functionPg = snippetCompiler.getPandaGenByName("test"); + let insns = functionPg!.getInsns(); + + expect(checkInstructions(insns, expected)).to.be.true; + }); });