/** Main function argv - command line arguments argc - number of arguments **/ int main(char** argv, int argc) { Array command=(Array){NULL,0}; while (1) { //Write a user prompt, unless there's multiple simple commands in one line of input if ( command.c==NULL || !isBooleanOperator(command.c[command.length-1].str) ){ write(0,">",1); } //Read the command in command = readCommand(); //If exit is the command called, quit running if (strcmp(command.c[0].str, "exit") == 0){ break; } //Run the process int status = processMgmt(command); int consume=1; //If there's a boolean operator, decide if you need to ignore the next command while ( isBooleanOperator(command.c[command.length-1].str) && consume){ switch (command.c[command.length-1].str[0]){ case '&': if (status!=0){ command=readCommand(); } else{ consume=0; } break; case '|': if (status==0){ command=readCommand(); } else{ consume=0; } break; case ';': consume=0; break; } } } write(0,"Good bye.\n",10); return 0; }
// Uninterpreted predicate p : U U* -> Bool bool Logic::isUP(PTRef ptr) const { Pterm& t = term_store[ptr]; SymRef sr = t.symb(); // Should this really be an uninterpreted predicate? // At least it falsely identifies (= true false) as an uninterpreted // predicate without the extra condition if (isEquality(sr) || isDisequality(sr)) { if (isBooleanOperator(sr)) return false; else return true; } Symbol& sym = sym_store[sr]; if (sym.nargs() == 0) return false; if (sym.rsort() != getSort_bool()) return false; if (isBooleanOperator(sr)) return false; return true; }
PTRef Logic::insertTerm(SymRef sym, vec<PTRef>& terms, const char** msg) { PTRef res; if (terms.size() == 0) { if (term_store.cterm_map.contains(sym)) res = term_store.cterm_map[sym]; else { res = term_store.pta.alloc(sym, terms); term_store.cterm_map.insert(sym, res); } } else if (!isBooleanOperator(sym)) { if (sym_store[sym].commutes()) { sort(terms, LessThan_PTRef()); } if (!sym_store[sym].left_assoc() && !sym_store[sym].right_assoc() && !sym_store[sym].chainable() && !sym_store[sym].pairwise() && sym_store[sym].nargs() != terms.size_()) { *msg = e_argnum_mismatch; return PTRef_Undef; } PTLKey k; k.sym = sym; terms.copyTo(k.args); if (term_store.cplx_map.contains(k)) res = term_store.cplx_map[k]; else { res = term_store.pta.alloc(sym, terms); term_store.cplx_map.insert(k, res); } } else { // Boolean operator PTLKey k; k.sym = sym; terms.copyTo(k.args); if (term_store.bool_map.contains(k)) { res = term_store.bool_map[k]; #ifdef SIMPLIFY_DEBUG char* ts = printTerm(res); cerr << "duplicate: " << ts << endl; ::free(ts); #endif } else { res = term_store.pta.alloc(sym, terms); term_store.bool_map.insert(k, res); #ifdef SIMPLIFY_DEBUG char* ts = printTerm(res); cerr << "new: " << ts << endl; ::free(ts); #endif } } return res; }
int processMgmt(Array command){ pid_t process = fork(); if (process<0){ return (int)process; } else if (process==0){ if (command.c[0].str[0]!='/'){ //Relative path char *pathList = getenv("PATH"); char *path = strtok(pathList,":"); char *temp; do{ temp = malloc(sizeof(char)*(command.c[0].length+strlen(path))); temp = strcpy(temp,path); strcat(temp,"/"); strcat(temp,command.c[0].str); } while (!isCommand(temp) && (path=strtok(NULL,":"))!=NULL ); if (path!=NULL){ command.c[0].str = temp; } } int argc=command.length+1; if (isBooleanOperator(command.c[command.length-1].str)){ argc--; } { char *args[argc]; int i; for (i=0;i<argc-1;i++){ args[i]=command.c[i].str; } args[i]=0; int status = execve(command.c[0].str,args,environ); } write(0,command.c[0].str,command.c[0].length); write(0,": command not found\n",20); exit(-1); } else if (process>0){ int status; waitpid(process,&status,0); return status; } return -1; }
// // Sort a term if it commutes. // The following simplifications implemented // (should be refactored to separate methods?): // - `and': // - drop constant true terms // - convert an empty `and' to the constant term `true' // - convert an `and' containing `false' to a replicate `false' // - `or': // - drop constant false terms // - convert an empty `or' to a replicate `false' term // - convert an `or' containing `true' to a replicate `true' // // void Logic::simplify(SymRef& s, vec<PTRef>& args) { // First sort it #ifdef SORT_BOOLEANS if (sym_store[s].commutes()) #else if (sym_store[s].commutes() && !isAnd(s) && !isOr(s)) #endif sort(args, LessThan_PTRef()); if (!isBooleanOperator(s) && !isEquality(s)) return; int dropped_args = 0; bool replace = false; if (s == getSym_and()) { int i, j; PTRef p = PTRef_Undef; for (i = j = 0; i < args.size(); i++) { if (args[i] == getTerm_false()) { args.clear(); s = getSym_false(); #ifdef SIMPLIFY_DEBUG cerr << "and -> false" << endl; #endif return; } else if (args[i] != getTerm_true() && args[i] != p) { args[j++] = p = args[i]; } else { #ifdef SIMPLIFY_DEBUG cerr << "and -> drop" << endl; #endif } } dropped_args = i-j; if (dropped_args == args.size()) { s = getSym_true(); args.clear(); #ifdef SIMPLIFY_DEBUG cerr << "and -> true" << endl; #endif return; } else if (dropped_args == args.size() - 1) replace = true; else if (dropped_args > 0) args.shrink(dropped_args); } if (s == getSym_or()) { int i, j; PTRef p = PTRef_Undef; for (i = j = 0; i < args.size(); i++) { if (args[i] == getTerm_true()) { args.clear(); s = getSym_true(); #ifdef SIMPLIFY_DEBUG cerr << "or -> true" << endl; #endif return; } else if (args[i] != getTerm_false() && args[i] != p) { args[j++] = p = args[i]; } else { #ifdef SIMPLIFY_DEBUG cerr << "or -> drop" << endl; #endif } } dropped_args = i-j; if (dropped_args == args.size()) { s = getSym_false(); args.clear(); #ifdef SIMPLIFY_DEBUG cerr << "or -> false" << endl; #endif return; } else if (dropped_args == args.size() - 1) replace = true; else if (dropped_args > 0) args.shrink(dropped_args); } if (isEquality(s)) { assert(args.size() == 2); if (isBooleanOperator(s) && (args[0] == getTerm_true())) { Pterm& t = getPterm(args[1]); s = t.symb(); args.clear(); for (int i = 0; i < t.size(); i++) args.push(t[i]); #ifdef SIMPLIFY_DEBUG cerr << "eq -> second" << endl; #endif return; } else if (isBooleanOperator(s) && (args[0] == getTerm_false())) { PTRef old = args[1]; PTRef tr = mkNot(args[1]); Pterm& t = getPterm(tr); s = t.symb(); args.clear(); args.push(old); #ifdef SIMPLIFY_DEBUG cerr << "eq -> not second" << endl; #endif return; } else if (isBooleanOperator(s) && (args[1] == getTerm_true())) { args.clear(); Pterm& t = getPterm(args[0]); s = t.symb(); args.clear(); for (int i = 0; i < t.size(); i++) args.push(t[i]); #ifdef SIMPLIFY_DEBUG cerr << "eq -> first" << endl; #endif return; } else if (isBooleanOperator(s) && (args[1] == getTerm_false())) { PTRef old = args[0]; PTRef tr = mkNot(args[0]); Pterm& t = getPterm(tr); s = t.symb(); args.clear(); args.push(old); #ifdef SIMPLIFY_DEBUG cerr << "eq -> not first"<< endl; #endif return; } else if (args[0] == args[1]) { args.clear(); s = getSym_true(); #ifdef SIMPLIFY_DEBUG cerr << "eq -> true" << endl; #endif return; } else if (isBooleanOperator(s) && (args[0] == mkNot(args[1]))) { args.clear(); s = getSym_false(); #ifdef SIMPLIFY_DEBUG cerr << "eq -> false" << endl; #endif return; } } if (isNot(s)) { if (isTrue(args[0])) { args.clear(); s = getSym_false(); #ifdef SIMPLIFY_DEBUG cerr << "not -> false" << endl; #endif return; } if (isFalse(args[0])) { args.clear(); s = getSym_true(); #ifdef SIMPLIFY_DEBUG cerr << "not -> true" << endl; #endif return; } } // Others, to be implemented: // - distinct // - implies // - xor // - ite if (replace) { // Return whatever is the sole argument Pterm& t = getPterm(args[0]); s = t.symb(); args.clear(); for (int i = 0; i < t.size(); i++) args.push(t[i]); #ifdef SIMPLIFY_DEBUG cerr << " replace" << endl; #endif } }
// // This method is currently under development // lbool Logic::simplifyTree(PTRef tr) { vec<pi> queue; Map<PTRef,bool,PTRefHash> processed; queue.push(pi(tr)); lbool last_val = l_Undef; while (queue.size() != 0) { // First find a node with all children processed. int i = queue.size()-1; if (processed.contains(queue[i].x)) { queue.pop(); continue; } bool unprocessed_children = false; if (queue[i].done == false) { #ifdef SIMPLIFY_DEBUG cerr << "looking at term num " << queue[i].x.x << endl; #endif Pterm& t = getPterm(queue[i].x); for (int j = 0; j < t.size(); j++) { PTRef cr = t[j]; if (!processed.contains(cr)) { unprocessed_children = true; queue.push(pi(cr)); #ifdef SIMPLIFY_DEBUG cerr << "pushing child " << cr.x << endl; #endif } } queue[i].done = true; } if (unprocessed_children) continue; #ifdef SIMPLIFY_DEBUG cerr << "Found a node " << queue[i].x.x << endl; cerr << "Before simplification it looks like " << term_store.printTerm(queue[i].x) << endl; #endif // (1) Check if my children (potentially simplified now) exist in // term store and if so, replace them with the term store // representative // (2) Simplify in place // (3) See if the simplifications resulted in me changing, and if so, // look up from the table whether I'm already listed somewhere and add // a mapping to the canonical representative, or create a new entry for // me in the map. Pterm& t = getPterm(queue[i].x); // (1) #ifdef SIMPLIFY_DEBUG if (t.size() > 0) cerr << "Now looking into the children of " << queue[i].x.x << endl; else cerr << "The node " << queue[i].x.x << " has no children" << endl; #endif for (int e = 0; e < t.size(); e++) { PTRef cr = t[e]; #ifdef SIMPLIFY_DEBUG cerr << "child n. " << e << " is " << cr.x << endl; #endif assert(cr != queue[i].x); Pterm& c = getPterm(cr); PTLKey k; k.sym = c.symb(); for (int j = 0; j < c.size(); j++) k.args.push(c[j]); if (!isBooleanOperator(k.sym)) { assert(term_store.cplx_map.contains(k)); #ifdef SIMPLIFY_DEBUG cerr << cr.x << " is not a boolean operator "; cerr << "and it maps to " << term_store.cplx_map[k].x << endl; #endif t[e] = term_store.cplx_map[k]; assert(t[e] != queue[i].x); } else { assert(term_store.bool_map.contains(k)); #ifdef SIMPLIFY_DEBUG cerr << cr.x << " is a boolean operator" << " and it maps to " << term_store.bool_map[k].x << endl; #endif t[e] = term_store.bool_map[k]; assert(t[e] != queue[i].x); } } #ifdef SIMPLIFY_DEBUG cerr << "After processing the children ended up with node " << term_store.printTerm(queue[i].x, true) << endl; #endif // (2) Simplify in place PTRef orig = queue[i].x; // We need to save the original type in case the term gets simplified simplify(queue[i].x); #ifdef SIMPLIFY_DEBUG cerr << "-> which was now simplified to " << term_store.printTerm(queue[i].x, true) << endl; // I don't seem to remember why this should be true or false? // if (orig != queue[i].x) { // assert(isTrue(queue[i].x) || isFalse(queue[i].x)); // assert(isAnd(orig) || isOr(orig) || isEquality(orig) || isNot(orig)); // } #endif processed.insert(orig, true); // Make sure my key is in term hash #ifdef SIMPLIFY_DEBUG cerr << "Making sure " << orig.x << " is in term_store hash" << endl; cerr << "Pushing symb " << t.symb().x << " to hash key" << endl; #endif PTLKey k; k.sym = t.symb(); for (int j = 0; j < t.size(); j++) { #ifdef SIMPLIFY_DEBUG cerr << "Pushing arg " << t[j].x << " to hash key" << endl; #endif k.args.push(t[j]); } if (!isBooleanOperator(k.sym)) { if (!term_store.cplx_map.contains(k)) { term_store.cplx_map.insert(k, queue[i].x); #ifdef SIMPLIFY_DEBUG cerr << "sym " << k.sym.x << " args <"; for (int j = 0; j < k.args.size(); j++) { cerr << k.args[j].x << " "; } cerr << "> maps to " << term_store.cplx_map[k].x << endl; #endif } PTRef l = term_store.cplx_map[k]; // This is being kept on record in case the root term gets simplified if (isTrue(l)) last_val = l_True; else if (isFalse(l)) last_val = l_False; else last_val = l_Undef; } else { if (!term_store.bool_map.contains(k)) { term_store.bool_map.insert(k, queue[i].x); #ifdef SIMPLIFY_DEBUG cerr << "sym " << k.sym.x << " args "; for (int j = 0; j < k.args.size(); j++) { cerr << k.args[j].x << " "; } cerr << "maps to " << term_store.bool_map[k].x << endl; #endif } PTRef l = term_store.bool_map[k]; // This is being kept on record in case the root term gets simplified if (isTrue(l)) last_val = l_True; else if (isFalse(l)) last_val = l_False; else last_val = l_Undef; } queue.pop(); } return last_val; }