Beispiel #1
0
    def generate_fcall_tail_call(self, opts):
        if opts["numbers"]:
            numbers = []
            for i in range(4):
                gen = self.rng.choice(opts["numbers"])
                gen.set_rng(self.rng)
                numbers.append(gen())
        else:
            numbers = ["1", "2", "3", "4"]

        func = self.create_function(["acc", "rest"])

        # generate an arith_integer function
        gen = pgen.ArithIntegerGenerator(
            self.module,
            self.stats,
            self.opts,
            self.rng)
        c = gen.generate(self.opts["arith_integer"], 2)
        self.module.content.insert(0, c)

        args = self.rng.sample(["acc", "rest"] + numbers, 2)
        result = self.next_variable()

        call = Assignment(result, '=', [CallStatement(c, args)])
        func.content.append(call)

        end = IfStatement("acc == 0",
                          ["return %s" % (result,)],
                          [Assignment(
                           "result", "=", [CallStatement(func, ["acc - 1", result])]),
                           "return result"])

        func.content.append(end)
        return func
Beispiel #2
0
    def generate_duck(self, literals):
        """Generate a duck typing callsite."""
        c, m = self.make_class_function()
        c_super, m_super = self.make_class_function()
        m_super.name = m.name

        self.make_fill(m)
        self.make_fill(m_super)

        class_var = self.next_variable()
        clause = self.rng.choice(
            list(
                literals)) + " < " + self.rng.choice(
                    list(
                        literals))
        i = IfStatement(clause,
                        [Assignment(class_var, '=', [CallStatement(c, [])])],
                        [Assignment(
                         class_var,
                         '=',
                         [CallStatement(c_super,
                                        [])])]
                        )
        result = [i]

        l = self.make_loop(literals, class_var, m)
        result.append(l)

        return result
Beispiel #3
0
    def generate_closure_tail_call(self, opts):
        if opts["numbers"]:
            numbers = []
            for i in range(4):
                gen = self.rng.choice(opts["numbers"])
                gen.set_rng(self.rng)
                numbers.append(gen())
        else:
            numbers = ["1", "2", "3", "4"]

        func = self.create_function(["acc", "rest"])

        exp = ArithGen(
            5,
            self.rng).generate(["closure[0]",
                                "acc",
                                "rest"] + numbers)

        var = self.next_variable()
        func.content.append(Assignment(var, '=', [exp]))
        func.content.append(Assignment("closure[0]", '+=', [var]))

        end = IfStatement("acc == 0",
                          ["return %s" % (var,)],
                          [Assignment(
                           "result", "=", [CallStatement(func, ["acc - 1", var])]),
                           "return result"])

        func.content.append(end)
        return func
Beispiel #4
0
    def generate(self, args_num, pliterals):
        """Returns a CallStatement."""

        args = self.generate_arguments(args_num)
        f = self.create_function(args)
        self.module.content.insert(0, f)

        literals = list(args) + [
            n.set_rng(self.rng)
            for n in [gen_max_int_gen(),
                      IntegerGen(-1000, 1000)]
        ]

        if self.stats.prog_size > 0:
            self.generate_child(f, literals)

        for i in range(10):
            result = self.next_variable()
            exp = ArithGen(2, self.rng).generate(literals)
            literals.append(result)

            f.content.append(Assignment(result, '=', [exp]))
            f.content.append("yield %s" % (result, ))

        pargs = self.rng.sample(pliterals, args_num)
        return CallStatement(f, pargs)
Beispiel #5
0
    def generate_child(self, func, literals):
        """Insert a function call to calculate some numbers."""
        gen = pgen.ArithIntegerGenerator(self.module, self.stats, self.opts,
                                         self.rng)
        c = gen.generate(self.opts["arith_integer"], 2)

        self.module.content.insert(0, c)

        args = self.rng.sample(literals, 2)
        result = self.next_variable()
        call = Assignment(result, '=', [CallStatement(c, args)])
        func.content.append(call)
        func.content.append("yield %s" % (result, ))
