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

Contents of /trunk/pygtk/library.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2003 - (show annotations) (download) (as text)
Fri Mar 13 05:30:00 2009 UTC (11 years, 6 months ago) by jpye
File MIME type: text/x-c++src
File size: 12548 byte(s)
Update to current freesteam.
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 <utilities/ascConfig.h>
14
15 #include <general/list.h>
16 #include <compiler/ascCompiler.h>
17
18 /* #include <compiler/redirectFile.h> */
19 #include <compiler/prototype.h>
20 #include <compiler/dump.h>
21 #include <compiler/childio.h>
22 #include <compiler/type_desc.h>
23 #include <compiler/typedef.h>
24 #include <compiler/library.h>
25 #include <system/slv_types.h>
26 #include <system/system.h>
27 #include <utilities/ascEnvVar.h>
28 #include <compiler/symtab.h>
29 #include <general/table.h>
30 #include <compiler/instance_enum.h>
31 #include <compiler/notate.h>
32 #include <compiler/simlist.h>
33 #include <compiler/parser.h>
34 #include <utilities/error.h>
35 #include <general/env.h>
36 #include <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 error_reporter_tree_start();
170 status = zz_parse();
171 switch(status){
172 case 0: break;
173 case 1: ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Parsing of %s was aborted",Asc_ModuleName(m)); break;
174 case 2: ERROR_REPORTER_NOLINE(ASC_PROG_FATAL,"Out of memory when parsing %s",Asc_ModuleName(m)); break;
175 default: ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Invalid return from zz_parse"); break;
176 }
177 status = error_reporter_tree_has_error();
178 error_reporter_tree_end();
179 /*
180 if(!status){
181 CONSOLE_DEBUG("CLEARING TREE...");
182 error_reporter_tree_clear();
183 CONSOLE_DEBUG("DONE CLEARING TREE...");
184 }else{
185 ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Error(s) when loading '%s'",nameprefix);
186 stringstream ss;
187 ss << "Errors found in '" << nameprefix << "'";
188 throw runtime_error(ss.str());
189 }
190 */
191
192 struct gl_list_t *l = Asc_TypeByModule(m);
193 CONSOLE_DEBUG("%lu library entries loaded from %s",gl_length(l), nameprefix);
194 }
195
196 const char *
197 Library::getLoadErrorMessage(int status){
198 const char *msg = NULL;
199 switch(status){
200 case 5:
201 msg = "The module '%s' already exists. "; break;
202 case 4:
203 msg = "Caught an attempt to do a recursive require under '%s'."; break;
204 case 3:
205 msg = "A new module was created from '%s', overwriting a module's alias."; break;
206 case 2:
207 msg = "An existing module is being returned for '%s'." ; break;
208 case 1:
209 msg = "An new version of an existing module was created for '%s'."; break;
210 case 0:
211 msg = "Module for '%s' created OK."; break;
212 case -1:
213 msg = "File not found for '%s'. (-1)"; break;
214 case -2:
215 msg = "Unable to open '%s' for reading. (-2)";break;
216 case -3:
217 msg = "Insuffient memory to create module for '%s'. (-3)"; break;
218 case -4:
219 msg = "Bad input, null or zero length filename in '%s'. (-4)"; break;
220 default:
221 throw std::runtime_error("Invalid status code in library.cpp");
222 }
223 return msg;
224 }
225
226
227
228
229
230 /**
231 Return a vector of all the Modules which have been loaded into
232 the current library.
233 */
234 vector<Module>
235 Library::getModules(const int module_type){
236 if(module_type < 0 || module_type > 2){
237 throw std::runtime_error("Library::getModules: invalid module_type parameter");
238 }
239
240 vector<Module> v;
241 struct gl_list_t *l = Asc_ModuleList(module_type);
242 if(l==NULL){
243 CONSOLE_DEBUG("list is empty");
244 return v;
245 }
246 for(int i=0, end=gl_length(l); i<end; ++i){
247 symchar *name = (symchar *)gl_fetch(l,i+1);
248 if(AscFindSymbol(name)==NULL){
249 throw runtime_error("Library::getModules: invalid symchar *");
250 }
251 //cerr << "GOT " << SCP( name ) << endl;
252 const module_t *m = Asc_GetModuleByName((const char *)name);
253 v.push_back(Module(m));
254 }
255 /*cerr << "LENGTH OF V IS " << v.size() << endl;
256 if(v.size()){
257 cerr << "MODULE 0's NAME IS " << v[0].getName() << endl;
258 }*/
259 return v;
260 }
261
262 /**
263 Output to stderr the names of the modules loaded into the current Library.
264 */
265 void
266 Library::listModules(const int module_type){
267 if(module_type < 0 || module_type > 2){
268 throw std::runtime_error("Library::listModules: invalid module_type parameter");
269 }
270
271 const char *type = NULL;
272 switch(module_type){
273 case 0: type = "defined types"; break;
274 case 1: type = "string definitions"; break;
275 case 2: type = "statements"; break;
276 }
277
278 vector<Module> v = getModules(module_type);
279 if(v.size()){
280 std::cerr << "Listing " << v.size() << " modules with " << type << std::endl;
281 for(vector<Module>::const_iterator i=v.begin(); i < v.end(); ++i){
282 cerr << " - " << i->getName() << endl;
283 vector<Type> tt = getModuleTypes(*i);
284 for(vector<Type>::const_iterator j = tt.begin(); j < tt.end(); ++j){
285 cerr << " * " << j->getName() << endl;
286 }
287 }
288 }else{
289 std::cerr << "Notice: No " << type << " found in module list." << std::endl;
290 }
291 }
292
293 Type &
294 Library::findType(const SymChar &sym){
295 TypeDescription *t = FindType(sym.getInternalType());
296 if(t==NULL){
297 stringstream ss;
298 ss << "Library::findType: type '" << sym << "' not found in library";
299 throw runtime_error(ss.str());
300 }/*else{
301 cerr << "Found something for type " << sym << endl;
302 }*/
303 Type *t2=new Type(t);
304 return *t2;
305 }
306
307 static int module_sort_cmp(const void *a, const void *b){
308 return strcmp((char *)a, (char *)b);
309 }
310
311 /**
312 This could be quite a bit more efficient if we could get a gl_list_t of TypeDescription rather than names
313 */
314 vector<Type>
315 Library::getModuleTypes(const Module &m){
316 //cerr << "GET MODULE TYPES\n" << endl;
317 vector<Type> v;
318 struct gl_list_t *l = Asc_TypeByModule(m.getInternalType());
319
320 gl_sort(l, &module_sort_cmp);
321
322 for(int i=0,end=gl_length(l); i<end; ++i){
323 char *name = (char *)gl_fetch(l,i+1);
324 //CONSOLE_DEBUG("Found type %s",name);
325 TypeDescription *t = FindType((const symchar *)name);
326 v.push_back(Type(t));
327 }
328 return v;
329 }
330
331 /**
332 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.
333 */
334 vector<ExtMethod>
335 Library::getExtMethods(){
336 // Clear the vector
337 extmethod_vector = vector<ExtMethod>();
338
339 // Traverse the vector
340 TraverseExtFuncLibrary(Library::extMethodTraverse, (void *)this);
341
342 return extmethod_vector;
343 }
344
345 /**
346 This method exists only to allow the TraverseExtFuncLibrary function
347 to make callbacks to the Library class from C.
348
349 @NOTE there might be issues with C/C++ linking here?
350 */
351 void
352 Library::extMethodTraverse(void *a1, void *a2){
353 Library *self = (Library *)a2;
354 self->appendToExtMethodVector(a1);
355 }
356
357 void
358 Library::appendToExtMethodVector(void *a1){
359 struct ExternalFunc *e = (struct ExternalFunc *)a1;
360 extmethod_vector.push_back(ExtMethod(e));
361 }
362
363 /**
364 Clear the library: 'DESTROY TYPES'
365
366 @TODO do this more efficiently, don't destroy the whole ASCEND compiler.
367 */
368 void
369 Library::clear(){
370 /* Asc_CompilerDestroy();
371 cerr << "COMPLETED ASC_COMPILERDESTROY" << endl;
372 Asc_CompilerInit(1);
373 cerr << "... ASC_COMPILERINIT OK" << endl;
374 Asc_ImportPathList(PATHENVIRONMENTVAR);
375 registerStandardSolvers();
376 cerr << "... REGISTER_STANDARD_SOLVERS" << endl;
377 DefineFundamentalTypes();
378 cerr << "... DEFINED FUND TYPES" << endl;
379 \*SetUniversalProcedureList(NULL);
380 */
381
382 //CONSOLE_DEBUG("Displaying library modules and types...");
383 //listModules();
384
385 CONSOLE_DEBUG("Destroying simulations...");
386 Asc_DestroySimulations();
387
388 CONSOLE_DEBUG("Clearing library...");
389 DestroyNotesDatabase(LibraryNote());
390 SetUniversalProcedureList(NULL);
391 DestroyLibrary();
392 DestroyPrototype();
393 EmptyTrash();
394 Asc_DestroyModules((DestroyFunc)DestroyStatementList);
395 //importhandler_destroylibrary();
396 WriteChildMissing(NULL,NULL,NULL);
397 //Asc_CompilerInit(1)
398 DefineFundamentalTypes();
399 InitNotesDatabase(LibraryNote());
400 ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"LIBRARY CLEARED!");
401 }
402
403 AnnotationDatabase
404 Library::getAnnotationDatabase(){
405 return AnnotationDatabase(SCP(LibraryNote()));
406 }
407
408 vector<UnitsM>
409 Library::getUnits() const{
410 vector<UnitsM> v;
411 register unsigned long c;
412 const struct Units *p;
413 for(c = 0;c<UNITS_HASH_SIZE;c++) {
414 for(p = g_units_hash_table[c];p!=NULL;p = p->next){
415 v.push_back(UnitsM(p));
416 }
417 }
418 return v;
419 }
420
421 set<Type>
422 Library::getRealAtomTypes() const{
423 set<Type> s;
424 struct gl_list_t *l = DefinitionList();
425 if(!l){
426 throw runtime_error("No types found in library (perhaps no files have been loaded?)");
427 }
428
429 for(unsigned i = 1; i<=gl_length(l); ++i) {
430 Type t((const struct TypeDescription *)gl_fetch(l,i));
431 if(t.isRefinedReal()){
432 Dimensions d = t.getDimensions();
433 if(d.isWild() || d.isDimensionless())continue; // skip this one
434 // it's got some dimensions, add it to the list
435 s.insert(t);
436 }
437 }
438 gl_destroy(l);
439 return s;
440 }
441

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