//: Structured programming //: //: Our jump operators 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 //: recipes '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_test) :(scenario "brace_conversion") recipe main [ { break 1:integer <- copy 0:literal } ] +after-brace: recipe main +after-brace: jump 1:offset +after-brace: copy ... //: one-time setup :(after "int main") Transform.push_back(transform_braces); :(code) void transform_braces(const recipe_number r) { //? cout << "AAA transform_braces\n"; //? 1 //? exit(0); //? 1 const int OPEN = 0, CLOSE = 1; list > braces; for (size_t index = 0; index < Recipe[r].steps.size(); ++index) { const instruction& inst = Recipe[r].steps[index]; if (inst.label == "{") { trace("brace") << r << ": push (open, " << index << ")"; braces.push_back(pair(OPEN, index)); } if (inst.label == "}") { trace("brace") << "push (close, " << index << ")"; braces.push_back(pair(CLOSE, index)); } } stack open_braces; trace("after-brace") << "recipe " << Recipe[r].name; for (size_t index = 0; index < Recipe[r].steps.size(); ++index) { instruction& inst = Recipe[r].steps[index]; //? cout << "AAA " << inst.name << ": " << inst.operation << '\n'; //? 1 if (inst.label == "{") open_braces.push(index); else if (inst.label == "}") open_braces.pop(); else if (inst.is_label) ; // do nothing else if (inst.operation == Recipe_number["loop"]) { inst.operation = Recipe_number["jump"]; if (inst.ingredients.size() > 0 && isa_literal(inst.ingredients[0])) { // explicit target; a later phase will handle it trace("after-brace") << "jump " << inst.ingredients[0].name << ":offset"; } else { reagent ing; ing.set_value(open_braces.top()-index); inst.ingredients.push_back(ing); trace("after-brace") << "jump " << ing.value << ":offset"; trace("after-brace") << index << ": " << ing.to_string(); trace("after-brace") << index << ": " << Recipe[r].steps[index].ingredients[0].to_string(); } } else if (inst.operation == Recipe_number["break"]) { inst.operation = Recipe_number["jump"]; if (inst.ingredients.size() > 0 && isa_literal(inst.ingredients[0])) { // explicit target; a later phase will handle it trace("after-brace") << "jump " << inst.ingredients[0].name << ":offset"; } else { reagent ing; ing.set_value(matching_brace(open_braces.top(), braces) - index - 1); inst.ingredients.push_back(ing); trace("after-brace") << "jump " << ing.value << ":offset"; } } else if (inst.operation == Recipe_number["loop-if"]) { inst.operation = Recipe_number["jump-if"]; if (inst.ingredients.size() > 1 && isa_literal(inst.ingredients[1])) { // explicit target; a later phase will handle it trace("after-brace") << "jump " << inst.ingredients[1].name << ":offset";
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Python: module all_tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head><body bgcolor="#f0f0f8">

<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#7799ee">
<td valign=bottom>&nbsp;<