void teval(vector<string> args) { random_device randomDevice; auto seed = randomDevice(); Database db{config::databaseFileName}; Options opts{}; opts.seed = seed; Bot pbrane{db, opts, Clock{}, setupBot}; pbrane.vars.set("bot.owner", "jac"); pbrane.vars.set("bot.admins", "jac"); if(!args.empty()) { for(auto &arg : args) { if(arg.empty() || startsWith(arg, "--")) continue; cout << ": " << arg << endl; try { auto expr = Parser::parse(arg); cout << "expr: " << (expr ? "true" : "false") << endl; // print computed AST cout << "final: " << endl; cout << expr->pretty() << endl; cout << "stringify: " << expr->toString() << endl; cout << "result: " << expr->evaluate(pbrane.vm, "jac").toString() << endl; // TODO: other exception types... } catch(ParseException e) { cout << e.pretty() << endl; } catch(StackTrace &e) { cout << e.toString() << endl; } catch(string &s) { cout << "\t: " << s << endl; } } return; } while(cin.good() && !cin.eof()) { string nick, line; getline(cin, nick); getline(cin, line); if(nick.empty() || line.empty()) break; try { auto expr = Parser::parse(line); cerr << "eval'ing: " << line << " as " << nick << endl; cerr << "final AST: " << endl; cerr << expr->pretty() << endl; cerr << "stringify: " << expr->toString() << endl; string res = expr->evaluate(pbrane.vm, nick).toString(); cerr << "result: " << res << endl; cout << nick + ": " << res << endl; // TODO: other exception types } catch(ParseException e) { cerr << e.pretty() << endl; } catch(StackTrace &e) { cout << e.toString() << endl; } catch(string &s) { cerr << "\texception: " << s << endl; cout << nick + ": error: " + s << endl; } } }
int main(int argc, char **argv) { vector<string> args; for(int i = 1; i < argc; ++i) args.push_back(argv[i]); Options opts{}; for(auto &arg : args) { if (arg == "--teval") { teval(args); return 0; } if(arg == "--pprint") { for(auto &arg2 : args) if(!startsWith(arg2, "--")) prettyPrint(arg2); return 0; } if(arg == "--importGoogle") { importGoogleNGramData(); return 0; } if(arg == "--import") { opts.import = true; cerr << "pbrane: import mode enabled" << endl; } else if(arg == "--debugSQL") { opts.debugSQL = true; cerr << "pbrane: debug sql enabled" << endl; } else if(arg == "--debugEventSystem") { opts.debugEventSystem = true; cerr << "pbrane: debug event system enabled" << endl; } else if(arg == "--debugFunctionBodies") { opts.debugFunctionBodies = true; cerr << "pbrane: debug function bodies enabled" << endl; } else if(arg == "--importLog") { opts.import = true; opts.importLog = true; cerr << "pbrane: import log enabled" << endl; } else { opts.seed = fromString<unsigned int>(argv[1]); } } if(args.empty()) { random_device randomDevice; opts.seed = randomDevice(); } Database db{config::databaseFileName}; Bot pbrane{db, opts, Clock{}, setupBot}; // while there is more input coming while(!cin.eof() && !pbrane.done) { // read the current line of input string line; getline(cin, line); if(line.find_first_not_of(" \t\r\n") == string::npos) continue; string network; auto ts = Clock{}.now(); if(!opts.importLog) { network = line.substr(0, line.find(" ")); line = line.substr(line.find(" ") + 1); if(line.find_first_not_of(" \t\r\n") == string::npos) continue; } else { auto fs = util::split(line, "|"); if(fs.size() < 3) { cerr << "unable to parse log line" << endl; cerr << "line: " << line << endl; return 32; } ts = util::fromString<sqlite_int64>(fs[0]); network = fs[1]; line = util::join(fs.begin() + 2, fs.end(), " "); } Entry entry{ts, network, line}; pbrane.journal.upsert(entry); auto fields = split(line); if(fields.empty()) continue; if(entry.type == EntryType::Text) { auto nick = entry.nick(); auto message = entry.arguments; auto target = entry.where; if(target == pbrane.vars.get("bot.nick").toString()) target = nick; // TODO: simplify construction? pbrane.vars.set("nick", nick); pbrane.vars.set("where", target); pbrane.vars.set("text", message); // check for a special hook bool wasHook = false; if(!opts.import) { for(auto h : hooks) if((*h)({ network, message, nick, target, pbrane })) { wasHook = true; break; } } if(wasHook) entry.etype = ExecuteType::Hook; // if the line is a ! command, run it else if(message[0] == '!' && message.length() > 1) { // it might be a !: to force intepretation line if(message.size() > 1 && message[1] == ':') pbrane.process(network, message.substr(2), nick, target); else pbrane.process(network, message, nick, target); entry.etype = ExecuteType::Function; } else if(message.substr(0, 2) == (string)"${" && message.back() == '}') { pbrane.process(network, message, nick, target); entry.etype = ExecuteType::Function; } else if(message.substr(0, 2) == (string)"::") { pbrane.process(network, message, nick, target); entry.etype = ExecuteType::Function; } // otherwise, run on text triggers else { entry.etype = ExecuteType::None; vector<Variable> results = pbrane.events.process(EventType::Text, pbrane.vm); if(results.size() == 1) pbrane.send(network, target, results.front().toString(), true); } } if(entry.type == EntryType::Join) { auto nick = entry.nick(), where = entry.where; // TODO: proper environment for triggers pbrane.vars.set("nick", nick); pbrane.vars.set("where", where); pbrane.vars.erase("text"); auto results = pbrane.events.process(EventType::Join, pbrane.vm); if(results.size() == 1) pbrane.send(network, where, results.front().toString(), true); } if(entry.type == EntryType::Nick) { ;// run nick triggers } if(entry.type == EntryType::Part || entry.type == EntryType::Quit) { ;// run leave triggers } pbrane.journal.upsert(entry); } cerr << "pbrane: exited main loop" << endl; return 0; }