summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/process.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/utils/asymptote/process.cc')
-rw-r--r--Build/source/utils/asymptote/process.cc1008
1 files changed, 0 insertions, 1008 deletions
diff --git a/Build/source/utils/asymptote/process.cc b/Build/source/utils/asymptote/process.cc
deleted file mode 100644
index acfd2f5e7f1..00000000000
--- a/Build/source/utils/asymptote/process.cc
+++ /dev/null
@@ -1,1008 +0,0 @@
-/*****
- * process.cc
- * Andy Hammerlindl 2006/08/19
- *
- * Handles processing blocks of code (including files, strings, and the
- * interactive prompt, for listing and parse-only modes as well as actually
- * running it.
- *****/
-
-#include "types.h"
-#include "errormsg.h"
-#include "genv.h"
-#include "stm.h"
-#include "settings.h"
-#include "vm.h"
-#include "program.h"
-#include "interact.h"
-#include "envcompleter.h"
-#include "parser.h"
-#include "fileio.h"
-
-#include "stack.h"
-#include "runtime.h"
-#include "texfile.h"
-
-#include "process.h"
-
-namespace camp {
-pen& defaultpen() {
- return processData().defaultpen;
-}
-}
-
-unsigned int count=0;
-
-namespace run {
-void cleanup();
-void exitFunction(vm::stack *Stack);
-void updateFunction(vm::stack *Stack);
-void purge(Int divisor=0);
-}
-
-namespace vm {
-bool indebugger;
-}
-
-using namespace settings;
-
-using absyntax::file;
-using trans::genv;
-using trans::coenv;
-using trans::env;
-using trans::coder;
-using types::record;
-
-using interact::interactive;
-using interact::uptodate;
-
-using absyntax::runnable;
-using absyntax::block;
-
-mem::stack<processDataStruct *> processDataStack;
-
-// Exception-safe way to push and pop the process data.
-class withProcessData {
- // Do not let this object be dynamically allocated.
- void *operator new(size_t);
-
- processDataStruct *pd_ptr;
-public:
-
- withProcessData(processDataStruct *pd_ptr) : pd_ptr(pd_ptr)
- {
- processDataStack.push(pd_ptr);
- }
-
- ~withProcessData()
- {
- assert(processDataStack.top() == pd_ptr);
- processDataStack.pop();
- }
-};
-
-processDataStruct &processData() {
- assert(!processDataStack.empty());
- return *processDataStack.top();
-}
-
-// A process environment. Basically this just serves as short-hand to start a
-// new global environment (genv) and new process data at the same time. When
-// it goes out of scope, the process data is popped off the stack. This also
-// ensures that the data is popped even if an exception is thrown.
-class penv {
- genv *_ge;
- processDataStruct _pd;
-
- // Do not let this object be dynamically allocated.
- void *operator new(size_t);
-
-public:
- penv() : _ge(0), _pd() {
- // Push the processData first, as it needs to be on the stack before genv
- // is initialized.
- processDataStack.push(&_pd);
- _ge = new genv;
- }
-
- virtual ~penv() {
- processDataStack.pop();
- delete _ge;
- }
-
- genv &ge() { return *_ge; }
-
- processDataStruct *pd() { return &_pd; }
-};
-
-
-void init(bool resetpath=true)
-{
- vm::indebugger=false;
- uptodate=false;
- if(resetpath)
- setPath(""); /* On second and subsequent calls, sets the path
- to what it was when the program started. */
-}
-
-// This helper class does nothing but call the interactiveTrans method of the
-// base object in place of trans, so that the runnable can exhibit special
-// behaviour when run at the interactive prompt.
-class interactiveRunnable : public runnable {
- runnable *base;
-
-public:
- interactiveRunnable(runnable *base)
- : runnable(base->getPos()), base(base) {}
-
- void prettyprint(ostream &out, Int indent) {
- absyntax::prettyname(out, "interactiveRunnable", indent);
- base->prettyprint(out, indent+1);
- }
-
- void trans(coenv &e) {
- base->interactiveTrans(e);
- }
-
- void transAsField(coenv &e, types::record *r) {
- // There is no interactiveTransAsField, as fields aren't declared at the top
- // level of the interactive prompt.
- base->transAsField(e, r);
- }
-};
-
-enum transMode {
- TRANS_INTERACTIVE,
- TRANS_NORMAL
-};
-
-
-// How to run a runnable in runnable-at-a-time mode.
-bool runRunnable(runnable *r, coenv &e, istack &s, transMode tm=TRANS_NORMAL) {
- e.e.beginScope();
-
- lambda *codelet= tm==TRANS_INTERACTIVE ?
- interactiveRunnable(r).transAsCodelet(e) :
- r->transAsCodelet(e);
- em.sync();
- if(!em.errors()) {
- if(getSetting<bool>("translate")) print(cout,codelet->code);
- s.run(codelet);
-
- // Commits the changes made to the environment.
- e.e.collapseScope();
- } else {
- e.e.endScope(); // Remove any changes to the environment.
-
- // Should an interactive error hurt the status?
- em.statusError();
-
- return false;
- }
- return true;
-}
-
-void runAutoplain(coenv &e, istack &s) {
- absyntax::runnable *r=absyntax::autoplainRunnable();
- runRunnable(r,e,s);
-}
-
-// Abstract base class for the core object being run in line-at-a-time mode, it
-// may be a block of code, file, or interactive prompt.
-struct icore {
- virtual ~icore() {}
-
- virtual void doParse() = 0;
- virtual void doList() = 0;
-
-public:
-
- // preRun and postRun are the optional activities that take place before and
- // after running the code specified. They can be overridden by a derived
- // class that wishes different behaviour.
- virtual void preRun(coenv &e, istack &s) {
- if(getSetting<bool>("autoplain"))
- runAutoplain(e,s);
- }
-
- virtual void run(coenv &e, istack &s, transMode tm=TRANS_NORMAL) = 0;
-
- virtual void postRun(coenv &, istack &s) {
- run::exitFunction(&s);
- }
-
- virtual void doRun(bool purge=false, transMode tm=TRANS_NORMAL) {
- em.sync();
- if(em.errors())
- return;
-
- try {
- if(purge) run::purge();
-
- penv pe;
- env base_env(pe.ge());
- coder base_coder(nullPos, "icore::doRun");
- coenv e(base_coder,base_env);
-
- vm::interactiveStack s;
- s.setInitMap(pe.ge().getInitMap());
- s.setEnvironment(&e);
-
- preRun(e,s);
-
- if(purge) run::purge();
-
- // Now that everything is set up, run the core.
- run(e,s,tm);
-
- postRun(e,s);
-
- } catch(std::bad_alloc&) {
- outOfMemory();
- } catch(quit) {
- // Exception to quit running the current code. Nothing more to do.
- } catch(handled_error) {
- em.statusError();
- }
-
- run::cleanup();
-
- em.clear();
- }
-
- virtual void process(bool purge=false) {
- if (!interactive && getSetting<bool>("parseonly"))
- doParse();
- else if (getSetting<bool>("listvariables"))
- doList();
- else
- doRun(purge);
- }
-};
-
-// Abstract base class for one-time processing of an abstract syntax tree.
-class itree : public icore {
- string name;
-
- block *cachedTree;
-public:
- itree(string name="<unnamed>")
- : name(name), cachedTree(0) {}
-
- // Build the tree, possibly throwing a handled_error if it cannot be built.
- virtual block *buildTree() = 0;
-
- virtual block *getTree() {
- if (cachedTree==0) {
- try {
- cachedTree=buildTree();
- } catch(handled_error) {
- em.statusError();
- return 0;
- }
- }
- return cachedTree;
- }
-
- virtual string getName() {
- return name;
- }
-
- void doParse() {
- block *tree=getTree();
- em.sync();
- if(tree && !em.errors())
- tree->prettyprint(cout, 0);
- }
-
- void doList() {
- block *tree=getTree();
- if (tree) {
- penv pe;
- record *r=tree->transAsFile(pe.ge(), symbol::trans(getName()));
- r->e.list(r);
- }
- }
-
- void run(coenv &e, istack &s, transMode tm=TRANS_NORMAL) {
- block *tree=getTree();
- if (tree) {
- for(mem::list<runnable *>::iterator r=tree->stms.begin();
- r != tree->stms.end(); ++r) {
- processData().fileName=(*r)->getPos().filename();
- if(!em.errors() || getSetting<bool>("debug"))
- runRunnable(*r,e,s,tm);
- }
- }
- }
-
- void doExec(transMode tm=TRANS_NORMAL) {
- // Don't prepare an environment to run the code if there isn't any code.
- if (getTree())
- icore::doRun(false,tm);
- }
-};
-
-class icode : public itree {
- block *tree;
-
-public:
- icode(block *tree, string name="<unnamed>")
- : itree(name), tree(tree) {}
-
- block *buildTree() {
- return tree;
- }
-};
-
-class istring : public itree {
- string str;
-
-public:
- istring(const string& str, string name="<eval>")
- : itree(name), str(str) {}
-
- block *buildTree() {
- return parser::parseString(str, getName());
- }
-};
-
-void printGreeting(bool interactive) {
- if(!getSetting<bool>("quiet")) {
- cout << "Welcome to " << PROGRAM << " version " << REVISION;
- if(interactive)
- cout << " (to view the manual, type help)";
- cout << endl;
- }
-}
-
-class ifile : public itree {
- string filename;
- string outname;
- string outname_save;
-
-public:
- ifile(const string& filename)
- : itree(filename),
- filename(filename),
- outname(stripDir(stripExt(string(filename == "-" ? settings::outname() : filename), suffix))) {}
-
- block *buildTree() {
- return !filename.empty() ? parser::parseFile(filename,"Loading") : 0;
- }
-
- void preRun(coenv& e, istack& s) {
- outname_save=getSetting<string>("outname");
- if(stripDir(outname_save).empty())
- Setting("outname")=outname_save+outname;
-
- itree::preRun(e, s);
- }
-
- void postRun(coenv &e, istack& s) {
- itree::postRun(e, s);
-
- Setting("outname")=outname_save;
- }
-
- void process(bool purge=false) {
- if(verbose > 1) printGreeting(false);
- try {
- init();
- } catch(handled_error) {
- }
-
- if (verbose >= 1)
- cout << "Processing " << outname << endl;
-
- try {
- icore::process(purge);
- }
- catch(handled_error) {
- em.statusError();
- }
- }
-};
-
-// Add a semi-colon terminator, if one is not there.
-string terminateLine(const string line) {
- return (!line.empty() && *(line.rbegin())!=';') ? (line+";") : line;
-}
-
-// cleanLine changes a C++ style comment (//) into a C-style comment (/* */) so
-// that comments don't absorb subsequent lines of code when multiline input is
-// collapsed to a single line in the history.
-//
-// ex. if (x==1) // test x
-// x=2;
-// becomes
-// if (x==1) /* test x */ x=2 (all on one line)
-//
-// cleanLine is a mess because we have to check that the // is not in a string
-// or c-style comment, which entails re-inventing much of the lexer. The
-// routine handles most cases, but multiline strings lose their newlines when
-// recorded in the history.
-typedef string::size_type size_type;
-const size_type npos=string::npos;
-
-inline size_type min(size_type a, size_type b) {
- return a < b ? a : b;
-}
-
-// If start is an offset somewhere within a string, this returns the first
-// offset outside of the string. sym is the character used to start the string,
-// ' or ".
-size_type endOfString(const char sym, const string line, size_type start) {
- size_type endString=line.find(sym, start);
- if (endString == npos)
- return npos;
-
- size_type escapeInString=min(line.find(string("\\")+sym, start),
- line.find("\\\\", start));
- if (endString < escapeInString)
- return endString+1;
- else
- return endOfString(sym, line, escapeInString+2);
-}
-
-// If start is an offset somewhere within a C-style comment, this returns the
-// first offset outside of the comment.
-size_type endOfComment(const string line, size_type start) {
- size_type endComment=line.find("*/", start);
- if (endComment == npos)
- return npos;
- else
- return endComment+2;
-}
-
-// Find the start of a string literal in the line.
-size_type stringPos(const string line, size_type start) {
- if (start == npos)
- return npos;
-
- size_type pos=line.find_first_of("\'\"", start);
- if (pos == npos)
- return npos;
-
- // Skip over comments /* */ and ignore anything after //
- size_type startComment=line.find("/*", start);
- size_type startLineComment=line.find("//", start);
-
- if (min(startComment,startLineComment) < pos)
- return stringPos(line,
- startComment < startLineComment ?
- endOfComment(line, startComment+2) :
- npos);
- else
- // Nothing to skip over - the symbol actually starts a string.
- return pos;
-}
-
-// A multiline string should retain its newlines when collapsed to a single
-// line. This converts
-// 'hello
-// there'
-// to
-// 'hello\nthere'
-// and
-// "hello
-// there"
-// to
-// "hello" '\n' "there"
-// If the line doesn't end mid-string, this adds a space to the end to preserve
-// whitespace, since it is the last function to touch the line.
-string endString(const string line, size_type start) {
- assert(start!=npos);
-
- size_type pos=stringPos(line, start);
-
- if (pos==npos)
- // String ends in normal code.
- return line+" ";
- else {
- char sym=line[pos];
- size_type eos=endOfString(sym, line, pos+1);
- if (eos==npos) {
- // Line ends while in a string, attach a newline symbol.
- switch (line[pos]) {
- case '\'':
- return line+"\\n";
- case '\"':
- return line+"\" \'\\n\' \"";
- default:
- assert(False);
- return line;
- }
- }
- else {
- return endString(line, eos+1);
- }
- }
-}
-
-// Find the first // that isn't in a C-style comment or a string.
-size_type slashPos(const string line, size_type start) {
- if (start == npos)
- return npos;
-
- size_type pos=line.find("//", start);
- if (pos == npos)
- return npos;
-
- // Skip over comments /* */ and strings both " " and ' '
- size_type startComment=line.find("/*", start);
- size_type startString=line.find_first_of("\'\"", start);
-
- if (min(startComment,startString) < pos)
- return slashPos(line,
- startComment < startString ?
- endOfComment(line, startComment+2) :
- endOfString(line[startString], line, startString+1));
- else
- // Nothing to skip over - the // actually starts a comment.
- return pos;
-}
-
-string endCommentOrString(const string line) {
- size_type pos=slashPos(line, 0);
- if (pos == npos)
- return endString(line, 0);
- else {
- string sub=line;
-
- // Replace the first // by /*
- sub[pos+1]='*';
-
- // Replace any */ in the comment by *!
- while ((pos = line.find("*/", pos+2)) != npos)
- sub[pos+1]='!';
-
- // Tack on a */ at the end.
- sub.append(" */ ");
- return sub;
- }
-}
-
-bool isSlashed(const string line) {
- // NOTE: This doesn't fully handle escaped slashed in a string literal.
- unsigned n=line.size();
- return n > 0 ? line[line.size()-1] == '\\' : false;
-}
-string deslash(const string line) {
- return isSlashed(line) ? line.substr(0,line.size()-1) : line;
-}
-
-// This transforms a line in to the history, so that when more code is added
-// after it, the code behaves the same as if there was a newline between the
-// two lines. This involves changing // style comments to /* */ style comments,
-// and adding explicit newlines to multiline strings.
-string cleanLine(const string line) {
- // First remove a trailing slash, if there is one.
- return endCommentOrString(deslash(line));
-}
-
-class iprompt : public icore {
- // Flag that is set to false to signal the prompt to exit.
- bool running;
-
- // Flag that is set to restart the main loop once it has exited.
- bool restart;
-
- // Code ran at start-up.
- string startline;
-
- void postRun(coenv &, istack &) {
- }
-
- // Commands are chopped into the starting word and the rest of the line.
- struct commandLine {
- string line;
- string word;
- string rest;
-
- commandLine(string line) : line(line) {
- string::iterator c=line.begin();
-
- // Skip leading whitespace
- while (c != line.end() && isspace(*c))
- ++c;
-
- // Only handle identifiers starting with a letter.
- if (c != line.end() && isalpha(*c)) {
- // Store the command name.
- while (c != line.end() && (isalnum(*c) || *c=='_')) {
- word.push_back(*c);
- ++c;
- }
- }
-
- // Copy the rest to rest.
- while (c != line.end()) {
- rest.push_back(*c);
- ++c;
- }
-
-#if 0
- cerr << "line: " << line << endl;
- cerr << "word: " << word << endl;
- cerr << "rest: " << rest << endl;
- cerr << "simple: " << simple() << endl;
-#endif
- }
-
- // Simple commands have at most spaces or semicolons after the command word.
- bool simple() {
- for (string::iterator c=rest.begin(); c != rest.end(); ++c)
- if (!isspace(*c) && *c != ';')
- return false;
- return true;
- }
- };
-
-
- // The interactive prompt has special functions that cannot be implemented as
- // normal functions. These special funtions take a commandLine as an argument
- // and return true if they can handle the command. If false is returned, the
- // line is treated as a normal line of code.
- // commands is a map of command names to methods which implement the commands.
- typedef bool (iprompt::*command)(coenv &, istack &, commandLine);
- typedef mem::map<CONST string, command> commandMap;
- commandMap commands;
-
- bool exit(coenv &, istack &, commandLine cl) {
- if (cl.simple()) {
- // Don't store exit commands in the history file.
- interact::deleteLastLine();
- running=false;
- return true;
- }
- else return false;
- }
-
- bool q(coenv &e, istack &s, commandLine cl) {
- if(e.e.ve.getType(symbol::trans("q"))) return false;
- return exit(e,s,cl);
- }
-
- bool reset(coenv &, istack &, commandLine cl) {
- if (cl.simple()) {
- running=false;
- restart=true;
- startline="";
- run::purge();
- return true;
- }
- else return false;
- }
-
- bool help(coenv &, istack &, commandLine cl) {
- if (cl.simple()) {
- popupHelp();
- return true;
- }
- else return false;
- }
-
- bool erase(coenv &e, istack &s, commandLine cl) {
- if (cl.simple()) {
- runLine(e,s,"erase();");
- return true;
- }
- else return false;
- }
-
- bool input(coenv &, istack &, commandLine cl) {
- running=false;
- restart=true;
- startline="include "+cl.rest;
- return true;
- }
-
- void initCommands() {
-#define ADDCOMMAND(name, func) \
- commands[#name]=&iprompt::func
-
- // keywords.pl looks for ADDCOMMAND to identify special commands in the
- // auto-completion.
- ADDCOMMAND(quit,exit);
- ADDCOMMAND(q,q);
- ADDCOMMAND(exit,exit);
- ADDCOMMAND(reset,reset);
- ADDCOMMAND(erase,erase);
- ADDCOMMAND(help,help);
- ADDCOMMAND(input,input);
-
-#undef ADDCOMMAND
- }
-
- bool handleCommand(coenv &e, istack &s, string line) {
- commandLine cl(line);
- if (cl.word != "") {
- commandMap::iterator p=commands.find(cl.word);
- if (p != commands.end()) {
- // Execute the command.
- command &com=p->second;
- return (this->*com)(e,s,cl);
- }
- else
- return false;
- }
- else
- return false;
- }
-
- void addToHistory(string line) {
- interact::addToHistory(line);
- }
-
- void addToLastLine(string line) {
- // Here we clean a line at the last possible point, when we know that more
- // code is going to be appended to it.
- string last=interact::getLastHistoryLine();
- interact::setLastHistoryLine(cleanLine(last)+line);
- }
-
- void terminateLastHistoryLine() {
- string last=interact::getLastHistoryLine();
- interact::setLastHistoryLine(terminateLine(last));
- }
-
- // Get input from the interactive prompt. Such input may be over several
- // user-typed lines if he/she ends a line a with backslash to continue input
- // on the next line. If continuation is true, the input started on a previous
- // line and is being continued (either because of a backslash or the parser
- // detecting it in multiline mode).
- string getline(bool continuation) {
- string prompt;
- if(!getSetting<bool>("xasy"))
- prompt=getSetting<string>(continuation ? "prompt2" : "prompt");
- string line=interact::simpleline(prompt);
-
- if (continuation)
- addToLastLine(line);
- else
- addToHistory(line);
-
- // If the line ends in a slash, get more input.
- return isSlashed(line) ? line+"\n"+getline(true) :
- line;
- }
-
- // Continue taking input for a line until it properly parses, or a syntax
- // error occurs. Returns the parsed code on success, and throws a
- // handled_error exception on failure.
- block *parseExtendableLine(string line) {
- block *code=parser::parseString(line, "-", true);
- if (code) {
- return code;
- } else {
- string nextline=getline(true);
- return parseExtendableLine(line+"\n"+nextline);
- }
- }
-
- // Continue taking input until a termination command is received from xasy.
- block *parseXasyLine(string line) {
-
-#ifdef __MSDOS__
- const string EOT="\x04\r\n";
-#else
- const string EOT="\x04\n";
-#endif
- string s;
- while((s=getline(true)) != EOT)
- line += s;
- return parser::parseString(line, "-", true);
- }
-
- void runLine(coenv &e, istack &s, string line) {
- try {
- if(getSetting<bool>("multiline")) {
- block *code=parseExtendableLine(line);
-
- icode i(code);
- i.run(e,s,TRANS_INTERACTIVE);
- } else if(getSetting<bool>("xasy")) {
- block *code=parseXasyLine(line);
-
- icode i(code);
- i.run(e,s,TRANS_INTERACTIVE);
- } else {
- // Add a semi-colon to the end of the line if one is not there. Do this
- // to the history as well, so the transcript can be run as regular asy
- // code. This also makes the history work correctly if the multiline
- // setting is changed within an interactive session.
- // It is added to the history at the last possible moment to avoid
- // tampering with other features, such as using a slash to extend a
- // line.
- terminateLastHistoryLine();
- istring i(terminateLine(line), "-");
- i.run(e,s,TRANS_INTERACTIVE);
- }
-
- run::updateFunction(&s);
- uptodate=false;
-
- } catch(handled_error) {
- vm::indebugger=false;
- } catch(interrupted&) {
- // Turn off the interrupted flag.
- em.Interrupt(false);
- uptodate=true;
- cout << endl;
- } catch(quit&) {
- }
-
- // Ignore errors from this line when trying to run subsequent lines.
- em.clear();
- }
-
- void runStartCode(coenv &e, istack &s) {
- if (!startline.empty())
- runLine(e, s, startline);
- }
-
-public:
- iprompt() : running(false), restart(false), startline("") {
- initCommands();
- }
-
- void doParse() {}
-
- void doList() {}
-
- void run(coenv &e, istack &s, transMode=TRANS_NORMAL) {
- running=true;
- interact::setCompleter(new trans::envCompleter(e.e));
-
- runStartCode(e, s);
-
- while (running) {
- // Read a line from the prompt.
- string line=getline(false);
- // Check if it is a special command.
- if (handleCommand(e,s,line))
- continue;
- else
- runLine(e, s, line);
- }
- }
-
- void process(bool purge=false) {
- printGreeting(true);
- interact::init_interactive();
- try {
- setPath("",true);
- } catch(handled_error) {
- }
-
- do {
- try {
- init(false);
- restart=false;
- icore::process();
- } catch(interrupted&) {
- em.Interrupt(false);
- restart=true;
- } catch(eof&) {
- restart=false;
- }
- } while(restart);
-
- interact::cleanup_interactive();
- }
-};
-
-void processCode(absyntax::block *code) {
- icode(code).process();
-}
-void processFile(const string& filename, bool purge) {
- ifile(filename).process(purge);
-}
-void processPrompt() {
- iprompt().process();
-}
-
-void runCode(absyntax::block *code) {
- icode(code).doExec();
-}
-void runString(const string& s, bool interactiveWrite) {
- istring(s).doExec(interactiveWrite ? TRANS_INTERACTIVE : TRANS_NORMAL);
-}
-void runFile(const string& filename) {
- ifile(filename).doExec();
-}
-void runPrompt() {
- iprompt().doRun();
-}
-
-void runCodeEmbedded(absyntax::block *code, trans::coenv &e, istack &s) {
- icode(code).run(e,s);
-}
-void runStringEmbedded(const string& str, trans::coenv &e, istack &s) {
- istring(str).run(e,s);
-}
-void runPromptEmbedded(trans::coenv &e, istack &s) {
- iprompt().run(e,s);
-}
-
-void doUnrestrictedList() {
- penv pe;
- env base_env(pe.ge());
- coder base_coder(nullPos, "doUnrestictedList");
- coenv e(base_coder,base_env);
-
- if (getSetting<bool>("autoplain"))
- absyntax::autoplainRunnable()->trans(e);
-
- e.e.list(0);
-}
-
-// Environment class used by external programs linking to the shared library.
-class fullenv : public gc {
- penv pe;
- env base_env;
- coder base_coder;
- coenv e;
-
- vm::interactiveStack s;
-
-public:
- fullenv() :
- pe(), base_env(pe.ge()), base_coder(nullPos, "fullenv"),
- e(base_coder, base_env), s()
- {
- s.setInitMap(pe.ge().getInitMap());
- s.setEnvironment(&e);
-
- // TODO: Add way to not run autoplain.
- runAutoplain(e, s);
- }
-
- coenv &getCoenv()
- {
- return e;
- }
-
- void runRunnable(runnable *r)
- {
- assert(!em.errors()); // TODO: Decide how to handle prior errors.
-
- try {
- { withProcessData token(pe.pd());
- ::runRunnable(r, e, s, TRANS_INTERACTIVE);
- }
- } catch(std::bad_alloc&) {
- // TODO: give calling application useful message.
- cerr << "out of memory" << endl;
- } catch (quit) {
- // I'm not sure whether this counts as successfully running the code or
- // not.
- cerr << "quit exception" << endl;
- } catch (handled_error) {
- // Normally, this is the result of an error that changes the return code
- // of the free-standing asymptote program.
- // An error should probably be reported to the application calling the
- // asymptote library.
- cerr << "handled error" << endl;
- }
-
- em.clear();
- }
-};
-
-fullenv &getFullEnv()
-{
- static fullenv fe;
- return fe;
-}
-
-coenv &coenvInOngoingProcess()
-{
- return getFullEnv().getCoenv();
-}
-
-void runInOngoingProcess(runnable *r)
-{
- getFullEnv().runRunnable(r);
-}