PH Logo
Logo intepreter modeled after UCB Logo.
/Users/paul/Documents/phlogo/core/Verbs.cpp
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 }
 All Classes Functions