lua++
|
00001 /* ###################################### */ 00002 /* ### Frost Engine, by Kalith ### */ 00003 /* ###################################### */ 00004 /* Lua source */ 00005 /* */ 00006 00007 #include "luapp_state.hpp" 00008 #include "luapp_function.hpp" 00009 #include <utils_string.hpp> 00010 00011 namespace lua 00012 { 00013 function::function(const std::string& sName, lua_State* pLua, uint uiReturnNbr) : 00014 sName_(sName), uiReturnNbr_(uiReturnNbr) 00015 { 00016 pLua_ = state::get_state(pLua); 00017 new_param_set(); 00018 } 00019 00020 function::function(const std::string& sName, state* pLua, uint uiReturnNbr) : 00021 sName_(sName), pLua_(pLua), uiReturnNbr_(uiReturnNbr) 00022 { 00023 new_param_set(); 00024 } 00025 00026 function::~function() 00027 { 00028 /*std::vector<argument_list>::iterator iterArgList; 00029 foreach (iterArgList, lArgListStack_) 00030 { 00031 std::map<uint, argument*>::iterator iter; 00032 foreach (iter, iterArgList->lOptional_) 00033 { 00034 iter->second.Delete(); 00035 } 00036 foreach (iter, iterArgList->lArg_) 00037 { 00038 iter->second.Delete(); 00039 } 00040 }*/ 00041 } 00042 00043 void function::add(uint uiIndex, const std::string& sName, type mLuaType, bool bOptional) 00044 { 00045 if (bOptional) 00046 { 00047 if (pArgList_->lOptional_.find(uiIndex) != pArgList_->lOptional_.end()) 00048 pArgList_->lOptional_[uiIndex]->add(sName, mLuaType); 00049 else 00050 pArgList_->lOptional_[uiIndex] = utils::refptr<argument>(new argument(sName, mLuaType, this)); 00051 } 00052 else 00053 { 00054 if (pArgList_->lArg_.find(uiIndex) != pArgList_->lArg_.end()) 00055 pArgList_->lArg_[uiIndex]->add(sName, mLuaType); 00056 else 00057 pArgList_->lArg_[uiIndex] = utils::refptr<argument>(new argument(sName, mLuaType, this)); 00058 } 00059 } 00060 00061 void function::new_param_set() 00062 { 00063 lArgListStack_.push_back(argument_list()); 00064 pArgList_ = &lArgListStack_.back(); 00065 pArgList_->uiRank_ = lArgListStack_.size()-1; 00066 } 00067 00068 uint function::get_param_set_rank() 00069 { 00070 return pArgList_->uiRank_; 00071 } 00072 00073 utils::wptr<argument> function::get(uint uiIndex) 00074 { 00075 if (pArgList_->lArg_.find(uiIndex) != pArgList_->lArg_.end()) 00076 { 00077 return pArgList_->lArg_[uiIndex]; 00078 } 00079 if (pArgList_->lOptional_.find(uiIndex) != pArgList_->lOptional_.end()) 00080 { 00081 return pArgList_->lOptional_[uiIndex]; 00082 } 00083 00084 return nullptr; 00085 } 00086 00087 bool function::is_provided( uint uiIndex ) const 00088 { 00089 std::map<uint, utils::refptr<argument>>::const_iterator iter = pArgList_->lArg_.find(uiIndex); 00090 if (iter != pArgList_->lArg_.end()) 00091 { 00092 return iter->second->is_provided(); 00093 } 00094 iter = pArgList_->lOptional_.find(uiIndex); 00095 if (iter != pArgList_->lOptional_.end()) 00096 { 00097 return iter->second->is_provided(); 00098 } 00099 00100 return false; 00101 } 00102 00103 uint function::get_argument_count() const 00104 { 00105 return uiArgumentCount_; 00106 } 00107 00108 bool function::check(bool bPrintError) 00109 { 00110 uiArgumentCount_ = pLua_->get_top(); 00111 00112 // Check if that's enough 00113 std::vector<argument_list>::iterator iterArgList; 00114 std::vector<argument_list*> lValidArgList; 00115 foreach (iterArgList, lArgListStack_) 00116 { 00117 if (uiArgumentCount_ >= iterArgList->lArg_.size()) 00118 lValidArgList.push_back(&(*iterArgList)); 00119 } 00120 00121 if (lValidArgList.empty()) 00122 { 00123 if (bPrintError) 00124 { 00125 std::string sError; 00126 foreach (iterArgList, lArgListStack_) 00127 { 00128 std::string sarguments = "\n - ["+utils::to_string(iterArgList->lArg_.size())+"] : "; 00129 std::map<uint, utils::refptr<argument>>::iterator iterArg; 00130 foreach (iterArg, iterArgList->lArg_) 00131 { 00132 if (iterArg != iterArgList->lArg_.begin()) 00133 sarguments += ", "; 00134 sarguments += iterArg->second->get_data()->get_name(); 00135 } 00136 if (iterArgList->lOptional_.size() > 0) 00137 { 00138 if (sarguments != "") 00139 sarguments += ", "; 00140 sarguments += "(+"; 00141 foreach (iterArg, iterArgList->lOptional_) 00142 { 00143 if (iterArg != iterArgList->lOptional_.begin()) 00144 sarguments += ", "; 00145 sarguments += iterArg->second->get_data()->get_name(); 00146 } 00147 sarguments += ")"; 00148 } 00149 sError += sarguments; 00150 } 00151 00152 if (lArgListStack_.size() == 1) 00153 { 00154 pLua_->print_error( 00155 "Too few arguments in \""+sName_+"\". Expected :"+sError 00156 ); 00157 } 00158 else 00159 { 00160 pLua_->print_error( 00161 "Too few arguments in \""+sName_+"\". Expected either :"+sError 00162 ); 00163 } 00164 } 00165 // So if there isn't enough, just return false 00166 return false; 00167 } 00168 00169 // We then check the value type 00170 int i; 00171 std::map<uint, utils::refptr<argument>>::iterator iterArg; 00172 if (lValidArgList.size() > 1) 00173 { 00174 std::vector<argument_list*>::iterator iterArgListPtr; 00175 pArgList_ = nullptr; 00176 foreach (iterArgListPtr, lValidArgList) 00177 { 00178 i = 1; 00179 bool bValid = true; 00180 foreach (iterArg, (*iterArgListPtr)->lArg_) 00181 { 00182 if (!iterArg->second->test(pLua_, i, false)) 00183 { 00184 bValid = false; 00185 break; 00186 } 00187 ++i; 00188 } 00189 if (bValid) 00190 { 00191 pArgList_ = (*iterArgListPtr); 00192 break; 00193 } 00194 } 00195 00196 if (!pArgList_) 00197 { 00198 if (bPrintError) 00199 { 00200 std::string sError; 00201 foreach (iterArgList, lArgListStack_) 00202 { 00203 std::string sarguments = "\n - ["+utils::to_string(iterArgList->lArg_.size())+"] : "; 00204 std::map<uint, utils::refptr<argument>>::iterator iterArg; 00205 foreach (iterArg, iterArgList->lArg_) 00206 { 00207 if (iterArg != iterArgList->lArg_.begin()) 00208 sarguments += ", "; 00209 sarguments += iterArg->second->get_data()->get_name(); 00210 } 00211 if (iterArgList->lOptional_.size() > 0) 00212 { 00213 if (sarguments != "") 00214 sarguments += ", "; 00215 sarguments += "(+"; 00216 foreach (iterArg, iterArgList->lOptional_) 00217 { 00218 if (iterArg != iterArgList->lOptional_.begin()) 00219 sarguments += ", "; 00220 sarguments += iterArg->second->get_data()->get_name(); 00221 } 00222 sarguments += ")"; 00223 } 00224 sError += sarguments; 00225 } 00226 00227 pLua_->print_error( 00228 "Wrong arguments provided to \""+sName_+"\". Expected either :"+sError 00229 ); 00230 } 00231 return false; 00232 } 00233 } 00234 else 00235 { 00236 pArgList_ = lValidArgList[0]; 00237 i = 1; 00238 bool bValid = true; 00239 foreach (iterArg, pArgList_->lArg_) 00240 { 00241 if (!iterArg->second->test(pLua_, i, bPrintError)) 00242 bValid = false; 00243 ++i; 00244 } 00245 00246 if (!bValid) 00247 return false; 00248 } 00249 00250 // We fill the stack with nil value until there are enough for optional arguments 00251 uint uiMaxArgs = pArgList_->lArg_.size() + pArgList_->lOptional_.size(); 00252 if (uiArgumentCount_ < uiMaxArgs) 00253 pLua_->push_nil(uiMaxArgs - uiArgumentCount_); 00254 00255 // And we check optional arguments 00256 bool bValid = true; 00257 foreach (iterArg, pArgList_->lOptional_) 00258 { 00259 if (pLua_->get_type(i) != TYPE_NIL) 00260 { 00261 if (!iterArg->second->test(pLua_, i, bPrintError)) 00262 bValid = false; 00263 } 00264 ++i; 00265 } 00266 00267 return bValid; 00268 } 00269 00270 const std::string& function::get_name() const 00271 { 00272 return sName_; 00273 } 00274 00275 void function::push( const var& vValue ) 00276 { 00277 if (uiReturnCount_ == uiReturnNbr_) 00278 ++uiReturnNbr_; 00279 00280 pLua_->push_var(vValue); 00281 00282 ++uiReturnCount_; 00283 } 00284 00285 void function::push_nil( uint uiNbr ) 00286 { 00287 for (uint ui = 0; ui < uiNbr; ++ui) 00288 { 00289 if (uiReturnCount_ == uiReturnNbr_) 00290 ++uiReturnNbr_; 00291 00292 pLua_->push_nil(); 00293 00294 ++uiReturnCount_; 00295 } 00296 } 00297 00298 void function::notify_pushed() 00299 { 00300 if (uiReturnCount_ == uiReturnNbr_) 00301 ++uiReturnNbr_; 00302 00303 ++uiReturnCount_; 00304 } 00305 00306 int function::on_return() 00307 { 00308 if (uiReturnNbr_ != 0) 00309 { 00310 // Fill with nil value 00311 if (uiReturnCount_ < uiReturnNbr_) 00312 pLua_->push_nil(uiReturnNbr_ - uiReturnCount_); 00313 00314 // Return the number of returned value 00315 return static_cast<int>(uiReturnNbr_); 00316 } 00317 else 00318 return 0; 00319 } 00320 00321 state* function::get_state() const 00322 { 00323 return pLua_; 00324 } 00325 }