Serenity Operating System
1/*
2 * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#pragma once
28
29#include <AK/FlyString.h>
30#include <AK/HashMap.h>
31#include <AK/NonnullRefPtrVector.h>
32#include <AK/RefPtr.h>
33#include <AK/String.h>
34#include <AK/Vector.h>
35#include <LibJS/Forward.h>
36#include <LibJS/Runtime/PropertyName.h>
37#include <LibJS/Runtime/Value.h>
38
39namespace JS {
40
41template<class T, class... Args>
42static inline NonnullRefPtr<T>
43create_ast_node(Args&&... args)
44{
45 return adopt(*new T(forward<Args>(args)...));
46}
47
48class ASTNode : public RefCounted<ASTNode> {
49public:
50 virtual ~ASTNode() {}
51 virtual const char* class_name() const = 0;
52 virtual Value execute(Interpreter&) const = 0;
53 virtual void dump(int indent) const;
54 virtual bool is_identifier() const { return false; }
55 virtual bool is_member_expression() const { return false; }
56 virtual bool is_scope_node() const { return false; }
57 virtual bool is_variable_declaration() const { return false; }
58 virtual bool is_new_expression() const { return false; }
59
60protected:
61 ASTNode() {}
62
63private:
64};
65
66class Statement : public ASTNode {
67};
68
69class ErrorStatement final : public Statement {
70public:
71 Value execute(Interpreter&) const override { return js_undefined(); }
72 const char* class_name() const override { return "ErrorStatement"; }
73};
74
75class ExpressionStatement final : public Statement {
76public:
77 ExpressionStatement(NonnullRefPtr<Expression> expression)
78 : m_expression(move(expression))
79 {
80 }
81
82 Value execute(Interpreter&) const override;
83 const char* class_name() const override { return "ExpressionStatement"; }
84 virtual void dump(int indent) const override;
85
86private:
87 NonnullRefPtr<Expression> m_expression;
88};
89
90class ScopeNode : public Statement {
91public:
92 template<typename T, typename... Args>
93 T& append(Args&&... args)
94 {
95 auto child = create_ast_node<T>(forward<Args>(args)...);
96 m_children.append(move(child));
97 return static_cast<T&>(m_children.last());
98 }
99 void append(NonnullRefPtr<Statement> child)
100 {
101 m_children.append(move(child));
102 }
103
104 const NonnullRefPtrVector<Statement>& children() const { return m_children; }
105 virtual Value execute(Interpreter&) const override;
106 virtual void dump(int indent) const override;
107
108protected:
109 ScopeNode() {}
110
111private:
112 virtual bool is_scope_node() const final { return true; }
113 NonnullRefPtrVector<Statement> m_children;
114};
115
116class Program : public ScopeNode {
117public:
118 Program() {}
119
120private:
121 virtual const char* class_name() const override { return "Program"; }
122};
123
124class BlockStatement : public ScopeNode {
125public:
126 BlockStatement() {}
127
128private:
129 virtual const char* class_name() const override { return "BlockStatement"; }
130};
131
132class Expression : public ASTNode {
133};
134
135class Declaration : public Statement {
136};
137
138class FunctionNode {
139public:
140 const FlyString& name() const { return m_name; }
141 const Statement& body() const { return *m_body; }
142 const Vector<FlyString>& parameters() const { return m_parameters; };
143
144protected:
145 FunctionNode(const FlyString& name, NonnullRefPtr<Statement> body, Vector<FlyString> parameters = {})
146 : m_name(name)
147 , m_body(move(body))
148 , m_parameters(move(parameters))
149 {
150 }
151
152 void dump(int indent, const char* class_name) const;
153
154private:
155 FlyString m_name;
156 NonnullRefPtr<Statement> m_body;
157 const Vector<FlyString> m_parameters;
158};
159
160class FunctionDeclaration final
161 : public Declaration
162 , public FunctionNode {
163public:
164 static bool must_have_name() { return true; }
165
166 FunctionDeclaration(String name, NonnullRefPtr<Statement> body, Vector<FlyString> parameters = {})
167 : FunctionNode(move(name), move(body), move(parameters))
168 {
169 }
170
171 virtual Value execute(Interpreter&) const override;
172 virtual void dump(int indent) const override;
173
174private:
175 virtual const char* class_name() const override { return "FunctionDeclaration"; }
176};
177
178class FunctionExpression final : public Expression
179 , public FunctionNode {
180public:
181 static bool must_have_name() { return false; }
182
183 FunctionExpression(const FlyString& name, NonnullRefPtr<Statement> body, Vector<FlyString> parameters = {})
184 : FunctionNode(name, move(body), move(parameters))
185 {
186 }
187
188 virtual Value execute(Interpreter&) const override;
189 virtual void dump(int indent) const override;
190
191private:
192 virtual const char* class_name() const override { return "FunctionExpression"; }
193};
194
195class ErrorExpression final : public Expression {
196public:
197 Value execute(Interpreter&) const override { return js_undefined(); }
198 const char* class_name() const override { return "ErrorExpression"; }
199};
200
201class ReturnStatement : public Statement {
202public:
203 explicit ReturnStatement(RefPtr<Expression> argument)
204 : m_argument(move(argument))
205 {
206 }
207
208 const Expression* argument() const { return m_argument; }
209
210 virtual Value execute(Interpreter&) const override;
211 virtual void dump(int indent) const override;
212
213private:
214 virtual const char* class_name() const override { return "ReturnStatement"; }
215
216 RefPtr<Expression> m_argument;
217};
218
219class IfStatement : public Statement {
220public:
221 IfStatement(NonnullRefPtr<Expression> predicate, NonnullRefPtr<Statement> consequent, RefPtr<Statement> alternate)
222 : m_predicate(move(predicate))
223 , m_consequent(move(consequent))
224 , m_alternate(move(alternate))
225 {
226 }
227
228 const Expression& predicate() const { return *m_predicate; }
229 const Statement& consequent() const { return *m_consequent; }
230 const Statement* alternate() const { return m_alternate; }
231
232 virtual Value execute(Interpreter&) const override;
233 virtual void dump(int indent) const override;
234
235private:
236 virtual const char* class_name() const override { return "IfStatement"; }
237
238 NonnullRefPtr<Expression> m_predicate;
239 NonnullRefPtr<Statement> m_consequent;
240 RefPtr<Statement> m_alternate;
241};
242
243class WhileStatement : public Statement {
244public:
245 WhileStatement(NonnullRefPtr<Expression> test, NonnullRefPtr<Statement> body)
246 : m_test(move(test))
247 , m_body(move(body))
248 {
249 }
250
251 const Expression& test() const { return *m_test; }
252 const Statement& body() const { return *m_body; }
253
254 virtual Value execute(Interpreter&) const override;
255 virtual void dump(int indent) const override;
256
257private:
258 virtual const char* class_name() const override { return "WhileStatement"; }
259
260 NonnullRefPtr<Expression> m_test;
261 NonnullRefPtr<Statement> m_body;
262};
263
264class DoWhileStatement : public Statement {
265public:
266 DoWhileStatement(NonnullRefPtr<Expression> test, NonnullRefPtr<Statement> body)
267 : m_test(move(test))
268 , m_body(move(body))
269 {
270 }
271
272 const Expression& test() const { return *m_test; }
273 const Statement& body() const { return *m_body; }
274
275 virtual Value execute(Interpreter&) const override;
276 virtual void dump(int indent) const override;
277
278private:
279 virtual const char* class_name() const override { return "DoWhileStatement"; }
280
281 NonnullRefPtr<Expression> m_test;
282 NonnullRefPtr<Statement> m_body;
283};
284
285class ForStatement : public Statement {
286public:
287 ForStatement(RefPtr<ASTNode> init, RefPtr<Expression> test, RefPtr<Expression> update, NonnullRefPtr<Statement> body)
288 : m_init(move(init))
289 , m_test(move(test))
290 , m_update(move(update))
291 , m_body(move(body))
292 {
293 }
294
295 const ASTNode* init() const { return m_init; }
296 const Expression* test() const { return m_test; }
297 const Expression* update() const { return m_update; }
298 const Statement& body() const { return *m_body; }
299
300 virtual Value execute(Interpreter&) const override;
301 virtual void dump(int indent) const override;
302
303private:
304 virtual const char* class_name() const override { return "ForStatement"; }
305
306 RefPtr<ASTNode> m_init;
307 RefPtr<Expression> m_test;
308 RefPtr<Expression> m_update;
309 NonnullRefPtr<Statement> m_body;
310};
311
312enum class BinaryOp {
313 Addition,
314 Subtraction,
315 Multiplication,
316 Division,
317 Modulo,
318 Exponentiation,
319 TypedEquals,
320 TypedInequals,
321 AbstractEquals,
322 AbstractInequals,
323 GreaterThan,
324 GreaterThanEquals,
325 LessThan,
326 LessThanEquals,
327 BitwiseAnd,
328 BitwiseOr,
329 BitwiseXor,
330 LeftShift,
331 RightShift,
332 InstanceOf,
333};
334
335class BinaryExpression : public Expression {
336public:
337 BinaryExpression(BinaryOp op, NonnullRefPtr<Expression> lhs, NonnullRefPtr<Expression> rhs)
338 : m_op(op)
339 , m_lhs(move(lhs))
340 , m_rhs(move(rhs))
341 {
342 }
343
344 virtual Value execute(Interpreter&) const override;
345 virtual void dump(int indent) const override;
346
347private:
348 virtual const char* class_name() const override { return "BinaryExpression"; }
349
350 BinaryOp m_op;
351 NonnullRefPtr<Expression> m_lhs;
352 NonnullRefPtr<Expression> m_rhs;
353};
354
355enum class LogicalOp {
356 And,
357 Or,
358};
359
360class LogicalExpression : public Expression {
361public:
362 LogicalExpression(LogicalOp op, NonnullRefPtr<Expression> lhs, NonnullRefPtr<Expression> rhs)
363 : m_op(op)
364 , m_lhs(move(lhs))
365 , m_rhs(move(rhs))
366 {
367 }
368
369 virtual Value execute(Interpreter&) const override;
370 virtual void dump(int indent) const override;
371
372private:
373 virtual const char* class_name() const override { return "LogicalExpression"; }
374
375 LogicalOp m_op;
376 NonnullRefPtr<Expression> m_lhs;
377 NonnullRefPtr<Expression> m_rhs;
378};
379
380enum class UnaryOp {
381 BitwiseNot,
382 Not,
383 Plus,
384 Minus,
385 Typeof,
386};
387
388class UnaryExpression : public Expression {
389public:
390 UnaryExpression(UnaryOp op, NonnullRefPtr<Expression> lhs)
391 : m_op(op)
392 , m_lhs(move(lhs))
393 {
394 }
395
396 virtual Value execute(Interpreter&) const override;
397 virtual void dump(int indent) const override;
398
399private:
400 virtual const char* class_name() const override { return "UnaryExpression"; }
401
402 UnaryOp m_op;
403 NonnullRefPtr<Expression> m_lhs;
404};
405
406class SequenceExpression final : public Expression {
407public:
408 SequenceExpression(NonnullRefPtrVector<Expression> expressions)
409 : m_expressions(move(expressions))
410 {
411 }
412
413 virtual void dump(int indent) const override;
414 virtual Value execute(Interpreter&) const override;
415
416private:
417 virtual const char* class_name() const override { return "SequenceExpression"; }
418
419 NonnullRefPtrVector<Expression> m_expressions;
420};
421
422class Literal : public Expression {
423protected:
424 explicit Literal() {}
425};
426
427class BooleanLiteral final : public Literal {
428public:
429 explicit BooleanLiteral(bool value)
430 : m_value(value)
431 {
432 }
433
434 virtual Value execute(Interpreter&) const override;
435 virtual void dump(int indent) const override;
436
437private:
438 virtual const char* class_name() const override { return "BooleanLiteral"; }
439
440 bool m_value { false };
441};
442
443class NumericLiteral final : public Literal {
444public:
445 explicit NumericLiteral(double value)
446 : m_value(value)
447 {
448 }
449
450 virtual Value execute(Interpreter&) const override;
451 virtual void dump(int indent) const override;
452
453private:
454 virtual const char* class_name() const override { return "NumericLiteral"; }
455
456 double m_value { 0 };
457};
458
459class StringLiteral final : public Literal {
460public:
461 explicit StringLiteral(String value)
462 : m_value(move(value))
463 {
464 }
465
466 virtual Value execute(Interpreter&) const override;
467 virtual void dump(int indent) const override;
468
469private:
470 virtual const char* class_name() const override { return "StringLiteral"; }
471
472 String m_value;
473};
474
475class NullLiteral final : public Literal {
476public:
477 explicit NullLiteral() {}
478
479 virtual Value execute(Interpreter&) const override;
480 virtual void dump(int indent) const override;
481
482private:
483 virtual const char* class_name() const override { return "NullLiteral"; }
484};
485
486class Identifier final : public Expression {
487public:
488 explicit Identifier(const FlyString& string)
489 : m_string(string)
490 {
491 }
492
493 const FlyString& string() const { return m_string; }
494
495 virtual Value execute(Interpreter&) const override;
496 virtual void dump(int indent) const override;
497 virtual bool is_identifier() const override { return true; }
498
499private:
500 virtual const char* class_name() const override { return "Identifier"; }
501
502 FlyString m_string;
503};
504
505class CallExpression : public Expression {
506public:
507 CallExpression(NonnullRefPtr<Expression> callee, NonnullRefPtrVector<Expression> arguments = {})
508 : m_callee(move(callee))
509 , m_arguments(move(arguments))
510 {
511 }
512
513 virtual Value execute(Interpreter&) const override;
514 virtual void dump(int indent) const override;
515
516private:
517 virtual const char* class_name() const override { return "CallExpression"; }
518
519 struct ThisAndCallee {
520 Value this_value;
521 Value callee;
522 };
523 ThisAndCallee compute_this_and_callee(Interpreter&) const;
524
525 NonnullRefPtr<Expression> m_callee;
526 const NonnullRefPtrVector<Expression> m_arguments;
527};
528
529class NewExpression final : public CallExpression {
530public:
531 NewExpression(NonnullRefPtr<Expression> callee, NonnullRefPtrVector<Expression> arguments = {})
532 : CallExpression(move(callee), move(arguments))
533 {
534 }
535
536private:
537 virtual const char* class_name() const override { return "NewExpression"; }
538 virtual bool is_new_expression() const override { return true; }
539};
540
541enum class AssignmentOp {
542 Assignment,
543 AdditionAssignment,
544 SubtractionAssignment,
545 MultiplicationAssignment,
546 DivisionAssignment,
547};
548
549class AssignmentExpression : public Expression {
550public:
551 AssignmentExpression(AssignmentOp op, NonnullRefPtr<ASTNode> lhs, NonnullRefPtr<Expression> rhs)
552 : m_op(op)
553 , m_lhs(move(lhs))
554 , m_rhs(move(rhs))
555 {
556 }
557
558 virtual Value execute(Interpreter&) const override;
559 virtual void dump(int indent) const override;
560
561private:
562 virtual const char* class_name() const override { return "AssignmentExpression"; }
563
564 AssignmentOp m_op;
565 NonnullRefPtr<ASTNode> m_lhs;
566 NonnullRefPtr<Expression> m_rhs;
567};
568
569enum class UpdateOp {
570 Increment,
571 Decrement,
572};
573
574class UpdateExpression : public Expression {
575public:
576 UpdateExpression(UpdateOp op, NonnullRefPtr<Expression> argument, bool prefixed = false)
577 : m_op(op)
578 , m_argument(move(argument))
579 , m_prefixed(prefixed)
580 {
581 }
582
583 virtual Value execute(Interpreter&) const override;
584 virtual void dump(int indent) const override;
585
586private:
587 virtual const char* class_name() const override { return "UpdateExpression"; }
588
589 UpdateOp m_op;
590 NonnullRefPtr<Expression> m_argument;
591 bool m_prefixed;
592};
593
594enum class DeclarationKind {
595 Var,
596 Let,
597 Const,
598};
599
600class VariableDeclarator final : public ASTNode {
601public:
602 VariableDeclarator(NonnullRefPtr<Identifier> id, RefPtr<Expression> init)
603 : m_id(move(id))
604 , m_init(move(init))
605 {
606 }
607
608 const Identifier& id() const { return m_id; }
609 const Expression* init() const { return m_init; }
610
611 virtual Value execute(Interpreter&) const override;
612 virtual void dump(int indent) const override;
613
614private:
615 virtual const char* class_name() const override { return "VariableDeclarator"; }
616
617 NonnullRefPtr<Identifier> m_id;
618 RefPtr<Expression> m_init;
619};
620
621class VariableDeclaration : public Declaration {
622public:
623 VariableDeclaration(DeclarationKind declaration_kind, NonnullRefPtrVector<VariableDeclarator> declarations)
624 : m_declaration_kind(declaration_kind)
625 , m_declarations(move(declarations))
626 {
627 }
628
629 virtual bool is_variable_declaration() const override { return true; }
630 DeclarationKind declaration_kind() const { return m_declaration_kind; }
631
632 virtual Value execute(Interpreter&) const override;
633 virtual void dump(int indent) const override;
634
635private:
636 virtual const char* class_name() const override { return "VariableDeclaration"; }
637
638 DeclarationKind m_declaration_kind;
639 NonnullRefPtrVector<VariableDeclarator> m_declarations;
640};
641
642class ObjectExpression : public Expression {
643public:
644 ObjectExpression(HashMap<FlyString, NonnullRefPtr<Expression>> properties = {})
645 : m_properties(move(properties))
646 {
647 }
648
649 virtual Value execute(Interpreter&) const override;
650 virtual void dump(int indent) const override;
651
652private:
653 virtual const char* class_name() const override { return "ObjectExpression"; }
654
655 HashMap<FlyString, NonnullRefPtr<Expression>> m_properties;
656};
657
658class ArrayExpression : public Expression {
659public:
660 ArrayExpression(NonnullRefPtrVector<Expression> elements)
661 : m_elements(move(elements))
662 {
663 }
664
665 const NonnullRefPtrVector<Expression>& elements() const { return m_elements; }
666
667 virtual Value execute(Interpreter&) const override;
668 virtual void dump(int indent) const override;
669
670private:
671 virtual const char* class_name() const override { return "ArrayExpression"; }
672
673 NonnullRefPtrVector<Expression> m_elements;
674};
675
676class MemberExpression final : public Expression {
677public:
678 MemberExpression(NonnullRefPtr<Expression> object, NonnullRefPtr<Expression> property, bool computed = false)
679 : m_object(move(object))
680 , m_property(move(property))
681 , m_computed(computed)
682 {
683 }
684
685 virtual Value execute(Interpreter&) const override;
686 virtual void dump(int indent) const override;
687
688 bool is_computed() const { return m_computed; }
689 const Expression& object() const { return *m_object; }
690 const Expression& property() const { return *m_property; }
691
692 PropertyName computed_property_name(Interpreter&) const;
693
694private:
695 virtual bool is_member_expression() const override { return true; }
696 virtual const char* class_name() const override { return "MemberExpression"; }
697
698 NonnullRefPtr<Expression> m_object;
699 NonnullRefPtr<Expression> m_property;
700 bool m_computed { false };
701};
702
703class ConditionalExpression final : public Expression {
704public:
705 ConditionalExpression(NonnullRefPtr<Expression> test, NonnullRefPtr<Expression> consequent, NonnullRefPtr<Expression> alternate)
706 : m_test(move(test))
707 , m_consequent(move(consequent))
708 , m_alternate(move(alternate))
709 {
710 }
711
712 virtual void dump(int indent) const override;
713 virtual Value execute(Interpreter&) const override;
714
715private:
716 virtual const char* class_name() const override { return "ConditionalExpression"; }
717
718 NonnullRefPtr<Expression> m_test;
719 NonnullRefPtr<Expression> m_consequent;
720 NonnullRefPtr<Expression> m_alternate;
721};
722
723class CatchClause final : public ASTNode {
724public:
725 CatchClause(const FlyString& parameter, NonnullRefPtr<BlockStatement> body)
726 : m_parameter(parameter)
727 , m_body(move(body))
728 {
729 }
730
731 const FlyString& parameter() const { return m_parameter; }
732 const BlockStatement& body() const { return m_body; }
733
734 virtual void dump(int indent) const override;
735 virtual Value execute(Interpreter&) const override;
736
737private:
738 virtual const char* class_name() const override { return "CatchClause"; }
739
740 FlyString m_parameter;
741 NonnullRefPtr<BlockStatement> m_body;
742};
743
744class TryStatement final : public Statement {
745public:
746 TryStatement(NonnullRefPtr<BlockStatement> block, RefPtr<CatchClause> handler, RefPtr<BlockStatement> finalizer)
747 : m_block(move(block))
748 , m_handler(move(handler))
749 , m_finalizer(move(finalizer))
750 {
751 }
752
753 const BlockStatement& block() const { return m_block; }
754 const CatchClause* handler() const { return m_handler; }
755 const BlockStatement* finalizer() const { return m_finalizer; }
756
757 virtual void dump(int indent) const override;
758 virtual Value execute(Interpreter&) const override;
759
760private:
761 virtual const char* class_name() const override { return "TryStatement"; }
762
763 NonnullRefPtr<BlockStatement> m_block;
764 RefPtr<CatchClause> m_handler;
765 RefPtr<BlockStatement> m_finalizer;
766};
767
768class ThrowStatement final : public Statement {
769public:
770 explicit ThrowStatement(NonnullRefPtr<Expression> argument)
771 : m_argument(move(argument))
772 {
773 }
774
775 const Expression& argument() const { return m_argument; }
776
777 virtual void dump(int indent) const override;
778 virtual Value execute(Interpreter&) const override;
779
780private:
781 virtual const char* class_name() const override { return "ThrowStatement"; }
782
783 NonnullRefPtr<Expression> m_argument;
784};
785
786class SwitchCase final : public ASTNode {
787public:
788 SwitchCase(RefPtr<Expression> test, NonnullRefPtrVector<Statement> consequent)
789 : m_test(move(test))
790 , m_consequent(move(consequent))
791 {
792 }
793
794 const Expression* test() const { return m_test; }
795 const NonnullRefPtrVector<Statement>& consequent() const { return m_consequent; }
796
797 virtual void dump(int indent) const override;
798 virtual Value execute(Interpreter&) const override;
799
800private:
801 virtual const char* class_name() const override { return "SwitchCase"; }
802
803 RefPtr<Expression> m_test;
804 NonnullRefPtrVector<Statement> m_consequent;
805};
806
807class SwitchStatement final : public Statement {
808public:
809 SwitchStatement(NonnullRefPtr<Expression> discriminant, NonnullRefPtrVector<SwitchCase> cases)
810 : m_discriminant(move(discriminant))
811 , m_cases(move(cases))
812 {
813 }
814
815 virtual void dump(int indent) const override;
816 virtual Value execute(Interpreter&) const override;
817
818private:
819 virtual const char* class_name() const override { return "SwitchStatement"; }
820
821 NonnullRefPtr<Expression> m_discriminant;
822 NonnullRefPtrVector<SwitchCase> m_cases;
823};
824
825class BreakStatement final : public Statement {
826public:
827 BreakStatement() {}
828
829 virtual Value execute(Interpreter&) const override;
830
831private:
832 virtual const char* class_name() const override { return "BreakStatement"; }
833};
834
835class ContinueStatement final : public Statement {
836public:
837 ContinueStatement() {}
838
839 virtual Value execute(Interpreter&) const override;
840
841private:
842 virtual const char* class_name() const override { return "ContinueStatement"; }
843};
844
845}