|
PH Logo
Logo intepreter modeled after UCB Logo.
|
00001 /* 00002 * Verbs.cpp 00003 * 00004 * Author: Paul Hamilton 00005 * Date: 6 Jun 2011 00006 * 00007 */ 00008 00009 #include "Verbs.h" 00010 00011 #include "Func.h" 00012 #include "Scope.h" 00013 #include "Exceptions.h" 00014 #include "List.h" 00015 #include "ListArrayParser.h" 00016 #include "StringTokenStream.h" 00017 #include "Interpreter.h" 00018 #include "Thing.h" 00019 #include "World.h" 00020 00021 #include <boost/lexical_cast.hpp> 00022 00023 using namespace std; 00024 using namespace boost; 00025 00026 namespace phlogo { 00027 00028 Verbs::Verbs(Interpreter *itp, World *world) { 00029 00030 _itp = itp; 00031 _world = world; 00032 00033 // initialise all of the verbs we know about. 00034 addMap("print", "$1.1", &Verbs::print); 00035 addMap("pr", "$1.1", &Verbs::print); 00036 addMap("+", "$+", &Verbs::add); 00037 addMap("-", "$-", &Verbs::sub); 00038 addMap("*", "$*", &Verbs::mul); 00039 addMap("/", "$/", &Verbs::div); 00040 addMap("clearscreen", "$1.2", &Verbs::clearscreen); 00041 addMap("cs", "$1.2", &Verbs::clearscreen); 00042 addMap("make", "$1.3", &Verbs::make); 00043 addMap("thing", "$1.4", &Verbs::thing); 00044 addMap("output", "$1.5", &Verbs::output); 00045 00046 addMap("test", "$1.6", &Verbs::test); 00047 addMap("testsuite", "$1.7", &Verbs::testsuite); 00048 00049 addMap("load", "$1.8", &Verbs::load); 00050 00051 addMap("word", "$2.1", &Verbs::word); 00052 addMap("list", "$2.2", &Verbs::list); 00053 addMap("sentence", "$2.3", &Verbs::sentence); 00054 addMap("se", "$2.4", &Verbs::sentence); 00055 addMap("fput", "$2.5", &Verbs::fput); 00056 addMap("lput", "$2.6", &Verbs::lput); 00057 addMap("array", "$2.7", &Verbs::array); 00058 addMap("mdarray", "$2.8", &Verbs::mdarray); 00059 addMap("listtoarray", "$2.9", &Verbs::listtoarray); 00060 addMap("arraytolist", "$2.10", &Verbs::arraytolist); 00061 addMap("combine", "$2.11", &Verbs::combine); 00062 addMap("reverse", "$2.12", &Verbs::reverse); 00063 addMap("gensym", "$2.13", &Verbs::gensym); 00064 00065 addMap("first", "$3.1", &Verbs::first); 00066 addMap("firsts", "$3.2", &Verbs::firsts); 00067 addMap("last", "$3.3", &Verbs::last); 00068 addMap("butfirst", "$3.4", &Verbs::butfirst); 00069 addMap("bf", "$3.4", &Verbs::butfirst); 00070 addMap("butfirsts", "$3.5", &Verbs::butfirsts); 00071 addMap("bfs", "$3.5", &Verbs::butfirsts); 00072 addMap("butlast", "$3.6", &Verbs::butlast); 00073 addMap("bl", "$3.6", &Verbs::butlast); 00074 addMap("item", "$3.7", &Verbs::item); 00075 addMap("mditem", "$3.8", &Verbs::mditem); 00076 addMap("pick", "$3.9", &Verbs::pick); 00077 addMap("remove", "$3.10", &Verbs::remove); 00078 addMap("remdup", "$3.11", &Verbs::remdup); 00079 addMap("quoted", "$3.12", &Verbs::quoted); 00080 00081 addMap("setitem", "$4.1", &Verbs::setitem); 00082 addMap("mdsetitem", "$4.2", &Verbs::mdsetitem); 00083 addMap("setfirst", "$4.3", &Verbs::setfirst); 00084 addMap("setbf", "$4.4", &Verbs::setbf); 00085 addMap("push", "$4.5", &Verbs::push); 00086 addMap("pop", "$4.6", &Verbs::pop); 00087 addMap("queue", "$4.7", &Verbs::queue); 00088 addMap("dequeue", "$4.8", &Verbs::dequeue); 00089 00090 addMap("wordp", "$6.1", &Verbs::wordp); 00091 addMap("listp", "$6.2", &Verbs::listp); 00092 addMap("arrayp", "$6.3", &Verbs::arrayp); 00093 addMap("emptyp", "$6.4", &Verbs::emptyp); 00094 addMap("equalp", "$6.5", &Verbs::equalp); 00095 addMap("notequalp", "$6.6", &Verbs::notequalp); 00096 addMap("beforep", "$6.7", &Verbs::beforep); 00097 addMap("eq", "$6.8", &Verbs::eq); 00098 addMap("memberp", "$6.9", &Verbs::memberp); 00099 addMap("substringp", "$6.10", &Verbs::substringp); 00100 addMap("numberp", "$6.11", &Verbs::numberp); 00101 00102 addMap("count", "$7.1", &Verbs::count); 00103 addMap("ascii", "$7.2", &Verbs::ascii); 00104 addMap("rawascii", "$7.2", &Verbs::ascii); 00105 addMap("char", "$7.3", &Verbs::ch); 00106 addMap("member", "$7.4", &Verbs::member); 00107 addMap("lowercase", "$7.5", &Verbs::lowercase); 00108 addMap("uppercase", "$7.6", &Verbs::uppercase); 00109 00110 addMap("sum", "$8.1", &Verbs::sum); 00111 addMap("difference", "$8.2", &Verbs::difference); 00112 addMap("minus", "$8.3", &Verbs::minus); 00113 addMap("product", "$8.4", &Verbs::product); 00114 addMap("quotient", "$8.5", &Verbs::quotient); 00115 addMap("remainder", "$8.6", &Verbs::remainder); 00116 addMap("modulo", "$8.6", &Verbs::remainder); 00117 addMap("int", "$8.7", &Verbs::integer); 00118 addMap("round", "$8.8", &Verbs::round); 00119 addMap("sqrt", "$8.9", &Verbs::sqrt); 00120 addMap("power", "$8.10", &Verbs::power); 00121 addMap("exp", "$8.11", &Verbs::exp); 00122 addMap("log10", "$8.12", &Verbs::log10); 00123 addMap("ln", "$8.13", &Verbs::ln); 00124 addMap("sin", "$8.14", &Verbs::sin); 00125 addMap("radsin", "$8.15", &Verbs::radsin); 00126 addMap("cos", "$8.16", &Verbs::cos); 00127 addMap("radcos", "$8.17", &Verbs::radcos); 00128 addMap("arctan", "$8.18", &Verbs::arctan); 00129 addMap("radarctan", "$8.19", &Verbs::radarctan); 00130 addMap("iseq", "$8.20", &Verbs::iseq); 00131 addMap("rseq", "$8.21", &Verbs::rseq); 00132 00133 addMap("lessp", "$9.1", &Verbs::lessp); 00134 addMap("greaterp", "$9.2", &Verbs::greaterp); 00135 addMap("lessequalp", "$9.3", &Verbs::lessequalp); 00136 addMap("greaterequalp", "$9.4", &Verbs::greaterequalp); 00137 00138 srand(time(NULL)); 00139 00140 addMap("random", "$10.1", &Verbs::random); 00141 addMap("rerandom", "$10.2", &Verbs::rerandom); 00142 00143 addMap("form", "$11.1", &Verbs::form); 00144 00145 addMap("bitand", "$12.1", &Verbs::bitAnd); 00146 addMap("bitor", "$12.2", &Verbs::bitOr); 00147 addMap("bitxor", "$12.3", &Verbs::bitxor); 00148 addMap("bitnot", "$12.4", &Verbs::bitnot); 00149 addMap("ashift", "$12.5", &Verbs::lshift); 00150 addMap("lshift", "$12.5", &Verbs::lshift); 00151 00152 addMap("and", "$13.1", &Verbs::And); 00153 addMap("or", "$13.2", &Verbs::Or); 00154 addMap("not", "$13.3", &Verbs::Not); 00155 00156 addMap("contents", "$14.1", &Verbs::contents); 00157 addMap("procedures", "$14.2", &Verbs::procedures); 00158 addMap("primitives", "$14.3", &Verbs::primitives); 00159 addMap("names", "$14.4", &Verbs::names); 00160 00161 addMap("erase", "$14.5", &Verbs::erase); 00162 addMap("erall", "$14.6", &Verbs::erall); 00163 addMap("erps", "$14.7", &Verbs::erps); 00164 addMap("erns", "$14.8", &Verbs::erns); 00165 addMap("ern", "$14.9", &Verbs::ern); 00166 00167 addMap("procedurep", "$14.10", &Verbs::procedurep); 00168 addMap("definedp", "$14.10", &Verbs::procedurep); 00169 addMap("primitivep", "$14.11", &Verbs::primitivep); 00170 addMap("namep", "$14.12", &Verbs::namep); 00171 00172 addMap("fd", "$5.1", &Verbs::fd); 00173 addMap("forward", "$5.1", &Verbs::fd); 00174 addMap("bk", "$5.2", &Verbs::bk); 00175 addMap("back", "$5.2", &Verbs::bk); 00176 addMap("lt", "$5.3", &Verbs::lt); 00177 addMap("left", "$5.3", &Verbs::lt); 00178 addMap("rt", "$5.4", &Verbs::rt); 00179 addMap("right", "$5.4", &Verbs::rt); 00180 addMap("repeat", "$5.5", &Verbs::repeat); 00181 addMap("pu", "$5.6", &Verbs::penup); 00182 addMap("penup", "$5.6", &Verbs::penup); 00183 addMap("pd", "$5.7", &Verbs::pendown); 00184 addMap("pendown", "$5.7", &Verbs::pendown); 00185 00186 addMap("setpos", "$5.8", &Verbs::setpos); 00187 addMap("setxy", "$5.9", &Verbs::setxy); 00188 addMap("setx", "$5.10", &Verbs::setx); 00189 addMap("sety", "$5.11", &Verbs::sety); 00190 addMap("setheading", "$5.12", &Verbs::setheading); 00191 addMap("home", "$5.13", &Verbs::home); 00192 00193 addMap("pos", "$5.14", &Verbs::pos); 00194 addMap("xcor", "$5.15", &Verbs::xcor); 00195 addMap("ycor", "$5.16", &Verbs::ycor); 00196 addMap("heading", "$5.17", &Verbs::heading); 00197 addMap("towards", "$5.18", &Verbs::towards); 00198 00199 } 00200 00201 void Verbs::addMap(const string &verb, const string &token, pVerb func) { 00202 _verbtokenmap[verb] = token; 00203 _map[token] = func; 00204 } 00205 00206 long Verbs::getLong(TokenStream *ts) { 00207 00208 pThing thing; 00209 _itp->getNextThing(_world, ts, &thing); 00210 return thing->asLong(); 00211 00212 } 00213 00214 double Verbs::getDouble(TokenStream *ts) { 00215 00216 pThing thing; 00217 _itp->getNextThing(_world, ts, &thing); 00218 return thing->asDouble(); 00219 00220 } 00221 00222 double Verbs::getNum(TokenStream *ts, bool *isdouble) { 00223 00224 pThing thing; 00225 _itp->getNextThing(_world, ts, &thing); 00226 00227 try { 00228 long x = thing->asLong(); 00229 *isdouble = false; 00230 return x; 00231 } 00232 catch (bad_cast &e) { 00233 double x = thing->asDouble(); 00234 *isdouble = true; 00235 return x; 00236 } 00237 00238 } 00239 00240 string Verbs::getWord(TokenStream *ts) { 00241 00242 pThing thing; 00243 _itp->getNextThing(_world, ts, &thing); 00244 if (!thing->isWord()) 00245 BOOST_THROW_EXCEPTION( no_word_in_thing_exception() ); 00246 00247 return thing->getWord(); 00248 } 00249 00250 void Verbs::run(TokenStream *ts) { 00251 00252 StringTokenStream *sts = static_cast<StringTokenStream *>(ts); 00253 00254 string name = sts->nextWord(); 00255 map<string, pVerb>::iterator i = _map.find(name); 00256 if (i != _map.end()) { 00257 try { 00258 (*i).second(this, sts); 00259 } 00260 catch( dont_know_how_exception & x ) { 00261 string *verb=get_error_info<errinfo_curr_verb>(x); 00262 if (!verb) 00263 x << errinfo_curr_verb(name); 00264 throw; 00265 } 00266 } 00267 else { 00268 // second chance, we see if there is a function that has this name. 00269 Func *func = getFunction(name); 00270 if (func == 0) { 00271 BOOST_THROW_EXCEPTION( dont_know_how_exception() << 00272 errinfo_curr_verb(name) << 00273 errinfo_bad_tokens(sts->remain()) ); 00274 } 00275 else { 00276 // this scope is for local vars of the functions. 00277 Scope scope(_world); 00278 func->execute(_itp, _world, sts); 00279 } 00280 } 00281 } 00282 00283 Func *Verbs::createFunction(const string &name, const string &args) { 00284 00285 map<string, string>::iterator i = _functokenmap.find(name); 00286 if (i != _functokenmap.end()) { 00287 BOOST_THROW_EXCEPTION( 00288 func_already_exists_exception() << errinfo_curr_verb(name) ); 00289 } 00290 else { 00291 shared_ptr<Func> func(new Func(args)); 00292 string id = "#" + lexical_cast<string>(_functokenmap.size()); 00293 _funcs[id] = func; 00294 _functokenmap[name] = id; 00295 return func.get(); 00296 } 00297 00298 } 00299 00300 Func *Verbs::getFunction(const string &name) { 00301 map<string, shared_ptr<Func> >::iterator i = _funcs.find(name); 00302 return i != _funcs.end() ? i->second.get() : 0; 00303 } 00304 00305 void Verbs::removeFunction(const std::string &name) { 00306 00307 { 00308 std::map<std::string, std::string>::iterator i = _functokenmap.begin(); 00309 for (; i != _functokenmap.end(); i++) { 00310 if (i->second == name) { 00311 _functokenmap.erase(i); 00312 break; 00313 } 00314 } 00315 } 00316 { 00317 map<string, shared_ptr<Func> >::iterator i = _funcs.find(name); 00318 if (i != _funcs.end()) 00319 _funcs.erase(i); 00320 } 00321 00322 } 00323 00324 void Verbs::removeFunctions() { 00325 00326 _funcs.clear(); 00327 _functokenmap.clear(); 00328 00329 } 00330 00331 pThing Verbs::getThing(TokenStream *ts) { 00332 pThing thing; 00333 _itp->getNextThing(_world, ts, &thing); 00334 return thing; 00335 } 00336 00337 void Verbs::setBooleanResult(bool flag) { 00338 pThing t(new Thing(flag ? "TRUE" : "FALSE")); 00339 _world->setResult(t); 00340 } 00341 00342 void Verbs::setLongResult(long n) { 00343 pThing t(new Thing()); 00344 t->set(n); 00345 _world->setResult(t); 00346 } 00347 00348 void Verbs::setDoubleResult(double n) { 00349 pThing t(new Thing()); 00350 t->set(n); 00351 _world->setResult(t); 00352 } 00353 00354 void Verbs::setStringResult(const std::string &s) { 00355 00356 pThing t(new Thing(s)); 00357 _world->setResult(t); 00358 00359 } 00360 00361 bool Verbs::equal(pThing thing1, pThing thing2) { 00362 00363 if (thing1->isWord() && thing2->isWord()) 00364 return thing1->getWord() == thing2->getWord(); 00365 else if (thing1->isLong() && thing2->isLong()) 00366 return thing1->getLong() == thing2->getLong(); 00367 else if (thing1->isDouble() && thing2->isDouble()) 00368 return thing1->getDouble() == thing2->getDouble(); 00369 else if (thing1->isList() && thing2->isList()) 00370 return thing1->getList().str() == thing2->getList().str(); 00371 else if (thing1->isArray() && thing2->isArray()) 00372 return thing1->getArray().getVector() == thing2->getArray().getVector(); 00373 else 00374 return false; 00375 } 00376 00377 }
1.7.4