/[ascend]/trunk/ascxx/library.cpp
ViewVC logotype

Contents of /trunk/ascxx/library.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2329 - (show annotations) (download) (as text)
Wed Dec 22 12:52:47 2010 UTC (13 years, 8 months ago) by jpye
File MIME type: text/x-c++src
File size: 12760 byte(s)
Suppressing some console output.
Added test case that current crashes ASCEND/IPOPT with a memory error.
Issue with library.cpp not containing any way to free libascend memory.
1 #include <Python.h>
2
3 #include <iostream>
4 #include <stdexcept>
5 #include <sstream>
6 using namespace std;
7
8 #undef NDEBUG
9
10 #include "config.h"
11
12 extern "C"{
13 #include <ascend/general/platform.h>
14
15 #include <ascend/general/list.h>
16 #include <ascend/compiler/ascCompiler.h>
17
18 /* #include <compiler/redirectFile.h> */
19 #include <ascend/compiler/prototype.h>
20 #include <ascend/compiler/dump.h>
21 #include <ascend/compiler/childio.h>
22 #include <ascend/compiler/type_desc.h>
23 #include <ascend/compiler/typedef.h>
24 #include <ascend/compiler/library.h>
25 #include <ascend/system/slv_types.h>
26 #include <ascend/system/system.h>
27 #include <ascend/utilities/ascEnvVar.h>
28 #include <ascend/compiler/symtab.h>
29 #include <ascend/general/table.h>
30 #include <ascend/compiler/instance_enum.h>
31 #include <ascend/compiler/notate.h>
32 #include <ascend/compiler/simlist.h>
33 #include <ascend/compiler/parser.h>
34 #include <ascend/utilities/error.h>
35 #include <ascend/general/env.h>
36 #include <ascend/compiler/importhandler.h>
37 }
38
39 #include "library.h"
40 #include "simulation.h"
41 #include "solver.h"
42
43 Library::Library(const char *defaultpath){
44 static int have_init;
45 if(!have_init){
46 //cerr << "Initialising ASCEND library..." << endl;
47
48 #ifdef REIMPLEMENT_STREAMS
49 Asc_RedirectCompilerDefault(); // Ensure that error message reach stderr
50 #endif
51
52 Asc_CompilerInit(1);
53 env_import(ASC_ENV_LIBRARY,getenv,Asc_PutEnv);
54 env_import(ASC_ENV_SOLVERS,getenv,Asc_PutEnv);
55
56 char *x = Asc_GetEnv(ASC_ENV_LIBRARY);
57 if(x==NULL || strcmp(x,"")==0){
58 if(defaultpath==NULL){
59 ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"Using default "
60 ASC_ENV_LIBRARY " = '" DEFAULT_ASCENDLIBRARY "'"
61 );
62 defaultpath = DEFAULT_ASCENDLIBRARY;
63 }
64
65 string s = string(ASC_ENV_LIBRARY "=") + defaultpath;
66 //ERROR_REPORTER_HERE(ASC_PROG_NOTE,"Setting %s",s.c_str());;
67 Asc_PutEnv(s.c_str());
68 }
69 Asc_ImportPathList(ASC_ENV_LIBRARY);
70 //cerr << PATHENVIRONMENTVAR << " = " << x << endl;
71 //cerr << "Created LIBRARY" << endl;
72 //cerr << "Registering solvers..." << endl;
73 registerStandardSolvers();
74 }/*else{
75 CONSOLE_DEBUG("Reusing LIBRARY");
76 }*/
77 have_init=1;
78 }
79
80 Library::~Library(){
81 //ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"DESTROYED LIBRARY!////////////////////////////////////////");
82 //DestroyLibrary();
83 // ... need to use some kind of reference counting before you can do that...
84 }
85
86 /**
87 Load an ASCEND model file into the Library. It will be parsed such that
88 its types will be visible to Library::findType.
89
90 @param filename Filename, will be searched for relative to ASCENDLIBRARY environment
91 variable, if necessary.
92 */
93 void
94 Library::load(const char *filename){
95
96 //std::cerr << "Loading '" << filename << "'" << std::endl;
97
98 int status;
99 struct module_t *m=Asc_RequireModule(filename,&status);
100 if(m!=NULL){
101 //std::cerr << "Loaded module '" << Asc_ModuleName(m) << "'" << std::endl;
102 }else{
103 std::cerr << "Error: unable to load module '" << filename << "'." << std::endl;
104 }
105
106 const char *msg = getLoadErrorMessage(status);
107
108 char msg1[100];
109 sprintf(msg1,msg,filename);
110
111 if(status<0 || status>0){
112 throw std::runtime_error(msg1);
113 }else{
114 std::cerr << "Note: Module " << Asc_ModuleName(m) << ": " << msg1 << std::endl;
115 }
116
117 CONSOLE_DEBUG("Beginning parse of %s",Asc_ModuleName(m));
118 error_reporter_tree_start();
119 status = zz_parse();
120 switch(status){
121 case 0: break;
122 case 1: ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Parsing of %s was aborted",Asc_ModuleName(m)); break;
123 case 2: ERROR_REPORTER_NOLINE(ASC_PROG_FATAL,"Out of memory when parsing %s",Asc_ModuleName(m)); break;
124 default: ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Invalid return from zz_parse"); break;
125 }
126 status = error_reporter_tree_has_error();
127 error_reporter_tree_end();
128 if(!status){
129 //CONSOLE_DEBUG("CLEARING TREE...");
130 error_reporter_tree_clear();
131 //CONSOLE_DEBUG("DONE CLEARING TREE...");
132 }else{
133 ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Error(s) when loading '%s'",filename);
134 stringstream ss;
135 ss << "Errors found in '" << filename << "'";
136 throw runtime_error(ss.str());
137 }
138
139
140 struct gl_list_t *l = Asc_TypeByModule(m);
141 CONSOLE_DEBUG("%lu library entries loaded from %s",gl_length(l), filename);
142 }
143
144 /**
145 Load MODELs specified inside a text string into the Library. The string is
146 parsed and its types will then be visible to Library::findType.
147
148 @param str String containing the model, in the ASCEND modelling language.
149 @param nameprefix Name to be used to refer tothe string module when eg using
150 the Library::getModules methood.
151 */
152 void
153 Library::loadString(const char *str, const char *nameprefix){
154 int status;
155 struct module_t *m = Asc_OpenStringModule(str, &status, nameprefix);
156
157 const char *msg = getLoadErrorMessage(status);
158
159 char msg1[100];
160 sprintf(msg1,msg,nameprefix);
161
162 if(status<0 || status>0){
163 throw std::runtime_error(msg1);
164 }else{
165 std::cerr << "Note: Module " << Asc_ModuleName(m) << ": " << msg1 << std::endl;
166 }
167
168 CONSOLE_DEBUG("Beginning parse of %s",Asc_ModuleName(m));
169 #ifdef LOADSTRING_ERROR_TREE
170 error_reporter_tree_start();
171 #endif
172 status = zz_parse();
173 switch(status){
174 case 0: break;
175 case 1: ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Parsing of %s was aborted",Asc_ModuleName(m)); break;
176 case 2: ERROR_REPORTER_NOLINE(ASC_PROG_FATAL,"Out of memory when parsing %s",Asc_ModuleName(m)); break;
177 default: ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Invalid return from zz_parse"); break;
178 }
179 #ifdef LOADSTRING_ERROR_TREE
180 status = error_reporter_tree_has_error();
181 error_reporter_tree_end();
182 if(!status){
183 CONSOLE_DEBUG("CLEARING TREE...");
184 error_reporter_tree_clear();
185 CONSOLE_DEBUG("DONE CLEARING TREE...");
186 }else{
187 ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Error(s) when loading '%s'",nameprefix);
188 stringstream ss;
189 ss << "Errors found in '" << nameprefix << "'";
190 throw runtime_error(ss.str());
191 }
192 #endif
193
194 struct gl_list_t *l = Asc_TypeByModule(m);
195 CONSOLE_DEBUG("%lu library entries loaded from %s",gl_length(l), nameprefix);
196 }
197
198 const char *
199 Library::getLoadErrorMessage(int status){
200 const char *msg = NULL;
201 switch(status){
202 case 5:
203 msg = "The module '%s' already exists. "; break;
204 case 4:
205 msg = "Caught an attempt to do a recursive require under '%s'."; break;
206 case 3:
207 msg = "A new module was created from '%s', overwriting a module's alias."; break;
208 case 2:
209 msg = "An existing module is being returned for '%s'." ; break;
210 case 1:
211 msg = "An new version of an existing module was created for '%s'."; break;
212 case 0:
213 msg = "Module for '%s' created OK."; break;
214 case -1:
215 msg = "File not found for '%s'. (-1)"; break;
216 case -2:
217 msg = "Unable to open '%s' for reading. (-2)";break;
218 case -3:
219 msg = "Insuffient memory to create module for '%s'. (-3)"; break;
220 case -4:
221 msg = "Bad input, null or zero length filename in '%s'. (-4)"; break;
222 default:
223 throw std::runtime_error("Invalid status code in library.cpp");
224 }
225 return msg;
226 }
227
228
229
230
231
232 /**
233 Return a vector of all the Modules which have been loaded into
234 the current library.
235 */
236 vector<Module>
237 Library::getModules(const int module_type){
238 if(module_type < 0 || module_type > 2){
239 throw std::runtime_error("Library::getModules: invalid module_type parameter");
240 }
241
242 vector<Module> v;
243 struct gl_list_t *l = Asc_ModuleList(module_type);
244 if(l==NULL){
245 CONSOLE_DEBUG("list is empty");
246 return v;
247 }
248 for(int i=0, end=gl_length(l); i<end; ++i){
249 symchar *name = (symchar *)gl_fetch(l,i+1);
250 if(AscFindSymbol(name)==NULL){
251 throw runtime_error("Library::getModules: invalid symchar *");
252 }
253 //cerr << "GOT " << SCP( name ) << endl;
254 const module_t *m = Asc_GetModuleByName((const char *)name);
255 v.push_back(Module(m));
256 }
257 /*cerr << "LENGTH OF V IS " << v.size() << endl;
258 if(v.size()){
259 cerr << "MODULE 0's NAME IS " << v[0].getName() << endl;
260 }*/
261 return v;
262 }
263
264 /**
265 Output to stderr the names of the modules loaded into the current Library.
266 */
267 void
268 Library::listModules(const int module_type){
269 if(module_type < 0 || module_type > 2){
270 throw std::runtime_error("Library::listModules: invalid module_type parameter");
271 }
272
273 const char *type = NULL;
274 switch(module_type){
275 case 0: type = "defined types"; break;
276 case 1: type = "string definitions"; break;
277 case 2: type = "statements"; break;
278 }
279
280 vector<Module> v = getModules(module_type);
281 if(v.size()){
282 std::cerr << "Listing " << v.size() << " modules with " << type << std::endl;
283 for(vector<Module>::const_iterator i=v.begin(); i < v.end(); ++i){
284 cerr << " - " << i->getName() << endl;
285 vector<Type> tt = getModuleTypes(*i);
286 for(vector<Type>::const_iterator j = tt.begin(); j < tt.end(); ++j){
287 cerr << " * " << j->getName() << endl;
288 }
289 }
290 }else{
291 std::cerr << "Notice: No " << type << " found in module list." << std::endl;
292 }
293 }
294
295 Type &
296 Library::findType(const SymChar &sym){
297 TypeDescription *t = FindType(sym.getInternalType());
298 if(t==NULL){
299 stringstream ss;
300 ss << "Library::findType: type '" << sym << "' not found in library";
301 throw runtime_error(ss.str());
302 }/*else{
303 cerr << "Found something for type " << sym << endl;
304 }*/
305 Type *t2=new Type(t);
306 return *t2;
307 }
308
309 static int module_sort_cmp(const void *a, const void *b){
310 return strcmp((char *)a, (char *)b);
311 }
312
313 /**
314 This could be quite a bit more efficient if we could get a gl_list_t of TypeDescription rather than names
315 */
316 vector<Type>
317 Library::getModuleTypes(const Module &m){
318 //cerr << "GET MODULE TYPES\n" << endl;
319 vector<Type> v;
320 struct gl_list_t *l = Asc_TypeByModule(m.getInternalType());
321
322 gl_sort(l, &module_sort_cmp);
323
324 for(int i=0,end=gl_length(l); i<end; ++i){
325 char *name = (char *)gl_fetch(l,i+1);
326 //CONSOLE_DEBUG("Found type %s",name);
327 TypeDescription *t = FindType((const symchar *)name);
328 v.push_back(Type(t));
329 }
330 return v;
331 }
332
333 /**
334 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.
335 */
336 vector<ExtMethod>
337 Library::getExtMethods(){
338 // Clear the vector
339 extmethod_vector = vector<ExtMethod>();
340
341 // Traverse the vector
342 TraverseExtFuncLibrary(Library::extMethodTraverse, (void *)this);
343
344 return extmethod_vector;
345 }
346
347 /**
348 This method exists only to allow the TraverseExtFuncLibrary function
349 to make callbacks to the Library class from C.
350
351 @NOTE there might be issues with C/C++ linking here?
352 */
353 void
354 Library::extMethodTraverse(void *a1, void *a2){
355 Library *self = (Library *)a2;
356 self->appendToExtMethodVector(a1);
357 }
358
359 void
360 Library::appendToExtMethodVector(void *a1){
361 struct ExternalFunc *e = (struct ExternalFunc *)a1;
362 extmethod_vector.push_back(ExtMethod(e));
363 }
364
365 /**
366 Clear the library: 'DESTROY TYPES'
367
368 @TODO do this more efficiently, don't destroy the whole ASCEND compiler.
369 */
370 void
371 Library::clear(){
372 /* Asc_CompilerDestroy();
373 cerr << "COMPLETED ASC_COMPILERDESTROY" << endl;
374 Asc_CompilerInit(1);
375 cerr << "... ASC_COMPILERINIT OK" << endl;
376 Asc_ImportPathList(PATHENVIRONMENTVAR);
377 registerStandardSolvers();
378 cerr << "... REGISTER_STANDARD_SOLVERS" << endl;
379 DefineFundamentalTypes();
380 cerr << "... DEFINED FUND TYPES" << endl;
381 \*SetUniversalProcedureList(NULL);
382 */
383
384 //CONSOLE_DEBUG("Displaying library modules and types...");
385 //listModules();
386
387 CONSOLE_DEBUG("Destroying simulations...");
388 Asc_DestroySimulations();
389
390 CONSOLE_DEBUG("Clearing library...");
391 DestroyNotesDatabase(LibraryNote());
392 SetUniversalProcedureList(NULL);
393 DestroyLibrary();
394 DestroyPrototype();
395 EmptyTrash();
396 Asc_DestroyModules((DestroyFunc)DestroyStatementList);
397 //importhandler_destroylibrary();
398 WriteChildMissing(NULL,NULL,NULL);
399 //Asc_CompilerInit(1)
400 DefineFundamentalTypes();
401 InitNotesDatabase(LibraryNote());
402 ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"LIBRARY CLEARED!");
403 }
404
405 AnnotationDatabase
406 Library::getAnnotationDatabase(){
407 return AnnotationDatabase(SCP(LibraryNote()));
408 }
409
410 vector<UnitsM>
411 Library::getUnits() const{
412 vector<UnitsM> v;
413 register unsigned long c;
414 const struct Units *p;
415 for(c = 0;c<UNITS_HASH_SIZE;c++) {
416 for(p = g_units_hash_table[c];p!=NULL;p = p->next){
417 v.push_back(UnitsM(p));
418 }
419 }
420 return v;
421 }
422
423 set<Type>
424 Library::getRealAtomTypes() const{
425 set<Type> s;
426 struct gl_list_t *l = DefinitionList();
427 if(!l){
428 throw runtime_error("No types found in library (perhaps no files have been loaded?)");
429 }
430
431 for(unsigned i = 1; i<=gl_length(l); ++i) {
432 Type t((const struct TypeDescription *)gl_fetch(l,i));
433 if(t.isRefinedReal()){
434 Dimensions d = t.getDimensions();
435 if(d.isWild() || d.isDimensionless())continue; // skip this one
436 // it's got some dimensions, add it to the list
437 s.insert(t);
438 }
439 }
440 gl_destroy(l);
441 return s;
442 }
443

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22