00001 #include "global.hpp"
00002
00003 #include <cmath>
00004 #include <set>
00005 #include <stdlib.h>
00006 #include <iostream>
00007 #include <string.h>
00008
00009 #include "boost/lexical_cast.hpp"
00010
00011
00012 #include "formatter.hpp"
00013 #include "formula.hpp"
00014 #include "formula_callable.hpp"
00015 #include "variant.hpp"
00016
00017 namespace {
00018 std::string variant_type_to_string(variant::TYPE type) {
00019 switch(type) {
00020 case variant::TYPE_NULL:
00021 return "null";
00022 case variant::TYPE_INT:
00023 return "int";
00024 case variant::TYPE_CALLABLE:
00025 return "object";
00026 case variant::TYPE_LIST:
00027 return "list";
00028 case variant::TYPE_STRING:
00029 return "string";
00030 case variant::TYPE_MAP:
00031 return "map";
00032 default:
00033 assert(false);
00034 return "invalid";
00035 }
00036 }
00037
00038 std::vector<const char*> call_stack;
00039 }
00040
00041 void push_call_stack(const char* str)
00042 {
00043 call_stack.push_back(str);
00044 }
00045
00046 void pop_call_stack()
00047 {
00048 call_stack.pop_back();
00049 }
00050
00051 std::string get_call_stack()
00052 {
00053 std::string res;
00054 for(std::vector<const char*>::const_iterator i = call_stack.begin();
00055 i != call_stack.end(); ++i) {
00056 if(!*i) {
00057 continue;
00058 }
00059 res += " ";
00060 res += *i;
00061 res += "\n";
00062 }
00063 return res;
00064 }
00065
00066 type_error::type_error(const std::string& str) : message(str) {
00067 std::cerr << "ERROR: " << message << "\n" << get_call_stack();
00068 }
00069
00070 struct variant_list {
00071 variant_list() : refcount(0)
00072 {}
00073 std::vector<variant> elements;
00074 int refcount;
00075 };
00076
00077 struct variant_string {
00078 variant_string() : refcount(0)
00079 {}
00080 std::string str;
00081 int refcount;
00082 };
00083
00084 struct variant_map {
00085 variant_map() : refcount(0)
00086 {}
00087 std::map<variant,variant> elements;
00088 int refcount;
00089 };
00090
00091 void variant::increment_refcount()
00092 {
00093 switch(type_) {
00094 case TYPE_LIST:
00095 ++list_->refcount;
00096 break;
00097 case TYPE_STRING:
00098 ++string_->refcount;
00099 break;
00100 case TYPE_MAP:
00101 ++map_->refcount;
00102 break;
00103 case TYPE_CALLABLE:
00104 intrusive_ptr_add_ref(callable_);
00105 break;
00106
00107
00108 case TYPE_NULL:
00109 case TYPE_INT :
00110 break;
00111 }
00112 }
00113
00114 void variant::release()
00115 {
00116 switch(type_) {
00117 case TYPE_LIST:
00118 if(--list_->refcount == 0) {
00119 delete list_;
00120 }
00121 break;
00122 case TYPE_STRING:
00123 if(--string_->refcount == 0) {
00124 delete string_;
00125 }
00126 break;
00127 case TYPE_MAP:
00128 if(--map_->refcount == 0) {
00129 delete map_;
00130 }
00131 break;
00132 case TYPE_CALLABLE:
00133 intrusive_ptr_release(callable_);
00134 break;
00135
00136
00137 case TYPE_NULL:
00138 case TYPE_INT :
00139 break;
00140 }
00141 }
00142
00143 variant::variant() : type_(TYPE_NULL), int_value_(0)
00144 {}
00145
00146 variant::variant(int n) : type_(TYPE_INT), int_value_(n)
00147 {}
00148
00149 variant::variant(const game_logic::formula_callable* callable)
00150 : type_(TYPE_CALLABLE), callable_(callable)
00151 {
00152 assert(callable_);
00153 increment_refcount();
00154 }
00155
00156 variant::variant(std::vector<variant>* array)
00157 : type_(TYPE_LIST)
00158 {
00159 assert(array);
00160 list_ = new variant_list;
00161 list_->elements.swap(*array);
00162 increment_refcount();
00163 }
00164
00165 variant::variant(const std::string& str)
00166 : type_(TYPE_STRING)
00167 {
00168 string_ = new variant_string;
00169 string_->str = str;
00170 increment_refcount();
00171 }
00172
00173 variant::variant(std::map<variant,variant>* map)
00174 : type_(TYPE_MAP)
00175 {
00176 assert(map);
00177 map_ = new variant_map;
00178 map_->elements.swap(*map);
00179 increment_refcount();
00180 }
00181
00182 variant::variant(const variant& v)
00183 {
00184 memcpy(this, &v, sizeof(v));
00185 increment_refcount();
00186 }
00187
00188 variant::~variant()
00189 {
00190 release();
00191 }
00192
00193 const variant& variant::operator=(const variant& v)
00194 {
00195 if(&v != this) {
00196 release();
00197 memcpy(this, &v, sizeof(v));
00198 increment_refcount();
00199 }
00200 return *this;
00201 }
00202
00203 const variant& variant::operator[](size_t n) const
00204 {
00205 if(type_ == TYPE_CALLABLE) {
00206 assert(n == 0);
00207 return *this;
00208 }
00209
00210 must_be(TYPE_LIST);
00211 assert(list_);
00212 if(n >= list_->elements.size()) {
00213 throw type_error("invalid index");
00214 }
00215
00216 return list_->elements[n];
00217 }
00218
00219 const variant& variant::operator[](const variant v) const
00220 {
00221 if(type_ == TYPE_CALLABLE) {
00222 assert(v.as_int() == 0);
00223 return *this;
00224 }
00225
00226 if(type_ == TYPE_MAP) {
00227 assert(map_);
00228 std::map<variant,variant>::const_iterator i = map_->elements.find(v);
00229 if (i == map_->elements.end())
00230 {
00231 static variant null_variant;
00232 return null_variant;
00233 }
00234 return i->second;
00235 } else if(type_ == TYPE_LIST) {
00236 return operator[](v.as_int());
00237 } else {
00238 throw type_error(formatter() << "type error: " << " expected a list or a map but found " << variant_type_to_string(type_) << " (" << to_debug_string() << ")");
00239 }
00240 }
00241
00242 std::map<variant, variant> variant::get_map() const
00243 {
00244 must_be(TYPE_MAP);
00245 return map_->elements;
00246 }
00247
00248 variant variant::get_keys() const
00249 {
00250 must_be(TYPE_MAP);
00251 assert(map_);
00252 std::vector<variant> tmp;
00253 for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
00254 tmp.push_back(i->first);
00255 }
00256 return variant(&tmp);
00257 }
00258
00259 variant variant::get_values() const
00260 {
00261 must_be(TYPE_MAP);
00262 assert(map_);
00263 std::vector<variant> tmp;
00264 for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
00265 tmp.push_back(i->second);
00266 }
00267 return variant(&tmp);
00268 }
00269
00270 size_t variant::num_elements() const
00271 {
00272 if(type_ == TYPE_CALLABLE) {
00273 return 1;
00274 }
00275
00276 if (type_ == TYPE_LIST) {
00277 assert(list_);
00278 return list_->elements.size();
00279 } else if (type_ == TYPE_MAP) {
00280 assert(map_);
00281 return map_->elements.size();
00282 } else {
00283 throw type_error(formatter() << "type error: " << " expected a list or a map but found " << variant_type_to_string(type_) << " (" << to_debug_string() << ")");
00284 }
00285 }
00286
00287 variant variant::get_member(const std::string& str) const
00288 {
00289 if(is_callable()) {
00290 return callable_->query_value(str);
00291 }
00292
00293 if(str == "self") {
00294 return *this;
00295 } else {
00296 return variant();
00297 }
00298 }
00299
00300 bool variant::as_bool() const
00301 {
00302 switch(type_) {
00303 case TYPE_NULL:
00304 return false;
00305 case TYPE_INT:
00306 return int_value_ != 0;
00307 case TYPE_CALLABLE:
00308 return callable_ != NULL;
00309 case TYPE_LIST:
00310 return !list_->elements.empty();
00311 case TYPE_MAP:
00312 return !map_->elements.empty();
00313 case TYPE_STRING:
00314 return !string_->str.empty();
00315 default:
00316 assert(false);
00317 return false;
00318 }
00319 }
00320
00321 const std::string& variant::as_string() const
00322 {
00323 must_be(TYPE_STRING);
00324 assert(string_);
00325 return string_->str;
00326 }
00327
00328 variant variant::operator+(const variant& v) const
00329 {
00330 if(type_ == TYPE_LIST) {
00331 if(v.type_ == TYPE_LIST) {
00332 std::vector<variant> res;
00333 res.reserve(list_->elements.size() + v.list_->elements.size());
00334 for(size_t i = 0; i<list_->elements.size(); ++i) {
00335 const variant& var = list_->elements[i];
00336 res.push_back(var);
00337 }
00338
00339 for(size_t j = 0; j<v.list_->elements.size(); ++j) {
00340 const variant& var = v.list_->elements[j];
00341 res.push_back(var);
00342 }
00343
00344 return variant(&res);
00345 }
00346 }
00347 if(type_ == TYPE_MAP) {
00348 if(v.type_ == TYPE_MAP) {
00349 std::map<variant,variant> res(map_->elements);
00350
00351 for(std::map<variant,variant>::const_iterator i = v.map_->elements.begin(); i != v.map_->elements.end(); ++i) {
00352 res[i->first] = i->second;
00353 }
00354
00355 return variant(&res);
00356 }
00357 }
00358
00359 return variant(as_int() + v.as_int());
00360 }
00361
00362 variant variant::operator-(const variant& v) const
00363 {
00364 return variant(as_int() - v.as_int());
00365 }
00366
00367 variant variant::operator*(const variant& v) const
00368 {
00369 return variant(as_int() * v.as_int());
00370 }
00371
00372 variant variant::operator/(const variant& v) const
00373 {
00374 const int numerator = as_int();
00375 const int denominator = v.as_int();
00376 if(denominator == 0) {
00377 throw type_error(formatter() << "divide by zero error");
00378 }
00379
00380 return variant(numerator/denominator);
00381 }
00382
00383 variant variant::operator%(const variant& v) const
00384 {
00385 const int numerator = as_int();
00386 const int denominator = v.as_int();
00387 if(denominator == 0) {
00388 throw type_error(formatter() << "divide by zero error");
00389 }
00390
00391 return variant(numerator%denominator);
00392 }
00393
00394 variant variant::operator^(const variant& v) const
00395 {
00396 return variant(static_cast<int>(pow(as_int(), v.as_int())));
00397 }
00398
00399 variant variant::operator-() const
00400 {
00401 return variant(-as_int());
00402 }
00403
00404 bool variant::operator==(const variant& v) const
00405 {
00406 if(type_ != v.type_) {
00407 return false;
00408 }
00409
00410 switch(type_) {
00411 case TYPE_NULL: {
00412 return v.is_null();
00413 }
00414
00415 case TYPE_STRING: {
00416 return string_->str == v.string_->str;
00417 }
00418
00419 case TYPE_INT: {
00420 return int_value_ == v.int_value_;
00421 }
00422
00423 case TYPE_LIST: {
00424 if(num_elements() != v.num_elements()) {
00425 return false;
00426 }
00427
00428 for(size_t n = 0; n != num_elements(); ++n) {
00429 if((*this)[n] != v[n]) {
00430 return false;
00431 }
00432 }
00433
00434 return true;
00435 }
00436
00437 case TYPE_MAP: {
00438 return map_->elements == v.map_->elements;
00439 }
00440
00441 case TYPE_CALLABLE: {
00442 return callable_->equals(v.callable_);
00443 }
00444 }
00445
00446 assert(false);
00447 return false;
00448 }
00449
00450 bool variant::operator!=(const variant& v) const
00451 {
00452 return !operator==(v);
00453 }
00454
00455 bool variant::operator<=(const variant& v) const
00456 {
00457 if(type_ != v.type_) {
00458 return type_ < v.type_;
00459 }
00460
00461 switch(type_) {
00462 case TYPE_NULL: {
00463 return true;
00464 }
00465
00466 case TYPE_STRING: {
00467 return string_->str <= v.string_->str;
00468 }
00469
00470 case TYPE_INT: {
00471 return int_value_ <= v.int_value_;
00472 }
00473
00474 case TYPE_LIST: {
00475 for(size_t n = 0; n != num_elements() && n != v.num_elements(); ++n) {
00476 if((*this)[n] < v[n]) {
00477 return true;
00478 } else if((*this)[n] > v[n]) {
00479 return false;
00480 }
00481 }
00482
00483 return num_elements() <= v.num_elements();
00484 }
00485
00486 case TYPE_MAP: {
00487 return map_->elements <= v.map_->elements;
00488 }
00489
00490 case TYPE_CALLABLE: {
00491 return !v.callable_->less(callable_);
00492 }
00493 }
00494
00495 assert(false);
00496 return false;
00497 }
00498
00499 bool variant::operator>=(const variant& v) const
00500 {
00501 return v <= *this;
00502 }
00503
00504 bool variant::operator<(const variant& v) const
00505 {
00506 return !(*this >= v);
00507 }
00508
00509 bool variant::operator>(const variant& v) const
00510 {
00511 return !(*this <= v);
00512 }
00513
00514 void variant::must_be(variant::TYPE t) const
00515 {
00516 if(type_ != t) {
00517 throw type_error(formatter() << "type error: " << " expected " << variant_type_to_string(t) << " but found " << variant_type_to_string(type_) << " (" << to_debug_string() << ")");
00518 }
00519 }
00520
00521 void variant::serialize_to_string(std::string& str) const
00522 {
00523 switch(type_) {
00524 case TYPE_NULL:
00525 str += "null()";
00526 case TYPE_INT:
00527 str += boost::lexical_cast<std::string>(int_value_);
00528 break;
00529 case TYPE_CALLABLE:
00530 callable_->serialize(str);
00531 break;
00532 case TYPE_LIST: {
00533 str += "[";
00534 bool first_time = true;
00535 for(size_t i=0; i<list_->elements.size(); ++i) {
00536 const variant& var = list_->elements[i];
00537 if(!first_time) {
00538 str += ",";
00539 }
00540 first_time = false;
00541 var.serialize_to_string(str);
00542 }
00543 str += "]";
00544 break;
00545 }
00546 case TYPE_MAP: {
00547 str += "{";
00548 bool first_time = true;
00549 for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
00550 if(!first_time) {
00551 str += ",";
00552 }
00553 first_time = false;
00554 i->first.serialize_to_string(str);
00555 str += "->";
00556 i->second.serialize_to_string(str);
00557 }
00558 str += "}";
00559 break;
00560 }
00561 case TYPE_STRING:
00562 str += "'";
00563 str += string_->str;
00564 str += "'";
00565 break;
00566 default:
00567 assert(false);
00568 }
00569 }
00570
00571 void variant::serialize_from_string(const std::string& str)
00572 {
00573 try {
00574 *this = game_logic::formula(str).execute();
00575 } catch(...) {
00576 *this = variant(str);
00577 }
00578 }
00579
00580 int variant::refcount() const
00581 {
00582 switch(type_) {
00583 case TYPE_LIST:
00584 return list_->refcount;
00585 break;
00586 case TYPE_STRING:
00587 return string_->refcount;
00588 break;
00589 case TYPE_MAP:
00590 return map_->refcount;
00591 break;
00592 case TYPE_CALLABLE:
00593 return callable_->refcount();
00594 break;
00595 default:
00596 return -1;
00597 }
00598 }
00599
00600 std::string variant::string_cast() const
00601 {
00602 switch(type_) {
00603 case TYPE_NULL:
00604 return "0";
00605 case TYPE_INT:
00606 return boost::lexical_cast<std::string>(int_value_);
00607 case TYPE_CALLABLE:
00608 return "(object)";
00609 case TYPE_LIST: {
00610 std::string res = "";
00611 for(size_t i=0; i<list_->elements.size(); ++i) {
00612 const variant& var = list_->elements[i];
00613 if(!res.empty()) {
00614 res += ", ";
00615 }
00616
00617 res += var.string_cast();
00618 }
00619
00620 return res;
00621 }
00622 case TYPE_MAP: {
00623 std::string res = "";
00624 for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
00625 if(!res.empty()) {
00626 res += ",";
00627 }
00628 res += i->first.string_cast();
00629 res += "->";
00630 res += i->second.string_cast();
00631 }
00632 return res;
00633 }
00634
00635 case TYPE_STRING:
00636 return string_->str;
00637 default:
00638 assert(false);
00639 return "invalid";
00640 }
00641 }
00642
00643 std::string variant::to_debug_string(std::vector<const game_logic::formula_callable*>* seen) const
00644 {
00645 std::vector<const game_logic::formula_callable*> seen_stack;
00646 if(!seen) {
00647 seen = &seen_stack;
00648 }
00649
00650 std::ostringstream s;
00651 switch(type_) {
00652 case TYPE_NULL:
00653 s << "(null)";
00654 case TYPE_INT:
00655 s << int_value_;
00656 break;
00657 case TYPE_LIST: {
00658 s << "[";
00659 for(size_t n = 0; n != num_elements(); ++n) {
00660 if(n != 0) {
00661 s << ", ";
00662 }
00663
00664 s << operator[](n).to_debug_string(seen);
00665 }
00666 s << "]";
00667 break;
00668 }
00669 case TYPE_CALLABLE: {
00670 s << "{";
00671 if(std::find(seen->begin(), seen->end(), callable_) == seen->end()) {
00672 seen->push_back(callable_);
00673 std::vector<game_logic::formula_input> v = callable_->inputs();
00674 bool first = true;
00675 for(size_t i=0; i<v.size(); ++i) {
00676 const game_logic::formula_input& input = v[i];
00677 if(!first) {
00678 s << ", ";
00679 }
00680 first = false;
00681 s << input.name << " ";
00682 if(input.access == game_logic::FORMULA_READ_WRITE) {
00683 s << "(read-write) ";
00684 } else if(input.access == game_logic::FORMULA_WRITE_ONLY) {
00685 s << "(writeonly) ";
00686 }
00687
00688 s << "-> " << callable_->query_value(input.name).to_debug_string(seen);
00689 }
00690 } else {
00691 s << "...";
00692 }
00693 s << "}";
00694 break;
00695 }
00696 case TYPE_MAP: {
00697 s << "{";
00698 bool first_time = true;
00699 for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
00700 if(!first_time) {
00701 s << ",";
00702 }
00703 first_time = false;
00704 s << i->first.to_debug_string(seen);
00705 s << "->";
00706 s << i->second.to_debug_string(seen);
00707 }
00708 s << "}";
00709 break;
00710 }
00711 case TYPE_STRING: {
00712 s << "'" << string_->str << "'";
00713 break;
00714 }
00715 }
00716
00717 return s.str();
00718 }