def SymbolicComprehensionSet_generator(self): varList = self.variable_list pred = self.predicate env = self.env interpret = self.interpret names = [x.idName for x in varList] env.push_new_frame(varList) domain_generator = self.domain_generator(pred, env, varList) for entry in domain_generator: for name in names: value = entry[name] env.set_value(name, value) try: if USE_RPYTHON_CODE: bool = interpret(pred, env).bvalue else: bool = interpret(pred, env) if bool: # test i = 0 name = names[0] tup = env.get_value(name) for name in names[1:]: value = env.get_value(name) i = i + 1 if USE_RPYTHON_CODE: tup = W_Tuple((tup, value)) else: tup = tuple([tup,value]) env.pop_frame() yield tup env.push_new_frame(varList) except ValueNotInDomainException: continue env.pop_frame()
def enumerate_all(self): if not self.explicit_set_computed: result = frozenset([]) varList = self.variable_list pred = self.predicate expr = self.expression env = self.env interpret = self.interpret node = self.node names = [x.idName for x in varList] # new scope env.push_new_frame(varList) domain_generator = self.domain_generator(pred, env, varList) for entry in domain_generator: for name in names: value = entry[name] env.set_value(name, value) try: tst = interpret(pred, env) if USE_RPYTHON_CODE: cond = tst.bvalue else: cond = tst if cond: # test (|= ior) aSet = interpret(expr, env) if isinstance(aSet, SymbolicSet): aSet = aSet.enumerate_all() result = result.union(aSet) except ValueNotInDomainException: continue env.pop_frame() self.explicit_set_repr = result self.explicit_set_computed = True return self.explicit_set_repr
def _try_all_values(root, env, idNodes, allNodes): if USE_RPYTHON_CODE: from rpython_interp import interpret else: from interp import interpret node = idNodes[0] all_values = enum_all_values_by_type(env, node) #print "trying", node.idName, all_values, pretty_print(root) if len(idNodes)<=1: for val in all_values: try: env.set_value(node.idName, val) #print "trying:" #for name in [n.idName for n in allNodes]: # print name, "=", env.get_value(name) if USE_RPYTHON_CODE: w_bool = interpret(root, env) if w_bool.bvalue: yield True else: if interpret(root, env): yield True except ValueNotInDomainException: continue else: for val in all_values: env.set_value(node.idName, val) gen = _try_all_values(root, env, idNodes[1:], allNodes) if gen.next(): yield True yield False
def __eq__(self, other): # check importent special case first # %(x,y).(x:S & y:T|y) = prj2(S,T) if isinstance(other, SymbolicLambda): if not len(other.variable_list)==2: return False if isinstance(other.predicate, AConjunctPredicate): belong_pred0 = other.predicate.children[0] belong_pred1 = other.predicate.children[1] if isinstance(belong_pred0, AMemberPredicate) and isinstance(belong_pred1, AMemberPredicate): x = other.variable_list[0].idName y = other.variable_list[1].idName xx = belong_pred0.children[0] yy = belong_pred1.children[0] if USE_RPYTHON_CODE: from rpython_interp import interpret else: from interp import interpret if isinstance(xx, AIdentifierExpression) and xx.idName==x: S = interpret(belong_pred0.children[1], self.env) if isinstance(yy, AIdentifierExpression) and yy.idName==y: T = interpret(belong_pred1.children[1], self.env) if isinstance(other.expression, AIdentifierExpression): # else: maybe equal. try: if self.left_set==S and self.right_set==T and y==other.expression.idName: return True except NameError: pass # maybe equal. use brute-force in symbolic set return SymbolicSet.__eq__(self, other)
def _run_model_checking_mode(env, mch): inv = mch.aInvariantMachineClause s_space = env.state_space while not env.state_space.empty(): # FIXME: dirty fix to avoid invariant checking of set up states if env.state_space.get_state().opName=="set up": env.state_space.undo() continue jitdriver.jit_merge_point(inv=inv, s_space=s_space, env=env, mch=mch) if not DISABLE_INVARIANT_MC_CHECK: w_bool = inv.eval(env) # 7. model check if not w_bool.bvalue: print "WARNING: invariant violation found after checking", len(env.state_space.seen_states),"states" violation = env.state_space.get_state() violation.print_bstate() #print env.state_space.history return -1 if EVAL_CHILD_INVARIANT: bstate = env.state_space.get_state() for bmachine in bstate.bmch_list: if not bmachine is None and not bmachine.mch_name==mch.mch_name : w_bool = interpret(bmachine.aInvariantMachineClause, env) if not w_bool.bvalue: print "WARNING: invariant violation in",bmachine.mch_name ," found after checking", len(env.state_space.seen_states),"states" return False next_states = calc_next_states(env, mch) s_space.undo() schedule_new_states(next_states, s_space) print "checked",len(s_space.seen_states),"states.\033[1m\033[92m No invariant violation found.\033[00m" if DISABLE_INVARIANT_MC_CHECK: print "invariant check was disabled" return 0
def test_genAST_sub_let2(self): string = ''' MACHINE Test VARIABLES X, Y INVARIANT X:NAT & Y:NAT INITIALISATION BEGIN X:=10; LET r1, X BE X = 6 & r1 = X / 2 IN Y := r1 END END END''' string_to_file(string, file_name) ast_string = file_to_AST_str(file_name) root = str_ast_to_python_ast(ast_string) # Test env = Environment() env._min_int = -1 env._max_int = 5 mch = parse_ast(root, env) type_check_bmch(root, env, mch) # also checks all included, seen, used and extend arbitrary_init_machine(root, env, mch) # init VARIABLES and eval INVARIANT assert isinstance(root.children[2], AInvariantMachineClause) assert interpret(root.children[2], env) assert env.get_value("X")==10 assert env.get_value("Y")==3
def test_genAST_sub_let(self): string = ''' MACHINE Test VARIABLES SumR, DifferenceR, Var1, Var2 INVARIANT SumR:NAT & DifferenceR:NAT & Var1:NAT & Var2:NAT INITIALISATION BEGIN Var1:=2; Var2:=3; LET r1, r2 BE r1 = (Var1 + Var2) / 2 & r2 = (Var1 - Var2) / 2 IN SumR := r1 + r2 || DifferenceR := r1 - r2 END END END''' string_to_file(string, file_name) ast_string = file_to_AST_str(file_name) root = str_ast_to_python_ast(ast_string) # Test env = Environment() env._min_int = -1 env._max_int = 5 mch = parse_ast(root, env) type_check_bmch(root, env, mch) # also checks all included, seen, used and extend arbitrary_init_machine(root, env, mch) # init VARIABLES and eval INVARIANT assert isinstance(root.children[2], AInvariantMachineClause) assert interpret(root.children[2], env) assert env.get_value("SumR")==1 assert env.get_value("DifferenceR")==3 assert env.get_value("Var1")==2 assert env.get_value("Var2")==3
def test_genAST_sub_any(self): string = ''' MACHINE Test VARIABLES xx INVARIANT xx:NAT INITIALISATION BEGIN xx:=1; ANY r1, r2 WHERE r1 : NAT & r2 : NAT & r1*r1 + r2*r2 = 25 THEN xx := r1 + r2 END END END''' string_to_file(string, file_name) ast_string = file_to_AST_str(file_name) root = str_ast_to_python_ast(ast_string) # Test env = Environment() env._min_int = -1 env._max_int = 5 mch = parse_ast(root, env) type_check_bmch(root, env, mch) # also checks all included, seen, used and extend arbitrary_init_machine(root, env, mch) # init VARIABLES and eval INVARIANT assert isinstance(root.children[2], AInvariantMachineClause) assert interpret(root.children[2], env) assert env.get_value("xx")==5 or env.get_value("xx")==7 # 3+4 or 5+0
def test_genAST_sub_var(self): # Build AST string = ''' MACHINE Test VARIABLES xx INVARIANT xx:NAT INITIALISATION BEGIN xx:=1; VAR varLoc1, varLoc2 IN varLoc1 := xx + 1 ; varLoc2 := 2 * varLoc1 ; xx := varLoc2 END END END''' string_to_file(string, file_name) ast_string = file_to_AST_str(file_name) root = str_ast_to_python_ast(ast_string) # Test env = Environment() env._min_int = -1 env._max_int = 5 mch = parse_ast(root, env) type_check_bmch(root, env, mch) # also checks all included, seen, used and extend arbitrary_init_machine(root, env, mch) # init VARIABLES and eval INVARIANT assert isinstance(root.children[2], AInvariantMachineClause) assert interpret(root.children[2], env) assert env.get_value("xx")==4
def test_genAST_sub_case3(self): # Build AST string = ''' MACHINE Test VARIABLES xx INVARIANT xx:NAT INITIALISATION BEGIN xx:=1; CASE 1+1 OF EITHER 4,5,6 THEN xx:=2 OR 7,8,9 THEN xx:=3 ELSE xx:=4 END END END END''' string_to_file(string, file_name) ast_string = file_to_AST_str(file_name) root = str_ast_to_python_ast(ast_string) # Test env = Environment() mch = parse_ast(root, env) type_check_bmch(root, env, mch) # also checks all included, seen, used and extend arbitrary_init_machine(root, env, mch) # init VARIABLES and eval INVARIANT assert isinstance(root.children[2], AInvariantMachineClause) assert interpret(root.children[2], env) assert env.get_value("xx")==4
def enumerate_all(self): if not self.explicit_set_computed: varList = self.variable_list pred = self.predicate env = self.env interpret = self.interpret names = [x.idName for x in varList] result = [] # new scope self.env.push_new_frame(varList) domain_generator = self.domain_generator(pred, env, varList) for entry in domain_generator: for name in names: value = entry[name] env.set_value(name, value) try: if USE_RPYTHON_CODE: bool = interpret(pred, env).bvalue else: bool = interpret(pred, env) if bool: # test i = 0 name = names[0] tup = env.get_value(name) for name in names[1:]: value = env.get_value(name) i = i + 1 if USE_RPYTHON_CODE: tup = W_Tuple((tup, value)) else: tup = tuple([tup,value]) result.append(tup) except ValueNotInDomainException: continue env.pop_frame() # will return empty set if predicate unfulfillable self.explicit_set_repr = frozenset(result) self.explicit_set_computed = True return self.explicit_set_repr
def run_checking_mode(): env = Environment() # 1. create env. file_name_str, solution_file_name_str = read_input_string(argv, 1) # 2. read filenames ast_string, error = file_to_AST_str_no_print(file_name_str) # 3. parse input-file to string if error: print error #env.set_search_dir(file_name_str) root = str_ast_to_python_ast(ast_string) # 4. parse string to python ast TODO: JSON #if solution_file_name_str: # 5. parse solution-file and write to env. # read_solution_file(env, solution_file_name_str) # The concreate solution values are added at # the bmachine object-init time to the respective mch # 6. replace defs and extern-functions inside mch and solution-file (if present) parse_object = remove_defs_and_parse_ast(root, env) # 7. which kind of ast? if not isinstance(parse_object, BMachine): # #PREDICATE or #EXPRESSION result = interpret(parse_object.root, env) # eval predicate or expression print result else: assert isinstance(parse_object, BMachine) # 8. typecheck type_check_root_bmch(root, env, parse_object) # also checks all included, seen, used and extend mch = parse_object #solution_file_read = not solution_file_name_str=="" bstates = set_up_constants(root, env, mch, solution_file_read=False) # also evals properties if not bstates==[]: bool = True for bstate in bstates: env.state_space.add_state(bstate) #if mch.has_properties_mc: # assert interpret(mch.aPropertiesMachineClause, env) init_bstates = exec_initialisation(root, env, mch, not solution_file_name_str=="") for init_bstate in init_bstates: env.state_space.add_state(init_bstate) if mch.has_invariant_mc: w_bool = interpret(mch.aInvariantMachineClause, env) bool = bool and w_bool.bvalue env.state_space.undo() if mch.has_assertions_mc: interpret(mch.aAssertionsMachineClause, env) env.state_space.undo() return bool else: # TODO: dont repeat yourself init_bstates = exec_initialisation(root, env, mch, not solution_file_name_str=="") for bstate in init_bstates: env.state_space.add_state(bstate) if mch.has_invariant_mc: w_bool = interpret(mch.aInvariantMachineClause, env) assert w_bool.bvalue if mch.has_assertions_mc: interpret(mch.aAssertionsMachineClause, env) env.state_space.undo() if not init_bstates==[]: env.state_space.add_state(init_bstates[0]) return eval_Invariant(root, env, mch)
def enumerate_all(self): if not self.explicit_set_computed: if isinstance(self.left_relation, frozenset) and isinstance(self.right_relation, SymbolicLambda): result = [] lambda_function = self.right_relation self.env.push_new_frame(lambda_function.variable_list) for tup in self.left_relation: domain = tup[0] args = remove_tuples(tup[1]) for i in range(len(lambda_function.variable_list)): idNode = lambda_function.variable_list[i] #TODO: check all tuple confusion e.g x:(NAT*(NAT*NAT) # onne carttype can contain more... # set args to correct bound variable in lambda expression using type-info atype = self.env.get_type_by_node(idNode) value = build_arg_by_type(atype, args) # args-mod via sideeffect self.env.set_value(idNode.idName, value) # check if value is in lambda domain if USE_RPYTHON_CODE: from rpython_interp import interpret else: from interp import interpret pre_result = interpret(lambda_function.predicate, self.env) if pre_result: # calculate element of composition expression lambda_image = interpret(lambda_function.expression, self.env) result.append(tuple([domain, lambda_image])) self.env.pop_frame() # exit scope self.explicit_set_repr = frozenset(result) else: result = [] for e in self.SymbolicCompositionSet_generator(): result.append(e) self.explicit_set_repr = frozenset(result) self.explicit_set_computed = True return self.explicit_set_repr
def parse_repl_input(input): try: string_to_file("#EXPRESSION "+input, "temp.b") ast_string,error = file_to_AST_str_no_print("temp.b") if ast_string=="\n": raise NameError() # FIXME: refactor this line root = str_ast_to_python_ast(ast_string) except NameError: #no expression string_to_file("#PREDICATE "+input, "temp.b") ast_string, error = file_to_AST_str_no_print("temp.b") if error: result = None return result, error root = str_ast_to_python_ast(ast_string) result = interpret(root, Environment() ) #printing via side effect error = None return result, error
def test_genAST_sub_func_overw(self): # Build AST string = ''' MACHINE Test VARIABLES f INVARIANT f:POW({1,2,3}*{1,2,3}) INITIALISATION f:={(1,2),(3,4)} ; f(3) := 1+2 END''' string_to_file(string, file_name) ast_string = file_to_AST_str(file_name) root = str_ast_to_python_ast(ast_string) # Test env = Environment() mch = parse_ast(root, env) type_check_bmch(root, env, mch) # also checks all included, seen, used and extend arbitrary_init_machine(root, env, mch) # init VARIABLES and eval INVARIANT assert isinstance(root.children[2], AInvariantMachineClause) assert interpret(root.children[2], env) assert env.get_value("f")==frozenset([(1,2),(3,3)])
def _is_solution(pred, env, varList, solution): if USE_RPYTHON_CODE: from rpython_interp import interpret else: from interp import interpret env.push_new_frame(varList) # avoid side effect for key in solution: value = solution[key] # print "set",key,"to",value env.set_value(key, value) try: res = interpret(pred, env) if USE_RPYTHON_CODE: result = res.bvalue else: result = res except ValueNotInDomainException: # function app with wrong value result = False env.pop_frame() # leave frame return result
def test_genAST_sub_enum_set_as(self): string = ''' MACHINE Test SETS ID={aa,bb} VARIABLES xx INVARIANT xx:ID INITIALISATION xx:=aa END''' string_to_file(string, file_name) ast_string = file_to_AST_str(file_name) root = str_ast_to_python_ast(ast_string) # Test env = Environment() mch = parse_ast(root, env) type_check_bmch(root, env, mch) # also checks all included, seen, used and extend arbitrary_init_machine(root, env, mch) # init VARIABLES and eval INVARIANT assert isinstance(root.children[3], AInvariantMachineClause) assert interpret(root.children[3], env) assert env.get_value("xx")=="aa"
def test_genAST_sub_simple_asgn(self): # Build AST string = ''' MACHINE Test VARIABLES xx INVARIANT xx:NAT INITIALISATION xx:=3 END''' string_to_file(string, file_name) ast_string = file_to_AST_str(file_name) root = str_ast_to_python_ast(ast_string) # Test env = Environment() mch = parse_ast(root, env) type_check_bmch(root, env, mch) # also checks all included, seen, used and extend arbitrary_init_machine(root, env, mch) # init VARIABLES and eval INVARIANT assert isinstance(root.children[2], AInvariantMachineClause) assert interpret(root.children[2], env) assert env.get_value("xx")==3 assert isinstance(get_type_by_name(env, "xx"), IntegerType)
def __calc_states_and_print_ui(root, env, mch, solution_file_read): # Schneider Book page 62-64: # The parameters p make the constraints C True # #p.C # Sets St and constants k which meet the constraints c make the properties B True # C => #St,k.B if not env.set_up_done: next_states = set_up_constants(root, env, mch, solution_file_read) if len(next_states)>0: print_set_up_bstates(next_states, mch) return next_states else: # no bstates and no exception: set up to do (e.g no constants) env.set_up_done = True # If C and B is True there should be Variables v which make the Invaraiant I True # B & C => #v.I if not env.init_done: next_states = exec_initialisation(root, env, mch, solution_file_read) if len(next_states)>0: undo_possible = not env.state_space.empty() print_init_bstates(next_states, mch, undo_possible) return next_states else: # no bstates and no exception: no init to do (e.g no variables) env.init_done = True print mch.mch_name," - Invariant:", eval_Invariant(root, env, mch) # TODO: move print to animation_clui if EVAL_CHILD_INVARIANT: bstate = env.state_space.get_state() for bmachine in bstate.bmch_list: if not bmachine is None and not bmachine.mch_name==mch.mch_name : print bmachine.mch_name, " - Invariant:", interpret(bmachine.aInvariantMachineClause, env) bstate_lst = calc_next_states(env, mch) show_ui(env, mch, bstate_lst) next_states = [] for n in bstate_lst: # all other data inside bstate_lst has already been processed by show_ui next_states.append(n.bstate) return next_states
def _abstr_eval(node, env): # print node if isinstance(node, ABoolSetExpression): return 2 elif isinstance(node, APowSubsetExpression) or isinstance(node, APow1SubsetExpression): time = _abstr_eval(node.children[0], env) # if time>=math.log(TOO_MANY_ITEMS,2): if time >= 22: # FIXME: math.log is not rpython return TOO_MANY_ITEMS else: # RPython does not support 2**(time) assert time >= 0 result = 1 for i in range(time): result = result * 2 return result # NATURAL, NATURAL1, INTEGER, STRING elif ( isinstance(node, AIntegerSetExpression) or isinstance(node, ANaturalSetExpression) or isinstance(node, ANatural1SetExpression) or isinstance(node, AStringSetExpression) ): raise InfiniteConstraintException("") # TODO: infinite exception # return TOO_MANY_ITEMS elif isinstance(node, ANatSetExpression) or isinstance(node, ANat1SetExpression): return env._max_int elif isinstance(node, AIntSetExpression): return env._min_int * -1 + env._max_int elif isinstance(node, AMultOrCartExpression): time0 = _abstr_eval(node.children[0], env) time1 = _abstr_eval(node.children[1], env) prod = time0 * time1 if prod > TOO_MANY_ITEMS: return TOO_MANY_ITEMS else: return prod ### Relations, functions, sequences elif ( isinstance(node, APartialFunctionExpression) or isinstance(node, ARelationsExpression) or isinstance(node, APartialFunctionExpression) or isinstance(node, ATotalFunctionExpression) or isinstance(node, APartialInjectionExpression) or isinstance(node, ATotalInjectionExpression) or isinstance(node, APartialSurjectionExpression) or isinstance(node, ATotalSurjectionExpression) or isinstance(node, ATotalBijectionExpression) or isinstance(node, APartialBijectionExpression) or isinstance(node, ASeqExpression) or isinstance(node, ASeq1Expression) or isinstance(node, AIseqExpression) or isinstance(node, AIseq1Expression) or isinstance(node, APermExpression) ): time0 = _abstr_eval(node.children[0], env) time1 = _abstr_eval(node.children[1], env) exp0 = time0 * time1 # if exp0>=math.log(TOO_MANY_ITEMS,2): if exp0 >= 22: # math.log is not rpython return TOO_MANY_ITEMS else: # return 2**(exp0) assert exp0 >= 0 result = 1 for i in range(exp0): result = result * 2 return result ### Leafs elif ( isinstance(node, AIdentifierExpression) or isinstance(node, APrimedIdentifierExpression) or isinstance(node, AIntegerExpression) or isinstance(node, AStringExpression) or isinstance(node, AEmptySetExpression) or isinstance(node, AEmptySequenceExpression) or isinstance(node, ABooleanTrueExpression) or isinstance(node, ABooleanFalseExpression) or isinstance(node, AMinIntExpression) or isinstance(node, AMaxIntExpression) ): return 1 elif isinstance(node, AIntervalExpression): left_node = node.children[0] right_node = node.children[1] time0 = _abstr_eval(left_node, env) time1 = _abstr_eval(right_node, env) # print time0, time1 if time0 < TOO_MANY_ITEMS and time1 < TOO_MANY_ITEMS: # TODO: This block is not O(n) - n ast nodes try: if USE_RPYTHON_CODE: from rpython_interp import interpret v0 = interpret(left_node, env) v1 = interpret(right_node, env) val0 = v0.ivalue val1 = v1.ivalue else: from interp import interpret val0 = interpret(left_node, env) val1 = interpret(right_node, env) except ValueNotInDomainException: # what went wrong: A bound variable is used to estimate this block # e.g. y: A..B. expect the worst case val0 = env._min_int val1 = env._max_int else: # over approximation to avoid long interpretation val0 = env._min_int val1 = env._max_int # BUGFIX: if this interpreter call cause the lookup of an unset variable, # this will crash. This is a quick fix. if not isinstance(val0, int) or not isinstance(val1, int): return TOO_MANY_ITEMS return val1 - val0 ### "meet" # Werden hier abstrakte Interpretation und Datenflussanalyse durcheinander geworfen? Denk noch mal drueber nach.... elif isinstance(node, AConjunctPredicate): # this information is used to generate test_sets for {x|P0(x) & P1(x)} # the predicate is a candidate, if P0 OR P1 is finite inf0 = False inf1 = False try: time0 = _abstr_eval(node.children[0], env) except InfiniteConstraintException: inf0 = True time0 = TOO_MANY_ITEMS try: time1 = _abstr_eval(node.children[1], env) except InfiniteConstraintException: inf1 = True time1 = TOO_MANY_ITEMS if inf0 and inf1: raise InfiniteConstraintException("") if time0 < time1: return time0 return time1 ### Default: else: time = 1 for child in node.children: time += _abstr_eval(child, env) return time
def _revise(node, env, var_node): if USE_RPYTHON_CODE: from rpython_interp import interpret else: from interp import interpret if isinstance(node, AEqualPredicate): # if elements of the set are equal to some expression, a set has to be generated # e.g {x| x:NAT & x=42} results in {42} if isinstance(node.children[0], AIdentifierExpression) and node.children[0].idName == var_node.idName: value = interpret(node.children[1], env) # FIXME: TypeError: unhashable instance e.g. run C578.EML.014/CF_CV_1 # somehow a set type is returned! if isinstance(value, SymbolicSet): return frozenset([value.enumerate_all()]) return frozenset([value]) if isinstance(node.children[1], AIdentifierExpression) and node.children[1].idName == var_node.idName: value = interpret(node.children[0], env) if isinstance(value, SymbolicSet): return frozenset([value.enumerate_all()]) return frozenset([value]) if isinstance(node.children[0], ACoupleExpression): # 2.1 search n-tuple for matching var (to be constraint) element_list = couple_tree_to_conj_list(node.children[0]) index = 0 match = False for e in element_list: if isinstance(e, AIdentifierExpression) and e.idName == var_node.idName: match = True break index = index + 1 # 2.2. compute set if match found if match: # FIXME: no caching! Recomputation at every call aset = interpret(node.children[1], env) # print # assert isinstance(set, frozenset) # 2.3. return correct part of the set corresponding to position of # searched variable inside the tuple on the left side return frozenset([remove_tuples(aset)[index]]) elif isinstance(node, AMemberPredicate): # belong-case 1: left side is just an id if isinstance(node.children[0], AIdentifierExpression) and node.children[0].idName == var_node.idName: # print var_node.idName, node.children[1] aset = interpret(node.children[1], env) # print "xxx", aset # e.g. x:{1,2,3} or x:S # return finite set on the left as test_set/constraint domain # FIXME: isinstance('x', frozenset) -> find enumeration order! if not isinstance(aset, frozenset): return aset.enumerate_all() # explicit domain needed return aset # belong-case 2: n-tuple on left side elif isinstance(node.children[0], ACoupleExpression): # e.g. (x,y){x|->y:{(1,2),(3,4)}...} (only one id-constraint found in this pass) # e.g. (x,y,z){x|->(y|->z):{(1,(2,3)),(4,(5,6))..} # TODO: Handle ((x|->y),(z|->a)):S # 2.1 search n-tuple for matching var (to be constraint) element_list = couple_tree_to_conj_list(node.children[0]) index = 0 match = False for e in element_list: if isinstance(e, AIdentifierExpression) and e.idName == var_node.idName: match = True break index = index + 1 # 2.2. compute set if match found if match: aset = interpret(node.children[1], env) # FIXME: C578.EML.014/R_PLACE_MAINTENANCE_2 returns SymbolicUnionSet if isinstance(aset, SymbolicSet): return frozenset([remove_tuples(t)[index] for t in aset.enumerate_all()]) assert isinstance(aset, frozenset) # 2.3. return correct part of the set corresponding to position of # searched variable inside the tuple on the left side return frozenset([remove_tuples(t)[index] for t in aset]) # this is only called because both branches (node.childern[0] and node.childern[1]) # of the disjunction are computable in finite time. (as analysed by _analyze_predicates) elif isinstance(node, ADisjunctPredicate): set0 = _revise(node.children[0], env, var_node) set1 = _revise(node.children[1], env, var_node) return set0.union(set1) elif isinstance(node, AConjunctPredicate): try: set0 = _revise(node.children[0], env, var_node) try: set1 = _revise(node.children[1], env, var_node) return set0.intersection(set1) except PredicateDoesNotMatchException: return set0 except PredicateDoesNotMatchException: set1 = _revise(node.children[1], env, var_node) return set1 else: raise PredicateDoesNotMatchException()
def run_animation_mode(argv): env = Environment() # 1. create env. file_name_str, solution_file_name_str = read_input_string(argv, 1) # 2. read filenames ast_string, error = file_to_AST_str_no_print(file_name_str) # 3. parse input-file to string if error: print error #env.set_search_dir(file_name_str) root = str_ast_to_python_ast(ast_string) # 4. parse string to python ast TODO: JSON # uncomment for profiling (e.g. performance tests) #import cProfile #cProfile.run('mch = interpret(root, env)','pyB_profile_out.txt') solution_file_present = not solution_file_name_str=="" #if solution_file_present: # 5. parse solution-file and write to env. # read_solution_file(env, solution_file_name_str) # The concreate solution values are added at # the bmachine object-init time to the respective mch # 6. replace defs and extern-functions inside mch and solution-file (if present) parse_object = remove_defs_and_parse_ast(root, env) # 7. which kind of ast? if not isinstance(parse_object, BMachine): is_ppu = isinstance(parse_object, PredicateParseUnit) is_epu = isinstance(parse_object, ExpressionParseUnit) assert is_ppu or is_epu result = interpret(parse_object.root, env) # eval predicate or expression print result # TODO: print_values_b_style needs symbolic set impl #print print_values_b_style(result) return 0 assert isinstance(parse_object, BMachine) # 8. typecheck mch = parse_object type_check_root_bmch(root, env, mch) # also checks all included, seen, used and extend # TODO: Check with B spec # 9. animate if ops are present # DO-WHILE Loop while True: next_states = __calc_states_and_print_ui(root, env, mch, solution_file_present) if next_states==[]: # BUG: no enabled ops doesnt mean there are none (deadlock-state) pass undo_possible = not env.state_space.empty() number_of_options = len(next_states) if undo_possible: number_of_options = number_of_options + 1 input_str = "Input (0-"+str(number_of_options)+"):" #number = raw_input(input_str) # XXXX number = number_of_options number = int(number) # quit if number == number_of_options: print "goodbye" break elif undo_possible and number == number_of_options-1: x = env.state_space.get_stack_size() x = x-1 # BUGFIX: empty state on stack if 2==x and env.init_state_on_stack and env.set_up_state_on_stack: env.init_state_on_stack==False env.init_done = False elif 1==x and env.init_state_on_stack and env.set_up_state_on_stack==False: env.init_state_on_stack==False env.init_done = False elif 1==x and env.set_up_state_on_stack: env.set_up_done = False env.set_up_state_on_stack = False env.set_up_bmachines_names = [] env.state_space.undo() elif not env.set_up_done: env.set_up_done = True env.set_up_state_on_stack = True bstate = next_states[number] env.state_space.add_state(bstate) elif not env.init_done: env.init_done = True env.init_state_on_stack = True bstate = next_states[number] env.state_space.add_state(bstate) # init and set_up done. Exec operation: elif len(next_states)>number and number >= 0: # switch state ( bstate = next_states[number] env.state_space.add_state(bstate) else: print "Error! Wrong input:", number return 0
def quick_member_eval(ast, env, element): if USE_RPYTHON_CODE: from rpython_interp import interpret else: from interp import interpret # Base case of recursion if isinstance(element, int) or isinstance(element, str): if isinstance(ast, ANaturalSetExpression): assert isinstance(element, int) # if False: typechecking Bug return element >=0 if isinstance(ast, ANatural1SetExpression): assert isinstance(element, int) # if False: typechecking Bug return element >0 elif isinstance(ast, AIntegerSetExpression): assert isinstance(element, int) return True elif isinstance(ast, ANatSetExpression): assert isinstance(element, int) return element >=0 and element <= env._max_int elif isinstance(ast, ANat1SetExpression): assert isinstance(element, int) return element >0 and element <= env._max_int elif isinstance(ast, AIntSetExpression): assert isinstance(element, int) return element >= env._min_int and element <= env._max_int elif isinstance(ast, AStringSetExpression): assert isinstance(element, str) return True # fallback: enumerate_all right side. This 'should' never happen... S = interpret(ast, env) #print "quck eval of:", element, val #S = list(val) #print element,S # DEBUG return element in S elif isinstance(element, SymbolicLambda): # only one special case #TODO: replace with general case #TODO: support lambdas with more than one arg # XXX: this line could case a infinit computation! aSet = interpret(ast, env) if (not isinstance(aSet, SymbolicRelationSet)) or isinstance(aSet, SymbolicPartialInjectionSet) or isinstance(aSet, SymbolicTotalInjectionSet) or isinstance(aSet, SymbolicPartialSurjectionSet) or isinstance(aSet, SymbolicTotalSurjectionSet) or isinstance(aSet, SymbolicTotalBijectionSet) or isinstance(aSet, SymbolicPartialBijectionSet): # XXX: Dont know how to check this for every lambda print "WARNING: Brute force lambda membership test lambda:S" print "S=", aSet element = element.enumerate_all() result = element in aSet return result else: types = [] for var in element.variable_list: atype = env.get_type_by_node(var) if types==[]: types = atype else: types = tuple([types,atype]) image_type = env.get_lambda_type_by_node(element.node) domain_element = False image_element = False domain_element = types in aSet.left_set image_element = image_type in aSet.right_set #print types, " in ", aSet.left_set, domain_element #print "image:",image_type, " in ", aSet.right_set, image_element if domain_element and image_element: # checking if a function is total is done via an approximation: # if no constraint of the domain is found, the answer is yes, # otherwise the answer is "dont know" if isinstance(aSet, ATotalFunctionExpression): # TODO: call check if len(element.variable_list)==1: # False or Dont know vcbp = var_constraint_by_predicate(element.variable_list, element.predicate) else: return True # else use other checks #TODO:(#ISSUE 18) no quick eval, can crash if isinstance(element, Node): element = interpret(element, env) aSet = interpret(ast, env) #print "element, set:", element, aSet return element in aSet