def test_genAST_para_def(self): # Build AST string =''' MACHINE Test VARIABLES z INVARIANT z:MyType INITIALISATION z:= Expr(2) DEFINITIONS Expr(X) == 1+X; MyType == NAT; 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() dh = DefinitionHandler(env, str_ast_to_python_ast) dh.repl_defs(root) 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 invariant = root.children[2] assert isinstance(invariant, AInvariantMachineClause) assert interpret(invariant, env) assert env.get_value("z")==3
def test_library_length(self): string = ''' MACHINE LibraryStrings CONSTANTS length PROPERTIES /* compute the length of a string */ length: STRING --> INTEGER & length = %x.(x:STRING|STRING_LENGTH(x)) DEFINITIONS STRING_LENGTH(x) == length(x); EXTERNAL_FUNCTION_STRING_LENGTH == STRING --> INTEGER; ASSERTIONS length("abc") = 3; length("") = 0; length("hello") = 5 END ''' # Build AST 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() dh = DefinitionHandler(env, str_ast_to_python_ast) dh.repl_defs(root) mch = parse_ast(root, env) type_check_bmch(root, env, mch) assert isinstance(get_type_by_name(env, "length"), PowerSetType) assert isinstance(get_type_by_name(env, "length").data, CartType) assert isinstance(get_type_by_name(env, "length").data.left.data, StringType) assert isinstance(get_type_by_name(env, "length").data.right.data, IntegerType) arbitrary_init_machine(root, env, mch) # init VARIABLES and eval INVARIANT assert isinstance(root.children[4], AAssertionsMachineClause) interpret(root.children[4], env)
def test_genAST_subst_def2(self): string=''' MACHINE Test VARIABLES z, b, x INVARIANT x:NAT & z:NAT & b:BOOL INITIALISATION x:=2 ; Assign(x+1, z) ; Assign(TRUE, b) DEFINITIONS Assign(Expr, VarName) == VarName := Expr; 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() dh = DefinitionHandler(env, str_ast_to_python_ast) dh.repl_defs(root) 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 invariant = root.children[2] assert isinstance(invariant, AInvariantMachineClause) assert interpret(invariant, env) assert env.get_value("z")==3 assert env.get_value("b")==True assert env.get_value("x")==2
def test_def_files(self): string=''' MACHINE Test DEFINITIONS "common1.def" ; begin==-2*UNIT ; end == 10 * UNIT END''' string_to_file(string, file_name, path="examples/") ast_string = file_to_AST_str(file_name, path="examples/") root = str_ast_to_python_ast(ast_string) env = Environment() dh = DefinitionHandler(env, str_ast_to_python_ast) # 5. replace defs if present dh.repl_defs(root)
def test_library_append(self): string = ''' MACHINE m DEFINITIONS EXTERNAL_FUNCTION_STRING_APPEND == STRING*STRING --> STRING; STRING_APPEND(x,y) == append(x,y); STRING_LENGTH(x) == length(x); EXTERNAL_FUNCTION_STRING_LENGTH == STRING --> INTEGER; ABSTRACT_CONSTANTS append, length PROPERTIES append = %(x,y).(x: STRING & y: STRING | STRING_APPEND(x,y)) & length: STRING --> INTEGER & length = %x.(x:STRING|STRING_LENGTH(x)) ASSERTIONS append("abc","abc") = "abcabc"; append("","abc") = "abc"; append("abc","") = "abc"; /*{x|x:{"abc","abcabc","hello"} & #(prefx).(append(prefx,"c")=x)} = {"abcabc","abc"};*/ {x|x/="" & #y.(append(x,y)="abc" & y/="")} = {"a","ab"}; /* compute true prefixes */ {x|x/="" & #y.(append(y,x)="abc" & y/="")} = {"c","bc"}; /* compute true postfixes */ {y|y/="" & #(x,z).(append(x,append(y,z))="abc" & length(x)+length(z)>0)} = /* compute true substrings */ {"a","ab","b","bc","c"}; {y|y/="" & #(x,z).(append(append(x,y),z)="abc" & length(x)+length(z)>0)} = /* compute true substrings */ {"a","ab","b","bc","c"} END''' # TODO: prolog-style args # {x|x:{"abc","abcabc","hello"} & #(prefx).(append(prefx,"c")=x)} = {"abcabc","abc"}; # Build AST 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() dh = DefinitionHandler(env, str_ast_to_python_ast) dh.repl_defs(root) mch = parse_ast(root, env) type_check_bmch(root, env, mch) assert isinstance(get_type_by_name(env, "append"), PowerSetType) assert isinstance(get_type_by_name(env, "append").data, CartType) assert isinstance(get_type_by_name(env, "append").data.left.data, CartType) assert isinstance(get_type_by_name(env, "append").data.left.data.left.data, StringType) assert isinstance(get_type_by_name(env, "append").data.left.data.right.data, StringType) assert isinstance(get_type_by_name(env, "append").data.right.data, StringType) arbitrary_init_machine(root, env, mch) # init VARIABLES and eval INVARIANT assert isinstance(root.children[4], AAssertionsMachineClause) interpret(root.children[4], env)
def test_genAST_subst_def3(self): string=''' MACHINE Test3 SEES UsingDefinitions 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() dh = DefinitionHandler(env, str_ast_to_python_ast) dh.repl_defs(root) 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)
def test_def_find(self): string=''' MACHINE Test VARIABLES z, b, x INVARIANT x:NAT & z:NAT & b:BOOL INITIALISATION x:=2 ; Assign(x+1, z) ; Assign(TRUE, b) DEFINITIONS Assign(Expr, VarName) == VarName := Expr; END''' string_to_file(string, file_name) ast_string = file_to_AST_str(file_name) root = str_ast_to_python_ast(ast_string) env = Environment() dh = DefinitionHandler(env, str_ast_to_python_ast) dh._save_definitions(root.children[4]) assert isinstance(dh.def_map["Assign"], ASubstitutionDefinitionDefinition)
def test_library_codes(self): string = ''' MACHINE LibraryStrings CONSTANTS codes, append PROPERTIES append = %(x,y).(x: STRING & y: STRING | STRING_APPEND(x,y)) & /* obtain the characters of a string as a B sequence of Ascii codes; it is reversible */ codes: STRING --> (INTEGER <-> INTEGER) & codes = %(s).(s:STRING|STRING_CODES(s)) DEFINITIONS STRING_CODES(x) == codes(x); EXTERNAL_FUNCTION_STRING_CODES == (STRING --> (INTEGER<->INTEGER)); EXTERNAL_FUNCTION_STRING_APPEND == STRING*STRING --> STRING; STRING_APPEND(x,y) == append(x,y) ASSERTIONS codes("") = <>; /* codes(" ") = [32]; the Java parser currently swallows whitespace within strings */ codes("abc") = [97,98,99]; {x| codes(x) = codes("abc") ^ codes("abc")} = {"abcabc"}; !(x,y).(x:{"abc","hello",""} & y:{"abc","hello",""} => codes(append(x,y)) = codes(x)^codes(y)) END ''' # FIXME: composition typechecking bug # {x| codes(x) = (codes("abc") ; succ) } = {"bcd"}; # TODO: prolog style args # {x| codes(x) = %i.(i:1..26|96+i)} = {"abcdefghijklmnopqrstuvwxyz"} # Build AST 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() dh = DefinitionHandler(env, str_ast_to_python_ast) dh.repl_defs(root) mch = parse_ast(root, env) type_check_bmch(root, env, mch) assert isinstance(get_type_by_name(env, "codes"), PowerSetType) assert isinstance(get_type_by_name(env, "codes").data, CartType) assert isinstance(get_type_by_name(env, "codes").data.left.data, StringType) assert isinstance(get_type_by_name(env, "codes").data.right.data.data, CartType) assert isinstance(get_type_by_name(env, "codes").data.right.data.data.left.data, IntegerType) assert isinstance(get_type_by_name(env, "codes").data.right.data.data.right.data, IntegerType) arbitrary_init_machine(root, env, mch) # init VARIABLES and eval INVARIANT assert isinstance(root.children[4], AAssertionsMachineClause) interpret(root.children[4], env)
def test_library_split(self): string = ''' MACHINE LibraryStrings CONSTANTS split PROPERTIES /* split a string according to a delimiter string into a sequence of strings */ split: STRING * STRING --> (INTEGER<->STRING) & split = %(x,y).(x:STRING & y:STRING|STRING_SPLIT(x,y)) DEFINITIONS STRING_SPLIT(x,y) == split(x,y); EXTERNAL_FUNCTION_STRING_SPLIT == ((STRING*STRING) --> (INTEGER<->STRING)); ASSERTIONS split("filename.ext",".") = ["filename","ext"]; split("filename.ext","/") = ["filename.ext"]; split("/usr/local/lib","/") = ["","usr","local","lib"]; split("/","/") = ["",""]; split("abcabc","bc") = ["a","a",""] END ''' # Build AST 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() dh = DefinitionHandler(env, str_ast_to_python_ast) dh.repl_defs(root) mch = parse_ast(root, env) type_check_bmch(root, env, mch) assert isinstance(get_type_by_name(env, "split"), PowerSetType) assert isinstance(get_type_by_name(env, "split").data, CartType) assert isinstance(get_type_by_name(env, "split").data.left.data, CartType) assert isinstance(get_type_by_name(env, "split").data.left.data.left.data, StringType) assert isinstance(get_type_by_name(env, "split").data.left.data.right.data, StringType) assert isinstance(get_type_by_name(env, "split").data.right.data.data, CartType) assert isinstance(get_type_by_name(env, "split").data.right.data.data.left.data, IntegerType) assert isinstance(get_type_by_name(env, "split").data.right.data.data.right.data, StringType) arbitrary_init_machine(root, env, mch) # init VARIABLES and eval INVARIANT assert isinstance(root.children[4], AAssertionsMachineClause) interpret(root.children[4], env)
def test_types_two_para_def(self): # Build AST string=''' MACHINE Test VARIABLES z INVARIANT z:MyDef(NAT,{0}) INITIALISATION z:= MyDef(5,1) DEFINITIONS MyDef(X,Y) == X-Y; END''' string_to_file(string, file_name) ast_string = file_to_AST_str(file_name) root = str_ast_to_python_ast(ast_string) # Type env = Environment() dh = DefinitionHandler(env, str_ast_to_python_ast) dh.repl_defs(root) parse_ast(root, env) lst = [] type_with_known_types(root, env, lst, ["z"]) assert isinstance(get_type_by_name(env, "z"), IntegerType)
def test_genAST_pred_def(self): string=''' MACHINE Test VARIABLES z INVARIANT z:NAT & MyDef(4,1,3) INITIALISATION z:= 4 DEFINITIONS MyDef(X,Y,Z) == X-Y=Z; 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() dh = DefinitionHandler(env, str_ast_to_python_ast) dh.repl_defs(root) 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 invariant = root.children[2] assert isinstance(invariant, AInvariantMachineClause) assert interpret(invariant, env)
def run_with_pyb(bfile_name, dir=""): # Build b-mch AST ast_string = file_to_AST_str("%s%s.mch" % (dir, bfile_name)) ast_root = str_ast_to_python_ast(ast_string) # Get ProB Solution, write to env env = Environment() env._min_int = -2**31 env._max_int = 2**31 ast_str, err = solution_file_to_AST_str("%s%s_values.txt" % (dir, bfile_name)) assert err=='' root = str_ast_to_python_ast(ast_str) env.solution_root = root env.write_solution_nodes_to_env(root) # Init B-mch #dh = DefinitionHandler(env, remove_defs_and_parse_ast) dh = DefinitionHandler(env, str_ast_to_python_ast) dh.repl_defs(ast_root) mch = parse_ast(ast_root, env) type_check_root_bmch(ast_root, env, mch) # also checks all included, seen, used and extend #if env.solution_root: # idNodes = find_var_nodes(root.children[0]) # idNames = [n.idName for n in idNodes] # type_check_predicate(env.solution_root, env, idNames) # side-effect: check properties and invariant print "team-test:calc set up.." bstates = set_up_constants(root, env, mch, solution_file_read=True) env.state_space.add_state(bstates[0]) print "team-test:calc set init.." bstates = exec_initialisation(root, env, mch, solution_file_read=True) env.state_space.add_state(bstates[0]) if mch.has_properties_mc: print "team-test:eval properties..." assert interpret(mch.aPropertiesMachineClause, env) if mch.has_invariant_mc: print "team-test:eval invariant..." assert interpret(mch.aInvariantMachineClause, env)
def test_replace_defs(self): string=''' MACHINE Test VARIABLES z, b, x INVARIANT x:NAT & z:NAT & b:BOOL INITIALISATION x:=2 ; Assign(x+1, z) ; Assign(TRUE, b) DEFINITIONS Assign(Expr, VarName) == VarName := Expr; END''' string_to_file(string, file_name) ast_string = file_to_AST_str(file_name) root = str_ast_to_python_ast(ast_string) env = Environment() init = root.children[3] assert isinstance(init, AInitialisationMachineClause) subst = init.children[0] assert isinstance(subst.children[1], ADefinitionSubstitution) assert isinstance(subst.children[2], ADefinitionSubstitution) dh = DefinitionHandler(env, str_ast_to_python_ast) dh._save_definitions(root.children[4]) def_free_ast = dh._replace_definitions(root) assert isinstance(subst.children[1], AAssignSubstitution) assert isinstance(subst.children[2], AAssignSubstitution)
def test_library_chars(self): string = ''' MACHINE LibraryStrings CONSTANTS chars, length, append PROPERTIES append = %(x,y).(x: STRING & y: STRING | STRING_APPEND(x,y)) & /* obtain the characters of a string as a B sequence of strings of length 1 */ chars: STRING --> (INTEGER <-> STRING) & chars = %(s).(s:STRING|STRING_CHARS(s)) & /* compute the length of a string */ length: STRING --> INTEGER & length = %x.(x:STRING|STRING_LENGTH(x)) DEFINITIONS EXTERNAL_FUNCTION_STRING_APPEND == STRING*STRING --> STRING; STRING_APPEND(x,y) == append(x,y); STRING_CHARS(x) == chars(x); EXTERNAL_FUNCTION_STRING_CHARS == (STRING --> (INTEGER<->STRING)); STRING_LENGTH(x) == length(x); EXTERNAL_FUNCTION_STRING_LENGTH == STRING --> INTEGER ASSERTIONS chars("") = <>; chars("abc") = ["a","b","c"]; /* find strings with b as character: */ {x|x:{"abc","abcabc","hello"} & "b" : ran(chars(x))} = {"abc", "abcabc"}; /* now find strings which have the same character set */ {x|x:{"abc","abcabc","hello"} & #y.(y:{"abc","abcabc","hello"} & ran(chars(x))=ran(chars(y)) & x/=y)} = {"abc", "abcabc"}; !(x,y).(x:{"abc","hello",""} & y:{"abc","hello",""} => chars(append(x,y)) = chars(x)^chars(y)) END ''' # TODO: performance # /* now find permutations */ # {x|x:{"abc","hello","cba",""} & #(y,p).(y:{"abc","hello","cba",""} & p:perm(1..size(chars(x))) & x/=y & length(x)=length(y) & /* a bit slower without this condition */ # (p;chars(x)) = chars(y))} = {"abc","cba"} # TODO: performance (30 sec) # card({x,y,z,v| x: {"abc","abcabcd","filename.ext","/usr/local/lib"} & # y:ran(chars(x)) & z:ran(chars(x)) & y/=z & # v:ran(chars(x)) & y/=v & z/=v & # length(x)+length(y)+length(z)+length(v)=6 }) = 6; # Build AST 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() dh = DefinitionHandler(env, str_ast_to_python_ast) dh.repl_defs(root) mch = parse_ast(root, env) type_check_bmch(root, env, mch) assert isinstance(get_type_by_name(env, "chars"), PowerSetType) assert isinstance(get_type_by_name(env, "chars").data, CartType) assert isinstance(get_type_by_name(env, "chars").data.left.data, StringType) assert isinstance(get_type_by_name(env, "chars").data.right.data.data, CartType) assert isinstance(get_type_by_name(env, "chars").data.right.data.data.left.data, IntegerType) assert isinstance(get_type_by_name(env, "chars").data.right.data.data.right.data, StringType) arbitrary_init_machine(root, env, mch) # init VARIABLES and eval INVARIANT assert isinstance(root.children[4], AAssertionsMachineClause) interpret(root.children[4], env)
def remove_definitions(root, env): dh = DefinitionHandler(env, str_ast_to_python_ast) dh.repl_defs(root) # side effect: change AST(root) return root