00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "ExNode.h"
00020 #include "ExVal.h"
00021
00022 using std::ostringstream;
00023 using namespace Marsyas;
00024
00025
00026
00027
00028
00029
00030 void
00031 ExVal::clear_list()
00032 {
00033 if (list_) {
00034 for (int i=0;i<natural_;++i) { list_[i]->deref(); }
00035 delete [] list_;
00036 list_=NULL;
00037 }
00038 }
00039
00040 void
00041 ExVal::clear()
00042 {
00043 clear_list();
00044 type_ ="";
00045 string_ ="";
00046 bool_ =false;
00047 natural_ =0;
00048 real_ =0.0;
00049 if (fun_) fun_->deref();
00050 fun_ =NULL;
00051 timer_ =NULL;
00052 scheduler_ =NULL;
00053 list_ =NULL;
00054 }
00055
00056 void ExVal::set(ExFun* x) { clear(); type_=(x==NULL) ? "" : x->getType(); fun_=x; }
00057 void ExVal::set(const mrs_string x) { clear(); type_="mrs_string"; string_=x; }
00058 void ExVal::set(double x) { clear(); type_="mrs_real"; real_=x; }
00059 void ExVal::set(float x) { clear(); type_="mrs_real"; real_=x; }
00060 void ExVal::set(mrs_natural x) { clear(); type_="mrs_natural"; natural_=x; }
00061 void ExVal::set(mrs_bool x) { clear(); type_="mrs_bool"; bool_=x; }
00062 void ExVal::set(TmTimer** t) { clear(); type_="mrs_timer"; timer_=t; }
00063 void ExVal::set(Scheduler** t) { clear(); type_="mrs_scheduler"; scheduler_=t; }
00064
00065 void
00066 ExVal::set(mrs_natural len, ExNode** xs, std::string t)
00067 {
00068 clear();
00069 if (xs!=NULL) { list_=xs; if((*xs)!=NULL&&len>0) { t=(*xs)->getType(); } }
00070 else { len=0; list_=new ExNode*[len]; }
00071 type_=t+" list"; natural_=len;
00072 }
00073
00074 void
00075 ExVal::set(mrs_natural len, std::string t)
00076 {
00077 (void) len;
00078 clear(); type_=t; natural_=0; list_=NULL;
00079 }
00080
00081 void
00082 ExVal::set(const ExVal& v)
00083 {
00084 clear();
00085 kind_ =v.kind_;
00086 type_ =v.type_;
00087 string_ =v.string_;
00088 natural_ =v.natural_;
00089 real_ =v.real_;
00090 bool_ =v.bool_;
00091 fun_ =(v.fun_==NULL) ? NULL : v.fun_->copy();
00092 timer_ =v.timer_;
00093 scheduler_ =v.scheduler_;
00094 if (is_list()) {
00095 list_=new ExNode*[natural_];
00096 for (int i=0;i<natural_;++i) {
00097 list_[i]=v.list_[i];
00098 list_[i]->inc_ref();
00099 }
00100 }
00101 else list_=NULL;
00102 }
00103
00104 ExVal::~ExVal()
00105 {
00106 if (fun_!=NULL) fun_->deref();
00107 clear_list();
00108 }
00109
00110 std::string
00111 ExVal::toString() const
00112 {
00113 if (type_=="mrs_string") { return string_; }
00114 else if (type_=="mrs_real") { return dtos(real_); }
00115 else if (type_=="mrs_natural") { return ltos(natural_); }
00116 else if (type_=="mrs_bool") { return btos(bool_); }
00117 else if (type_=="mrs_fun") { return "<mrs_fun>"; }
00118 else if (type_=="mrs_timer") { return "<mrs_timer>"; }
00119 else if (type_=="mrs_scheduler") { return "<mrs_scheduler>"; }
00120 else if (type_=="") { return "unknown value"; }
00121 return type_;
00122 }
00123
00124 ExVal
00125 ExVal::defaultExValue(std::string type)
00126 {
00127 if (type=="mrs_string") return (std::string)"";
00128 if (type=="mrs_bool") return (bool)false;
00129 if (type=="mrs_natural") return (long)0;
00130 if (type=="mrs_real") return (double)0.0;
00131 if (type=="mrs_timer") { ExVal v((TmTimer**)NULL); return v; }
00132 if (type=="mrs_scheduler") { ExVal v((Scheduler**)NULL); return v; }
00133 return ExVal();
00134 }
00135
00136 std::string
00137 ExVal::getBaseType() const
00138 {
00139 mrs_natural p=(mrs_natural)type_.find(' ');
00140 if (p<0) return type_;
00141 return type_.substr(0,p);
00142 }
00143
00144 std::string
00145 ExVal::getElemType() const
00146 {
00147 if (type_=="mrs_string") {
00148 return "mrs_string";
00149 }
00150 else if (is_list()) {
00151 return type_.substr(0,type_.length()-5);
00152 }
00153 return "";
00154 }
00155
00156 bool
00157 ExVal::is_list() const
00158 {
00159 size_t len = type_.length();
00160 return (len>3)
00161 && (type_[len-4]=='l')
00162 && (type_[len-3]=='i')
00163 && (type_[len-2]=='s')
00164 && (type_[len-1]=='t');
00165 }
00166
00167 bool
00168 ExVal::is_seq() const
00169 {
00170 return type_=="mrs_string"||is_list();
00171 }
00172
00173 ExVal
00174 ExVal::getSeqRange(int lidx, int ridx)
00175 {
00176 if (!is_seq()) {
00177 return defaultExValue(getBaseType());
00178 }
00179 if (lidx<0) lidx=0;
00180
00181 mrs_natural len;
00182 if (is_list()) {
00183 len=natural_;
00184 if (len<=0||lidx>=len) { return ExVal(0,getType()); }
00185
00186 if (ridx<lidx) ridx=lidx;
00187 else if (ridx>=len) ridx=len-1;
00188 mrs_natural new_len=ridx-lidx;
00189
00190 ExNode** new_list=new ExNode*[new_len];
00191 int p=0;
00192 for (int i=lidx;i<ridx;++i) {
00193 ExNode* e=list_[i];
00194 new_list[p]=e; p++;
00195 e->inc_ref();
00196 }
00197 return ExVal(new_len,(ExNode**)new_list);
00198 }
00199 else {
00200 len=(mrs_natural)string_.length();
00201 if (len<=0||lidx>=len) { return (std::string)""; }
00202
00203 if (ridx<lidx) ridx=lidx;
00204 else if (ridx>=len) ridx=len-1;
00205
00206 return (std::string)string_.substr(lidx,ridx-1);
00207 }
00208 }
00209
00210 ExVal
00211 ExVal::getSeqElem(int idx)
00212 {
00213 if (is_list()) {
00214 if (idx>=natural_||idx<0) {
00215 MRSWARN("ExVal::getSeqElem index exceeds list length");
00216 return defaultExValue(getBaseType());
00217 }
00218 return list_[idx]->eval();
00219 }
00220 else if (type_=="mrs_string") {
00221 if (idx>=0&&idx<=(int)string_.length())
00222 return (std::string)string_.substr(idx,1);
00223 return (std::string)"";
00224 }
00225 else {
00226 MRSWARN("ExVal::getSeqElem element access on non-sequence type: "+type_);
00227 return defaultExValue(getBaseType());
00228 }
00229 }
00230
00231 void
00232 ExVal::setSeqElem(int idx, ExVal v)
00233 {
00234 if (idx<0||idx>=natural_) {
00235 MRSWARN("ExVal::set[] Index out of bounds");
00236 return;
00237 }
00238 list_[idx]->deref();
00239 list_[idx]=new ExNode(v);
00240 }
00241
00242 std::ostream&
00243 Marsyas::operator<<(std::ostream& o, ExVal& v)
00244 {
00245 bool i_am_a_list = v.is_list();
00246 if (i_am_a_list) {
00247 o<<"[";
00248 for (int i=0;i<v.natural_;++i) {
00249 ExVal x=v.list_[i]->eval();
00250 o<<x;
00251 if (i<v.natural_-1) { o<<", "; }
00252 }
00253 o<<"]";
00254 }
00255 else if (v.type_=="mrs_string") o<<"'"<<v.string_<<"'";
00256 else if (v.type_=="mrs_natural") o<<ltos(v.natural_);
00257 else if (v.type_=="mrs_real") o<<dtos(v.real_);
00258 else if (v.type_=="mrs_bool") o<<btos(v.bool_);
00259 return o;
00260 }
00261
00262 ExVal
00263 ExVal::append(const ExVal v) const
00264 {
00265 if (!is_list()||!v.is_list()) {
00266 MRSWARN("ExVal::append only sequence types may be appended: "+getType()+", "+v.getType());
00267 return *this;
00268 }
00269 if (getType()==" list"||v.getType()==" list"||getType()==v.getType()) {
00270 mrs_natural len=natural_+v.toNatural(); ExNode** elems=new ExNode*[len];
00271 int l=0;
00272 if (natural_>0) {
00273 for (int i=0;i<natural_;++i,l++) {
00274 elems[l]=list_[i];
00275 elems[l]->inc_ref();
00276 }
00277 }
00278 if (v.toNatural()>0) {
00279 for (int i=0;i<v.toNatural();++i,l++) {
00280 elems[l]=v.list_[i];
00281 elems[l]->inc_ref();
00282 }
00283 }
00284 return ExVal(len,elems);
00285 }
00286 MRSWARN("ExVal::append type mismatch in list concat: "+getType()+","+v.getType());
00287 return *this;
00288 }