void executeAbsDbl(Executer &executer) { auto argument = executer.topDbl(); if (argument < 0) { executer.setTop(-argument); } }
void executeExponentialIntDbl(Executer &executer) { auto y = executer.topDbl(); executer.pop(); auto x = executer.topIntAsDbl(); calculatePowerDblDbl(executer, x, y); }
void executeCatTmpTmp(Executer &executer) { auto rhs = executer.moveTopTmpStr(); executer.pop(); *executer.topTmpStr() += *rhs; }
inline int32_t popIntegerDivisor(Executer &executer) { auto rhs = executer.topInt(); checkDivideByZero(executer, rhs); executer.pop(); return rhs; }
inline double popDoubleDivisor(Executer &executer) { auto rhs = executer.topDbl(); checkDivideByZero(executer, rhs); executer.pop(); return rhs; }
void executeDivideDblInt(Executer &executer) { auto rhs = static_cast<double>(popIntegerDivisor(executer)); auto lhs = executer.topDbl(); auto result = lhs / rhs; executer.setTop(result); }
void executeExponentialIntInt(Executer &executer) { auto y = executer.topInt(); executer.pop(); auto x = executer.topInt(); executer.setTop(PowerIntInt{executer, x, y}()); }
void executeMultiplyIntDbl(Executer &executer) { auto rhs = executer.topDbl(); executer.pop(); auto lhs = executer.topIntAsDbl(); multiplyAndCheckResult(executer, lhs, rhs); }
void executeSubtractDblDbl(Executer &executer) { auto rhs = executer.topDbl(); executer.pop(); auto result = executer.topDbl() - rhs; checkDoubleOverflow(executer, result); executer.setTop(result); }
void executeCatStrStr(Executer &executer) { auto rhs = executer.topStr(); executer.pop(); executer.setTop(*executer.topStr()); *executer.topTmpStr() += *rhs; }
void executeIntegerDivide(Executer &executer) { auto rhs = popDoubleDivisor(executer); auto lhs = executer.topDbl(); auto result = lhs / rhs; checkIntegerOverflow(executer, result); executer.setTopIntFromDouble(result); }
void executeAbsInt(Executer &executer) { auto argument = executer.topInt(); if (argument < 0) { checkNegativeIntegerOverflow(executer, argument); executer.setTop(-argument); } }
void executeSqr(Executer &executer) { auto argument = executer.topDbl(); if (argument < 0) { throw RunError {"square root of negative number", executer.currentOffset()}; } executer.setTop(std::sqrt(argument)); }
void executeRndInt(Executer &executer) { auto argument = executer.topInt(); if (argument <= 0) { throw RunError {"random function on zero or negative number", executer.currentOffset()}; } executer.setTop(executer.getRandomNumber(argument)); }
void executeLog(Executer &executer) { auto argument = executer.topDbl(); if (argument <= 0) { throw RunError {"logarithm of non-positive number", executer.currentOffset()}; } executer.setTop(std::log(argument)); }
void executeSubtractIntInt(Executer &executer) { auto rhs = executer.topInt(); executer.pop(); auto result = int64_t{executer.topInt()}; result -= rhs; checkIntegerOverflow(executer, result); executer.setTopIntFromInt64(result); }
inline void executeSgn(Executer &executer) { auto argument = executer.top<T>(); if (argument > T{0}) { executer.setTop(T{1}); } else if (argument < 0.0) { executer.setTop(T{-1}); } else { executer.setTop(T{0}); } }
void executeCatStrTmp(Executer &executer) { auto rhs_result = executer.topTmpStr(); executer.pop(); auto lhs_rhs = std::string{*executer.topStr()}; std::swap(lhs_rhs, *rhs_result); executer.setTop(rhs_result); *executer.topTmpStr() += lhs_rhs; }
inline void validatePowerResult(double x, double result, Executer &executer) { if (std::isnan(result)) { throw RunError {"domain error (non-integer exponent)", executer.currentOffset()}; } else if (result == HUGE_VAL) { if (x == 0) { throw RunError {"divide by zero", executer.currentOffset()}; } else { throw RunError {"overflow", executer.currentOffset()}; } } }
QScriptValue clearConsoleFunction(QScriptContext *context, QScriptEngine *engine) { if(!Executer::isExecuterRunning()) return QScriptValue(); QApplication::processEvents();//Call this to prevent UI freeze when calling clear often QScriptValue calleeData = context->callee().data(); Executer *executer = qobject_cast<Executer *>(calleeData.toQObject()); executer->consoleWidget()->clearExceptSeparators(); return engine->undefinedValue(); }
QScriptValue callProcedureFunction(QScriptContext *context, QScriptEngine *engine) { if(!Executer::isExecuterRunning()) return QScriptValue(); if(context->argumentCount() < 1) return engine->undefinedValue(); QScriptValue calleeData = context->callee().data(); Executer *executer = qobject_cast<Executer *>(calleeData.toQObject()); ActionTools::ActionInstance *currentActionInstance = executer->currentActionInstance(); if(currentActionInstance) currentActionInstance->callProcedure(context->argument(0).toString()); return engine->undefinedValue(); }
void printCall(QScriptContext *context, ActionTools::ConsoleWidget::Type type) { QApplication::processEvents();//Call this to prevent UI freeze when calling print often QScriptValue calleeData = context->callee().data(); Executer *executer = qobject_cast<Executer *>(calleeData.toQObject()); QString message; ScriptAgent *agent = executer->scriptAgent(); if(!agent) return; for(int argumentIndex = 0; argumentIndex < context->argumentCount(); ++argumentIndex) message += context->argument(argumentIndex).toString(); switch(executer->scriptAgent()->context()) { case ScriptAgent::Parameters: executer->consoleWidget()->addScriptParameterLine(message, agent->currentParameter(), agent->currentLine(), agent->currentColumn(), type); break; case ScriptAgent::Actions: { ActionTools::ActionInstance *currentAction = executer->script()->actionAt(executer->currentActionIndex()); qint64 currentActionRuntimeId = -1; if(currentAction) currentActionRuntimeId = currentAction->runtimeId(); executer->consoleWidget()->addUserLine(message, currentActionRuntimeId, context->engine()->globalObject().property("currentParameter").toString(), context->engine()->globalObject().property("currentSubParameter").toString(), agent->currentLine(), agent->currentColumn(), context->backtrace(), type); } break; default: return; } }
variant execution_context::execute() { size_t isz = instructions_.size(); while(pc_ < isz) { instruction& i = instructions_[pc_]; //td: a fuction table would be better, no? switch(i.id) { case i_jump: { pc_ = i.data.value; jump_ = true; break; } case i_jump_if: { bool control = pop(); if (control) { pc_ = i.data.value; jump_ = true; } break; } case i_jump_if_not: { bool control = variant_cast<bool>(pop(), false); //td: its bool or false if (!control) { pc_ = i.data.value; jump_ = true; } break; } case i_store: { stack_[i.data.value] = pop(); break; } case i_load: { operands_.push(stack_[i.data.value]); break; } case i_load_constant: { operands_.push(constants_[i.data.value]); break; } case i_return: return variant(); case i_return_value: return operands_.top(); case i_dup_top: { variant top = operands_.top(); operands_.push( top ); break; } case i_pop: operands_.pop(); break; case i_binary_operator: { operator_exec* e = operators_.get_operator(i.data.value); variant arg2 = pop(); variant arg1 = pop(); variant result = e->exec(arg1, arg2); operands_.push(result); break; } case i_unary_operator: { operator_exec* e = operators_.get_operator(i.data.value); variant arg1 = pop(); variant useless; variant result = e->exec(arg1, useless); operands_.push(result); break; } case i_dynamic_binary_operator: { variant arg2 = pop(); variant arg1 = pop(); schema* type1 = true_type(arg1); assert(type1); schema* type2 = true_type(arg2); assert(type2); variant result; operator_type opid = (operator_type)i.data.value; operator_exec* opexec = operators_.get_operator(opid, type1, type2); if (!opexec) { schema_item custom_operator; if (type1->resolve(vm_operator_name[opid], custom_operator)) { assert(custom_operator.exec); //read only void* caller_id; if (custom_operator.flags & DYNAMIC_ACCESS) { IDynamicObject* obj = arg1; //td: catch type mismatch caller_id = obj; } else caller_id = arg1.get_pointer(); param_list args; args.add(arg2); result = custom_operator.exec->exec(caller_id, args ); } else { if (operators_.get_default_operator(opid, &opexec, null)) { result = opexec->exec(arg1, arg2); } else { param_list error; error.add("id", SRuntime); error.add("desc", SCannotResolveOperator); error.add("operator", str(vm_operator_name[opid])); runtime_throw(error); } } } else result = opexec->exec(arg1, arg2); operands_.push(result); break; } case i_dynamic_binary_assign_operator: { bool assign = false; variant arg1 = pop(); variant arg2 = pop(); schema* type1 = true_type(arg1); assert(type1); schema* type2 = true_type(arg2); assert(type2); variant result; operator_type opid = (operator_type)i.data.value; operator_exec* opexec = operators_.get_operator(opid, type1, type2); if (!opexec) { schema_item custom_operator; if (type1->resolve(vm_operator_name[opid], custom_operator)) { assert(custom_operator.exec); //read only void* caller_id; if (custom_operator.flags & DYNAMIC_ACCESS) { IDynamicObject* obj = arg1; //td: catch type mismatch caller_id = obj; } else caller_id = arg1.get_pointer(); param_list args; args.add(arg2); result = custom_operator.exec->exec(caller_id, args ); } else { operator_exec* nopexec = operators_.get_operator(vm_native_op[opid], type1, type2); if (nopexec) { result = nopexec->exec(arg1, arg2); assign = true; } else { param_list error; error.add("id", SRuntime); error.add("desc", SCannotResolveOperator); error.add("operator", str(vm_operator_name[opid])); runtime_throw(error); } } } else result = opexec->exec(arg1, arg2); operands_.push(result); operands_.push(!assign); break; } case i_dynamic_unary_operator: { variant arg1 = pop(); schema* type1 = true_type(arg1); assert(type1); variant result; operator_type opid = (operator_type)i.data.value; operator_exec* opexec = operators_.get_operator(opid, type1, null); if (!opexec) { schema_item custom_operator; if (type1->resolve(vm_operator_name[opid], custom_operator)) { assert(custom_operator.exec); //read only void* caller_id; if (custom_operator.flags & DYNAMIC_ACCESS) { IDynamicObject* obj = arg1; //td: catch type mismatch caller_id = obj; } else caller_id = arg1.get_pointer(); param_list args; result = custom_operator.exec->exec(caller_id, args ); } else { param_list error; error.add("id", SRuntime); error.add("desc", SCannotResolveOperator); error.add("operator", str(vm_operator_name[opid])); runtime_throw(error); } } else { variant arg2; result = opexec->exec(arg1, arg2); } operands_.push(result); break; } case i_dynamic_get: { str getter_name = constants_[i.data.value]; variant getted = pop(); variant result; if (!dynamic_try_get(getted, getter_name, result)) { param_list error; error.add("id", SRuntime); error.add("desc", SCannotResolveDynamically); error.add("object", getted); error.add("property", getter_name); runtime_throw(error); } operands_.push(result); break; } case i_dynamic_set: { str getter_name = constants_[i.data.value]; variant getted = pop(); variant value = pop(); variant result; if (!dynamic_set(getted, getter_name, value)) { param_list error; error.add("id", SRuntime); error.add("desc", SCannotAssignDynamically); error.add("object", getted); error.add("property", getter_name); runtime_throw(error); } operands_.push(result); break; } case i_dynamic_resolve: { str resolve_name = constants_[i.data.value]; variant resolver = operands_.top(); schema* resolver_type = true_type(resolver); schema_item itm; if (resolver_type->resolve(resolve_name, itm)) { operands_.push(itm.exec); //td: not sure this should be done exclusively for executers } else { IDynamicObject* obj = variant_cast<IDynamicObject*>(resolver, null); if (obj && obj->resolve(resolve_name, itm)) { if (!itm.exec) { param_list error; error.add("id", SRuntime); error.add("desc", SNotExecutableDynamic); error.add("object", obj); error.add("method", resolve_name); runtime_throw(error); } operands_.push(itm.exec); } else { param_list error; error.add("id", SRuntime); error.add("desc", SCannotResolveDynamically); error.add("object", obj); error.add("method", resolve_name); runtime_throw(error); } } break; } case i_load_this: { operands_.push( this_ ); break; } case i_call: { Executer call = pop(); param_list pl; variant caller; if (i.data.call_data.invert) { caller = pop(); for(int p = 0; p < i.data.call_data.param_count; p++) { pl.add(pop()); } } else { for(int p = 0; p < i.data.call_data.param_count; p++) { pl.add(pop()); } caller = pop(); } if (caller.empty()) { param_list error; error.add("id", SRuntime); error.add("desc", SCallingNull); runtime_throw(error); } void* caller_id; if (i.data.call_data.is_dynamic) { IDynamicObject* obj = variant_cast<IDynamicObject*>(caller, null); if (obj) caller_id = obj; else caller_id = caller.get_pointer(); //revert to undynamic, there should be a better solution } else caller_id = caller.get_pointer(); variant result = call->exec(caller_id, pl); operands_.push( result ); break; } case i_this_call: { Executer call = pop(); param_list pl; for(int p = 0; p < i.data.call_data.param_count; p++) { pl.add(pop()); } void* caller_id; if (i.data.call_data.is_dynamic) { IDynamicObject* obj = this_; //td: catch type mismatch caller_id = obj; } else caller_id = this_.get_pointer(); operands_.push( call->exec(caller_id, pl) ); break; } case i_get: { Getter call = pop(); variant caller = pop(); if (caller.empty()) { param_list error; error.add("id", SRuntime); error.add("desc", SCallingNull); runtime_throw(error); } void* caller_id; if (i.data.value) { IDynamicObject* obj = caller; //td: catch type mismatch caller_id = obj; } else caller_id = caller.get_pointer(); variant result = call->get(caller_id); operands_.push(result); break; } case i_set: { Setter call = pop(); variant value; variant caller; if (i.data.set_data.invert) { caller = pop(); value = pop(); } else { value = pop(); caller = pop(); } void* caller_id; if (i.data.set_data.is_dynamic) { IDynamicObject* obj = caller; //td: catch type mismatch caller_id = obj; } else caller_id = caller.get_pointer(); call->set(caller_id, value); break; } case i_instantiate: { schema* type = pop(); param_list pl; for(int p = 0; p < i.data.value; p++) { pl.add(pop()); } variant result; if (type->create(result, &pl)) operands_.push(result); else { param_list error; error.add("id", SRuntime); error.add("desc", STypeDoesNotInstantiate); runtime_throw(error); } break; } case i_dispatch: { event_info ev = pop(); IDynamicObject* caller = pop(); param_list pl; for(int p = 0; p < i.data.value; p++) { pl.add(pop()); } caller->dispatch_event(ev.id, pl); break; } case i_nop: break; default: assert(false); //say wha } if (!jump_) pc_++; jump_ = false; } return variant(); }
int main() { Engine* engine = new Engine(); Executer* executer = new Executer(); Parser* parser = new Parser(); string q1 = "a <- Project (Animal, Number) animals;"; string q2 = "a <- cross1 * cross2"; string q3 = "a <- cross1 - cross3"; string q4 = "a <- cross1 + cross2;"; string q5 = "a<- j1 JOIN j2"; //all test queries above this function correctly string q6 = ""; string createTest = "CREATE TABLE Teams (id INTEGER, favnum INTEGER, state INTEGER) PRIMARY KEY (id)"; string insertTest = "INSERT INTO Students VALUES FROM (Mouse, 12345665, Mexico)"; string insertTest2 = "INSERT INTO Mammals VALUES FROM (Mouse, 12345665, Mexico)"; string DiffTest = "a <- All_Warriors - Warriors_Starters;"; engine->open("join1.txt"); engine->changeRelationName(0, "j1"); engine->show("j1"); engine->open("join2.txt"); engine->changeRelationName(1, "j2"); engine->show("j2"); vector<int> theVec; // To test use the different hardcoded strings to parse first. //vector<Token> tok = parser->splitInput(q1); //vector<Token> tok = parser->splitInput(insertTest2); vector<Token> tokenvec = parser->splitInput(q5); //vector<Token> tokenvec0 = parser->splitInput(q2); Executer* exec = new Executer(); exec->execute(engine, tokenvec); /*for(int i = 0; i < tok.size(); i++){ cout << "tok value: " << tok.at(i).getValue() << "\t" << tok.at(i).getTokenType() << endl; } cout << endl; for(int j =0; j < tokenvec.size(); j++){ cout << "token value: " << tokenvec.at(j).getValue() << "\t" << tokenvec.at(j).getTokenType() << endl; }*/ //engine->show("Students"); //engine->show("Mammals"); //engine->show("Teams"); //engine->show("projection"); //engine->show("Students"); /*cout << "Running" << endl; while (true) { string line; getline(cin, line); // temp if (line == "q" || line == "quit") return 0; else if (line == "h" || line == "help") help(); // parsing vector<int> conditions; parser->splitInput (line, conditions); // create condition tree // executer executer->execute (engine, parser->getTokenVector().at(0)); // NOT ALWAYS ZERO! }*/ }
int Parser::execute() { // If I use my imagination hard enough // this will magically work // every odd number is a connector (besides the last one); // 0 and even numbers are the commands int status = 0; unsigned int i = 0; Executer E; // if user puts "ls test ||" or "echo test &&", etc // then prompt the user ">" and another command if ((cmd.size() != 1) && ((cmd.back() == "||") || (cmd.back() == "&&"))) { string cmd; cout << ">"; getline(cin, cmd); setCommand(cmd); parse(); } //for(unsigned int i = 0; i < cmd.size(); i++) // cout << i << ": " << cmd.at(i) << endl; //for(unsigned int i = 0; i < test.size(); i++) // cout << test[i] << endl; //for(unsigned int i = 0; i < cmd.size(); i++) // cout << cmd[i] << endl; // this loop analyzes the connectors // and determines what gets runned while(i < cmd.size()) { E.setCount(i); this->bPtr = &E; status = bPtr->execute(); if(status == -1) // if status is -1 then "exit was inputted" { // so we want to exit rshell program return status; } // should on on connector now // b/c connectors are on odd numbers i++; if(i >= cmd.size()) { return status; } if(cmd.at(i) == ";") { //cout << "Before i++" << endl; i++; //cout << "After i++" << endl; } // if next one is && move to the next one if // previous worked else if(cmd.at(i) == "&&") { // if previous worked if(status == 0) { i++; // go to the next command } else { i+=3; // moves on to next connector } } else if(cmd.at(i) == "||") { // if previous failed if(status == 149) { i++; // go to the next command } else { i+=3; } } //cout << "i after everything: " << i << endl; if(isOdd(i) || i > cmd.size()) { //cout << "goes here" << endl; return status; } } return status; }
void executeInt(Executer &executer) { executer.setTop(std::floor(executer.topDbl())); }
void executeRnd(Executer &executer) { executer.push(executer.getRandomNumber()); }
void main(void) { Lexer objLex; objLex.Init(); while (true) { string strInput = ""; while (strInput.empty()) { cout << "Input a filename or 'q' to quit: "; if (!getline(cin,strInput) || strInput == "q") { strInput = ""; break; } } // User typed "q" if it's empty (got here with "break") if (strInput.empty()) break; if (!objLex.Open(strInput.c_str())) { cout << "Error opening file: " << strInput << endl; continue; } Parser objParse(&objLex); bool created = false; try { if (objParse.Validate()) { created = true; Executer exe; exe.Execute(objParse.lstParseTree); //cout << exe.symTable << endl << endl; vector<DataValue>::iterator it; } else { cout << "Invalid source file, parse tree was not created." << endl; } } catch (Token objToken) { cout << "Lexer Error: " << objToken.dtValue << endl; } /*if (!created) { string strTemp; do { cout << "Would you like to view the partial parse-tree (y/n)? "; cin >> strTemp; cin.ignore(); cin.clear(); } while (strTemp!="y"&&strTemp!="Y"&&strTemp!="n"&&strTemp!="N"); if (tolower(strTemp[0]) == 'y') objParse.PrintTree(cout); }*/ objLex.Close(); cout << "End of file." << endl; } }
int main() { Executer exe; exe.execute(); }
void executeFix(Executer &executer) { executer.setTop(std::trunc(executer.topDbl())); }