summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/genv.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/utils/asymptote/genv.cc')
-rw-r--r--Build/source/utils/asymptote/genv.cc134
1 files changed, 134 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/genv.cc b/Build/source/utils/asymptote/genv.cc
new file mode 100644
index 00000000000..a191d525db9
--- /dev/null
+++ b/Build/source/utils/asymptote/genv.cc
@@ -0,0 +1,134 @@
+/*****
+ * genv.cc
+ * Andy Hammerlindl 2002/08/29
+ *
+ * This is the global environment for the translation of programs. In
+ * actuality, it is basically a module manager. When a module is
+ * requested, it looks for the corresponding filename, and if found,
+ * parses and translates the file, returning the resultant module.
+ *
+ * genv sets up the basic type bindings and function bindings for
+ * builtin functions, casts and operators, and imports plain (if set),
+ * but all other initialization is done by the local environment defined
+ * in env.h.
+ *****/
+
+#include <sstream>
+#include <unistd.h>
+#include <algorithm>
+
+#include "genv.h"
+#include "env.h"
+#include "dec.h"
+#include "stm.h"
+#include "types.h"
+#include "settings.h"
+#include "runtime.h"
+#include "parser.h"
+#include "locate.h"
+#include "interact.h"
+#include "builtin.h"
+
+using namespace types;
+using settings::getSetting;
+using settings::Setting;
+
+// Dynamic loading of external libraries.
+types::record *transExternalModule(trans::genv& ge, string filename, symbol id);
+
+namespace trans {
+
+genv::genv()
+ : imap()
+{
+ // Add settings as a module. This is so that the init file ~/.asy/config.asy
+ // can set settings.
+ imap["settings"]=settings::getSettingsModule();
+
+ // Translate plain in advance, if we're using autoplain.
+ if(getSetting<bool>("autoplain")) {
+ Setting("autoplain")=false;
+
+ // Translate plain without autoplain.
+ getModule(symbol::trans("plain"), "plain");
+
+ Setting("autoplain")=true;
+ }
+#ifdef HAVE_LIBGSL
+ imap["gsl"]=trans::getGSLModule();
+#endif
+}
+
+bool endswith(string suffix, string str)
+{
+ return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
+}
+
+record *genv::loadModule(symbol id, string filename) {
+ // Hackish way to load an external library.
+#if 0
+ if (endswith(".so", filename)) {
+ return transExternalModule(*this, filename, id);
+ }
+#endif
+
+ // Get the abstract syntax tree.
+ absyntax::file *ast = parser::parseFile(filename,"Loading");
+
+ inTranslation.push_front(filename);
+
+ em.sync();
+
+ record *r=ast->transAsFile(*this, id);
+
+ inTranslation.remove(filename);
+
+ return r;
+}
+
+void genv::checkRecursion(string filename) {
+ if (find(inTranslation.begin(), inTranslation.end(), filename) !=
+ inTranslation.end()) {
+ em.sync();
+ em << "error: recursive loading of module '" << filename << "'\n";
+ em.sync();
+ throw handled_error();
+ }
+}
+
+record *genv::getModule(symbol id, string filename) {
+ checkRecursion(filename);
+
+ record *r=imap[filename];
+ if (r)
+ return r;
+ else {
+ record *r=loadModule(id, filename);
+ // Don't add an erroneous module to the dictionary in interactive mode, as
+ // the user may try to load it again.
+ if (!interact::interactive || !em.errors())
+ imap[filename]=r;
+
+ return r;
+ }
+
+}
+
+typedef vm::stack::importInitMap importInitMap;
+
+importInitMap *genv::getInitMap()
+{
+ struct initMap : public importInitMap, public gc {
+ genv &ge;
+ initMap(genv &ge)
+ : ge(ge) {}
+ lambda *operator[](string s) {
+ record *r=ge.imap[s];
+ return r ? r->getInit() : 0;
+ }
+ };
+
+ return new initMap(*this);
+}
+
+} // namespace trans