Beispiel #6
0
    def generate(self, opts, args_num, globals=[]):
        """Insert a new arithmetic function using only integers."""
        args = self.generate_arguments(args_num)

        closure = self.create_function(args)

        gen = self.create_function([])

        if opts['numbers']:
            number_gen = self.rng.choice(opts['numbers'])
            number_gen.set_rng(self.rng)
            number = number_gen()
        else:
            number = 0

        gen.content.extend([
            'closure = [%s]' % (number, ),
            closure,
            Assignment('func', '=', [closure.name]),
            'return func',
        ])

        c_var = self.next_variable()

        self.module.content.insert(0, gen)
        self.module.content.insert(
            1, Assignment(c_var, '=', [CallStatement(gen, [])]))

        gen_ai = ArithIntegerGenerator(self.module, self.stats, self.opts,
                                       self.rng)
        f = gen_ai.generate(self.opts['arith_integer'], args_num, [])

        self.module.content.insert(0, f)

        closure.content.append(
            Assignment('closure[0]', '+=', [CallStatement(f, args)]))
        closure.content.append('return closure[0]')

        return c_var
Beispiel #7
0
    def generate_monomorphic(self, literals):
        """Generates a monomorphic callsite."""
        c, m = self.make_class_function()

        self.make_fill(m)

        result = []

        class_var = self.next_variable()
        result.append(Assignment(class_var, '=', [CallStatement(c, [])]))

        l = self.make_loop(literals, class_var, m)
        result.append(l)
        return result
Beispiel #8
0
    def generate(self, opts, args_num, globals):
        fon = self.generate_globalon(opts)
        foff = self.generate_globaloff(opts)

        self.module.content.insert(0, fon)
        self.module.content.insert(0, foff)

        from . import iterables
        iter_gen = iterables.IterableGenerator(
            self.module,
            self.stats,
            self.opts,
            self.rng)

        if opts["numbers"]:
            numbers = []
            for i in range(4):
                gen = self.rng.choice(opts["numbers"])
                gen.set_rng(self.rng)
                numbers.append(gen())
        else:
            numbers = ["1", "2", "3", "4"]

        iter = iter_gen.get_iterable(numbers)

        f = self.create_function([])
        f.content.extend(
            [
                CallStatement(fon, []),
                Assignment("result", '=', [CallStatement("len", iter)]),
                CallStatement(foff, []),
                "return result"
            ]
        )

        return f
Beispiel #9
0
    def generate(self):
        """Instantiates a new module and fills it randomly."""
        self.module = Module(main=True)
        self.func_number = 1
        self.arg_number = 1
        lopts = self.opts["module"]

        self.prog_size = lopts["prog_size"]
        self.module_size = lopts["module_size"] - self.prog_size

        while self.module_size > 0 or self.prog_size > 0:
            main = []

            loop = ForLoop('i', ['range(%d)' % (lopts["mainloop"], )], main)

            if "children" in lopts:
                branch = eval_branches(self.rng, lopts["children"])
                if branch == "arith_integer":
                    main.append(Assignment('x', '=', ['5']))
                    f = self.arith_integer(self.opts[branch], 2)
                    main.append(
                        Assignment('x', '=', [CallStatement(f, ['x', 'i'])]))
                    main.append("print(x, end='')")

                    self.module.content.insert(0, f)
                if branch == "arith_float":
                    main.append(Assignment('x', '=', ['5.0']))
                    main.append("print(x, end='')")

            self.module.main_body.append(
                "print('prog_size: %d')" %
                (lopts["prog_size"] - self.prog_size, ))
            self.module.main_body.append("print('func_number: %d')" %
                                         (self.func_number, ))
            self.module.main_body.append("print('arg_number: %d')" %
                                         (self.arg_number, ))
            self.module.main_body.append(loop)

            created_size = lopts["prog_size"] - self.prog_size
            refill = min(created_size, self.module_size)

            self.module_size -= refill
            self.prog_size += refill

        self.module.content.insert(0, 'from __future__ import print_function')

        return self.module
