LibJS: Implement basic execution of "switch" statements

The "break" keyword now unwinds to the nearest ScopeType::Breakable.
There's no support for break labels yet, but we'll get there too.
This commit is contained in:
Andreas Kling 2020-03-29 14:34:25 +02:00
parent 1923051c5b
commit 2285f84596
Notes: sideshowbarker 2024-07-19 08:04:58 +09:00
6 changed files with 57 additions and 2 deletions

View file

@ -873,7 +873,31 @@ Value ThrowStatement::execute(Interpreter& interpreter) const
Value SwitchStatement::execute(Interpreter& interpreter) const
{
(void)interpreter;
auto discriminant_result = m_discriminant->execute(interpreter);
if (interpreter.exception())
return {};
bool falling_through = false;
for (auto& switch_case : m_cases) {
if (!falling_through && switch_case.test()) {
auto test_result = switch_case.test()->execute(interpreter);
if (interpreter.exception())
return {};
if (!eq(discriminant_result, test_result).to_boolean())
continue;
}
falling_through = true;
for (auto& statement : switch_case.consequent()) {
statement.execute(interpreter);
if (interpreter.exception())
return {};
if (interpreter.should_unwind())
return {};
}
}
return {};
}
@ -885,7 +909,7 @@ Value SwitchCase::execute(Interpreter& interpreter) const
Value BreakStatement::execute(Interpreter& interpreter) const
{
(void)interpreter;
interpreter.unwind(ScopeType::Breakable);
return {};
}

View file

@ -715,6 +715,9 @@ public:
{
}
const Expression* test() const { return m_test; }
const NonnullRefPtrVector<Statement>& consequent() const { return m_consequent; }
virtual void dump(int indent) const override;
virtual Value execute(Interpreter&) const override;

View file

@ -42,6 +42,7 @@ enum class ScopeType {
Function,
Block,
Try,
Breakable,
};
struct Variable {
@ -78,6 +79,7 @@ public:
Heap& heap() { return m_heap; }
void unwind(ScopeType type) { m_unwind_until = type; }
bool should_unwind() const { return m_unwind_until != ScopeType::None; }
Optional<Value> get_variable(const FlyString& name);
void set_variable(const FlyString& name, Value, bool first_assignment = false);

View file

@ -0,0 +1,10 @@
var a = "foo";
switch (a + "bar") {
case 1:
break;
case "foobar":
case 2:
console.log("PASS");
break;
}

View file

@ -0,0 +1,6 @@
var a = "foo";
switch (100) {
default:
console.log("PASS");
}

View file

@ -0,0 +1,10 @@
switch (1 + 2) {
case 3:
console.log("PASS");
break;
case 5:
case 1:
break;
default:
break;
}