1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
/*****
* 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 <bits/stl_algo.h>
#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;
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
}
record *genv::loadModule(symbol *id, string filename) {
// 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 ≥
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
|