From 51728d9334f642958f80bf442b40a76decdccafe Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sat, 19 Aug 2017 05:53:31 -0700 Subject: 3971 --- html/020run.cc.html | 541 ++++++++++++++++++++++++++-------------------------- 1 file changed, 270 insertions(+), 271 deletions(-) (limited to 'html/020run.cc.html') diff --git a/html/020run.cc.html b/html/020run.cc.html index 57220e78..70697d67 100644 --- a/html/020run.cc.html +++ b/html/020run.cc.html @@ -115,7 +115,7 @@ if ('onhashchange' in window) { 48 49 :(before "End Globals") 50 routine* Current_routine = NULL; - 51 :(before "End Setup") + 51 :(before "End Reset") 52 Current_routine = NULL; 53 54 :(code) @@ -275,282 +275,281 @@ if ('onhashchange' in window) { 208 :(before "End Main") 209 if (!Run_tests && contains_key(Recipe_ordinal, "main") && contains_key(Recipe, get(Recipe_ordinal, "main"))) { 210 // Running Main -211 setup(); +211 reset(); 212 if (Start_tracing) { 213 ¦ Trace_stream = new trace_stream; 214 ¦ Save_trace = true; 215 } 216 trace(2, "run") << "=== Starting to run" << end(); 217 assert(Num_calls_to_transform_all == 1); -218 run_main(argc, argv); -219 teardown(); -220 } -221 :(code) -222 void run_main(int argc, char* argv[]) { -223 recipe_ordinal r = get(Recipe_ordinal, "main"); -224 if (r) run(r); -225 } -226 -227 //: By default we don't maintain the trace while running main because its -228 //: overheads can grow rapidly. However, it's useful when debugging. -229 :(before "End Globals") -230 bool Start_tracing = false; -231 :(before "End Commandline Options(*arg)") -232 else if (is_equal(*arg, "--trace")) { -233 Start_tracing = true; -234 } -235 -236 :(code) -237 void cleanup_main() { -238 if (Save_trace && Trace_stream) { -239 ¦ cerr << "writing trace to 'last_run'\n"; -240 ¦ ofstream fout("last_run"); -241 ¦ fout << Trace_stream->readable_contents(""); -242 ¦ fout.close(); -243 } -244 if (Trace_stream) delete Trace_stream, Trace_stream = NULL; -245 } -246 :(before "End One-time Setup") -247 atexit(cleanup_main); -248 -249 :(code) -250 void load_file_or_directory(string filename) { -251 if (is_directory(filename)) { -252 ¦ load_all(filename); -253 ¦ return; -254 } -255 ifstream fin(filename.c_str()); -256 if (!fin) { -257 ¦ cerr << "no such file '" << filename << "'\n" << end(); // don't raise, just warn. just in case it's just a name for a scenario to run. -258 ¦ return; -259 } -260 trace(9990, "load") << "=== " << filename << end(); -261 load(fin); -262 fin.close(); -263 } -264 -265 bool is_directory(string path) { -266 struct stat info; -267 if (stat(path.c_str(), &info)) return false; // error -268 return info.st_mode & S_IFDIR; -269 } -270 -271 void load_all(string dir) { -272 dirent** files; -273 int num_files = scandir(dir.c_str(), &files, NULL, alphasort); -274 for (int i = 0; i < num_files; ++i) { -275 ¦ string curr_file = files[i]->d_name; -276 ¦ if (isdigit(curr_file.at(0))) -277 ¦ ¦ load_file_or_directory(dir+'/'+curr_file); -278 ¦ free(files[i]); -279 ¦ files[i] = NULL; -280 } -281 free(files); -282 } -283 :(before "End Includes") -284 #include <dirent.h> -285 #include <sys/stat.h> -286 -287 //:: Reading from memory, writing to memory. -288 -289 :(code) -290 vector<double> read_memory(reagent/*copy*/ x) { -291 // Begin Preprocess read_memory(x) -292 vector<double> result; -293 if (is_literal(x)) { -294 ¦ result.push_back(x.value); -295 ¦ return result; -296 } -297 // End Preprocess read_memory(x) -298 int size = size_of(x); -299 for (int offset = 0; offset < size; ++offset) { -300 ¦ double val = get_or_insert(Memory, x.value+offset); -301 ¦ trace(9999, "mem") << "location " << x.value+offset << " is " << no_scientific(val) << end(); -302 ¦ result.push_back(val); -303 } -304 return result; -305 } -306 -307 void write_memory(reagent/*copy*/ x, const vector<double>& data) { -308 assert(Current_routine); // run-time only -309 // Begin Preprocess write_memory(x, data) -310 if (!x.type) { -311 ¦ raise << "can't write to '" << to_string(x) << "'; no type\n" << end(); -312 ¦ return; -313 } -314 if (is_dummy(x)) return; -315 if (is_literal(x)) return; -316 // End Preprocess write_memory(x, data) -317 if (x.value == 0) { -318 ¦ raise << "can't write to location 0 in '" << to_original_string(current_instruction()) << "'\n" << end(); -319 ¦ return; -320 } -321 if (size_mismatch(x, data)) { -322 ¦ raise << maybe(current_recipe_name()) << "size mismatch in storing to '" << x.original_string << "' (" << size_of(x) << " vs " << SIZE(data) << ") at '" << to_original_string(current_instruction()) << "'\n" << end(); -323 ¦ return; -324 } -325 // End write_memory(x) Special-cases -326 for (int offset = 0; offset < SIZE(data); ++offset) { -327 ¦ assert(x.value+offset > 0); -328 ¦ trace(9999, "mem") << "storing " << no_scientific(data.at(offset)) << " in location " << x.value+offset << end(); -329 ¦ put(Memory, x.value+offset, data.at(offset)); -330 } -331 } -332 -333 :(code) -334 int size_of(const reagent& r) { -335 if (!r.type) return 0; -336 // End size_of(reagent r) Special-cases -337 return size_of(r.type); -338 } -339 int size_of(const type_tree* type) { -340 if (!type) return 0; -341 if (type->atom) { -342 ¦ if (type->value == -1) return 1; // error value, but we'll raise it elsewhere -343 ¦ if (type->value == 0) return 1; -344 ¦ // End size_of(type) Atom Special-cases -345 } -346 else { -347 ¦ if (!type->left->atom) { -348 ¦ ¦ raise << "invalid type " << to_string(type) << '\n' << end(); -349 ¦ ¦ return 0; -350 ¦ } -351 ¦ if (type->left->value == get(Type_ordinal, "address")) return 1; -352 ¦ // End size_of(type) Non-atom Special-cases -353 } -354 // End size_of(type) Special-cases -355 return 1; -356 } -357 -358 bool size_mismatch(const reagent& x, const vector<double>& data) { -359 if (!x.type) return true; -360 // End size_mismatch(x) Special-cases -361 //? if (size_of(x) != SIZE(data)) cerr << size_of(x) << " vs " << SIZE(data) << '\n'; -362 return size_of(x) != SIZE(data); -363 } -364 -365 bool is_literal(const reagent& r) { -366 return is_literal(r.type); -367 } -368 bool is_literal(const type_tree* type) { -369 if (!type) return false; -370 if (!type->atom) return false; -371 return type->value == 0; -372 } -373 -374 bool scalar(const vector<int>& x) { -375 return SIZE(x) == 1; -376 } -377 bool scalar(const vector<double>& x) { -378 return SIZE(x) == 1; -379 } -380 -381 // helper for tests -382 void run(const string& form) { -383 vector<recipe_ordinal> tmp = load(form); -384 transform_all(); -385 if (tmp.empty()) return; -386 if (trace_contains_errors()) return; -387 // if a test defines main, it probably wants to start there regardless of -388 // definition order -389 if (contains_key(Recipe, get(Recipe_ordinal, "main"))) -390 ¦ run(get(Recipe_ordinal, "main")); -391 else -392 ¦ run(tmp.front()); -393 } -394 -395 :(scenario run_label) -396 def main [ -397 +foo -398 1:num <- copy 23 -399 2:num <- copy 1:num -400 ] -401 +run: {1: "number"} <- copy {23: "literal"} -402 +run: {2: "number"} <- copy {1: "number"} -403 -run: +foo -404 -405 :(scenario run_dummy) -406 def main [ -407 _ <- copy 0 -408 ] -409 +run: _ <- copy {0: "literal"} -410 -411 :(scenario write_to_0_disallowed) -412 % Hide_errors = true; -413 def main [ -414 0:num <- copy 34 -415 ] -416 -mem: storing 34 in location 0 -417 -418 //: Mu is robust to various combinations of commas and spaces. You just have -419 //: to put spaces around the '<-'. -420 -421 :(scenario comma_without_space) -422 def main [ -423 1:num, 2:num <- copy 2,2 -424 ] -425 +mem: storing 2 in location 1 -426 -427 :(scenario space_without_comma) -428 def main [ -429 1:num, 2:num <- copy 2 2 -430 ] -431 +mem: storing 2 in location 1 -432 -433 :(scenario comma_before_space) -434 def main [ -435 1:num, 2:num <- copy 2, 2 -436 ] -437 +mem: storing 2 in location 1 -438 -439 :(scenario comma_after_space) -440 def main [ -441 1:num, 2:num <- copy 2 ,2 -442 ] -443 +mem: storing 2 in location 1 -444 -445 //:: Counters for trying to understand where Mu programs are spending their -446 //:: time. -447 -448 :(before "End Globals") -449 bool Run_profiler = false; -450 // We'll key profile information by recipe_ordinal rather than name because -451 // it's more efficient, and because later layers will show more than just the -452 // name of a recipe. -453 // -454 // One drawback: if you're clearing recipes your profile will be inaccurate. -455 // So far that happens in tests, and in `run-sandboxed` in a later layer. -456 map<recipe_ordinal, int> Instructions_running; -457 :(before "End Commandline Options(*arg)") -458 else if (is_equal(*arg, "--profile")) { -459 Run_profiler = true; -460 } -461 :(after "Running One Instruction") -462 if (Run_profiler) Instructions_running[currently_running_recipe()]++; -463 :(before "End One-time Setup") -464 atexit(dump_profile); -465 :(code) -466 void dump_profile() { -467 if (!Run_profiler) return; -468 if (Run_tests) { -469 ¦ cerr << "It's not a good idea to profile a run with tests, since tests can create conflicting recipes and mislead you. To try it anyway, comment out this check in the code.\n"; -470 ¦ return; -471 } -472 ofstream fout; -473 fout.open("profile.instructions"); -474 if (fout) { -475 ¦ for (map<recipe_ordinal, int>::iterator p = Instructions_running.begin(); p != Instructions_running.end(); ++p) { -476 ¦ ¦ fout << std::setw(9) << p->second << ' ' << header_label(p->first) << '\n'; -477 ¦ } -478 } -479 fout.close(); -480 // End dump_profile -481 } -482 -483 // overridden in a later layer -484 string header_label(const recipe_ordinal r) { -485 return get(Recipe, r).name; -486 } +218 run_main(argc, argv); +219 } +220 :(code) +221 void run_main(int argc, char* argv[]) { +222 recipe_ordinal r = get(Recipe_ordinal, "main"); +223 if (r) run(r); +224 } +225 +226 //: By default we don't maintain the trace while running main because its +227 //: overheads can grow rapidly. However, it's useful when debugging. +228 :(before "End Globals") +229 bool Start_tracing = false; +230 :(before "End Commandline Options(*arg)") +231 else if (is_equal(*arg, "--trace")) { +232 Start_tracing = true; +233 } +234 +235 :(code) +236 void cleanup_main() { +237 if (Save_trace && Trace_stream) { +238 ¦ cerr << "writing trace to 'last_run'\n"; +239 ¦ ofstream fout("last_run"); +240 ¦ fout << Trace_stream->readable_contents(""); +241 ¦ fout.close(); +242 } +243 if (Trace_stream) delete Trace_stream, Trace_stream = NULL; +244 } +245 :(before "End One-time Setup") +246 atexit(cleanup_main); +247 +248 :(code) +249 void load_file_or_directory(string filename) { +250 if (is_directory(filename)) { +251 ¦ load_all(filename); +252 ¦ return; +253 } +254 ifstream fin(filename.c_str()); +255 if (!fin) { +256 ¦ cerr << "no such file '" << filename << "'\n" << end(); // don't raise, just warn. just in case it's just a name for a scenario to run. +257 ¦ return; +258 } +259 trace(9990, "load") << "=== " << filename << end(); +260 load(fin); +261 fin.close(); +262 } +263 +264 bool is_directory(string path) { +265 struct stat info; +266 if (stat(path.c_str(), &info)) return false; // error +267 return info.st_mode & S_IFDIR; +268 } +269 +270 void load_all(string dir) { +271 dirent** files; +272 int num_files = scandir(dir.c_str(), &files, NULL, alphasort); +273 for (int i = 0; i < num_files; ++i) { +274 ¦ string curr_file = files[i]->d_name; +275 ¦ if (isdigit(curr_file.at(0))) +276 ¦ ¦ load_file_or_directory(dir+'/'+curr_file); +277 ¦ free(files[i]); +278 ¦ files[i] = NULL; +279 } +280 free(files); +281 } +282 :(before "End Includes") +283 #include <dirent.h> +284 #include <sys/stat.h> +285 +286 //:: Reading from memory, writing to memory. +287 +288 :(code) +289 vector<double> read_memory(reagent/*copy*/ x) { +290 // Begin Preprocess read_memory(x) +291 vector<double> result; +292 if (is_literal(x)) { +293 ¦ result.push_back(x.value); +294 ¦ return result; +295 } +296 // End Preprocess read_memory(x) +297 int size = size_of(x); +298 for (int offset = 0; offset < size; ++offset) { +299 ¦ double val = get_or_insert(Memory, x.value+offset); +300 ¦ trace(9999, "mem") << "location " << x.value+offset << " is " << no_scientific(val) << end(); +301 ¦ result.push_back(val); +302 } +303 return result; +304 } +305 +306 void write_memory(reagent/*copy*/ x, const vector<double>& data) { +307 assert(Current_routine); // run-time only +308 // Begin Preprocess write_memory(x, data) +309 if (!x.type) { +310 ¦ raise << "can't write to '" << to_string(x) << "'; no type\n" << end(); +311 ¦ return; +312 } +313 if (is_dummy(x)) return; +314 if (is_literal(x)) return; +315 // End Preprocess write_memory(x, data) +316 if (x.value == 0) { +317 ¦ raise << "can't write to location 0 in '" << to_original_string(current_instruction()) << "'\n" << end(); +318 ¦ return; +319 } +320 if (size_mismatch(x, data)) { +321 ¦ raise << maybe(current_recipe_name()) << "size mismatch in storing to '" << x.original_string << "' (" << size_of(x) << " vs " << SIZE(data) << ") at '" << to_original_string(current_instruction()) << "'\n" << end(); +322 ¦ return; +323 } +324 // End write_memory(x) Special-cases +325 for (int offset = 0; offset < SIZE(data); ++offset) { +326 ¦ assert(x.value+offset > 0); +327 ¦ trace(9999, "mem") << "storing " << no_scientific(data.at(offset)) << " in location " << x.value+offset << end(); +328 ¦ put(Memory, x.value+offset, data.at(offset)); +329 } +330 } +331 +332 :(code) +333 int size_of(const reagent& r) { +334 if (!r.type) return 0; +335 // End size_of(reagent r) Special-cases +336 return size_of(r.type); +337 } +338 int size_of(const type_tree* type) { +339 if (!type) return 0; +340 if (type->atom) { +341 ¦ if (type->value == -1) return 1; // error value, but we'll raise it elsewhere +342 ¦ if (type->value == 0) return 1; +343 ¦ // End size_of(type) Atom Special-cases +344 } +345 else { +346 ¦ if (!type->left->atom) { +347 ¦ ¦ raise << "invalid type " << to_string(type) << '\n' << end(); +348 ¦ ¦ return 0; +349 ¦ } +350 ¦ if (type->left->value == get(Type_ordinal, "address")) return 1; +351 ¦ // End size_of(type) Non-atom Special-cases +352 } +353 // End size_of(type) Special-cases +354 return 1; +355 } +356 +357 bool size_mismatch(const reagent& x, const vector<double>& data) { +358 if (!x.type) return true; +359 // End size_mismatch(x) Special-cases +360 //? if (size_of(x) != SIZE(data)) cerr << size_of(x) << " vs " << SIZE(data) << '\n'; +361 return size_of(x) != SIZE(data); +362 } +363 +364 bool is_literal(const reagent& r) { +365 return is_literal(r.type); +366 } +367 bool is_literal(const type_tree* type) { +368 if (!type) return false; +369 if (!type->atom) return false; +370 return type->value == 0; +371 } +372 +373 bool scalar(const vector<int>& x) { +374 return SIZE(x) == 1; +375 } +376 bool scalar(const vector<double>& x) { +377 return SIZE(x) == 1; +378 } +379 +380 // helper for tests +381 void run(const string& form) { +382 vector<recipe_ordinal> tmp = load(form); +383 transform_all(); +384 if (tmp.empty()) return; +385 if (trace_contains_errors()) return; +386 // if a test defines main, it probably wants to start there regardless of +387 // definition order +388 if (contains_key(Recipe, get(Recipe_ordinal, "main"))) +389 ¦ run(get(Recipe_ordinal, "main")); +390 else +391 ¦ run(tmp.front()); +392 } +393 +394 :(scenario run_label) +395 def main [ +396 +foo +397 1:num <- copy 23 +398 2:num <- copy 1:num +399 ] +400 +run: {1: "number"} <- copy {23: "literal"} +401 +run: {2: "number"} <- copy {1: "number"} +402 -run: +foo +403 +404 :(scenario run_dummy) +405 def main [ +406 _ <- copy 0 +407 ] +408 +run: _ <- copy {0: "literal"} +409 +410 :(scenario write_to_0_disallowed) +411 % Hide_errors = true; +412 def main [ +413 0:num <- copy 34 +414 ] +415 -mem: storing 34 in location 0 +416 +417 //: Mu is robust to various combinations of commas and spaces. You just have +418 //: to put spaces around the '<-'. +419 +420 :(scenario comma_without_space) +421 def main [ +422 1:num, 2:num <- copy 2,2 +423 ] +424 +mem: storing 2 in location 1 +425 +426 :(scenario space_without_comma) +427 def main [ +428 1:num, 2:num <- copy 2 2 +429 ] +430 +mem: storing 2 in location 1 +431 +432 :(scenario comma_before_space) +433 def main [ +434 1:num, 2:num <- copy 2, 2 +435 ] +436 +mem: storing 2 in location 1 +437 +438 :(scenario comma_after_space) +439 def main [ +440 1:num, 2:num <- copy 2 ,2 +441 ] +442 +mem: storing 2 in location 1 +443 +444 //:: Counters for trying to understand where Mu programs are spending their +445 //:: time. +446 +447 :(before "End Globals") +448 bool Run_profiler = false; +449 // We'll key profile information by recipe_ordinal rather than name because +450 // it's more efficient, and because later layers will show more than just the +451 // name of a recipe. +452 // +453 // One drawback: if you're clearing recipes your profile will be inaccurate. +454 // So far that happens in tests, and in `run-sandboxed` in a later layer. +455 map<recipe_ordinal, int> Instructions_running; +456 :(before "End Commandline Options(*arg)") +457 else if (is_equal(*arg, "--profile")) { +458 Run_profiler = true; +459 } +460 :(after "Running One Instruction") +461 if (Run_profiler) Instructions_running[currently_running_recipe()]++; +462 :(before "End One-time Setup") +463 atexit(dump_profile); +464 :(code) +465 void dump_profile() { +466 if (!Run_profiler) return; +467 if (Run_tests) { +468 ¦ cerr << "It's not a good idea to profile a run with tests, since tests can create conflicting recipes and mislead you. To try it anyway, comment out this check in the code.\n"; +469 ¦ return; +470 } +471 ofstream fout; +472 fout.open("profile.instructions"); +473 if (fout) { +474 ¦ for (map<recipe_ordinal, int>::iterator p = Instructions_running.begin(); p != Instructions_running.end(); ++p) { +475 ¦ ¦ fout << std::setw(9) << p->second << ' ' << header_label(p->first) << '\n'; +476 ¦ } +477 } +478 fout.close(); +479 // End dump_profile +480 } +481 +482 // overridden in a later layer +483 string header_label(const recipe_ordinal r) { +484 return get(Recipe, r).name; +485 } -- cgit 1.4.1-2-gfad0