1 |
#include <iostream> |
2 |
#include <stdexcept> |
3 |
#include <sstream> |
4 |
using namespace std; |
5 |
|
6 |
#undef NDEBUG |
7 |
|
8 |
//#include <compiler/module.h> |
9 |
extern "C"{ |
10 |
#include <utilities/ascConfig.h> |
11 |
#include <general/list.h> |
12 |
#include <compiler/slist.h> |
13 |
#include <compiler/ascCompiler.h> |
14 |
#include <compiler/fractions.h> |
15 |
#include <compiler/compiler.h> |
16 |
#include <compiler/redirectFile.h> |
17 |
#include <compiler/module.h> |
18 |
#include <compiler/prototype.h> |
19 |
#include <compiler/dump.h> |
20 |
#include <compiler/dimen.h> |
21 |
#include <compiler/child.h> |
22 |
#include <compiler/childio.h> |
23 |
#include <compiler/type_desc.h> |
24 |
#include <compiler/typedef.h> |
25 |
#include <compiler/library.h> |
26 |
#include <compiler/childinfo.h> |
27 |
#include <solver/slv_types.h> |
28 |
#include <solver/system.h> |
29 |
#include <utilities/ascEnvVar.h> |
30 |
#include <compiler/symtab.h> |
31 |
#include <general/table.h> |
32 |
#include <compiler/instance_enum.h> |
33 |
#include <compiler/notate.h> |
34 |
#include <compiler/simlist.h> |
35 |
|
36 |
int yyparse(); |
37 |
} |
38 |
|
39 |
#include "library.h" |
40 |
#include "simulation.h" |
41 |
#include "solver.h" |
42 |
|
43 |
Library::Library(string defaultpath){ |
44 |
static int have_init; |
45 |
if(!have_init){ |
46 |
cerr << "Initialising ASCEND library..." << endl; |
47 |
Asc_RedirectCompilerDefault(); // Ensure that error message reach stderr |
48 |
Asc_CompilerInit(1); |
49 |
Asc_ImportPathList(PATHENVIRONMENTVAR); |
50 |
char *x = Asc_GetEnv(PATHENVIRONMENTVAR); |
51 |
if(x==NULL || strcmp(x,"")==0){ |
52 |
string s = string(PATHENVIRONMENTVAR "=") + defaultpath; |
53 |
cerr << "SETTING " << s << endl; |
54 |
Asc_PutEnv(s.c_str()); |
55 |
} |
56 |
Asc_ImportPathList(PATHENVIRONMENTVAR); |
57 |
cerr << PATHENVIRONMENTVAR << " = " << x << endl; |
58 |
cerr << "Created LIBRARY" << endl; |
59 |
cerr << "Registering solvers..." << endl; |
60 |
registerStandardSolvers(); |
61 |
}/*else{ |
62 |
std::cerr << "Reusing LIBRARY" << std::endl; |
63 |
}*/ |
64 |
have_init=1; |
65 |
} |
66 |
|
67 |
Library::~Library(){ |
68 |
//ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"DESTROYED LIBRARY!"); |
69 |
//DestroyLibrary(); |
70 |
// ... need to use some kind of reference counting before you can do that... |
71 |
} |
72 |
|
73 |
/** |
74 |
Load an ASCEND model file into the Library. It will be parsed such that |
75 |
its types will be visible to Library::findType. |
76 |
|
77 |
@param filename Filename, will be searched for relative to ASCENDLIBRARY environment |
78 |
variable, if necessary. |
79 |
*/ |
80 |
void |
81 |
Library::load(const char *filename){ |
82 |
|
83 |
//std::cerr << "Loading '" << filename << "'" << std::endl; |
84 |
|
85 |
int status; |
86 |
struct module_t *m=Asc_RequireModule(filename,&status); |
87 |
if(m!=NULL){ |
88 |
//std::cerr << "Loaded module '" << Asc_ModuleName(m) << "'" << std::endl; |
89 |
}else{ |
90 |
std::cerr << "Error: unable to load module '" << filename << "'." << std::endl; |
91 |
} |
92 |
|
93 |
char *msg; |
94 |
switch(status){ |
95 |
case 5: |
96 |
msg = "The module '%s' already exists. "; break; |
97 |
case 4: |
98 |
msg = "Caught an attempt to do a recursive require under '%s'."; break; |
99 |
case 3: |
100 |
msg = "A new module was created from '%s', overwriting a module's alias."; break; |
101 |
case 2: |
102 |
msg = "An existing module is being returned for '%s'." ; break; |
103 |
case 1: |
104 |
msg = "An new version of an existing module was created for '%s'."; break; |
105 |
case 0: |
106 |
msg = "Module for '%s' created OK."; break; |
107 |
case -1: |
108 |
msg = "Error: File not found for '%s'. (-1)"; break; |
109 |
case -2: |
110 |
msg = "Error: Unable to open '%s' for reading. (-2)";break; |
111 |
case -3: |
112 |
msg = "Error: Insuffient memory to create module for '%s'. (-3)"; break; |
113 |
case -4: |
114 |
msg = "Error: bad input, null or zero length filename in '%s'. (-4)"; break; |
115 |
default: |
116 |
throw std::runtime_error("Invalid status code in library.cpp"); |
117 |
} |
118 |
|
119 |
char msg1[100]; |
120 |
sprintf(msg1,msg,filename); |
121 |
|
122 |
if(status<0 || status>0){ |
123 |
throw std::runtime_error(msg1); |
124 |
}else{ |
125 |
std::cerr << "Note: Module " << Asc_ModuleName(m) << ": " << msg1 << std::endl; |
126 |
} |
127 |
|
128 |
std::cerr << "Note: Beginning yyparse of " << Asc_ModuleName(m) << "..." << std::endl; |
129 |
yyparse(); |
130 |
std::cerr << "Note: ...yyparse of " << Asc_ModuleName(m) << " completed." << std::endl; |
131 |
|
132 |
struct gl_list_t *l = Asc_TypeByModule(m); |
133 |
std::cerr << "Note: " << gl_length(l) << " library entries loaded from '" << filename << "'" << std::endl; |
134 |
} |
135 |
|
136 |
/** |
137 |
Return a vector of all the Modules which have been loaded into |
138 |
the current library. |
139 |
*/ |
140 |
vector<Module> |
141 |
Library::getModules(){ |
142 |
//cerr << "GET MODULES\n" << endl; |
143 |
|
144 |
vector<Module> v; |
145 |
struct gl_list_t *l = Asc_ModuleList(0); |
146 |
for(int i=0, end=gl_length(l); i<end; ++i){ |
147 |
symchar *name = (symchar *)gl_fetch(l,i+1); |
148 |
if(AscFindSymbol(name)==NULL){ |
149 |
throw runtime_error("Library::getModules: invalid symchar *"); |
150 |
} |
151 |
//cerr << "GOT " << SCP( name ) << endl; |
152 |
const module_t *m = Asc_GetModuleByName((const char *)name); |
153 |
v.push_back(Module(m)); |
154 |
} |
155 |
/*cerr << "LENGTH OF V IS " << v.size() << endl; |
156 |
if(v.size()){ |
157 |
cerr << "MODULE 0's NAME IS " << v[0].getName() << endl; |
158 |
}*/ |
159 |
return v; |
160 |
} |
161 |
|
162 |
/** |
163 |
Output to stderr the names of the modules loaded into the current Library. |
164 |
*/ |
165 |
void |
166 |
Library::listModules(const int &module_type) const{ |
167 |
|
168 |
if(module_type < 0 || module_type > 2){ |
169 |
throw std::runtime_error("Library::listModules: invalid module_type parameter"); |
170 |
} |
171 |
|
172 |
struct gl_list_t *l; |
173 |
|
174 |
l = Asc_ModuleList(module_type); |
175 |
|
176 |
if(l==NULL){ |
177 |
std::cerr << "Library::listModules: list is empty" << std::endl; |
178 |
return; |
179 |
//throw std::runtime_error("Library::listModules: Asc_ModuleList returned NULL"); |
180 |
} |
181 |
|
182 |
char *type; |
183 |
switch(module_type){ |
184 |
case 0: type = "modules containing defined types"; break; |
185 |
case 1: type = "modules with string definitions"; break; |
186 |
case 2: type = "modules with statements"; break; |
187 |
} |
188 |
int n=gl_length(l); |
189 |
if(n){ |
190 |
std::cerr << "Listing " << gl_length(l) << " " << type << std::endl; |
191 |
gl_iterate(l,Library::displayModule); |
192 |
}else{ |
193 |
std::cerr << "Notice: No " << type << " found in module list." << std::endl; |
194 |
} |
195 |
} |
196 |
|
197 |
void |
198 |
Library::displayModule(void *v){ |
199 |
//module_t *m = (module_t *)v; |
200 |
std::cerr << " - " << (char *)v << std::endl; |
201 |
} |
202 |
|
203 |
Type & |
204 |
Library::findType(SymChar sym){ |
205 |
TypeDescription *t = FindType(sym.getInternalType()); |
206 |
if(t==NULL){ |
207 |
stringstream ss; |
208 |
ss << "Library::findType: type '" << sym << "' not found in library"; |
209 |
throw runtime_error(ss.str()); |
210 |
}/*else{ |
211 |
cerr << "Found something for type " << sym << endl; |
212 |
}*/ |
213 |
Type *t2=new Type(t); |
214 |
return *t2; |
215 |
} |
216 |
|
217 |
/** |
218 |
This could be quite a bit more efficient if we could get a gl_list_t of TypeDescription rather than names |
219 |
*/ |
220 |
vector<Type> |
221 |
Library::getModuleTypes(const Module &m){ |
222 |
//cerr << "GET MODULE TYPES\n" << endl; |
223 |
vector<Type> v; |
224 |
struct gl_list_t *l = Asc_TypeByModule(m.getInternalType()); |
225 |
for(int i=0,end=gl_length(l); i<end; ++i){ |
226 |
char *name = (char *)gl_fetch(l,i+1); |
227 |
//CONSOLE_DEBUG("Found type %s",name); |
228 |
TypeDescription *t = FindType((const symchar *)name); |
229 |
v.push_back(Type(t)); |
230 |
} |
231 |
return v; |
232 |
} |
233 |
|
234 |
/** |
235 |
This function is kinda fighting against the Table implementation of the external function library. What we really need is some kind of iterator on the Table struct, but it doesn't seem to be implemented. Instead there is a C-style equivalent of the STL 'bind1st' function which we can use, but it's not exported from the current extfunc.h so we need to add it. |
236 |
*/ |
237 |
vector<ExtMethod> |
238 |
Library::getExtMethods(){ |
239 |
// Clear the vector |
240 |
extmethod_vector = vector<ExtMethod>(); |
241 |
|
242 |
// Traverse the vector |
243 |
TraverseExtFuncLibrary(Library::extMethodTraverse, (void *)this); |
244 |
|
245 |
return extmethod_vector; |
246 |
} |
247 |
|
248 |
/** |
249 |
This method exists only to allow the TraverseExtFuncLibrary function |
250 |
to make callbacks to the Library class from C. |
251 |
|
252 |
@NOTE there might be issues with C/C++ linking here? |
253 |
*/ |
254 |
void |
255 |
Library::extMethodTraverse(void *a1, void *a2){ |
256 |
Library *self = (Library *)a2; |
257 |
self->appendToExtMethodVector(a1); |
258 |
} |
259 |
|
260 |
void |
261 |
Library::appendToExtMethodVector(void *a1){ |
262 |
struct ExternalFunc *e = (struct ExternalFunc *)a1; |
263 |
extmethod_vector.push_back(ExtMethod(e)); |
264 |
} |
265 |
|
266 |
/** |
267 |
Clear the library: 'DESTROY TYPES' |
268 |
|
269 |
@TODO do this more efficiently, don't destroy the whole ASCEND compiler. |
270 |
*/ |
271 |
void |
272 |
Library::clear(){ |
273 |
//DestroyNotesDatabase(LibraryNote()); |
274 |
/* Asc_CompilerDestroy(); |
275 |
cerr << "COMPLETED ASC_COMPILERDESTROY" << endl; |
276 |
Asc_CompilerInit(1); |
277 |
cerr << "... ASC_COMPILERINIT OK" << endl; |
278 |
Asc_ImportPathList(PATHENVIRONMENTVAR); |
279 |
registerStandardSolvers(); |
280 |
cerr << "... REGISTER_STANDARD_SOLVERS" << endl; |
281 |
DefineFundamentalTypes(); |
282 |
cerr << "... DEFINED FUND TYPES" << endl; |
283 |
/*SetUniversalProcedureList(NULL); |
284 |
*/ |
285 |
ERROR_REPORTER_NOLINE(ASC_PROG_NOTE,"Destroying simulations...\n"); |
286 |
Asc_DestroySimulations(); |
287 |
|
288 |
ERROR_REPORTER_NOLINE(ASC_PROG_NOTE,"Clearing library...\n"); |
289 |
DestroyNotesDatabase(LibraryNote()); |
290 |
SetUniversalProcedureList(NULL); |
291 |
DestroyLibrary(); |
292 |
DestroyPrototype(); |
293 |
EmptyTrash(); |
294 |
Asc_DestroyModules((DestroyFunc)DestroyStatementList); |
295 |
WriteChildMissing(NULL,NULL,NULL); |
296 |
//Asc_CompilerInit(1) |
297 |
DefineFundamentalTypes(); |
298 |
InitNotesDatabase(LibraryNote()); |
299 |
ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"LIBRARY CLEARED!"); |
300 |
} |
301 |
|
302 |
|