Beispiel #10
0
    def make_loop(self, literals, class_var, m):
        loop_var = self.next_variable()
        iter = self.get_iterable(literals)

        l = ForLoop(loop_var, iter)

        loop_literals = list(literals) + [loop_var]

        args = [self.rng.choice(loop_literals) for i in m.args]
        if self.rng.random() < 0.5:
            func = class_var + '.' + m.name
        else:  # Sometimes copy the function into a variable
            func = self.next_variable()
            l.content.append(Assignment(func, '=', [class_var + '.' + m.name]))

        l.content.append(CallStatement(func, args))

        return l
Beispiel #11
0
    def generate(self, opts, args_num, globals):
        args = self.generate_arguments(args_num)
        func = self.create_function(args)

        branch = eval_branches(self.rng, opts["type"])

        if branch == "standard":
            rec = self.generate_standard_tail_call(opts)
        elif branch == "closure":
            func.content.append(Assignment("closure", "=", ["[0]"]))
            rec = self.generate_closure_tail_call(opts)
        else:
            rec = self.generate_fcall_tail_call(opts)

        func.content.append(rec)

        func.content.extend(
            [Assignment("result", "=", [CallStatement(rec, ["10", "0"])]),
             "return result"])

        self.module.content.append(func)

        return func
Beispiel #12
0
    def generate_child(self, opts, f, literals):
        branch = eval_branches(self.rng, opts['children'])
        if branch == 'arith_integer':
            gen = ArithIntegerGenerator(self.module, self.stats, self.opts,
                                        self.rng)
            c = gen.generate(opts, 2)
            self.module.content.insert(0, c)

            args = self.rng.sample(list(literals), 2)
            result = self.next_variable()

            call = Assignment(result, '=', [CallStatement(c, args)])
            f.content.append(call)
            literals.add(result)

        if branch == ('arith_integer', 'local'):
            gen = ArithIntegerGenerator(self.module, self.stats, self.opts,
                                        self.rng)
            c = gen.generate(opts, 2, list(literals))

            f.content.append(c)

            args = self.rng.sample(list(literals), 2)
            result = self.next_variable()

            call = Assignment(result, '=', [CallStatement(c, args)])
            f.content.append(call)
            literals.add(result)

        if branch == 'loop_integer':
            gen = LoopIntegerGenerator(self.module, self.stats, self.opts,
                                       self.rng)

            c = gen.generate(self.opts['loop_integer'], 2, [])
            self.module.content.insert(0, c)

            args = self.rng.sample(list(literals), 2)
            result = self.next_variable()

            call = Assignment(result, '=', [CallStatement(c, args)])
            f.content.append(call)
            literals.add(result)

        if branch == 'change_global':
            gen = ChangeGlobalGenerator(self.module, self.stats, self.opts,
                                        self.rng)

            c = gen.generate(self.opts['change_global'], 0, [])
            self.module.content.insert(0, c)

            result = self.next_variable()

            call = Assignment(result, '=', [CallStatement(c, [])])
            f.content.append(call)
            literals.add(result)

        if branch == 'integer_closure':
            gen = IntegerClosureGenerator(self.module, self.stats, self.opts,
                                          self.rng)
            func = gen.generate(self.opts['integer_closure'], 2, [])

            args = self.rng.sample(list(literals), 2)
            result = self.next_variable()

            call = Assignment(result, '=', [CallStatement(func, args)])
            f.content.append(call)
            literals.add(result)

        if branch == 'tail_recursion':
            gen = TailRecursionGenerator(self.module, self.stats, self.opts,
                                         self.rng)
            func = gen.generate(self.opts['tail_recursion'], 2, [])

            args = self.rng.sample(list(literals), 2)
            result = self.next_variable()

            call = Assignment(result, '=', [CallStatement(func, args)])
            f.content.append(call)
            literals.add(result)

        if branch == 'classes':
            from . import classes
            gen = classes.ClassGenerator(self.module, self.stats, self.opts,
                                         self.rng)
            result = gen.generate_inline(literals)

            f.content.extend(result)