about summary refs log tree commit diff stats
path: root/066stream.mu
Commit message (Expand)AuthorAgeFilesLines
* 4262 - literal 'null'Kartik Agaram2018-06-171-1/+1
* 4261 - start using literals for 'true' and 'false'Kartik Agaram2018-06-171-4/+4
* 4134 - 'input' = 'ingredient'Kartik K. Agaram2017-12-031-6/+6
* 3817 - better errors on streams from null textsKartik K. Agaram2017-04-131-0/+6
* 3390Kartik K. Agaram2016-09-171-5/+5
* 3389Kartik K. Agaram2016-09-171-12/+12
* 3386Kartik K. Agaram2016-09-171-6/+6
* 3385Kartik K. Agaram2016-09-171-9/+9
* 3379Kartik K. Agaram2016-09-171-1/+1
* 3341Kartik K. Agaram2016-09-121-1/+1
* 3337 - first use of type abbreviations: textKartik K. Agaram2016-09-121-2/+2
* 3156Kartik K. Agaram2016-07-271-14/+24
* 3155Kartik K. Agaram2016-07-271-2/+2
* 3154 - reorg before making 'random' more testableKartik K. Agaram2016-07-271-0/+64
* 2430 - make room for more transformsKartik K. Agaram2015-11-131-44/+0
* 2225Kartik K. Agaram2015-10-011-1/+1
* 1883 - type-deducing in more .mu filesKartik K. Agaram2015-07-291-19/+19
* 1869 - rename the /deref property to /lookupKartik K. Agaram2015-07-281-14/+14
* 1868 - start using naked literals everywhereKartik K. Agaram2015-07-281-4/+4
* 1780 - now we always reclaim local scopesKartik K. Agaram2015-07-131-4/+4
* 1773 - update all mu recipes to new-default-spaceKartik K. Agaram2015-07-131-4/+4
* 1597 - port more helpers from arc versionKartik K. Agaram2015-06-191-0/+44
r: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
//: Dead simple persistence.
//:   'restore' - reads string from a file
//:   'save' - writes string to a file

:(before "End Primitive Recipe Declarations")
RESTORE,
:(before "End Primitive Recipe Numbers")
put(Recipe_ordinal, "restore", RESTORE);
:(before "End Primitive Recipe Checks")
case RESTORE: {
  if (SIZE(inst.ingredients) != 1) {
    raise << maybe(get(Recipe, r).name) << "'restore' requires exactly one ingredient, but got '" << inst.original_string << "'\n" << end();
    break;
  }
  string filename;
  if (is_literal_text(inst.ingredients.at(0))) {
    ;
  }
  else if (is_mu_text(inst.ingredients.at(0))) {
    ;
  }
  else {
    raise << maybe(get(Recipe, r).name) << "first ingredient of 'restore' should be a string, but got '" << to_string(inst.ingredients.at(0)) << "'\n" << end();
    break;
  }
  break;
}
:(before "End Primitive Recipe Implementations")
case RESTORE: {
  string filename;
  if (is_literal_text(current_instruction().ingredients.at(0))) {
    filename = current_instruction().ingredients.at(0).name;
  }
  else if (is_mu_text(current_instruction().ingredients.at(0))) {
    filename = read_mu_text(ingredients.at(0).at(0));
  }
  if (Current_scenario) {
    // do nothing in tests
    products.resize(1);
    products.at(0).push_back(0);
    break;
  }
  string contents = slurp("lesson/"+filename);
  products.resize(1);
  if (contents.empty())
    products.at(0).push_back(0);
  else
    products.at(0).push_back(new_mu_text(contents));
  break;
}

:(code)
// http://cpp.indi.frih.net/blog/2014/09/how-to-read-an-entire-file-into-memory-in-cpp
string slurp(const string& filename) {
  ifstream fin(filename.c_str());
  fin.peek();
  if (!fin) return "";  // don't bother checking errno
  ostringstream result;
  result << fin.rdbuf();
  fin.close();
  return result.str();
}

:(before "End Primitive Recipe Declarations")
SAVE,
:(before "End Primitive Recipe Numbers")
put(Recipe_ordinal, "save", SAVE);
:(before "End Primitive Recipe Checks")
case SAVE: {
  if (SIZE(inst.ingredients) != 2) {
    raise << maybe(get(Recipe, r).name) << "'save' requires exactly two ingredients, but got '" << inst.original_string << "'\n" << end();
    break;
  }
  if (is_literal_text(inst.ingredients.at(0))) {
    ;
  }
  else if (is_mu_text(inst.ingredients.at(0))) {
    ;
  }
  else {
    raise << maybe(get(Recipe, r).name) << "first ingredient of 'save' should be a string, but got '" << to_string(inst.ingredients.at(0)) << "'\n" << end();
    break;
  }
  if (!is_mu_text(inst.ingredients.at(1))) {
    raise << maybe(get(Recipe, r).name) << "second ingredient of 'save' should be an address:array:character, but got '" << to_string(inst.ingredients.at(1)) << "'\n" << end();
    break;
  }
  break;
}
:(before "End Primitive Recipe Implementations")
case SAVE: {
  if (Current_scenario) break;  // do nothing in tests
  string filename;
  if (is_literal_text(current_instruction().ingredients.at(0))) {
    filename = current_instruction().ingredients.at(0).name;
  }
  else if (is_mu_text(current_instruction().ingredients.at(0))) {
    filename = read_mu_text(ingredients.at(0).at(0));
  }
  ofstream fout(("lesson/"+filename).c_str());
  string contents = read_mu_text(ingredients.at(1).at(0));
  fout << contents;
  fout.close();
  if (!exists("lesson/.git")) break;
  // bug in git: git diff -q messes up --exit-code
  // explicitly say '--all' for git 1.9
  int status = system("cd lesson; git add --all .; git diff HEAD --exit-code >/dev/null || git commit -a -m . >/dev/null");
  if (status != 0)
    raise << "error in commit: contents " << contents << '\n' << end();
  break;
}

:(code)
bool exists(const string& filename) {
  struct stat dummy;
  return 0 == stat(filename.c_str(), &dummy);
}