//: Take raw control of the text-mode display and console, putting it in //: 'console' mode rather than the usual automatically-scrolling 'typewriter' //: mode. //:: Display management :(before "End Globals") int Display_row = 0; int Display_column = 0; :(before "End Includes") #define CHECK_SCREEN \ if (!tb_is_active()) { \ if (Run_tests) \ raise << maybe(current_recipe_name()) << "tried to print to real screen in a test!\n" << end(); \ else \ raise << maybe(current_recipe_name()) << "tried to print to real screen before 'open-console' or after 'close-console'\n" << end(); \ break; \ } #define CHECK_CONSOLE \ if (!tb_is_active()) { \ if (Run_tests) \ raise << maybe(current_recipe_name()) << "tried to read event from real keyboard/mouse in a test!\n" << end(); \ else \ raise << maybe(current_recipe_name()) << "tried to read event from real keyboard/mouse before 'open-console' or after 'close-console'\n" << end(); \ break; \ } :(before "End Primitive Recipe Declarations") OPEN_CONSOLE, :(before "End Primitive Recipe Numbers") put(Recipe_ordinal, "open-console", OPEN_CONSOLE); :(before "End Primitive Recipe Checks") case OPEN_CONSOLE: { break; } :(before "End Primitive Recipe Implementations") case OPEN_CONSOLE: { tb_init(); std::setvbuf(stdout, NULL, _IONBF, 0); // disable buffering in cout Display_row = Display_column = 0; int width = tb_width(); int height = tb_height(); if (width > 222 || height > 222) { if (width > 222) raise << "sorry, Mu doesn't support windows wider than 222 characters in console mode. Please resize your window.\n" << end(); if (height > 222) raise << "sorry, Mu doesn't support windows taller than 222 characters in console mode. Please resize your window.\n" << end(); exit(1); } break; } :(before "End Primitive Recipe Declarations") CLOSE_CONSOLE, :(before "End Primitive Recipe Numbers") put(Recipe_ordinal, "close-console", CLOSE_CONSOLE); :(before "End Primitive Recipe Checks") case CLOSE_CONSOLE: { break; } :(before "End Primitive Recipe Implementations") case CLOSE_CONSOLE: { tb_shutdown(); break; } :(before "End Primitive Recipe Declarations") CLEAR_DISPLAY, :(before "End Primitive Recipe Numbers") put(Recipe_ordinal, "clear-display", CLEAR_DISPLAY); :(before "End Primitive Recipe Checks") case CLEAR_DISPLAY: { break; } :(before "End Primitive Recipe Implementations") case CLEAR_DISPLAY: { CHECK_SCREEN; tb_clear(); Display_row = Display_column = 0; break; } :(before "End Primitive Recipe Declarations") PRINT_CHARACTER_TO_DISPLAY, :(before "End Primitive Recipe Numbers") put(Recipe_ordinal, "print-character-to-display", PRINT_CHARACTER_TO_DISPLAY); :(before "End Primitive Recipe Checks") case PRINT_CHARACTER_TO_DISPLAY: { if (inst.ingredients.empty()) { raise << maybe(get(Recipe, r).name) << "'print-character-to-display' requires at least one ingredient, but got '" << to_original_string(inst) << "'\n" << end(); break; } if (!is_mu_number(inst.ingredients.at(0))) { raise << maybe(get(Recipe, r).name) << "first ingredient of 'print-character-to-display' should be a character, but got '" << inst.ingredients.at(0).original_string << "'\n" << end(); break; } if (SIZE(inst.ingredients) > 1) { if (!is_mu_number(inst.ingredients.at(1))) { raise << maybe(get(Recipe, r).name) << "second ingredient of 'print-character-to-display' should be a foreground color number, but got '" << inst.ingredients.at(1).original_string << "'\n" << end(); break; } } if (SIZE(inst.ingredients) > 2) { if (!is_mu_number(inst.ingredients.at(2))) { raise << maybe(get(Recipe, r).name) << "third ingr
// So far instructions can only contain linear lists of properties. Now we add
// support for more complex trees of properties in dilated reagents. This will
// come in handy later for expressing complex types, like "a dictionary from
// (address to array of charaters) to (list of numbers)".
//
// Type trees aren't as general as s-expressions even if they look like them:
// the first element of a type tree is always an atom, and it can never be
// dotted (right->right->right->...->right is always NULL).
//
// For now you can't use the simpler 'colon-based' representation inside type
// trees. Once you start typing parens, keep on typing parens.

void test_dilated_reagent_with_nested_brackets() {
  load(
      "def main [\n"
      "  {1: number, foo: (bar (baz quux))} <- copy 34\n"
      "]\n"
  );
  CHECK_TRACE_CONTENTS(
      "parse:   product: {1: \"number\", \"foo\": (\"bar\" (\"baz<