def testParseSet(self): test_data = [("({}::'a set)", "(∅::'a set)", "'a set"), ("x Mem A", "x ∈ A", "bool"), ("A Sub B", "A ⊆ B", "bool"), ("A Int B", "A ∩ B", "'a set"), ("A Un B", "A ∪ B", "'a set"), ("{x}", "{x}", "'a set"), ("{x, y}", "{x, y}", "'a set"), ("insert x A", "insert x A", "'a set"), ("{x. P x}", "{x. P x}", "'a set"), ("collect P", "collect P", "'a set"), ("UN S", "⋃S", "'a set"), ("INT S", "⋂S", "'a set"), ("INT (image f S)", "⋂(image f S)", "'a set"), ("f (INT S)", "f (⋃S)", "'a set")] vars = { "x": "'a", "y": "'a", "A": "'a set", "B": "'a set", "P": "'a => bool", "S": "'a set set", "f": "'a set => 'a set" } for s1, s2, Ts in test_data: with global_setting(unicode=False): self.run_test('set', vars=vars, s=s1, Ts=Ts) with global_setting(unicode=True): self.run_test('set', vars=vars, s=s2, Ts=Ts)
def testPrintSet(self): A = Var("A", set.setT(Ta)) B = Var("B", set.setT(Ta)) x = Var("x", Ta) y = Var("y", Ta) P = Var("P", TFun(Ta, BoolType)) S = Var("S", set.setT(set.setT(Ta))) test_data = [ (set.empty_set(Ta), "({}::'a set)", "(∅::'a set)"), (set.mk_mem(x, A), "x Mem A", "x ∈ A"), (set.mk_subset(A, B), "A Sub B", "A ⊆ B"), (set.mk_inter(A, B), "A Int B", "A ∩ B"), (set.mk_union(A, B), "A Un B", "A ∪ B"), (set.mk_insert(x, set.empty_set(Ta)), "{x}", "{x}"), (set.mk_insert(x, set.mk_insert(y, set.empty_set(Ta))), "{x, y}", "{x, y}"), (set.mk_insert(x, A), "insert x A", "insert x A"), (set.mk_collect(x, P(x)), "{x. P x}", "{x. P x}"), (set.collect(Ta)(P), "collect P", "collect P"), (set.mk_Union(S), "UN S", "⋃S"), (set.mk_Inter(S), "INT S", "⋂S"), ] for t, s1, s2 in test_data: with global_setting(unicode=False): self.assertEqual(printer.print_term(t), s1) with global_setting(unicode=True): self.assertEqual(printer.print_term(t), s2)
def search_method(): """Match for applicable methods and their arguments. Input: * username: username. * theory_name: name of the theory. * thm_name: name of the theorem. Returns: * search_res: list of search results. * ctxt: current proof context. """ data = json.loads(request.get_data().decode("utf-8")) if data['profile']: pr = cProfile.Profile() pr.enable() if not proof_cache.check_cache(data): start_time = time.perf_counter() proof_cache.create_cache(data) print("Load: %f" % (time.perf_counter() - start_time)) if data['thm_name'] != '': limit = ('thm', data['thm_name']) else: limit = None basic.load_theory(data['theory_name'], limit=limit, username=data['username']) start_time = time.perf_counter() state = proof_cache.states[data['index']] fact_ids = data['step']['fact_ids'] goal_id = data['step']['goal_id'] search_res = state.search_method(goal_id, fact_ids) with settings.global_setting(unicode=True): for res in search_res: if '_goal' in res: res['_goal'] = [printer.print_term(t) for t in res['_goal']] if '_fact' in res: res['_fact'] = [printer.print_term(t) for t in res['_fact']] vars = state.get_vars(goal_id) with settings.global_setting(unicode=True, highlight=True): print_vars = dict((k, printer.print_type(v)) for k, v in vars.items()) print("Response:", time.perf_counter() - start_time) if data['profile']: p = Stats(pr) p.strip_dirs() p.sort_stats('cumtime') p.print_stats() return jsonify({'search_res': search_res, 'ctxt': print_vars})
def json_data(self): """Export proof in json format.""" with global_setting(unicode=True): vars = {v.name: printer.print_type(v.T) for v in self.vars} with global_setting(unicode=True, highlight=True): res = { "vars": vars, "proof": self.export_proof(), "num_gaps": len(self.rpt.gaps), "method_sig": method.get_method_sig(), } return res
def testParseType(self): test_data = [ "'b", "?'b", "nat", "'a list", "nat list", "nat list list", "'a => 'b", "'a => 'b => 'c", "('a => 'b) => 'c", "('a => 'b) => 'c => 'd", "(('a => 'b) => 'c) => 'd", "?'a => ?'b", "'a => 'b list", "('a => 'b) list", "'a list list", "'a list => 'b list", "('a list => 'b) list", ] basic.load_theory('list') for s in test_data: T = parser.parse_type(s) self.assertIsInstance(T, Type) with global_setting(unicode=False): self.assertEqual(str(T), s)
def export_term(t): """Function for printing a term for export to json.""" with global_setting(unicode=True, line_length=80): res = printer.print_term(t) if len(res) == 1: res = res[0] return res
def run_test(self, thy_name, s, expected_res, **kwargs): context.set_context(thy_name) t = parser.parse_term(s) with global_setting(**kwargs): ast = pprint.get_ast_term(t) res = pprint.print_ast(ast) self.assertEqual(res, expected_res)
def testPrintType(self): test_data = [ (Ta, "'a"), (TVar("ab"), "'ab"), (TConst("bool"), "bool"), (TConst("list", Ta), "'a list"), (TConst("list", TConst("list", Ta)), "'a list list"), (TConst("tree", Ta, Tb), "('a, 'b) tree"), (TFun(Ta, Tb), "'a => 'b"), (TFun(Ta, Tb, Tc), "'a => 'b => 'c"), (TFun(TFun(Ta, Tb), Tc), "('a => 'b) => 'c"), (TFun(TConst("list", Ta), Tb), "'a list => 'b"), (TFun(Ta, TConst("list", Tb)), "'a => 'b list"), (TConst("list", TFun(Ta, Tb)), "('a => 'b) list"), (TConst("list", TConst("list", TFun(Ta, Tb))), "('a => 'b) list list"), (TFun(TConst("list", Ta), TConst("list", Tb)), "'a list => 'b list"), (TConst("list", TFun(TConst("list", Ta), Tb)), "('a list => 'b) list"), ] for T, str_T in test_data: with global_setting(unicode=False): self.assertEqual(str(T), str_T)
def testParseReal(self): test_data = [ ("x + y", "real"), ("x * y", "real"), ("x - y", "real"), ("-x", "real"), ("x - -y", "real"), ("--x", "real"), ("-(x - y)", "real"), ("(0::real)", "real"), ("(1::real)", "real"), ("(2::real)", "real"), ("x + 1", "real"), ("x ^ n", "real"), ("-(x ^ n)", "real"), ("-x ^ n", "real"), ("(1::real) + 2", "real"), ("(2::real) + 1", "real"), ("[(2::real), 3]", "real list"), ("{(2::real), 3}", "real set"), ("{(2::real), 3} Un {4, 5}", "real set"), ("{t::real. abs t <= 1}", "real set"), ] vars = {'x': 'real', 'y': 'real', 'n': 'nat'} for s, Ts in test_data: with global_setting(unicode=False): self.run_test('real', vars=vars, s=s, Ts=Ts)
def print_type(T): """Pretty-printing for types.""" typecheck.checkinstance('print_type', T, Type) ast = pprint.get_ast_type(T) with global_setting(line_length=None): return pprint.print_ast(ast)
def testDatatypeProd(self): basic.load_theory('logic_base') prod_item = items.parse_item({ "args": ["a", "b"], "constrs": [{ "args": ["a", "b"], "name": "Pair", "type": "'a => 'b => ('a, 'b) prod" }], "name": "prod", "ty": "type.ind" }) self.assertIsNone(prod_item.error) ext = prod_item.get_extension() theory.thy.unchecked_extend(ext) ext_output = [ "Type prod 2", "Constant Pair :: 'a => 'b => ('a, 'b) prod", "Theorem prod_Pair_inject: Pair a b = Pair a1 b1 --> a = a1 & b = b1", "Theorem prod_induct: (!a. !b. P (Pair a b)) --> P x", "Attribute prod_induct [var_induct]" ] with global_setting(unicode=False): self.assertEqual(printer.print_extensions(ext), '\n'.join(ext_output))
def print_length(ast): with global_setting(line_length=None): res = print_ast(ast) if settings.highlight: return sum(len(node['text']) for node in res) else: return len(res)
def testPredEven(self): basic.load_theory('nat', limit=('def', 'one')) even_item = items.parse_item({ "name": "even", "rules": [{ "name": "even_zero", "prop": "even 0" }, { "name": "even_Suc", "prop": "even n --> even (Suc (Suc n))" }], "ty": "def.pred", "type": "nat => bool" }) self.assertIsNone(even_item.error) ext = even_item.get_extension() theory.thy.unchecked_extend(ext) ext_output = [ "Constant even :: nat => bool", "Theorem even_zero: even 0", "Attribute even_zero [hint_backward]", "Theorem even_Suc: even n --> even (Suc (Suc n))", "Attribute even_Suc [hint_backward]", "Theorem even_cases: even _a1 --> (_a1 = 0 --> P) --> (!n. _a1 = Suc (Suc n) --> even n --> P) --> P" ] with global_setting(unicode=False): self.assertEqual(printer.print_extensions(ext), '\n'.join(ext_output))
def testDatatypeList(self): basic.load_theory('logic_base') list_item = items.parse_item({ "args": ["a"], "constrs": [{ "args": [], "name": "nil", "type": "'a list" }, { "args": ["x", "xs"], "name": "cons", "type": "'a => 'a list => 'a list" }], "name": "list", "ty": "type.ind" }) self.assertIsNone(list_item.error) ext = list_item.get_extension() theory.thy.unchecked_extend(ext) ext_output = [ "Type list 1", "Constant nil :: 'a list", "Constant cons :: 'a => 'a list => 'a list", "Theorem list_nil_cons_neq: ~([] = x # xs)", "Theorem list_cons_inject: x # xs = x1 # xs1 --> x = x1 & xs = xs1", "Theorem list_induct: P [] --> (!x1. !xs. P xs --> P (x1 # xs)) --> P x", "Attribute list_induct [var_induct]" ] with global_setting(unicode=False): self.assertEqual(printer.print_extensions(ext), '\n'.join(ext_output))
def testFunPlus(self): basic.load_theory('nat', limit=('def', 'one')) plus_item = items.parse_item({ "name": "plus", "rules": [{ "prop": "0 + n = n" }, { "prop": "Suc m + n = Suc (m + n)" }], "ty": "def.ind", "type": "nat ⇒ nat ⇒ nat" }) self.assertIsNone(plus_item.error) ext = plus_item.get_extension() theory.thy.unchecked_extend(ext) ext_output = [ "Constant plus :: nat => nat => nat", "Theorem plus_def_1: 0 + n = n", "Attribute plus_def_1 [hint_rewrite]", "Theorem plus_def_2: Suc m + n = Suc (m + n)", "Attribute plus_def_2 [hint_rewrite]" ] with global_setting(unicode=False): self.assertEqual(printer.print_extensions(ext), '\n'.join(ext_output))
def testInferType2(self): test_data = [("%x::nat. (0::nat)", "nat => nat"), ("(%x::nat. (0::nat))(1 := 7)", "nat => nat")] for s, Ts in test_data: with global_setting(unicode=False): self.run_test('function', s=s, Ts=Ts)
def check_modify(): """Check a modified item for validity. Input: * username: username. * filename: name of the file. * line_length: maximum length of printed line. * item: item to be checked. Returns: * checked item. """ data = json.loads(request.get_data().decode("utf-8")) username = data['username'] edit_item = data['item'] line_length = data.get('line_length') if 'limit_ty' in data: limit = (data['limit_ty'], data['limit_name']) else: limit = None basic.load_theory(data['filename'], limit=limit, username=username) item = items.parse_edit(edit_item) if item.error is None: theory.thy.unchecked_extend(item.get_extension()) with settings.global_setting(line_length=line_length): output_item = item.export_web() return jsonify({'item': output_item})
def parse_steps(self, steps): """Parse and apply a list of steps to self. Return the output from the list of steps. """ history = [] for step in steps: with global_setting(unicode=True, highlight=True): step_output = method.output_step(self, step) history.append({ 'step_output': step_output, 'goal_id': step['goal_id'], 'fact_ids': step.get('fact_ids', []) }) try: method.apply_method(self, step) self.check_proof(compute_only=True) except Exception as e: history[-1]['error'] = { 'err_type': e.__class__.__name__, 'err_str': str(e), 'trace': traceback2.format_exc() } return history
def testParseUnicode(self): test_data = [ ("A ∧ B", "A & B"), ("A ∨ B", "A | B"), ("A ⟶ B ⟶ C", "A --> B --> C"), ("A ∧ B | C", "A & B | C"), ("¬A", "~A"), ("λx::'a. x", "%x::'a. x"), ("∀x::'a. P x", "!x. P x"), ("∃x::'a. P x", "?x. P x"), ("∀x::'a. P x ∧ Q x", "!x. P x & Q x"), ("(∀x::'a. P x) & Q y", "(!x. P x) & Q y"), ] context.set_context('logic_base', vars={ 'A': 'bool', 'B': 'bool', 'C': 'bool', 'P': "'a => bool", 'Q': "'a => bool" }) for s, ascii_s in test_data: t = parser.parse_term(s) self.assertIsInstance(t, Term) with global_setting(unicode=False): self.assertEqual(print_term(t), ascii_s)
def search_method(self, id, prevs): """Perform search for each method.""" id = ItemID(id) prevs = [ItemID(prev) for prev in prevs] if prevs else [] results = [] all_methods = method.get_all_methods() for name in all_methods: cur_method = all_methods[name] if hasattr(cur_method, 'no_order'): test_prevs = [prevs] else: test_prevs = itertools.permutations(prevs) for perm_prevs in test_prevs: res = cur_method.search(self, id, perm_prevs) for r in res: r['method_name'] = name r['goal_id'] = str(id) if prevs: r['fact_ids'] = list(str(id) for id in perm_prevs) with global_setting(unicode=True, highlight=True): r['display'] = method.output_hint(self, r) results.extend(res) # If there is an element in results that solves the goal, # output only results that solves. if any('_goal' in r and len(r['_goal']) == 0 for r in results): results = list( filter(lambda r: '_goal' in r and len(r['_goal']) == 0, results)) return results
def testDatatypeNat(self): basic.load_theory('logic_base') nat_item = items.parse_item({ "args": [], "constrs": [{ "args": [], "name": "zero", "type": "nat" }, { "args": ["n"], "name": "Suc", "type": "nat => nat" }], "name": "nat", "ty": "type.ind" }) self.assertIsNone(nat_item.error) ext = nat_item.get_extension() theory.thy.unchecked_extend(ext) ext_output = [ "Type nat 0", "Constant zero :: nat", "Constant Suc :: nat => nat", "Theorem nat_zero_Suc_neq: ~(0 = Suc n)", "Theorem nat_Suc_inject: Suc n = Suc n1 --> n = n1", "Theorem nat_induct: P 0 --> (!n. P n --> P (Suc n)) --> P x", "Attribute nat_induct [var_induct]" ] with global_setting(unicode=False): self.assertEqual(printer.print_extensions(ext), '\n'.join(ext_output))
def testPrintExtension(self): exts = [TConst("nat", 0), Constant("id", TFun(TVar("a"), TVar("a")))] str_exts = ["Type nat 0", "Constant id :: 'a => 'a"] for ext, str_ext in zip(exts, str_exts): with global_setting(unicode=False): self.assertEqual(str(ext), str_ext)
def testParseUnicodeType(self): test_data = ["'a ⇒ 'b"] basic.load_theory('list') for s in test_data: T = parser.parse_type(s) self.assertIsInstance(T, Type) with global_setting(unicode=True): self.assertEqual(print_type(T), s)
def export_web(self): res = self.export_json() with global_setting(highlight=True, unicode=True): res['display'] = self.get_display() with global_setting(highlight=False, unicode=True): res['edit'] = self.get_display() if self.error is None: with global_setting(highlight=False, unicode=True, line_length=None): res['ext'] = printer.print_extensions(self.get_extension()) else: res['error'] = { "err_type": self.error.__class__.__name__, "err_str": str(self.error), "trace": self.trace } return res
def testPrintThm(self): test_data = [ (Thm([], A), "|- A"), (Thm([A], A), "A |- A"), (Thm([A,B], A), "A, B |- A"), ] for th, str_th in test_data: with global_setting(unicode=False): self.assertEqual(str(th), str_th)
def testPrintWithType(self): test_data = [ (list.nil(Ta), "([]::'a list)"), (Eq(list.nil(Ta), list.nil(Ta)), "([]::'a list) = []"), (Forall(a, Eq(a, a)), "!a::'a. a = a"), ] with global_setting(unicode=False): for t, s in test_data: self.assertEqual(printer.print_term(t), s)
def testPrintExtensionReport2(self): ext_report = ExtensionReport() ext_report.add_axiom("nat", 0) ext_report.add_axiom("id", TFun(Ta, Ta)) str_ext_report = "\n".join( ["Axiom added: 2", "Type nat with arity 0", "id :: 'a => 'a"]) with global_setting(unicode=False): self.assertEqual(str(ext_report), str_ext_report)
def testParseTypedTerm(self): test_data = [ ("([]::'a list)", "'a list"), ("([]::nat list)", "nat list"), ("([]::'a list) = []", "bool"), ("!a::'a. a = a", "bool"), ] for s, Ts in test_data: with global_setting(unicode=False): self.run_test('list', s=s, Ts=Ts)
def export_json(self): with global_setting(unicode=True): res = { 'ty': 'def.ax', 'name': self.name, 'type': self.type if self.error else printer.print_type(self.type) } if self.overloaded: res['overloaded'] = True return res
def check_proof(item, *, rewrite): if item.steps: context.set_context(None, vars=item.vars) state = server.parse_init_state(item.prop) history = state.parse_steps(item.steps) if rewrite: with global_setting(unicode=True): item.proof = state.export_proof() for step in history: if 'error' in step: return { 'status': 'Failed', 'err_type': step['error']['err_type'], 'err_str': step['error']['err_str'], 'trace': step['error']['trace'] } try: state.check_proof() except Exception as e: return { 'status': 'Failed', 'err_type': e.__class__.__name__, 'err_str': str(e), 'trace': traceback2.format_exc() } # Otherwise OK return { 'status': 'OK' if len(state.rpt.gaps) == 0 else 'Partial', 'num_steps': len(item.steps), } elif item.proof: try: context.set_context(None, vars=item.vars) state = server.parse_proof(item.proof) state.check_proof(no_gaps=True) except Exception as e: return { 'status': 'ProofFail', 'err_type': e.__class__.__name__, 'err_str': str(e), 'trace': traceback2.format_exc() } return { 'status': 'ProofOK' } else: return { 'status': 'NoSteps' }