//: Structured programming //: //: Our jump recipes are quite inconvenient to use, so Mu provides a //: lightweight tool called 'transform_braces' to work in a slightly more //: convenient format with nested braces: //: //: { //: some instructions //: { //: more instructions //: } //: } //: //: Braces are just labels, they require no special parsing. The pseudo //: instructions 'loop' and 'break' jump to just after the enclosing '{' and //: '}' respectively. //: //: Conditional and unconditional 'loop' and 'break' should give us 80% of the //: benefits of the control-flow primitives we're used to in other languages, //: like 'if', 'while', 'for', etc. :(scenarios transform) :(scenario brace_conversion) def main [ { break 1:num <- copy 0 } ] +transform: --- transform braces for recipe main +transform: jump 1:offset +transform: copy ... :(before "End Instruction Modifying Transforms") Transform.push_back(transform_braces); // idempotent :(code) void transform_braces(const recipe_ordinal r) { const int OPEN = 0, CLOSE = 1; // use signed integer for step index because we'll be doing arithmetic on it list > braces; trace(9991, "transform") << "--- transform braces for recipe " << get(Recipe, r).name << end(); for (int index = 0; index < SIZE(get(Recipe, r).steps); ++index) { const instruction& inst = get(Recipe, r).steps.at(index); if (inst.label == "{") { trace(9993, "transform") << maybe(get(Recipe, r).name) << "push (open, " << index << ")" << end(); braces.push_back(pair(OPEN, index)); } if (inst.label == "}") { trace(9993, "transform") << "push (close, " << index << ")" << end(); braces.push_back(pair(CLOSE, index)); } } stack open_braces; for (int index = 0; index < SIZE(get(Recipe, r).steps); ++index) { instruction& inst = get(Recipe, r).steps.at(index); if (inst.label == "{") { open_braces.push(index); continue; } if (inst.label == "}") { if (open_braces.empty()) { raise << maybe(get(Recipe, r).name) << "unbalanced '}'\n" << end(); return; } open_braces.pop(); continue; } if (inst.is_label) continue; if (inst.name != "loop" && inst.name != "loop-if" && inst.name != "loop-unless" && inst.name != "break" && inst.name != "break-if" && inst.name != "break-unless") { trace(9992, "transform") << inst.name << " ..." << end(); continue; } // check for errors if (inst.name.find("-if") != string::npos || inst.name.find("-unless") != string::npos) { if (inst.ingredients.empty()) { raise << maybe(get(Recipe, r).name) << "'" << inst.name << "' expects 1 or 2 ingredients, but got none\n" << end(); continue; } } // update instruction operation string old_name = inst.name; // save a copy if (inst.name.find("-if") != string::npos) { inst.name = "jump-if"; inst.operation = JUMP_IF; } else if (inst.name.find("-unless") != string::npos) { inst.name = "jump-unless"; inst.operation = JUMP_UNLESS; } else { inst.name = "jump"; inst.operation = JUMP; } // check for explicitly provided targets if (inst.name.find("-if") != string::npos || inst.name.find("-unless") != string::npos) { // conditional branches check arg 1 if (SIZE(inst.ingredients) > 1 && is_literal(inst.ingredients.at(1))) { trace(9992, "transform") << inst.name << ' ' << inst.ingredients.at(1).name << ":offset" << end(); continue; } } else { // unconditional branches check arg 0 if (!inst.ingredients.empty() && is_literal(inst.ingredients.at(0))) { trace(9992, "transform") << "jump " << inst.ingredients.at(0).name << ":offset" << end(); continue; } } // if implicit, compute target reagent target; target.type = new type_tree("offset"); target.set_value(0); if (open_braces.empty()) raise << maybe(get(Recipe, r).name) << "'" << old_name << "' needs a '{' before\n" << end(); else if (old_name.find("loop") != string::npos) target.set_value(open_braces.top()-index); else // break instruction target.set_value(matching_brace(open_braces.top(), braces, r) - index - 1); inst.ingredients.push_back(target); // log computed target
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>

#include "xmpp/xmpp.h"

#include "ui/ui.h"
#include "ui/stub_ui.h"

#include "command/cmd_funcs.h"

#define CMD_SUB "/sub"

void cmd_sub_shows_message_when_not_connected(void **state)
{
    gchar *args[] = { NULL };

    will_return(connection_get_status