about summary refs log blame commit diff stats
path: root/081run_interactive.cc
blob: 9ef0f8a9f3b30433bf60afeaee26dbff9bc7e068 (plain) (tree)















































                                                                          



                                             
                                                    



                                                                 









                                                                                    


       


                                                                                            

                                       


                                         





                                                                     
                                                          

                                                                 
                                                   
                                    
                            



                                                                                    
   
                                                                                                       


                                                                                          
   
                                       
                                              
                                                
                                                 
                  
                                                                         

              
 
 

                                  









                                                


                      
                                                                    

                      

                               

 




                                             
                                          




                                                
//: Helper for various programming environments: run arbitrary mu code and
//: return some result in string form.

:(scenario run_interactive_location)
recipe main [
  1:number <- copy 34:literal
  2:address:array:character <- new [1
]
  3:address:array:character <- run-interactive 2:address:array:character
  4:array:character <- copy 3:address:array:character/deref
]
#? ?
# size of string
+mem: storing 2 in location 4
# unicode '3'
+mem: storing 51 in location 5
# unicode '4'
+mem: storing 52 in location 6

:(scenario run_interactive_code)
recipe main [
  2:address:array:character <- new [1:number <- copy 34:literal
]
  run-interactive 2:address:array:character  # code won't return a result
]
+mem: storing 34 in location 1

:(scenario run_interactive_name)
recipe main [
  2:address:array:character <- new [x:number <- copy 34:literal
]
  run-interactive 2:address:array:character
  3:address:array:character <- new [x
]
  4:address:array:character <- run-interactive 3:address:array:character
  5:array:character <- copy 4:address:array:character/deref
]
# result is string "34"
+mem: storing 2 in location 5
+mem: storing 51 in location 6
+mem: storing 52 in location 7

:(scenario run_interactive_empty)
recipe main [
  1:address:array:character <- run-interactive 0:literal
]
# result is null
+mem: storing 0 in location 1

:(before "End Primitive Recipe Declarations")
RUN_INTERACTIVE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["run-interactive"] = RUN_INTERACTIVE;
//? cerr << "run-interactive: " << RUN_INTERACTIVE << '\n'; //? 1
:(before "End Primitive Recipe Implementations")
case RUN_INTERACTIVE: {
  assert(scalar(ingredients.at(0)));
  products.resize(1);
  long long int result = 0;
  bool new_code_pushed_to_stack = run_interactive(ingredients.at(0).at(0), &result);
  if (!new_code_pushed_to_stack) {
    products.at(0).push_back(result);
    break;
  }
  else {
    continue;  // not done with caller; don't increment current_step_index()
  }
}

:(code)
// reads a string. if it's a variable, stores its value as a string and returns false.
// if it's lines of code, calls them and returns true (no result available yet to be stored)
bool run_interactive(long long int address, long long int* result) {
  long long int size = Memory[address];
  if (size == 0) {
//?     trace(1, "foo") << "AAA\n"; //? 1
    *result = 0;
    return false;
  }
  ostringstream tmp;
  for (long long int curr = address+1; curr < address+size; ++curr) {
    // todo: unicode
    tmp << (char)(int)Memory[curr];
  }
  assert(Memory[address+size] == 10);  // skip the newline
  if (Recipe_ordinal.find("interactive") == Recipe_ordinal.end())
    Recipe_ordinal["interactive"] = Next_recipe_ordinal++;
  string command = trim(strip_comments(tmp.str()));
  if (command.empty()) return false;
  if (is_integer(command)) {
//?     trace(1, "foo") << "BBB\n"; //? 1
    *result = stringified_value_of_location(to_integer(command));
//?     trace(1, "foo") << *result << " " << result << " " << Memory[*result]; //? 1
    return false;
  }
  if (Name[Recipe_ordinal["interactive"]].find(command) != Name[Recipe_ordinal["interactive"]].end()) {
//?     trace(1, "foo") << "CCC\n"; //? 1
    *result = stringified_value_of_location(Name[Recipe_ordinal["interactive"]][command]);
    return false;
  }
//?   trace(1, "foo") << "DDD\n"; //? 1
  Recipe.erase(Recipe_ordinal["interactive"]);
  // call run(string) but without the scheduling
  load("recipe interactive [\n"+command+"\n]\n");
  transform_all();
  Current_routine->calls.push_front(call(Recipe_ordinal["interactive"]));
  *result = 0;
  return true;
}

string strip_comments(string in) {
  ostringstream result;
  for (long long int i = 0; i < SIZE(in); ++i) {
    if (in.at(i) != '#') {
      result << in.at(i);
    }
    else {
      while (i < SIZE(in) && in.at(i) != '\n')
        ++i;
      if (i < SIZE(in) && in.at(i) == '\n') ++i;
    }
  }
  return result.str();
}

long long int stringified_value_of_location(long long int address) {
  // convert to string
  ostringstream out;
  out << Memory[address];
  return new_string(out.str());
}

//:: debugging tool

:(before "End Primitive Recipe Declarations")
_RUN_DEPTH,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$run-depth"] = _RUN_DEPTH;
:(before "End Primitive Recipe Implementations")
case _RUN_DEPTH: {
  cerr << Current_routine->calls.size();
  break;
}