mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 22:17:42 +00:00
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:
parent
1923051c5b
commit
2285f84596
6 changed files with 57 additions and 2 deletions
|
@ -873,7 +873,31 @@ Value ThrowStatement::execute(Interpreter& interpreter) const
|
||||||
|
|
||||||
Value SwitchStatement::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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -885,7 +909,7 @@ Value SwitchCase::execute(Interpreter& interpreter) const
|
||||||
|
|
||||||
Value BreakStatement::execute(Interpreter& interpreter) const
|
Value BreakStatement::execute(Interpreter& interpreter) const
|
||||||
{
|
{
|
||||||
(void)interpreter;
|
interpreter.unwind(ScopeType::Breakable);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 void dump(int indent) const override;
|
||||||
virtual Value execute(Interpreter&) const override;
|
virtual Value execute(Interpreter&) const override;
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ enum class ScopeType {
|
||||||
Function,
|
Function,
|
||||||
Block,
|
Block,
|
||||||
Try,
|
Try,
|
||||||
|
Breakable,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Variable {
|
struct Variable {
|
||||||
|
@ -78,6 +79,7 @@ public:
|
||||||
Heap& heap() { return m_heap; }
|
Heap& heap() { return m_heap; }
|
||||||
|
|
||||||
void unwind(ScopeType type) { m_unwind_until = type; }
|
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);
|
Optional<Value> get_variable(const FlyString& name);
|
||||||
void set_variable(const FlyString& name, Value, bool first_assignment = false);
|
void set_variable(const FlyString& name, Value, bool first_assignment = false);
|
||||||
|
|
10
Libraries/LibJS/Tests/switch-basic-2.js
Normal file
10
Libraries/LibJS/Tests/switch-basic-2.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
var a = "foo";
|
||||||
|
|
||||||
|
switch (a + "bar") {
|
||||||
|
case 1:
|
||||||
|
break;
|
||||||
|
case "foobar":
|
||||||
|
case 2:
|
||||||
|
console.log("PASS");
|
||||||
|
break;
|
||||||
|
}
|
6
Libraries/LibJS/Tests/switch-basic-3.js
Normal file
6
Libraries/LibJS/Tests/switch-basic-3.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
var a = "foo";
|
||||||
|
|
||||||
|
switch (100) {
|
||||||
|
default:
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
10
Libraries/LibJS/Tests/switch-basic.js
Normal file
10
Libraries/LibJS/Tests/switch-basic.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
switch (1 + 2) {
|
||||||
|
case 3:
|
||||||
|
console.log("PASS");
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
case 1:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue