00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "ExSymTbl.h"
00020 #include "ExNode.h"
00021
00022 using std::ostringstream;
00023 using namespace Marsyas;
00024
00025 ExRecord::ExRecord() : ExRefCount()
00026 {
00027 kind_=0;
00028 name_="";
00029 reserved_=false;
00030 }
00031 ExRecord::ExRecord(int kind) : ExRefCount()
00032 {
00033 kind_=kind;
00034 name_="";
00035 reserved_=false;
00036 }
00037
00038 ExRecord::ExRecord(int kind, ExFun* fun, bool reserved) : ExRefCount()
00039 {
00040 kind_=kind;
00041 name_=fun->getSignature();
00042 value_.set(fun);
00043 reserved_=reserved;
00044 }
00045 ExRecord::ExRecord(int kind, std::string name, ExVal& value, bool reserved) : ExRefCount()
00046 {
00047 kind_=kind;
00048 name_=name;
00049 value_=value;
00050
00051 reserved_=reserved;
00052 }
00053
00054 ExRecord::~ExRecord()
00055 {
00056 if (!syms_.empty()) {
00057 std::map<std::string,ExRecord*>::iterator it;
00058 for(it=syms_.begin();it!=syms_.end();++it) {
00059 ((*it).second)->deref();
00060 }
00061 }
00062 }
00063
00064 std::string
00065 ExRecord::getType(std::string path)
00066 {
00067 if (path=="") return value_.getType();
00068 ExRecord* r=getRecord(path);
00069 return (r==NULL) ? "" : r->getType();
00070 }
00071
00072 std::string
00073 ExRecord::getElemType(std::string path)
00074 {
00075 if (path=="") return value_.getElemType();
00076 ExRecord* r=getRecord(path);
00077 return (r==NULL) ? "" : r->getElemType();
00078 }
00079
00080
00081 int
00082 ExRecord::getKind(std::string path)
00083 {
00084 if (path=="") return kind_;
00085 ExRecord* r=getRecord(path);
00086 return (r==NULL) ? 0 : r->getKind();
00087 }
00088
00089
00090 bool
00091 ExRecord::is_reserved(std::string path)
00092 {
00093 if (path=="") return reserved_;
00094 ExRecord* r=getRecord(path);
00095 return (r==NULL) ? false : r->is_reserved();
00096 }
00097
00098 bool
00099 ExRecord::is_list()
00100 {
00101 return value_.is_list();
00102 }
00103
00104 bool
00105 ExRecord::is_seq()
00106 {
00107 return value_.is_seq();
00108 }
00109
00110 ExRecord*
00111 ExRecord::getRecord(std::string path)
00112 {
00113 ExRecord* r=find_sym(path);
00114 if (r==NULL&&imports_.size()>0) {
00115 std::vector<std::string>::iterator iter_;
00116 for (iter_=imports_.begin();r==NULL&&iter_!=imports_.end();iter_++) {
00117 r=find_sym((*iter_)+"."+path);
00118 }
00119 }
00120 return r;
00121 }
00122 bool
00123 ExRecord::params_compare(std::string a, std::string b)
00124 {
00125 int p1=0;
00126 int p2=0;
00127 int len1=a.length();
00128 int len2=b.length();
00129 int start=1;
00130
00131 while (p1<len1&&p2<len2) {
00132 if (a[p1]!=b[p2]) {
00133 if (a[p1]==','&&b[p2]=='|') {
00134 while (p2<len2) {
00135 if (b[p2]==',') break;
00136 if (b[p2]==')') return false;
00137 p2++;
00138 }
00139 p1++;
00140 p2++;
00141 }
00142 else if (a[p1]==')'&&b[p2]=='|') {
00143 while (p2<len2) {
00144 if (b[p2]==',') return false;
00145 if (b[p2]==')') return true;
00146 p2++;
00147 }
00148 return false;
00149 }
00150 else {
00151 while(p2<len2) {
00152 if (b[p2]=='|') break;
00153 if (b[p2]==','||b[p2]==')') return false;
00154 p2++;
00155 }
00156 p1=start; p2++;
00157 }
00158 }
00159 else {
00160 if (a[p1]==',') start=p1+1;
00161 p1++; p2++;
00162 }
00163 if (a[p1]==')'&&b[p2]==')') return true;
00164 }
00165 return false;
00166 }
00167
00168
00169
00170
00171 ExFun*
00172 ExRecord::getFunctionCopy(std::string path)
00173 {
00174 if (path=="") {
00175 if (kind_!=T_FUN) return NULL;
00176 ExFun* f=value_.toFun();
00177 return (f==NULL) ? NULL : f->copy();
00178 }
00179 ExRecord* r=getRecord(path);
00180 return (r==NULL) ? NULL : r->getFunctionCopy();
00181 }
00182
00183 void
00184 ExRecord::split_on(std::string p, char c, std::string& hd, std::string& tl, bool keep)
00185 {
00186 int adj=(keep) ? 0 : 1;
00187 size_t i;
00188 for(i=0;i<p.length()&&p[i]!=c;++i);
00189 if (p[i]==c) { hd=p.substr(0,i); tl=p.substr(i+adj,p.length()-i-adj); }
00190 else { hd=p; tl=""; }
00191 }
00192
00193 void
00194 ExRecord::rsplit_on(std::string p, char c, std::string& hd, std::string& tl)
00195 {
00196 int i; for(i=p.length()-1;i>=0&&p[i]!=c;++i);
00197 if (p[i]==c) { hd=p.substr(0,i); tl=p.substr(i+1,p.length()-i-1); }
00198 else { hd=""; tl=p; }
00199 }
00200
00201 ExRecord*
00202 ExRecord::find_sym(std::string path)
00203 {
00204
00205 std::string ghd, gtl; split_on(path,'.',ghd,gtl);
00206 if (gtl==""&&ghd[0]!='(') {
00207 split_on(ghd,'(',ghd,gtl,true);
00208 }
00209 if (gtl!="") {
00210
00211 std::map<std::string, ExRecord*>::iterator gi=syms_.find(ghd);
00212 if (gi==syms_.end()) {
00213 std::map<std::string,std::string>::iterator it = syms_aliases_.find(ghd);
00214
00215 if (it==syms_aliases_.end())
00216 return NULL;
00217 else
00218 return syms_[it->second]->find_sym(gtl);
00219 }
00220
00221 return (gi->second)->find_sym(gtl);
00222 }
00223 if (path[0]=='(') {
00224 ExRecord* answer=NULL;
00225 std::map<std::string,ExRecord*>::iterator is=syms_.begin();
00226 while (is!=syms_.end()&&!answer) {
00227 if (params_compare((is->first),path)) { answer=is->second; }
00228 else is++;
00229 }
00230 if (!answer) {
00231 std::map<std::string,std::string>::iterator it=syms_aliases_.begin();
00232 while (it!=syms_aliases_.end()&&!answer) {
00233 if (params_compare((it->first),path))
00234 answer=syms_[it->second];
00235 else
00236 ++it;
00237 }
00238 }
00239 return answer;
00240 }
00241 std::map<std::string,ExRecord*>::iterator gi=syms_.find(ghd);
00242 if (gi==syms_.end()) {
00243
00244 std::map<std::string,std::string>::iterator ni=syms_aliases_.find(ghd);
00245 if (ni==syms_aliases_.end()) { return NULL; }
00246 return syms_[ni->second];
00247 }
00248 return (gi->second);
00249 }
00250
00251 void
00252 ExRecord::addAliases(std::string path, std::string name)
00253 {
00254 std::string nhd, ntl;
00255
00256 split_on(path,'|',nhd,ntl);
00257 while (nhd!="") {
00258 syms_aliases_[nhd]=name;
00259 split_on(ntl,'|',nhd,ntl);
00260 }
00261 }
00262
00263 void
00264 ExRecord::addRecord(std::string path, ExRecord* sym)
00265 {
00266
00267 std::string ghd; std::string gtl; split_on(path,'.',ghd,gtl);
00268 if (gtl!="") {
00269
00270 std::string nhd, ntl; split_on(ghd,'|',nhd,ntl);
00271 std::string name_=nhd;
00272 std::map<std::string, ExRecord*>::iterator gi=syms_.find(name_);
00273 ExRecord* syms=NULL;
00274
00275 if (gi==syms_.end()) { syms=new ExRecord(T_LIB); syms_[name_]=syms; syms->inc_ref(); }
00276 else { syms=(gi->second); }
00277
00278
00279 addAliases(ntl,name_);
00280 syms->addRecord(gtl,sym);
00281 }
00282 else {
00283
00284 std::string params;
00285 if (ghd[0]!='(') split_on(ghd,'(',ghd,params,true);
00286
00287 std::string nhd, ntl; split_on(ghd,'|',nhd,ntl);
00288 std::map<std::string, ExRecord*>::iterator gi=syms_.find(nhd);
00289 if (gi==syms_.end()) {
00290 if (params!="") {
00291 ExRecord* e=new ExRecord(T_FUN); e->inc_ref();
00292 syms_[nhd]=e;
00293 e->addRecord(params,sym);
00294 }
00295 else {
00296 syms_[nhd]=sym;
00297 sym->inc_ref();
00298 }
00299 }
00300 else if (params!="") {
00301 (gi->second)->addRecord(params,sym);
00302 }
00303 else {
00304 MRSWARN("ExRecord::addRecord '"+nhd+"' already refers to a symbol");
00305 sym->deref();
00306 return;
00307 }
00308 addAliases(ntl,nhd);
00309 }
00310 }
00311 ExRecord*
00312 ExRecord::rmvRecord(std::string path)
00313 {
00314
00315 std::string ghd, gtl; split_on(path,'.',ghd,gtl);
00316 std::map<std::string, ExRecord*>::iterator rec_i;
00317 std::map<std::string,std::string>::iterator alias_i;
00318
00319 if (gtl==""&&ghd[0]!='(') {
00320 split_on(ghd,'(',ghd,gtl,true);
00321 }
00322 rec_i=syms_.find(ghd);
00323 if (rec_i==syms_.end()) {
00324 alias_i=syms_aliases_.find(ghd);
00325
00326 if (alias_i==syms_aliases_.end()) { return NULL; }
00327 ghd=alias_i->second;
00328 rec_i=syms_.find(ghd);
00329 }
00330 ExRecord* r;
00331 bool del_rec=false;
00332 if (gtl!="") r=(rec_i->second)->rmvRecord(gtl);
00333 else { r=rec_i->second; del_rec=true; }
00334 if (r!=NULL) {
00335 std::vector<std::string> names_;
00336
00337 for (alias_i=syms_aliases_.begin();alias_i!=syms_aliases_.end();++alias_i) {
00338 if (alias_i->second==ghd) names_.push_back(alias_i->first);
00339 }
00340 if (names_.size()>0) {
00341
00342 std::vector<std::string>::iterator nmi;
00343 for (nmi=names_.begin();nmi!=names_.end();++nmi) {
00344 syms_aliases_.erase(*nmi);
00345 }
00346 }
00347
00348 syms_.erase(rec_i);
00349 if (del_rec&&r->size()>0) r->deref();
00350 }
00351 return r;
00352 }
00353 void
00354 ExRecord::addReserved(std::string path, ExFun* fun)
00355 {
00356 addRecord(path,new ExRecord(T_FUN,fun,true));
00357 }
00358 void
00359 ExRecord::addReserved(std::string path, ExVal v, std::string nm, int kind)
00360 {
00361 addRecord(path,new ExRecord(kind,nm,v,true));
00362 }
00363
00364 void
00365 ExRecord::setValue(ExVal& v, std::string path, int elem_pos)
00366 {
00367 if (path!="") {
00368
00369 std::string name; split_on(path,'.',name,path);
00370 if (path!="") {
00371
00372 std::map<std::string, ExRecord*>::iterator iter=syms_.find(name);
00373 ExRecord* syms=NULL;
00374 if (iter==syms_.end()) { syms=new ExRecord(); syms_[name]=syms; syms->inc_ref(); }
00375 else { syms=iter->second; }
00376 syms->setValue(v,path);
00377 return;
00378 }
00379 else {
00380
00381 std::map<std::string, ExRecord*>::iterator iter=syms_.find(name);
00382 if (iter==syms_.end()) {
00383 ExRecord* r=new ExRecord(T_VAR,name,v,false); r->inc_ref();
00384 syms_[name]=r;
00385 return;
00386 }
00387 else {
00388 (iter->second)->setValue(v);
00389 return;
00390 }
00391 }
00392 }
00393 if (getKind()!=T_VAR) {
00394 MRSWARN("ExRecord::setValue Attempting assignment to non-variable");
00395 }
00396 else if (elem_pos>=0) {
00397 if (getElemType()!=v.getType()) {
00398 MRSWARN("ExRecord::setValue Type mismatch in assignment of element: "+getElemType()+" << "+v.getType());
00399 }
00400 else value_.setSeqElem(elem_pos, v);
00401 }
00402 else if (getType()!=v.getType()) {
00403 MRSWARN("ExRecord::setValue Type mismatch in assignment: "+getType()+" << "+v.getType());
00404 } else value_=v;
00405 }
00406
00407
00408 ExVal
00409 ExRecord::getValue(std::string path)
00410 {
00411 if (path=="") return value_;
00412 ExRecord* s=getRecord(path);
00413 return (s==NULL) ? false : s->getValue();
00414 }
00415
00416 void
00417 ExRecord::import(std::string a)
00418 {
00419 std::vector<std::string>::iterator p; bool added=false;
00420 for (p=imports_.begin();p!=imports_.end();++p) {
00421 if ((*p)==a) { added=true; break; }
00422 }
00423 if (!added) imports_.push_back(a);
00424 }
00425
00426 void
00427 ExRecord::rmv_import(std::string a)
00428 {
00429 std::vector<std::string>::iterator p;
00430 for (p=imports_.begin();p!=imports_.end();++p) {
00431 if ((*p)==a) { imports_.erase(p); break; }
00432 }
00433 }
00434
00435
00436 ExSymTbl::~ExSymTbl()
00437 {
00438 while (rho_.size()>0) {
00439 ExRecord* r=rho_.back();
00440 rho_.pop_back();
00441 r->deref();
00442 }
00443 }
00444 void ExSymTbl::block_open()
00445 {
00446 env_id++;
00447 ExRecord* r=new ExRecord();
00448 rho_.push_back(r);
00449 curr_=r;
00450 r->inc_ref();
00451 }
00452 void
00453 ExSymTbl::block_close()
00454 {
00455 if (rho_.size()>0) {
00456 ExRecord* r=rho_.back();
00457 rho_.pop_back();
00458 r->deref();
00459 if (rho_.size()>0) curr_=rho_.back();
00460 else curr_=NULL;
00461 }
00462 }
00463 void
00464 ExSymTbl::addTable(ExRecord* r)
00465 {
00466 if (r) {
00467 env_id++;
00468 rho_.push_back(r);
00469 curr_=r;
00470 r->inc_ref();
00471 }
00472 }
00473 ExRecord*
00474 ExSymTbl::getRecord(std::string nm)
00475 {
00476 if (rho_.size()>0) {
00477 std::vector<ExRecord*>::reverse_iterator i;
00478 for(i=rho_.rbegin(); i!=rho_.rend(); ++i) {
00479 ExRecord* r=(*i)->getRecord(nm);
00480 if (r!=NULL) return r;
00481 }
00482 }
00483 return NULL;
00484 }
00485 ExVal
00486 ExSymTbl::getValue(std::string path)
00487 {
00488 ExRecord* r=getRecord(path);
00489 return (r) ? r->getValue() : ExVal();
00490 }
00491 ExFun*
00492 ExSymTbl::getFunctionCopy(std::string path)
00493 {
00494 ExRecord* r=getRecord(path);
00495 return (r) ? r->getFunctionCopy() : NULL;
00496 }
00497 void
00498 ExSymTbl::import(std::string n)
00499 {
00500 if (curr_) curr_->import(n);
00501 }
00502 void
00503 ExSymTbl::rmv_import(std::string n)
00504 {
00505 if (curr_) curr_->rmv_import(n);
00506 }
00507 void
00508 ExSymTbl::addRecord(std::string path, ExRecord* sym)
00509 {
00510 if (curr_) curr_->addRecord(path,sym);
00511 }
00512 ExRecord*
00513 ExSymTbl::rmvRecord(std::string path)
00514 {
00515 return (curr_) ? curr_->rmvRecord(path) : NULL;
00516 }
00517 void
00518 ExSymTbl::addReserved(std::string path, ExFun* f)
00519 {
00520 if (curr_) curr_->addReserved(path,f);
00521 }
00522 void
00523 ExSymTbl::addReserved(std::string path, ExVal v, std::string nm, int kind)
00524 {
00525 if (curr_) curr_->addReserved(path,v,nm,kind);
00526 }
00527 void
00528 ExSymTbl::setValue(ExVal& v, std::string path)
00529 {
00530 if (curr_) curr_->setValue(v,path);
00531 }