def process_examples(self, examples: List[Example],
                      equal_output: Callable[[Any, Any], bool]):
     try:
         all_ok = all([
             self.process_example(example, equal_output)
             for example in examples
         ])
         if all_ok:
             return ok()
         else:
             blames = self._get_blames()
             if len(blames) == 0:
                 return bad()
             else:
                 return bad(why=blames)
     except PruningException as e:
         node = e.node
         # Blame should include all children of node
         blame_nodes = {child for child in dfs(node)}
         # Blame should also include all non-children non-leaf nodes with constraints
         for prog_node in dfs(self._prog):
             if prog_node.is_param():
                 blame_nodes.add(node)
             elif prog_node.is_apply() and len(
                     prog_node.production.constraints) > 0:
                 blame_nodes.add(node)
         return bad([[Blame(node, node.production)
                      for node in blame_nodes]])
    def test_blame(self):
        enode0 = builder.make_enum('SmallInt', '-3')
        enode1 = builder.make_enum('SmallInt', '-2')
        snode = builder.make_apply('sqrt', [enode0])
        inode = builder.make_apply('id', [snode])

        interp = FooInterpreter()
        handler = AssertionViolationHandler(spec, interp)

        with self.assertRaises(AssertionViolation) as cm:
            interp.eval(inode, [])
        type_error = cm.exception
        blames = handler.handle_interpreter_error(type_error)
        self.assertIsNotNone(blames)
        self.assertEqual(len(blames), 2)
        for blame in blames:
            self.assertNotIn(Blame(inode, inode.production), blame)
            self.assertIn(Blame(snode, snode.production), blame)
            self.assertTrue((Blame(enode0, enode0.production) in blame)
                            or (Blame(enode0, enode1.production) in blame))
 def _analyze_enum(self, prod: Production, error: AssertionViolation) -> List[List[Blame]]:
     blames = list()
     arg_node = error.arg
     blame_base = self._compute_blame_base(error)
     blames.append(blame_base + [Blame(arg_node, prod)])
     # for alt_prod in self._spec.get_productions_with_lhs(prod.lhs):
     #     alt_node = AtomNode(alt_prod)
     #     # Inputs doesn't matter here as we don't have any ParamNode
     #     value = self._interp.eval(alt_node, [])
     #     if not error.reason(value):
     #         blames.append(blame_base + [Blame(arg_node, alt_prod)])
     return blames
    def _compute_blame_base(self, error: AssertionViolation) -> List[Blame]:
        node = error.node
        capture_set = set(error.captures)
        # Exclude the failed child itself
        capture_set.discard(error.index)
        capture_nodes = [node.children[x] for x in capture_set]

        blame_nodes = [node]
        for capture_node in capture_nodes:
            for child in dfs(capture_node):
                blame_nodes.append(child)
        return [Blame(n, n.production) for n in blame_nodes]
    def test_blame_with_capture(self):
        enode0 = builder.make_enum('SmallInt', '-2')
        cnode = builder.make_apply('const', [enode0])
        enode1 = builder.make_enum('SmallInt', '-3')
        enode2 = builder.make_enum('SmallInt', '3')
        dnode = builder.make_apply('idiv', [cnode, enode1])

        interp = FooInterpreter()
        handler = AssertionViolationHandler(spec, interp)

        with self.assertRaises(AssertionViolation) as cm:
            interp.eval(dnode, [])
        type_error = cm.exception
        blames = handler.handle_interpreter_error(type_error)
        self.assertIsNotNone(blames)
        self.assertEqual(len(blames), 2)
        for blame in blames:
            self.assertIn(Blame(dnode, dnode.production), blame)
            self.assertTrue((Blame(enode1, enode1.production) in blame)
                            or (Blame(enode1, enode2.production) in blame))
            # These nodes are captured in our assertion
            self.assertIn(Blame(cnode, cnode.production), blame)
            self.assertIn(Blame(enode0, enode0.production), blame)
Esempio n. 6
0
    def process_example(self, example: Example,
                        equal_output: Callable[[Any, Any], bool], prune: str,
                        abstract_eval_memory):
        """check whether an example program is consistent with the input-output spec """
        prune = AbstractPrune(self._interp, example, prune,
                              abstract_eval_memory)

        if prune.is_unsat(self._prog):
            # If abstract semantics cannot be satisfiable, perform blame analysis
            blame_nodes = prune.get_blame_nodes()

            if blame_nodes is not None:
                self._blames_collection.add(
                    frozenset([Blame(n, n.production) for n in blame_nodes]))

            return False
        else:
            # If abstract semantics is satisfiable, start interpretation
            constraint_interpreter = ConstraintInterpreter(
                self._interp, example.input)
            interpreter_output = constraint_interpreter.interpret(self._prog)
            return equal_output(interpreter_output, example.output)
 def gen_blame(prod):
     return frozenset([
         Blame(node=n, production=(prod if n is node else n.production))
         for n in base_nodes
     ])