+struct ast_loop : ast_expression
+{
+ ast_loop() = delete;
+ ast_loop(lex_ctx_t ctx,
+ ast_expression *initexpr,
+ ast_expression *precond, bool pre_not,
+ ast_expression *postcond, bool post_not,
+ ast_expression *increment,
+ ast_expression *body);
+ ~ast_loop();
+
+ bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
+
+ ast_expression *m_initexpr;
+ ast_expression *m_precond;
+ ast_expression *m_postcond;
+ ast_expression *m_increment;
+ ast_expression *m_body;
+ /* For now we allow a seperate flag on whether or not the condition
+ * is supposed to be true or false.
+ * That way, the parser can generate a 'while not(!x)' for `while(x)`
+ * if desired, which is useful for the new -f{true,false}-empty-strings
+ * flag.
+ */
+ bool m_pre_not;
+ bool m_post_not;
+};
+
+/* Break/Continue
+ */
+struct ast_breakcont : ast_expression
+{
+ ast_breakcont() = delete;
+ ast_breakcont(lex_ctx_t ctx, bool iscont, unsigned int levels);
+ ~ast_breakcont();
+
+ bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
+
+
+ bool m_is_continue;
+ unsigned int m_levels;
+};
+
+/* Switch Statements
+ *
+ * A few notes about this: with the original QCVM, no real optimization
+ * is possible. The SWITCH instruction set isn't really helping a lot, since
+ * it only collapes the EQ and IF instructions into one.
+ * Note: Declaring local variables inside caseblocks is normal.
+ * Since we don't have to deal with a stack there's no unnatural behaviour to
+ * be expected from it.
+ * TODO: Ticket #20
+ */
+struct ast_switch_case {
+ ast_expression *m_value; /* #20 will replace this */
+ ast_expression *m_code;
+};
+
+struct ast_switch : ast_expression
+{
+ ast_switch() = delete;
+ ast_switch(lex_ctx_t ctx, ast_expression *op);
+ ~ast_switch();
+
+ bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
+
+ ast_expression *m_operand;
+ std::vector<ast_switch_case> m_cases;
+};
+
+
+/* Label nodes
+ *
+ * Introduce a label which can be used together with 'goto'
+ */
+struct ast_label : ast_expression
+{
+ ast_label() = delete;
+ ast_label(lex_ctx_t ctx, const std::string &name, bool undefined);
+ ~ast_label();
+
+ bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
+
+ std::string m_name;
+ ir_block *m_irblock;
+ std::vector<ast_goto*> m_gotos;
+
+ /* means it has not yet been defined */
+ bool m_undefined;
+
+private:
+ void registerGoto(ast_goto*);
+ friend struct ast_goto;
+};
+
+/* GOTO nodes
+ *
+ * Go to a label, the label node is filled in at a later point!
+ */
+struct ast_goto : ast_expression