def insertAssign(C6, v, etree): """updates the store of C6 with an assignment. If v already exists in C6's store, saves former value as v_old for later use in proof reasoning. params: v - has form, ["var", s] or ["index", ["var", s], etree] etree - another etree, to be assigned to the var. """ sigma = C6["store"] heap = C6["heap"] badvars = C6["novars"] if v[0] == "var" : vtree = v elif v[0] == "index" : vtree = v[1] vold = Parse.makeOldVar(vtree) # ["var", vname_old] # first, check if we are allowed to update v: if (vtree in badvars) : error("you may not update a protected global var outside of its maintenance function") return # if possible, rename current value of var v as v_old: if v[0] == "var" and v[1] in sigma : # and lookupType(C6, v[1]) != "array": sigma[vold[1]] = sigma[v[1]] # assign v's current value to v_old elif v[0] == "index" and lookupType(C6, v[1][1]) == "array": vname = v[1][1] loc = PE.peToTuple(sigma[vname]) length = heap[loc][0] vector = heap[loc][1] # make copy: copy = {} for k in vector : copy[k] = vector[k] # assign original to v_old and copy to v : sigma[vold[1]] = sigma[vname] newloc = PE.make(PE.makeSym()) sigma[vname] = newloc heap[ PE.peToTuple(newloc) ] = (length, copy) # (later, vold will be erased from sigma....) # now, eval assignment's rhs and store it into v: rhs = PE.evall(C6, etree) if v[0] == "var": # simple var sigma[v[1]] = rhs elif v[0] == "index": # an array/list reference # eval index expression (NOTE: no nested indexing allowed): indexpe = PE.evall(C6, v[2]) # save values in sigma[vname][1] provably distinct from vname[index]: vname = v[1][1] if vname not in sigma or lookupType(C6, vname) != "array" : error(vname + " is not an array in the store") #sigma[vname] = PE.makeArray() else : vmap = heap[PE.peToTuple(sigma[vname])][1] saveDistinctElements(C6, vmap, indexpe) vmap[PE.peToTuple(indexpe)] = rhs
def insertAppend(C6, v, e) : """appends e to the end of array/list v in the heap. Does the same actions as an insertAssign to an indexed array, but preserves more heap info since the append does not produce any aliases within v params : C6; v - a vartee; e - an etree """ sigma = C6["store"] heap = C6["heap"] vname = v[1] vold = Parse.makeOldVar(v) if lookupType(C6, vname) != "array" : error("cannot append to a non-list/array") else : loc = PE.peToTuple(sigma[vname]) length = heap[loc][0] newlength = PE.add(length, PE.make(1)) vector = heap[loc][1] # assign original to v_old: sigma[vold[1]] = sigma[vname] # make copy for the new value of v: copy = {} for k in vector : copy[k] = vector[k] newloc = PE.make(PE.makeSym()) rhs = PE.evall(C6, e) copy[ PE.peToTuple(length) ] = rhs sigma[vname] = newloc heap[ PE.peToTuple(newloc) ] = (newlength, copy)
def verifyRelation(C6, bfactlist, bgoal) : """attempts to verify bgoal, which is a primitive (relop or forall) params: C6 table bfactlist: a list of facts of form [relop, e1, e2] or [forall/exists, lo, i, hi, e] bgoal: a single fact of form [relop, e1, e2] or [forall/exists, lo, i, hi, e] returns : True, if bfactlist |- bgoal is proved False, if not """ #print "verifyRelation: C6"#, C6 #print "bfactlist:", bfactlist #print "bgoal:", bgoal #raw_input("press Enter") if (bgoal[0] in RELOPS) : # [relop, e1, e2] # eval goal: pe1 = PE.evall(C6, bgoal[1]) pe2 = PE.evall(C6, bgoal[2]) goal = [bgoal[0], pe1, pe2] # eval all facts in the bfactlist: factlist = [] for f in list(bfactlist) : if f[0] in RELOPS : pe1 = PE.evall(C6, f[1]) pe2 = PE.evall(C6, f[2]) factlist.append([f[0], pe1, pe2]) elif f[0] in ("forall", "exists") : pass # can't handle quantified phrases (yet) in PE! # If I am brave, I might try to evaluate lower and upper # bounds of quantification and enumerate the facts therein. # But this is high overhead.... # send off the PE-valued facts and goal to the prover: #print "In verifyrelation; ready to call PE.prove:" #print "all facts=", factlist + C6["rels"] #print "goal=", goal return PE.prove(factlist + C6["rels"], goal) elif bgoal[0] == "forall" : return proveUniversal(C6, bfactlist, bgoal) else : # ["exists", lo, i, hi, e] ??? return False
def insertRelation(C6, btree): """extracts all [RELOP, e1, e2]-relations asserted within btree and places them into the rels table in C6 params: C6 table and btree """ #sigma = C6["store"] # eval all facts in the bfactlist: cnffact = NF.cnf(btree) # returns a list of disjunctive clauses # save any disjunctive clause that is exactly [[RELOP, b1, b2]]: for clause in cnffact : if len(clause) == 1 and clause[0][0] in RELOPS : relop = clause[0][0] pe1 = PE.evall(C6, clause[0][1]) pe2 = PE.evall(C6, clause[0][2]) if pe1 != {} and pe2 != {} : newrel = [relop, pe1, pe2] if newrel not in C6["rels"] : C6["rels"] = [newrel] + C6["rels"] # new fact at front
def reset(C6, modified_vars) : """changes C6's sigma so that new constants are generated for each var mentioned in modified_vars. param: modified_vars, a sequence of lhs-trees; can be either ["var", s] or ["index" ["var", s] pe]. IMPORTANT: in the latter case, the etree has been replaced by its pe-value """ sigma = C6["store"] heap = C6["heap"] #print "In reset" #print "store=", sigma for m in modified_vars : if m[0] == "var" and lookupType(C6, m[1]) != "array" : # simple var sigma[m[1]] = PE.make(PE.makeSym()) elif m[0] == "var" and lookupType(C6, m[1]) == "array" : arrayname = m[1] newarray = PE.makeArray() newloc = PE.make(PE.makeSym()) sigma[m[1]] = newloc heap[PE.peToTuple(newloc)] = newarray elif m[0] == "index" or m[0] == "len" : vname = m[1][1] loc = PE.peToTuple(sigma[vname]) length = heap[loc][0] vector = heap[loc][1] # make copy: copy = {} for k in vector : copy[k] = vector[k] newloc = PE.make(PE.makeSym()) if m[0] == "index" : # indexed var ["index" ["var", s] pe] saveDistinctElements(C6, copy, PE.evall(C6, m[2])) elif m[0] == "len": # ["len", ["var", s]], as a result of append length = PE.make(PE.makeSym()) sigma[vname] = newloc heap[PE.peToTuple(newloc)] = (length, copy)