Exemple #1
0
    def _codegenNtDefinition(self, languagename, ntdef):
        assert isinstance(ntdef, tlform.DefineLanguage.NtDefinition)
        for pat in ntdef.patterns:
            if self.context.get_toplevel_function_for_pattern(
                    languagename, repr(pat)) is None:
                PatternCodegen(self.modulebuilder, pat, self.context,
                               languagename, self.symgen).run()

        nameof_this_func = 'lang_{}_isa_nt_{}'.format(languagename,
                                                      ntdef.nt.prefix)
        term, match, matches = rpy.gen_pyid_for('term', 'match', 'matches')
        # for each pattern in ntdefinition
        # match = Match(...)
        # matches = matchpat(term, match, 0, 1)
        # if len(matches) != 0:
        #   return True
        fb = rpy.BlockBuilder()

        for pat in ntdef.patterns:
            func2call = self.context.get_toplevel_function_for_pattern(
                languagename, repr(pat))

            ifb = rpy.BlockBuilder()
            ifb.Return(rpy.PyBoolean(True))

            fb.AssignTo(matches).FunctionCall(func2call, term)
            fb.If.LengthOf(matches).NotEqual(rpy.PyInt(0)).ThenBlock(ifb)
        fb.Return(rpy.PyBoolean(False))

        self.modulebuilder.Function(nameof_this_func).WithParameters(
            term).Block(fb)
Exemple #2
0
    def run(self):
        self.modulebuilder.IncludeFromPythonSource('runtime/term.py')
        self.modulebuilder.IncludeFromPythonSource('runtime/parser.py')
        self.modulebuilder.IncludeFromPythonSource('runtime/fresh.py')
        self.modulebuilder.IncludeFromPythonSource('runtime/match.py')

        # parse all term literals.
        # ~~ 26.07.2020 disable lit terms for now, need to implement
        # nt caching acceleration technique first.
        """
        tmp0, tmp1 = rpy.gen_pyid_temporaries(2, self.symgen)
        for trm, sym1 in self.context._litterms.items():
            sym1 = rpy.gen_pyid_for(sym1)
            self.modulebuilder.AssignTo(tmp0).New('Parser', rpy.PyString(repr(trm)))
            self.modulebuilder.AssignTo(sym1).MethodCall(tmp0, 'parse')
        """

        # variable-not-otherwise-mentioned of given define language
        for ident, variables in self.context.get_variables_mentioned_all():
            ident = rpy.gen_pyid_for(ident)
            variables = map(lambda v: rpy.PyString(v), variables)
            self.modulebuilder.AssignTo(ident).PySet(*variables)

        for form in self.module.tlforms:
            self._visit(form)

        # generate main
        fb = rpy.BlockBuilder()
        symgen = SymGen()
        ## emit some dummy Terms to aid RPython with type inference.
        tmp0, tmp1, tmp2, tmp3, tmp4 = rpy.gen_pyid_temporaries(5, symgen)
        fb.AssignTo(tmp0).New('Integer', rpy.PyInt(0))
        fb.AssignTo(tmp1).New('Float', rpy.PyFloat(0.0))
        fb.AssignTo(tmp2).New('String', rpy.PyString("\"hello world!\""))
        fb.AssignTo(tmp3).New('Boolean', rpy.PyString("#f"))
        fb.AssignTo(tmp4).New('Variable', rpy.PyString("x"))
        for procedure in self.main_procedurecalls:
            tmpi = rpy.gen_pyid_temporaries(1, symgen)
            fb.AssignTo(tmpi).FunctionCall(procedure)
        fb.Return(rpy.PyInt(0))
        self.modulebuilder.Function('entrypoint').WithParameters(
            rpy.PyId('argv')).Block(fb)

        #required entry procedure for Rpython.

        fb = rpy.BlockBuilder()
        fb.Return(rpy.PyTuple(rpy.PyId('entrypoint'), rpy.PyNone()))
        self.modulebuilder.Function('target').WithParameters(
            rpy.PyVarArg('args')).Block(fb)

        # if __name__ == '__main__': entrypoint()
        # for python2.7 compatibility.
        ifb = rpy.BlockBuilder()
        tmp = rpy.gen_pyid_temporaries(1, self.symgen)
        ifb.AssignTo(tmp).FunctionCall('entrypoint', rpy.PyList())
        self.modulebuilder.If.Equal(rpy.PyId('__name__'),
                                    rpy.PyString('__main__')).ThenBlock(ifb)

        return rpy.Module(self.modulebuilder.build())
Exemple #3
0
    def _visitDefineReductionRelation(self, form):
        assert isinstance(form, tlform.DefineReductionRelation)
        # def reduction_relation_name(term):
        #   outterms = []
        # {for each case}
        # tmpi = rc(term)
        # outterms = outterms + tmp{i}
        # return outterms
        if form.domain != None:
            if self.context.get_toplevel_function_for_pattern(
                    form.languagename, repr(form.domain)) is None:
                PatternCodegen(self.modulebuilder, form.domain, self.context,
                               form.languagename, self.symgen).run()

        nameof_domaincheck = None
        if form.domain != None:
            nameof_domaincheck = self.context.get_toplevel_function_for_pattern(
                form.languagename, repr(form.domain))

        rcfuncs = []
        for rc in form.reductioncases:
            rcfunc = self._codegenReductionCase(rc, form.languagename,
                                                form.name, nameof_domaincheck)
            rcfuncs.append(rcfunc)

        terms, term = rpy.gen_pyid_for('terms', 'term')
        symgen = SymGen()

        fb = rpy.BlockBuilder()

        if nameof_domaincheck != None:
            tmp0 = rpy.gen_pyid_temporaries(1, symgen)
            ifb = rpy.BlockBuilder()
            tmpa = rpy.gen_pyid_temporaries(1, symgen)
            ifb.AssignTo(tmpa).MethodCall(term, TermMethodTable.ToString)
            ifb.RaiseException('reduction-relation not defined for %s', tmpa)

            fb.AssignTo(tmp0).FunctionCall(nameof_domaincheck, term)
            fb.If.LengthOf(tmp0).Equal(rpy.PyInt(0)).ThenBlock(ifb)

        fb.AssignTo(terms).PyList()
        for rcfunc in rcfuncs:
            tmpi = rpy.gen_pyid_temporaries(1, symgen)
            fb.AssignTo(tmpi).FunctionCall(rcfunc, term)
            fb.AssignTo(terms).Add(terms, tmpi)
        fb.Return(terms)

        nameof_function = '{}_{}'.format(form.languagename, form.name)
        self.context.add_reduction_relation(form.name, nameof_function)
        self.modulebuilder.Function(nameof_function).WithParameters(
            term).Block(fb)
        return form
Exemple #4
0
    def _visitRedexMatch(self, form, callself=True):
        assert isinstance(form, tlform.RedexMatch)
        assert False
        if self.context.get_toplevel_function_for_pattern(
                form.languagename, repr(form.pat)) is None:
            PatternCodegen(self.modulebuilder, form.pat, self.context,
                           form.languagename, self.symgen).run()

        TermCodegen(self.modulebuilder, self.context).transform(form.termstr)
        termfunc = self.context.get_function_for_term_template(form.termstr)

        matchfunc = self.context.get_toplevel_function_for_pattern(
            form.languagename, repr(form.pat))
        symgen = SymGen()

        matches, match, term = rpy.gen_pyid_for('matches', 'match', 'term')
        tmp0 = rpy.gen_pyid_temporaries(1, symgen)

        fb = rpy.BlockBuilder()
        fb.AssignTo(tmp0).New('Match')
        fb.AssignTo(term).FunctionCall(termfunc, tmp0)
        fb.AssignTo(matches).FunctionCall(matchfunc, term)
        fb.Print(matches)
        fb.Return(matches)

        # call redex-match itself.
        nameof_this_func = self.symgen.get('redexmatch')
        self.context.add_redexmatch_for(form, nameof_this_func)
        self.modulebuilder.Function(nameof_this_func).Block(fb)

        if callself:
            tmp0 = rpy.gen_pyid_temporaries(1, self.symgen)
            self.modulebuilder.AssignTo(tmp0).FunctionCall(nameof_this_func)
Exemple #5
0
    def _visitApplyReductionRelationAssertEqual(self, form):
        assert isinstance(form, tlform.ApplyReductionRelationAssertEqual)

        def gen_terms(termtemplates, fb, symgen):
            processed = []
            for expectedterm in termtemplates:
                TermCodegen(self.modulebuilder,
                            self.context).transform(expectedterm)
                expectedtermfunc = self.context.get_function_for_term_template(
                    expectedterm)
                tmpi, tmpj = rpy.gen_pyid_temporaries(2, symgen)
                fb.AssignTo(tmpi).New('Match')
                fb.AssignTo(tmpj).FunctionCall(expectedtermfunc, tmpi)
                processed.append(tmpj)
            tmpi = rpy.gen_pyid_temporaries(1, symgen)
            fb.AssignTo(tmpi).PyList(*processed)
            return tmpi

        nameof_reductionrelation = self.context.get_reduction_relation(
            form.reductionrelationname)

        fb = rpy.BlockBuilder()
        symgen = SymGen()
        tmp0 = rpy.gen_pyid_temporaries(1, symgen)
        expectedterms = gen_terms(form.expected_termtemplates, fb, symgen)
        terms = self._genreductionrelation(fb, symgen,
                                           nameof_reductionrelation, form.term)
        fb.AssignTo(tmp0).FunctionCall(TermHelperFuncs.AssertTermListsEqual,
                                       terms, expectedterms)

        nameof_function = self.symgen.get('applyreductionrelationassertequal')
        self.modulebuilder.Function(nameof_function).Block(fb)
        self.main_procedurecalls.append(nameof_function)
Exemple #6
0
    def transformMetafunctionApplication(self, node):
        assert isinstance(node, term.MetafunctionApplication)
        nameof_function = self.context.get_function_for_term_template(node)
        nodematch, nodeparameters, nodematchreads = self._gen_inputs(node)
        assert len(nodematchreads) == 0

        self.transform(node.termtemplate)

        ttmatch, ttparameters, _ = self._gen_inputs(node.termtemplate)
        func_tocall = self.context.get_function_for_term_template(
            node.termtemplate)

        metafunctionfunc = self.context.get_metafunction(node.metafunctionname)

        symgen = SymGen()
        tmp0, tmp1 = rpy.gen_pyid_temporaries(2, symgen)

        fb = rpy.BlockBuilder()
        fb.AssignTo(tmp0).FunctionCall(func_tocall, ttmatch, *ttparameters)
        fb.AssignTo(tmp1).FunctionCall(metafunctionfunc, tmp0)
        fb.Return(tmp1)
        self.modulebuilder.Function(nameof_function).WithParameters(
            nodematch, *nodeparameters).Block(fb)

        return node
Exemple #7
0
    def transformTermLiteral(self, node):
        assert isinstance(node, term.TermLiteral)
        funcname = self.context.get_function_for_term_template(node)
        match, parameters, matchreads = self._gen_inputs(node)

        symgen = SymGen()
        fb = rpy.BlockBuilder()
        tmp0 = rpy.gen_pyid_temporaries(1, symgen)
        if node.kind == term.TermLiteralKind.Variable:
            fb.AssignTo(tmp0).New('Variable', rpy.PyString(node.value))
        if node.kind == term.TermLiteralKind.Integer:
            fb.AssignTo(tmp0).New('Integer', rpy.PyInt(int(node.value)))
        if node.kind == term.TermLiteralKind.Float:
            fb.AssignTo(tmp0).New('Float', rpy.PyFloat(float(node.value)))
        if node.kind == term.TermLiteralKind.Hole:
            fb.AssignTo(tmp0).New('Hole')
        if node.kind == term.TermLiteralKind.String:
            fb.AssignTo(tmp0).New('String', rpy.PyString(node.value))
        if node.kind == term.TermLiteralKind.Boolean:
            fb.AssignTo(tmp0).New('Boolean', rpy.PyString(node.value))

        fb.Return(tmp0)

        self.modulebuilder.SingleLineComment(repr(node))
        self.modulebuilder.Function(funcname).WithParameters(match).Block(fb)
        return node
Exemple #8
0
    def __init__(self, module, context):
        assert isinstance(module, tlform.Module)
        assert isinstance(context, CompilationContext)
        self.module = module
        self.context = context
        self.symgen = SymGen()
        self.modulebuilder = rpy.BlockBuilder()

        self.main_procedurecalls = []
Exemple #9
0
    def _visitRedexMatchAssertEqual(self, form):
        def gen_matches(expectedmatches, fb, symgen):
            processedmatches = []
            for m in expectedmatches:
                tmp0 = rpy.gen_pyid_temporaries(1, symgen)
                fb.AssignTo(tmp0).New('Match')
                processedmatches.append(tmp0)
                for sym, termx in m.bindings:
                    tmp1, tmp2, tmp3, tmp4 = rpy.gen_pyid_temporaries(
                        4, symgen)
                    TermCodegen(self.modulebuilder,
                                self.context).transform(termx)
                    termfunc = self.context.get_function_for_term_template(
                        termx)
                    fb.AssignTo(tmp1).New('Match')
                    fb.AssignTo(tmp2).FunctionCall(termfunc, tmp1)
                    fb.AssignTo(tmp3).MethodCall(tmp0, MatchMethodTable.AddKey,
                                                 rpy.PyString(sym))
                    fb.AssignTo(tmp4).MethodCall(tmp0,
                                                 MatchMethodTable.AddToBinding,
                                                 rpy.PyString(sym), tmp2)
            tmpi = rpy.gen_pyid_temporaries(1, symgen)
            fb.AssignTo(tmpi).PyList(*processedmatches)
            return tmpi

        assert isinstance(form, tlform.RedexMatchAssertEqual)
        if self.context.get_toplevel_function_for_pattern(
                form.languagename, repr(form.pat)) is None:
            PatternCodegen(self.modulebuilder, form.pat, self.context,
                           form.languagename, self.symgen).run()
        TermCodegen(self.modulebuilder,
                    self.context).transform(form.termtemplate)
        matchfunc = self.context.get_toplevel_function_for_pattern(
            form.languagename, repr(form.pat))
        termfunc = self.context.get_function_for_term_template(
            form.termtemplate)
        symgen = SymGen()

        matches, match, term = rpy.gen_pyid_for('matches', 'match', 'term')
        fb = rpy.BlockBuilder()
        expectedmatches = gen_matches(form.expectedmatches, fb, symgen)
        tmp0, tmp1, tmp2 = rpy.gen_pyid_temporaries(3, symgen)
        fb.AssignTo(tmp0).New('Match')
        fb.AssignTo(term).FunctionCall(termfunc, tmp0)
        fb.AssignTo(matches).FunctionCall(matchfunc, term)
        fb.AssignTo(tmp1).FunctionCall('assert_compare_match_lists', matches,
                                       expectedmatches)
        fb.AssignTo(tmp2).FunctionCall(MatchHelperFuncs.PrintMatchList,
                                       matches)
        fb.Return(matches)

        nameof_this_func = self.symgen.get('redexmatchassertequal')
        self.context.add_redexmatch_for(form, nameof_this_func)
        self.modulebuilder.Function(nameof_this_func).Block(fb)

        self.main_procedurecalls.append(nameof_this_func)
Exemple #10
0
    def _visitReadFromStdinAndApplyReductionRelation(self, form):
        assert isinstance(form, tlform.ReadFromStdinAndApplyReductionRelation)

        reduction_relation_func = self.context.get_reduction_relation(
            form.reductionrelationname)
        symgen = SymGen()
        term = rpy.gen_pyid_for('term')
        tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7 = rpy.gen_pyid_temporaries(
            8, symgen)

        forb = rpy.BlockBuilder()
        forb.AssignTo(tmp3).FunctionCall(reduction_relation_func, term)
        forb.AssignTo(tmp2).Add(tmp2, tmp3)

        wh = rpy.BlockBuilder()
        wh.AssignTo(tmp2).PyList()
        wh.For(term).In(tmp1).Block(forb)
        wh.AssignTo(tmp1).PyId(tmp2)
        wh.AssignTo(tmp4).FunctionCall(TermHelperFuncs.PrintTermList, tmp1)

        fb = rpy.BlockBuilder()
        fb.AssignTo(tmp0).FunctionCall(ReadFromStdinAndParse)
        if form.metafunctionname != None:
            mfname = self.context.get_metafunction(form.metafunctionname)
            fb.AssignTo(tmp5).New('Variable',
                                  rpy.PyString(form.metafunctionname))
            fb.AssignTo(tmp6).New('Sequence', rpy.PyList(tmp5, tmp0))
            fb.AssignTo(tmp0).FunctionCall(mfname, tmp6)

        fb.AssignTo(tmp1).PyList(tmp0)
        fb.AssignTo(tmp4).FunctionCall(TermHelperFuncs.PrintTermList, tmp1)
        fb.While.LengthOf(tmp1).NotEqual(rpy.PyInt(0)).Block(wh)

        nameof_this_func = self.symgen.get('readfromstdinandeval')
        self.modulebuilder.Function(nameof_this_func).Block(fb)
        self.main_procedurecalls.append(nameof_this_func)

        return form
Exemple #11
0
    def _visitApplyReductionRelation(self, form):
        assert isinstance(form, tlform.ApplyReductionRelation)
        nameof_reductionrelation = self.context.get_reduction_relation(
            form.reductionrelationname)
        assert nameof_reductionrelation != None

        fb = rpy.BlockBuilder()
        symgen = SymGen()
        self._genreductionrelation(fb, symgen, nameof_reductionrelation,
                                   form.term)
        tmp1 = rpy.gen_pyid_temporaries(1, symgen)
        nameof_function = self.symgen.get('applyreductionrelation')
        self.modulebuilder.Function(nameof_function).Block(fb)
        self.modulebuilder.AssignTo(tmp1).FunctionCall(nameof_function)
Exemple #12
0
    def run(self):
        if self.context.get_function_for_pattern(self.languagename, repr(self.pattern)) is None:
            self.transform(self.pattern)

        if self.context.get_toplevel_function_for_pattern(self.languagename, repr(self.pattern)) is None:
            nameof_this_func = 'lang_{}_{}_toplevel'.format(self.languagename, self.symgen.get('pat'))
            self.context.add_toplevel_function_for_pattern(self.languagename, repr(self.pattern), nameof_this_func)

            assignable_symbols = self.pattern.getattribute(pattern.PatternAttribute.PatternVariables)
            symgen = SymGen()

            func2call = self.context.get_function_for_pattern(self.languagename, repr(self.pattern))

            term, match, matches, ret = rpy.gen_pyid_for('term', 'match', 'matches', 'ret')
            m, h, t = rpy.gen_pyid_for('m', 'h', 't')
            tmp0, tmp1 = rpy.gen_pyid_temporaries(2, symgen)

            forb = rpy.BlockBuilder()
            try: 
                symstoremove = self.pattern.getattribute(pattern.PatternAttribute.PatternVariablesToRemove)
                for sym in symstoremove:
                    tmpi = rpy.gen_pyid_temporaries(1, symgen)
                    forb.AssignTo(tmpi).MethodCall(m, MatchMethodTable.RemoveKey, rpy.PyString(sym))
            except: 
                pass
            forb.AssignTo(tmp0).MethodCall(ret, 'append', m)
            fb = rpy.BlockBuilder()
            fb.AssignTo(match).New('Match', self._assignable_symbols_to_rpylist(assignable_symbols))
            fb.AssignTo(matches).FunctionCall(func2call, term, match, rpy.PyInt(0), rpy.PyInt(1))
            fb.AssignTo(ret).PyList()
            fb.For(m, h, t).In(matches).Block(forb)
            fb.Return(ret)
            
            self.modulebuilder.SingleLineComment('toplevel {}'.format(repr(self.pattern)))
            self.modulebuilder.Function(nameof_this_func).WithParameters(term).Block(fb)

        return self.pattern
Exemple #13
0
    def _gen_match_function_for_primitive(self, functionname, isafunction, patstr, sym=None):
        # tmp0 = asafunction(term)
        # if tmp0 == True:
        #   tmp1 = match.addtobinding(sym, term) # this is optional of sym != None; useful for holes.
        #   head = head + 1
        #   return [(match, head, tail)]
        # return []
        symgen = SymGen()
        term, match, head, tail = rpy.gen_pyid_for('term', 'match', 'head', 'tail')
        tmp0, tmp1 = rpy.gen_pyid_temporaries(2, symgen)

        ifb1 = rpy.BlockBuilder()
        if sym is not None:
            ifb1.AssignTo(tmp0).MethodCall(match, MatchMethodTable.AddToBinding, rpy.PyString(sym), term)
        ifb1.AssignTo(head).Add(head, rpy.PyInt(1))
        ifb1.Return(rpy.PyList( rpy.PyTuple(match, head, tail) ))

        fb = rpy.BlockBuilder()
        fb.AssignTo(tmp0).FunctionCall(isafunction, term)
        fb.If.Equal(tmp0, rpy.PyBoolean(True)).ThenBlock(ifb1)
        fb.Return(rpy.PyList())

        self.modulebuilder.SingleLineComment(patstr)
        self.modulebuilder.Function(functionname).WithParameters(term, match, head, tail).Block(fb)
Exemple #14
0
    def _gen_inconsistent_ellipsis_match_counts(self, foreach, bb, symgen):
        # store in the set and assert length of the set is 1
        assert isinstance(bb, rpy.BlockBuilder)
        tmps = []
        for ident, _ in foreach:
            idnt = rpy.gen_pyid_for(ident)
            tmpi = rpy.gen_pyid_temporaries(1, symgen)
            tmps.append(tmpi)
            bb.AssignTo(tmpi).MethodCall(idnt, TermMethodTable.Length)

        ifb = rpy.BlockBuilder()
        ifb.RaiseException('inconsistent ellipsis match counts')

        lengths = rpy.gen_pyid_for('lengths')
        bb.AssignTo(lengths).PySet(*tmps)
        bb.If.LengthOf(lengths).NotEqual(rpy.PyInt(1)).ThenBlock(ifb)
Exemple #15
0
    def gen_procedure_for_lit(self, lit, consumeprocedure, exactvalue):
        if self.context.get_function_for_pattern(self.languagename, repr(lit)) is not None:
            return lit

        nameof_this_func = 'lang_{}_consume_lit{}'.format(self.languagename, self.symgen.get())
        self.context.add_function_for_pattern(self.languagename, repr(lit), nameof_this_func)

        symgen = SymGen()
        term, match, head, tail = rpy.gen_pyid_for('term', 'match', 'head', 'tail')
        tmp0 = rpy.gen_pyid_temporaries(1, symgen)

        fb = rpy.BlockBuilder()
        fb.AssignTo(tmp0).FunctionCall(consumeprocedure, term, match, head, tail, exactvalue)
        fb.Return(tmp0)

        self.modulebuilder.SingleLineComment('#{}'.format(repr(lit)))
        self.modulebuilder.Function(nameof_this_func).WithParameters(term, match, head, tail).Block(fb)
        return lit
Exemple #16
0
    def _visitTermLetAssertEqual(self, form):
        assert isinstance(form, tlform.TermLetAssertEqual)

        template = form.template
        TermCodegen(self.modulebuilder, self.context).transform(template)
        templatetermfunc = self.context.get_function_for_term_template(
            template)

        TermCodegen(self.modulebuilder, self.context).transform(form.expected)
        expectedtermfunc = self.context.get_function_for_term_template(
            form.expected)

        fb = rpy.BlockBuilder()
        symgen = SymGen()

        expected, match = rpy.gen_pyid_for('expected', 'match')
        tmp0 = rpy.gen_pyid_temporaries(1, symgen)

        fb.AssignTo(tmp0).New('Match')
        fb.AssignTo(expected).FunctionCall(expectedtermfunc, tmp0)

        fb.AssignTo(match).New('Match')
        for variable, term in form.variableassignments.items():
            tmp1, tmp2, tmp3, tmp4 = rpy.gen_pyid_temporaries(4, symgen)

            TermCodegen(self.modulebuilder, self.context).transform(term)
            termfunc = self.context.get_function_for_term_template(term)

            fb.AssignTo(tmp1).New('Match')
            fb.AssignTo(tmp2).FunctionCall(termfunc, tmp1)
            fb.AssignTo(tmp3).MethodCall(match, MatchMethodTable.AddKey,
                                         rpy.PyString(variable))
            fb.AssignTo(tmp4).MethodCall(match, MatchMethodTable.AddToBinding,
                                         rpy.PyString(variable), tmp2)

        tmp0, tmp1, tmp2 = rpy.gen_pyid_temporaries(3, symgen)
        fb.AssignTo(tmp0).FunctionCall(templatetermfunc, match)
        fb.AssignTo(tmp1).FunctionCall('asserttermsequal', tmp0, expected)
        fb.AssignTo(tmp2).FunctionCall(TermHelperFuncs.PrintTerm, tmp0)

        nameof_this_func = self.symgen.get('asserttermequal')
        self.modulebuilder.Function(nameof_this_func).Block(fb)
        self.main_procedurecalls.append(nameof_this_func)
Exemple #17
0
    def transformPatternVariable(self, node):
        funcname = self.context.get_function_for_term_template(node)
        match, parameters, matchreads = self._gen_inputs(node)

        bb = rpy.BlockBuilder()

        if len(parameters) == 0:
            # must be of ellipsis depth 0
            assert len(matchreads) == 1
            ident, sym = matchreads[0]
            bb.AssignTo(ident).MethodCall(match, MatchMethodTable.GetBinding,
                                          sym)
            bb.Return(ident)
        else:
            assert len(parameters) == 1
            bb.Return(parameters[0])

        self.modulebuilder.SingleLineComment(repr(node))
        self.modulebuilder.Function(funcname).WithParameters(
            match, *parameters).Block(bb)
        return node
Exemple #18
0
    def transformPyCall(self, pycall):
        assert isinstance(pycall, term.PyCall)
        # codegen nested terms
        for t in pycall.termargs:
            self.transform(t)

        match, parameters, matchreads = self._gen_inputs(pycall)
        assert len(matchreads) == 0 and len(
            parameters) == 0  # expecting only match parameter for pycalls.

        # First generate nested terms and then call python function with them as arguments
        symgen = SymGen()
        pycallarguments = [
        ]  # will be calling python function with these arguments.

        fb = rpy.BlockBuilder()
        for t in pycall.termargs:
            tmpi = rpy.gen_pyid_temporaries(1, symgen)
            funcname = self.context.get_function_for_term_template(t)

            tmatch, tparameters, _ = self._gen_inputs(t)
            assert len(tparameters) == 0
            tmpi = rpy.gen_pyid_temporaries(1, symgen)
            pycallarguments.append(tmpi)
            fb.AssignTo(tmpi).FunctionCall(funcname, tmatch, *tparameters)

        funcname = self.context.get_function_for_term_template(pycall)
        tmpi = rpy.gen_pyid_temporaries(1, symgen)

        fb.AssignTo(tmpi).FunctionCall(pycall.functionname, *pycallarguments)
        fb.Return(tmpi)

        self.modulebuilder.SingleLineComment(repr(pycall))
        self.modulebuilder.Function(funcname).WithParameters(
            match, *parameters).Block(fb)

        return pycall
Exemple #19
0
    def transformInHole(self, inhole):
        assert isinstance(inhole, term.InHole)
        # T1 = call inhole.term1
        # T2 = call inhole.term2
        # plug(T1, T2)
        self.transform(inhole.term1)
        self.transform(inhole.term2)

        funcname = self.context.get_function_for_term_template(inhole)
        match, parameters, matchreads = self._gen_inputs(inhole)
        #FIXME not sure about this.
        assert len(matchreads) == 0

        fb = rpy.BlockBuilder()

        plugholeargs = []
        t1 = rpy.gen_pyid_for('t1')
        t1func = self.context.get_function_for_term_template(inhole.term1)
        t1match, t1parameters, _ = self._gen_inputs(inhole.term1)
        fb.AssignTo(t1).FunctionCall(t1func, t1match, *t1parameters)
        plugholeargs.append(t1)

        t2 = rpy.gen_pyid_for('t2')
        t2func = self.context.get_function_for_term_template(inhole.term2)
        t2match, t2parameters, _ = self._gen_inputs(inhole.term2)
        fb.AssignTo(t2).FunctionCall(t2func, t2match, *t2parameters)
        plugholeargs.append(t2)

        ret = rpy.gen_pyid_for('ret')
        fb.AssignTo(ret).FunctionCall('plughole', *plugholeargs)
        fb.Return(ret)

        self.modulebuilder.SingleLineComment(repr(inhole))
        self.modulebuilder.Function(funcname).WithParameters(
            match, *parameters).Block(fb)
        return inhole
Exemple #20
0
    def _visitParseAssertEqual(self, form):
        assert isinstance(form, tlform.ParseAssertEqual)

        TermCodegen(self.modulebuilder,
                    self.context).transform(form.expected_termtemplate)
        termfunc = self.context.get_function_for_term_template(
            form.expected_termtemplate)

        symgen = SymGen()
        argterm = rpy.gen_pyid_for('argterm')
        tmp0, tmp1, tmp2, tmp3, tmp4, tmp5 = rpy.gen_pyid_temporaries(
            6, symgen)

        fb = rpy.BlockBuilder()
        fb.AssignTo(tmp0).New('Parser', rpy.PyString(form.string2parse))
        fb.AssignTo(tmp1).MethodCall(tmp0, 'parse')
        fb.AssignTo(tmp2).New('Match')
        fb.AssignTo(tmp3).FunctionCall(termfunc, tmp2)
        fb.AssignTo(tmp4).FunctionCall('asserttermsequal', tmp1, tmp3)
        fb.AssignTo(tmp5).FunctionCall(TermHelperFuncs.PrintTerm, tmp1)

        nameof_this_func = self.symgen.get('parseassertequal')
        self.modulebuilder.Function(nameof_this_func).Block(fb)
        self.main_procedurecalls.append(nameof_this_func)
Exemple #21
0
    def transformBuiltInPat(self, pat):
        assert isinstance(pat, pattern.BuiltInPat) 
        if pat.kind == pattern.BuiltInPatKind.Any:
            if self.context.get_function_for_pattern(self.languagename, repr(pat)) is None:
                nameof_this_func = 'match_lang_{}_builtin_{}'.format(self.languagename, self.symgen.get())
                self.context.add_function_for_pattern(self.languagename, repr(pat), nameof_this_func)

                # tmp0 = match.addtobinding(sym, term) 
                # head = head + 1
                # return [(match, head, tail)]
                symgen = SymGen()
                term, match, head, tail = rpy.gen_pyid_for('term', 'match', 'head', 'tail')
                tmp0 = rpy.gen_pyid_temporaries(1, symgen)

                fb = rpy.BlockBuilder()
                fb.AssignTo(tmp0).MethodCall(match, MatchMethodTable.AddToBinding, rpy.PyString(pat.sym), term)
                fb.AssignTo(head).Add(head, rpy.PyInt(1))
                fb.Return(rpy.PyList( rpy.PyTuple(match, head, tail) ))

                self.modulebuilder.SingleLineComment(repr(pat))
                self.modulebuilder.Function(nameof_this_func).WithParameters(term, match, head, tail).Block(fb)
            return pat

        elif pat.kind == pattern.BuiltInPatKind.VariableNotOtherwiseDefined:
            # generate isa function for variable-not-otherwise-mentioned here because we need to reference
            # compile-time generated language-specific array 'langname_variable_mentioned'
            if self.context.get_isa_function_name(self.languagename, pat.prefix) is None:
                nameof_this_func = 'lang_{}_isa_builtin_variable_not_othewise_mentioned'.format(self.languagename)
                self.context.add_isa_function_name(self.languagename, pat.prefix, nameof_this_func)

                symgen = SymGen()
                var, _ = self.context.get_variables_mentioned(self.languagename)
                var = rpy.gen_pyid_for(var)
                term = rpy.gen_pyid_for('term')
                tmp0, tmp1 = rpy.gen_pyid_temporaries(2, symgen)

                fb = rpy.BlockBuilder()
                fb.AssignTo(tmp0).FunctionCall(TermHelperFuncs.TermIsVariableNotOtherwiseMentioned, term, var)
                fb.Return(tmp0)

                self.modulebuilder.SingleLineComment('#Is this term {}?'.format(pat.prefix))
                self.modulebuilder.Function(nameof_this_func).WithParameters(term).Block(fb)
                """
                # tmp0 = term.kind()
                # if tmp0 == TermKind.Variable:
                #   tmp1 = term.value()
                #   if tmp1 not in var:
                #     return True
                # return False
                # This one is different from other built-in isa funcs because we do set membership test here.
                ifb2 = rpy.BlockBuilder()
                ifb2.Return(rpy.PyBoolean(True))

                ifb1 = rpy.BlockBuilder()
                ifb1.AssignTo(tmp1).MethodCall(term, TermMethodTable.Value)
                ifb1.If.NotContains(tmp1).In(var).ThenBlock(ifb2)

                fb = rpy.BlockBuilder()
                fb.If.IsInstance(term, 'Variable').ThenBlock(ifb1)
                fb.Return(rpy.PyBoolean(False))

                self.modulebuilder.SingleLineComment('#Is this term {}?'.format(pat.prefix))
                self.modulebuilder.Function(nameof_this_func).WithParameters(term).Block(fb)
                """

            ##----- generate actual match function
            if self.context.get_function_for_pattern(self.languagename, repr(pat)) is None:
                nameof_this_func = 'match_lang_{}_builtin_{}'.format(self.languagename, self.symgen.get())
                self.context.add_function_for_pattern(self.languagename, repr(pat), nameof_this_func)
                isafunc = self.context.get_isa_function_name(self.languagename, pat.prefix)
                self._gen_match_function_for_primitive(nameof_this_func, isafunc, repr(pat), sym=pat.sym)
            return pat
        else:
            if self.context.get_function_for_pattern(self.languagename, repr(pat)) is None:
                pat_isA_tab = {
                    pattern.BuiltInPatKind.Number:  TermHelperFuncs.TermIsNumber,
                    pattern.BuiltInPatKind.Integer: TermHelperFuncs.TermIsInteger,
                    pattern.BuiltInPatKind.Natural: TermHelperFuncs.TermIsNatural,
                    pattern.BuiltInPatKind.Float:   TermHelperFuncs.TermIsFloat,
                    pattern.BuiltInPatKind.String:  TermHelperFuncs.TermIsString,
                    pattern.BuiltInPatKind.Boolean: TermHelperFuncs.TermIsBoolean,
                    pattern.BuiltInPatKind.Hole:    TermHelperFuncs.TermIsHole,
                }

                try:
                    term_func = pat_isA_tab[pat.kind]
                    nameof_this_func = 'match_lang_{}_builtin_{}'.format(self.languagename, self.symgen.get())
                    self.context.add_function_for_pattern(self.languagename, repr(pat), nameof_this_func)
                    if pat.kind == pattern.BuiltInPatKind.Hole:
                        # 'hole' key is not present in the final Match object.
                        self._gen_match_function_for_primitive(nameof_this_func, term_func, repr(pat))
                    else:
                        self._gen_match_function_for_primitive(nameof_this_func, term_func, repr(pat), sym=pat.sym)
                except KeyError:
                    assert False, 'unsupported pattern' + pat.kind
            return pat
Exemple #22
0
    def transformInHole(self, pat):
        assert isinstance(pat, pattern.InHole)
        if not self.context.get_function_for_pattern(self.languagename, repr(pat)):
            functionname = 'lang_{}_builtin_inhole_{}'.format(self.languagename, self.symgen.get())
            self.context.add_function_for_pattern(self.languagename, repr(pat), functionname)
            # 1. Look up all the terms that match pat2. Store (term, [match]) pairs.
            # 2. For each matching term,
            #    1. Replace term with hole
            #    2. Try match pat1. If match is successful, copy term recursively starting from hole, 
            #       and add appropriate binding into matches associated with the term.
            #    3. Replace hole with term to restore the whole term to it's original state.

            pat1, pat2 = pat.pat1, pat.pat2
            self.transform(pat1)
            self.transform(pat2)

            matchpat1 = self.context.get_function_for_pattern(self.languagename, repr(pat1))
            matchpat2 = self.context.get_function_for_pattern(self.languagename, repr(pat2))

            assignable_syms1 = pat1.getattribute(pattern.PatternAttribute.PatternVariables)
            assignable_syms2 = pat2.getattribute(pattern.PatternAttribute.PatternVariables)
            assignable_syms_all = assignable_syms1.union(assignable_syms2)

            # def inhole(term, match, head, tail, path):
            # matches = []
            # inpat2match = Match(...)
            # pat2matches = pat2matchfunc(term, inpat2match, 0, 1)
            # if len(pat2matches) != 0:
            #     inpat1match = Match(...)
            #     tmp0 = path + [term]
            #     tmp1 = copy_path_and_replace_last(tmp0, hole)
            #     pat1matches = pat1matchfunc(tmp1, inpat1match, 0, 1)
            #     if len(pat1matches) != 0:
            #         tmp11 = head + 1
            #         for m1, h1, t1 in pat1matches:
            #             for m2, h2, t2 in pat2matches:
            #                 tmp2 = combine_matches(m1, m2)
            #                 tmp{i} = match.copy()
            #                 tmp{j} = tmp2.getbinding(...)              ; same for inpat2match
            #                 tmp{k} = tmp{i}.addtobinding(..., tmp{j})  ; same for inpat2match
            #                 tmp3 = matches.append((tmp{i}, tmp11, tail))
            # tmp4 = term.kind()
            # if tmp4 == Term.Sequence:
            #     tmp5 = path.append(term)
            #     tmp6 = term.length()
            #     for tmp10 in range(tmp6):
            #         tmp7 = term.get(tmp10)
            #         tmp8 = inhole(tmp7, match, head, tail, path)
            #         matches = matches + tmp8
            #     tmp9 = path.pop()
            # return matches 

            symgen = SymGen()
            lookupfuncname = 'lang_{}_inhole_{}_impl'.format(self.languagename, self.symgen.get())

            matches, hole = rpy.gen_pyid_for('matches', '{}_hole'.format(self.languagename))

            term, match, head, tail, path = rpy.gen_pyid_for('term', 'match', 'head', 'tail', 'path')
            m1, h1, t1 = rpy.gen_pyid_for('m1', 'h1', 't1')
            m2, h2, t2 = rpy.gen_pyid_for('m2', 'h2', 't2')

            pat1matches, inpat1match = rpy.gen_pyid_for('pat1matches', 'inpat1match')
            pat2matches, inpat2match = rpy.gen_pyid_for('pat2matches', 'inpat2match')

            tmp0, tmp1, tmp2, tmp3, tmp4 = rpy.gen_pyid_temporaries(5, symgen)
            tmp5, tmp6, tmp7, tmp8, tmp9 = rpy.gen_pyid_temporaries(5, symgen)
            tmp10, tmp11, tmp12 = rpy.gen_pyid_temporaries(3, symgen)

            tmpm = rpy.gen_pyid_temporaries(1, symgen)

            forb2 = rpy.BlockBuilder()
            forb2.AssignTo(tmp2).FunctionCall(MatchHelperFuncs.CombineMatches, m1, m2) 
            forb2.AssignTo(tmpm).MethodCall(match, MatchMethodTable.DeepCopy)
            for sym in assignable_syms_all:
                tmpi, tmpj = rpy.gen_pyid_temporaries(2, symgen)
                forb2.AssignTo(tmpi).MethodCall(tmp2, MatchMethodTable.GetBinding, rpy.PyString(sym))
                forb2.AssignTo(tmpj).MethodCall(tmpm, MatchMethodTable.AddToBinding, rpy.PyString(sym), tmpi)
            forb2.AssignTo(tmp3).MethodCall(matches, 'append', rpy.PyTuple(tmpm, tmp11, tail))

            forb1 = rpy.BlockBuilder()
            forb1.For(m2, h2, t2).In(pat2matches).Block(forb2)

            ifb0 = rpy.BlockBuilder()
            ifb0.AssignTo(tmp11).Add(head, rpy.PyInt(1))
            ifb0.AssignTo(tmp2).FunctionCall(MatchHelperFuncs.CartesianProductAndCombineWith, pat1matches, pat2matches, match, tmp11, tail)
            ifb0.AssignTo(matches).Add(matches, tmp2)

            #ifb0.For(m1, h1, t1).In(pat1matches).Block(forb1)

            ifb1 = rpy.BlockBuilder()
            ifb1.AssignTo(inpat1match).New('Match', self._assignable_symbols_to_rpylist(assignable_syms1))
            ifb1.AssignTo(tmp0).Add(path, rpy.PyList(term))
            ifb1.AssignTo(tmp1).FunctionCall(TermHelperFuncs.CopyPathAndReplaceLast, tmp0, hole)
            ifb1.AssignTo(pat1matches).FunctionCall(matchpat1, tmp1, inpat1match, rpy.PyInt(0), rpy.PyInt(1)) 
            ifb1.If.LengthOf(pat1matches).NotEqual(rpy.PyInt(0)).ThenBlock(ifb0)

            # ---------------

            forb1 = rpy.BlockBuilder()
            forb1.AssignTo(tmp7).MethodCall(term, TermMethodTable.Get, tmp10)
            forb1.AssignTo(tmp8).FunctionCall(lookupfuncname, tmp7, match, head, tail, path)
            forb1.AssignTo(matches).Add(matches, tmp8)

            ifb3 = rpy.BlockBuilder()
            ifb3.AssignTo(tmp5).MethodCall(path, 'append', term)
            ifb3.AssignTo(tmp6).MethodCall(term, TermMethodTable.Length)
            ifb3.For(tmp10).InRange(tmp6).Block(forb1)
            ifb3.AssignTo(tmp9).MethodCall(path, 'pop')

            # ----------------

            fb = rpy.BlockBuilder()
            fb.AssignTo(matches).PyList()
            fb.AssignTo(inpat2match).New('Match', self._assignable_symbols_to_rpylist(assignable_syms2))
            fb.AssignTo(pat2matches).FunctionCall(matchpat2, term, inpat2match, rpy.PyInt(0), rpy.PyInt(1))
            fb.If.LengthOf(pat2matches).NotEqual(rpy.PyInt(0)).ThenBlock(ifb1)
            #fb.AssignTo(tmp4).MethodCall(term, TermMethodTable.Kind)
            fb.If.IsInstance(term, 'Sequence').ThenBlock(ifb3)
            fb.Return(matches)

            self.modulebuilder.SingleLineComment('{}'.format(repr(pat)))
            self.modulebuilder.Function(lookupfuncname).WithParameters(term, match, head, tail, path).Block(fb)

            #-------- this produces top-level function with empty list representing the path.
            # We do constraint checking here also.
            symgen = SymGen()

            m, h, t = rpy.gen_pyid_for('m', 'h', 't')
            fb = rpy.BlockBuilder()
            fb.AssignTo(tmp0).FunctionCall(lookupfuncname, term, match, head, tail, rpy.PyList())
            if pat.constraintchecks != None:
                fb.AssignTo(matches).PyList()
                forb = rpy.BlockBuilder()
                for chck in pat.constraintchecks:
                    tmpi = rpy.gen_pyid_temporaries(1, symgen)
                    ifb = rpy.BlockBuilder()
                    ifb.Continue

                    forb.AssignTo(tmpi).MethodCall(m, MatchMethodTable.CompareKeys, rpy.PyString(chck.sym1), rpy.PyString(chck.sym2))
                    forb.If.NotEqual(tmpi, rpy.PyBoolean(True)).ThenBlock(ifb)

                tmp = rpy.gen_pyid_temporaries(1, symgen)
                forb.AssignTo(tmp).MethodCall(matches, 'append', rpy.PyTuple(m, h, t))
                fb.For(m, h, t).In(tmp0).Block(forb)
                fb.Return(matches)
            else:
                fb.Return(tmp0)

            self.modulebuilder.Function(functionname).WithParameters(term, match, head, tail).Block(fb)
Exemple #23
0
    def transformPatSequence(self, seq):
        assert isinstance(seq, pattern.PatSequence)
        if self.context.get_function_for_pattern(self.languagename, repr(seq)) is None:
            match_fn = 'language_{}_match_term_{}'.format(self.languagename, self.symgen.get())
            self.context.add_function_for_pattern(self.languagename, repr(seq), match_fn)
            
            # generate code for all elements of the sequence.
            for pat in seq:
                if not isinstance(pat, pattern.CheckConstraint):
                    self.transform(pat)

            # symgen for the function
            symgen = SymGen()
            term, match, head, tail = rpy.gen_pyid_for('term', 'match', 'head', 'tail')
            m, h, t = rpy.gen_pyid_for('m', 'h', 't')
            subhead, subtail = rpy.gen_pyid_for('subhead', 'subtail')

            fb = rpy.BlockBuilder()

            # ensure term is actually a sequence.
            #
            # tmp{i} = term.kind()
            # if tmp{i} != TermKind.Sequence:
            #   return []
            tmpi = rpy.gen_pyid_temporaries(1, symgen)

            ifb = rpy.BlockBuilder()
            ifb.Return(rpy.PyList())
            
            fb.If.NotIsInstance(term, 'Sequence').ThenBlock(ifb)

            # 'enter' the term
            # subhead = 0
            # subtail = term.length()
            fb.AssignTo(subhead).PyInt(0)
            fb.AssignTo(subtail).MethodCall(term, TermMethodTable.Length)

            # ensure number of terms in the sequence is at least equal to number of non Repeat patterns. 
            # if num_required is zero, condition is always false.
            # tmp{i} = subtail - subhead
            # if tmp{i} < num_required:
            #   return []
            num_required = seq.get_number_of_nonoptional_matches_between(0, len(seq))
            tmpi = rpy.gen_pyid_temporaries(1, symgen)

            ifb = rpy.BlockBuilder()
            ifb.Return(rpy.PyList())

            fb.AssignTo(tmpi).Subtract(subtail, subhead)
            fb.If.LessThan(tmpi, rpy.PyInt(num_required)).ThenBlock(ifb)

            # stick initial match object into array - simplifies codegen.
            previousmatches = rpy.gen_pyid_for('matches')
            fb.AssignTo(previousmatches).PyList( rpy.PyTuple(match, subhead, subtail) )

            for i, pat in enumerate(seq):
                matches = rpy.gen_pyid_temporary_with_sym('matches', symgen)

                if isinstance(pat, pattern.Repeat) :
                    # matches{i} = [] # get temporary with symbol
                    # for m,h,t in matches{i-1}:
                    #   tmp{i} = matchfn(term, m, h, t)   
                    #   matches{i} = matches{i} + tmp{i}
                    functionname = self.context.get_function_for_pattern(self.languagename, repr(pat))

                    tmpi, tmpj  = rpy.gen_pyid_temporaries(2, symgen)
                    forb = rpy.BlockBuilder()
                    forb.AssignTo(tmpi).FunctionCall(functionname, term, m, h, t)
                    forb.AssignTo(matches).Add(matches, tmpi)
                    fb.AssignTo(matches).PyList()
                    fb.For(m, h, t).In(previousmatches).Block(forb)

                    # ensure number of terms in the sequence is at least equal to number of non Repeat patterns after 
                    # this repeat pattern.
                    #
                    # matches{i} = []
                    # for m, h, t in matches{i-1}:
                    #   tmp{i} = t - h
                    #   if tmp{i} >= num_required:
                    #     tmp{j} = matches{i}.append((m, h, t))
                    # if len(matches{i}) == 0:
                    #   return matches{i} 
                    num_required = seq.get_number_of_nonoptional_matches_between(i, len(seq))
                    if num_required > 0:
                        previousmatches = matches
                        matches = rpy.gen_pyid_temporary_with_sym('matches', symgen)
                        tmpi, tmpj  = rpy.gen_pyid_temporaries(2, symgen)

                        ifb1 = rpy.BlockBuilder()
                        ifb1.AssignTo(tmpj).MethodCall(matches, 'append', rpy.PyTuple(m, h, t))

                        forb = rpy.BlockBuilder()
                        forb.AssignTo(tmpi).Subtract(t, h)
                        forb.If.GreaterEqual(tmpi, rpy.PyInt(num_required)).ThenBlock(ifb1)

                        ifb2 = rpy.BlockBuilder()
                        ifb2.Return(matches)

                        fb.AssignTo(matches).PyList()
                        fb.For(m, h, t).In(previousmatches).Block(forb)
                        fb.If.LengthOf(matches).Equal(rpy.PyInt(0)).ThenBlock(ifb2)

                            
                elif isinstance(pat, pattern.CheckConstraint):
                    # matches{i} = []
                    # for m, h, t in matches{i-1}:
                    #   tmp{i} = m.CompareKeys(sym1, sym2)
                    #   if tmp{i} == True:
                    #     tmp{j} = matches{i}.append( (m, h, t) )
                    # if len(matches{i}) == 0:
                    #   return matches{i} 
                    tmpi, tmpj, tmpk  = rpy.gen_pyid_temporaries(3, symgen)

                    ifb1 = rpy.BlockBuilder()
                    ifb1.AssignTo(tmpj).MethodCall(matches, 'append', rpy.PyTuple(m, h, t))

                    forb = rpy.BlockBuilder()
                    forb.AssignTo(tmpi).MethodCall(m, MatchMethodTable.CompareKeys, rpy.PyString(pat.sym1), rpy.PyString(pat.sym2))
                    forb.If.Equal(tmpi, rpy.PyBoolean(True)).ThenBlock(ifb1)

                    ifb2 = rpy.BlockBuilder()
                    ifb2.Return(matches)

                    fb.AssignTo(matches).PyList()
                    fb.For(m, h, t).In(previousmatches).Block(forb)
                    fb.If.LengthOf(matches).Equal(rpy.PyInt(0)).ThenBlock(ifb2)

                else:
                    # matches{i} = []
                    # for m, h, t in matches{i-1}:
                    #   tmp{j} = term.get(h)
                    #   tmp{i} = func(tmp{j}, m, h, t)
                    #   matches{i} = matches{i} + tmp{i}
                    # if len(matches{i}) == 0: 
                    #   return  matches{i} 
                    function = self.context.get_function_for_pattern(self.languagename, repr(pat))
                    tmpi, tmpj = rpy.gen_pyid_temporaries(2, symgen)

                    forb = rpy.BlockBuilder()

                    forb.AssignTo(tmpj).MethodCall(term, TermMethodTable.Get, h)
                    forb.AssignTo(tmpi).FunctionCall(function, tmpj, m, h, t)
                    forb.AssignTo(matches).Add(matches, tmpi)

                    ifb1 = rpy.BlockBuilder()
                    ifb1.Return(matches)

                    fb.AssignTo(matches).PyList()
                    fb.For(m, h, t).In(previousmatches).Block(forb)
                    fb.If.LengthOf(matches).Equal(rpy.PyInt(0)).ThenBlock(ifb1)

                previousmatches = matches

            # exit term
            # 
            # matches{i} = []
            # for m, h, t in matches{i-1}:
            #   if h == t:
            #     tmp{k} = head + 1
            #     tmp{i} = (m, head, tail)
            #     tmp{j} = matches{i}.append(tmp{i})
            # return matches{i}
            tmpi, tmpj, tmpk = rpy.gen_pyid_temporaries(3, symgen)
            matches = rpy.gen_pyid_temporary_with_sym('matches', symgen)

            ifb = rpy.BlockBuilder()
            ifb.AssignTo(tmpk).Add(head, rpy.PyInt(1))
            ifb.AssignTo(tmpi).PyTuple(m, tmpk, tail)
            ifb.AssignTo(tmpj).MethodCall(matches, 'append', tmpi)

            forb = rpy.BlockBuilder()
            forb.If.Equal(h, t).ThenBlock(ifb)

            fb.AssignTo(matches).PyList()
            fb.For(m, h, t).In(previousmatches).Block(forb)
            fb.Return(matches)

            self.modulebuilder.SingleLineComment(repr(seq))
            self.modulebuilder.Function(match_fn).WithParameters(term, match, head, tail).Block(fb)
Exemple #24
0
    def _visitDefineMetafunction(self, form):
        assert isinstance(form, tlform.DefineMetafunction)
        #def mf(argterm):
        #  tmp0 = domaincheck(argterm)
        #  if len(tmp0) == 0:
        #    raise Exception('mfname: term is not in my domain')
        #  { foreach reductioncase
        #  tmp{i} = mfcase(term)
        #  if len(tmp{i}) == 1:
        #    tmp{j} = tmp{i}[0]
        #    tmp{k} = codomaincheck(tmp{j})
        #    if len(tmp{k}) == 0:
        #      raise Exception('mfname: term not in my codomain')
        #    return tmp{j}
        #  }
        #  raise Exception('no metafuncion cases matched for term')
        mfname = form.contract.name
        nameof_function = self.symgen.get('metafunction')
        self.context.add_metafunction(mfname, nameof_function)

        if self.context.get_toplevel_function_for_pattern(
                form.languagename, repr(form.contract.domain)) is None:
            PatternCodegen(self.modulebuilder, form.contract.domain,
                           self.context, form.languagename, self.symgen).run()
        domainmatchfunc = self.context.get_toplevel_function_for_pattern(
            form.languagename, repr(form.contract.domain))
        if self.context.get_toplevel_function_for_pattern(
                form.languagename, repr(form.contract.codomain)) is None:
            PatternCodegen(self.modulebuilder, form.contract.codomain,
                           self.context, form.languagename, self.symgen).run()
        codomainmatchfunc = self.context.get_toplevel_function_for_pattern(
            form.languagename, repr(form.contract.codomain))

        symgen = SymGen()
        argterm = rpy.gen_pyid_for('argterm')
        tmp0, tmp1, tmp2 = rpy.gen_pyid_temporaries(3, symgen)

        tmpa = rpy.gen_pyid_temporaries(1, symgen)
        ifbd = rpy.BlockBuilder()
        ifbd.AssignTo(tmpa).MethodCall(argterm, TermMethodTable.ToString)
        ifbd.RaiseException(
            'meta-function {}: term %s not in my domain'.format(mfname), tmpa)

        fb = rpy.BlockBuilder()
        fb.AssignTo(tmp0).FunctionCall(domainmatchfunc, argterm)
        fb.If.LengthOf(tmp0).Equal(rpy.PyInt(0)).ThenBlock(ifbd)

        for i, mfcase in enumerate(form.cases):
            tmpi, tmpj, tmpk = rpy.gen_pyid_temporaries(3, symgen)
            mfcasefunc = self._codegenMetafunctionCase(form, mfcase, i,
                                                       nameof_function)

            tmpa = rpy.gen_pyid_temporaries(1, symgen)
            ifbi1 = rpy.BlockBuilder()
            ifbi1.AssignTo(tmpa).MethodCall(tmpj, TermMethodTable.ToString)
            ifbi1.RaiseException(
                'meta-function {}: term %s not in my codomain'.format(mfname),
                tmpa)

            ifbi2 = rpy.BlockBuilder()
            ifbi2.AssignTo(tmpj).ArrayGet(tmpi, rpy.PyInt(0))
            ifbi2.AssignTo(tmpk).FunctionCall(codomainmatchfunc, tmpj)
            ifbi2.If.LengthOf(tmpk).Equal(rpy.PyInt(0)).ThenBlock(ifbi1)
            ifbi2.Return(tmpj)

            fb.AssignTo(tmpi).FunctionCall(mfcasefunc, argterm)
            fb.If.LengthOf(tmpi).Equal(rpy.PyInt(1)).ThenBlock(ifbi2)

        fb.RaiseException(
            'meta-function \\"{}\\": no clauses matches'.format(mfname))

        self.modulebuilder.Function(nameof_function).WithParameters(
            argterm).Block(fb)
        return nameof_function
Exemple #25
0
            PatternCodegen(self.modulebuilder, case.patternsequence,
                           self.context, metafunction.languagename,
                           self.symgen).run()
        TermCodegen(self.modulebuilder,
                    self.context).transform(case.termtemplate)
        matchfunc = self.context.get_toplevel_function_for_pattern(
            metafunction.languagename, repr(case.patternsequence))
        termfunc = self.context.get_function_for_term_template(
            case.termtemplate)

        symgen = SymGen()
        argterm = rpy.gen_pyid_for('argterm')
        tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6 = rpy.gen_pyid_temporaries(
            7, symgen)

        ifb1 = rpy.BlockBuilder()
        ifb1.Return(tmp1)

        ifbx = rpy.BlockBuilder()
        ifbx.Continue

        forb = rpy.BlockBuilder()
        forb.AssignTo(tmp3).FunctionCall(termfunc, tmp2)

        ##FIXME temporary hack to simulate side-conditions in metafunctions.
        ##You'd use hand-written python function that returns None upon side-condition
        ## failure. Python functions are not allowed to return None otherwise.
        forb.If.IsNone(tmp3).ThenBlock(ifbx)
        forb.AssignTo(tmp4).MethodCall(tmp1, 'append', tmp3)

        tmpa = rpy.gen_pyid_temporaries(1, symgen)
Exemple #26
0
    def _codegenReductionCase(self,
                              rc,
                              languagename,
                              reductionrelationname,
                              nameof_domaincheck=None):
        assert isinstance(rc, tlform.DefineReductionRelation.ReductionCase)

        if self.context.get_toplevel_function_for_pattern(
                languagename, repr(rc.pattern)) is None:
            PatternCodegen(self.modulebuilder, rc.pattern, self.context,
                           languagename, self.symgen).run()
        TermCodegen(self.modulebuilder,
                    self.context).transform(rc.termtemplate)

        nameof_matchfn = self.context.get_toplevel_function_for_pattern(
            languagename, repr(rc.pattern))
        nameof_termfn = self.context.get_function_for_term_template(
            rc.termtemplate)

        nameof_rc = self.symgen.get('{}_{}_case'.format(
            languagename, reductionrelationname))

        symgen = SymGen()
        # terms = []
        # matches = match(term)
        # if len(matches) != 0:
        #   for match in matches:
        #     tmp0 = gen_term(match)
        #     tmp2 = match_domain(tmp0)
        #     if len(tmp2) == 0:
        #       raise Exception('reduction-relation {}: term reduced from {} to {} via rule {} and is outside domain')
        #     tmp1 = terms.append(tmp0)
        # return terms

        terms, term, matches, match = rpy.gen_pyid_for('terms', 'term',
                                                       'matches', 'match')
        tmp0, tmp1, tmp2 = rpy.gen_pyid_temporaries(3, symgen)

        forb = rpy.BlockBuilder()
        forb.AssignTo(tmp0).FunctionCall(nameof_termfn, match)
        if nameof_domaincheck is not None:
            ifb = rpy.BlockBuilder()
            tmpa, tmpb = rpy.gen_pyid_temporaries(2, symgen)
            ifb.AssignTo(tmpa).MethodCall(term, TermMethodTable.ToString)
            ifb.AssignTo(tmpb).MethodCall(tmp0, TermMethodTable.ToString)
            ifb.RaiseException('reduction-relation \\"{}\\": term reduced from %s to %s via rule \\"{}\\" is outside domain' \
                    .format(reductionrelationname, rc.name),
                    tmpa, tmpb)
            forb.AssignTo(tmp2).FunctionCall(nameof_domaincheck, tmp0)
            forb.If.LengthOf(tmp2).Equal(rpy.PyInt(0)).ThenBlock(ifb)
        forb.AssignTo(tmp1).MethodCall(terms, 'append', tmp0)

        ifb = rpy.BlockBuilder()
        ifb.For(match).In(matches).Block(forb)

        fb = rpy.BlockBuilder()
        fb.AssignTo(terms).PyList()
        fb.AssignTo(matches).FunctionCall(nameof_matchfn, term)
        fb.If.LengthOf(matches).NotEqual(rpy.PyInt(0)).ThenBlock(ifb)
        fb.Return(terms)

        self.modulebuilder.Function(nameof_rc).WithParameters(term).Block(fb)
        return nameof_rc
Exemple #27
0
    def transformRepeat(self, repeat):
        assert isinstance(repeat, pattern.Repeat)
        if self.context.get_function_for_pattern(self.languagename, repr(repeat)) is None:
            match_fn = 'match_{}_term_{}'.format(self.languagename, self.symgen.get())
            self.context.add_function_for_pattern(self.languagename, repr(repeat), match_fn)

            # codegen enclosed pattern 
            self.transform(repeat.pat)

            functionname = self.context.get_function_for_pattern(self.languagename, repr(repeat.pat))

            # retrieve all bindable elements
            assignable_symbols = repeat.getattribute(pattern.PatternAttribute.PatternVariables)

            symgen = SymGen()
            term, match, head, tail = rpy.gen_pyid_for('term', 'match', 'head', 'tail')
            if repeat.matchmode == pattern.RepeatMatchMode.Deterministic:
                
                tmp0, tmp1, tmp2, tmp3, tmp4 = rpy.gen_pyid_temporaries(5, symgen)

                # tmp0 = match.increasedepth(...)
                # while True:
                #   if head == tail:
                #     break
                #   tmp1 = term.get[head]
                #   tmp2 = match_term(tmp1, match, head, tail)
                #   if len(tmp2) == 0:
                #     break
                #   if len(tmp2) != 1:
                #     raise Exception
                #   tmp3 = tmp2[0]
                #   match = tmp3[0]
                #   head  = tmp3[1]
                # tmp4 = match.decreasedepth(...)
                # return (match, head, tail)

                # tmp0 = match.increasedepth(...)
                # outmatches = []
                # matches = [(tmp0, head, tail)]
                # while len(matches) != 0:
                #   nmatches = []
                #   for m, h, t in matches:
                #     if h == t:
                #       tmp1 = (m,h,t)
                #       tmp1 = completedmatches.append()
                #       continue
                #     tmp2 = term.get[h]
                #     tmp3 = match_term(tmp2, m, h, t) 
                #     if len(tmp3) == 0:
                #       completedmatches.append((m,h,t))
                #       continue
                #     nmatches = nmatches + tmp3
                #   matches = nmatches 
                # for match in outmatches:
                #   tmp4 = match.decreasedepth(...)
                # return outmatches
                matches, nmatches, outmatches = rpy.gen_pyid_for('matches', 'nmatches', 'outmatches')
                m, h, t = rpy.gen_pyid_for('m', 'h', 't')

                ifb1 = rpy.BlockBuilder()
                ifb1.AssignTo(tmp1).PyTuple(m, h, t)
                ifb1.AssignTo(tmp1).MethodCall(outmatches, 'append', tmp1)
                ifb1.Continue

                ifb2 = rpy.BlockBuilder()
                ifb2.AssignTo(tmp4).PyTuple(m, h, t)
                ifb2.AssignTo(tmp4).MethodCall(outmatches, 'append', tmp4)
                ifb2.Continue

                forb1 = rpy.BlockBuilder()
                forb1.If.Equal(h, t).ThenBlock(ifb1)
                forb1.AssignTo(tmp2).MethodCall(term, TermMethodTable.Get, h)
                forb1.AssignTo(tmp3).FunctionCall(functionname, tmp2, m, h, t)
                forb1.If.LengthOf(tmp3).Equal(rpy.PyInt(0)).ThenBlock(ifb2)
                forb1.AssignTo(nmatches).Add(nmatches, tmp3)

                whb = rpy.BlockBuilder()
                whb.AssignTo(nmatches).PyList()
                whb.For(m,h,t).In(matches).Block(forb1)
                whb.AssignTo(matches).PyId(nmatches)


                if len(assignable_symbols) != 0:
                    forb2 = rpy.BlockBuilder()
                    for bindable in assignable_symbols:
                        forb2.AssignTo(tmp4).MethodCall(m, MatchMethodTable.DecreaseDepth, rpy.PyString(bindable))


                fb = rpy.BlockBuilder()
                for bindable in assignable_symbols:
                    fb.AssignTo(tmp0).MethodCall(match, MatchMethodTable.IncreaseDepth, rpy.PyString(bindable))
                fb.AssignTo(outmatches).PyList()
                fb.AssignTo(matches).PyList( rpy.PyTuple(match, head, tail) )
                fb.While.LengthOf(matches).NotEqual(rpy.PyInt(0)).Block(whb)
                if len(assignable_symbols) != 0:
                    fb.For(m,h,t).In(outmatches).Block(forb2)
                fb.Return(outmatches)

                self.modulebuilder.SingleLineComment('{} deterministic'.format(repr(repeat)))
                self.modulebuilder.Function(match_fn).WithParameters(term, match, head, tail).Block(fb)

            if repeat.matchmode == pattern.RepeatMatchMode.NonDetermininstic:
                matches, queue = rpy.gen_pyid_for('matches', 'queue')
                m, h, t = rpy.gen_pyid_for('m', 'h', 't')
                tmp0, tmp1, tmp2, tmp3, tmp4 = rpy.gen_pyid_temporaries(5, symgen)

                # tmp0 = match.increasedepth(...)
                # tmp1 = (match, head, tail)
                # matches = [ tmp1 ]
                # queue   = [ tmp1 ]
                # while len(queue) != 0:
                #   m, h, t = queue.pop(0)
                #   if h == t:
                #      continue
                #   m = m.copy()
                #   tmp2 = term.get[h]
                #   tmp3 = match_term(tmp2, m, h, t)
                #   matches = matches + tmp3
                #   queue   = queue + tmp3
                # for m, h, t in matches:
                #   tmp4 = m.decreasedepth(...)
                # return matches
                ifb = rpy.BlockBuilder()
                ifb.Continue

                wb = rpy.BlockBuilder()
                wb.AssignTo(m, h, t).MethodCall(queue, 'pop', rpy.PyInt(0))
                wb.If.Equal(h, t).ThenBlock(ifb)
                wb.AssignTo(m).MethodCall(m, MatchMethodTable.DeepCopy)
                wb.AssignTo(tmp2).MethodCall(term, TermMethodTable.Get, h)
                wb.AssignTo(tmp3).FunctionCall(functionname, tmp2, m, h, t)
                wb.AssignTo(matches).Add(matches, tmp3)
                wb.AssignTo(queue).Add(queue, tmp3)

                if len(assignable_symbols) != 0:
                    forb = rpy.BlockBuilder()
                    for bindable in assignable_symbols:
                        forb.AssignTo(tmp4).MethodCall(m, MatchMethodTable.DecreaseDepth, rpy.PyString(bindable))

                fb = rpy.BlockBuilder()
                for bindable in assignable_symbols:
                    fb.AssignTo(tmp0).MethodCall(match, MatchMethodTable.IncreaseDepth, rpy.PyString(bindable))
                fb.AssignTo(tmp1).PyTuple(match, head, tail)
                fb.AssignTo(matches).PyList(tmp1)
                fb.AssignTo(queue).PyList(tmp1)
                fb.While.LengthOf(queue).NotEqual(rpy.PyInt(0)).Block(wb)
                if len(assignable_symbols) != 0:
                    fb.For(m, h, t).In(matches).Block(forb)
                fb.Return(matches)

                self.modulebuilder.SingleLineComment('{} non-deterministic'.format(repr(repeat)))
                self.modulebuilder.Function(match_fn).WithParameters(term, match, head, tail).Block(fb)
Exemple #28
0
    def transformTermSequence(self, termsequence):
        assert isinstance(termsequence, term.TermSequence)
        seqfuncname = self.context.get_function_for_term_template(termsequence)
        symgen = SymGen()

        match, parameters, matchreads = self._gen_inputs(termsequence)
        lst = rpy.gen_pyid_for('lst')
        fb = rpy.BlockBuilder()

        fb.AssignTo(lst).PyList()

        for var, sym in matchreads:
            fb.AssignTo(var).MethodCall(match, MatchMethodTable.GetBinding,
                                        sym)

        terms2codegen = [
        ]  # we will generate all nested terms after doing this sequence first.
        for t in termsequence.seq:
            if isinstance(t, term.Repeat):

                # for i in range(len(term)):
                #   tmp{i} = term{i}.get{i}
                #   tmp{j} = term{j}.get{i}
                #   ...
                #   tmp{x} = gen_term(tmp{i}, tmp{j} ...)
                #   seq.append(tmp{x})
                terms2codegen.append(
                    t.term
                )  ## FIXME it was term2codegen.append(t) before. Why did it work?
                foreach = t.getattribute(term.TermAttribute.ForEach)
                self._gen_inconsistent_ellipsis_match_counts(
                    foreach, fb, symgen)

                forb = rpy.BlockBuilder()
                tmpi = rpy.gen_pyid_temporaries(1, symgen)
                targuments = []
                for param, _ in foreach:
                    tmpj, param = rpy.gen_pyid_temporaries(
                        1, symgen), rpy.gen_pyid_for(param)
                    targuments.append(tmpj)
                    forb.AssignTo(tmpj).MethodCall(param, TermMethodTable.Get,
                                                   tmpi)

                tfunctionname = self.context.get_function_for_term_template(
                    t.term)
                tmpx, tmpy, tmpz = rpy.gen_pyid_temporaries(3, symgen)
                forb.AssignTo(tmpx).FunctionCall(tfunctionname, match,
                                                 *targuments)
                forb.AssignTo(tmpy).MethodCall(lst, 'append', tmpx)

                fb.AssignTo(tmpz).MethodCall(rpy.gen_pyid_for(foreach[0][0]),
                                             TermMethodTable.Length)
                fb.For(tmpi).InRange(tmpz).Block(forb)

            if isinstance(t, term.PatternVariable) or \
               isinstance(t, term.TermSequence)    or \
               isinstance(t, term.TermLiteral)     or \
               isinstance(t, term.InHole)          or \
               isinstance(t, term.MetafunctionApplication):
                terms2codegen.append(t)
                tmatch, tparameters, _ = self._gen_inputs(t)
                func_tocall = self.context.get_function_for_term_template(t)
                tmp0, tmp1 = rpy.gen_pyid_temporaries(2, symgen)

                fb.AssignTo(tmp0).FunctionCall(func_tocall, tmatch,
                                               *tparameters)
                fb.AssignTo(tmp1).MethodCall(lst, 'append', tmp0)

            if isinstance(t, term.PyCall):
                terms2codegen.append(t)
                funcname = self.context.get_function_for_term_template(t)
                tmatch, tparameters, _ = self._gen_inputs(t)
                assert len(tparameters) == 0

                if t.mode == term.PyCallInsertionMode.Append:
                    tmp0, tmp1 = rpy.gen_pyid_temporaries(2, symgen)
                    fb.AssignTo(tmp0).FunctionCall(funcname, tmatch,
                                                   *tparameters)
                    fb.AssignTo(tmp1).MethodCall(lst, 'append', tmp0)
                else:
                    # tmp0 = genterm(...)
                    # tmp1 = tmp0.kind()
                    # if tmp1 != TermKind.Sequence:
                    #  raise Exception(...)
                    # tmp4 = tmp0.length()
                    # for tmp5 in range(tmp4):
                    #   tmp2 = tmp0.get(tmp5)
                    #   tmp3 = lst.append(tmp2)
                    tmp0, tmp1, tmp2, tmp3, tmp4, tmp5 = rpy.gen_pyid_temporaries(
                        6, symgen)

                    ifb = rpy.BlockBuilder()
                    ifb.RaiseException('term is not Sequence!')

                    forb = rpy.BlockBuilder()
                    forb.AssignTo(tmp2).MethodCall(tmp0, TermMethodTable.Get,
                                                   tmp5)
                    forb.AssignTo(tmp3).MethodCall(lst, 'append', tmp2)

                    fb.AssignTo(tmp0).FunctionCall(funcname, tmatch,
                                                   *tparameters)
                    fb.If.NotIsInstance(tmp0, 'Sequence').ThenBlock(ifb)
                    fb.AssignTo(tmp4).MethodCall(tmp0, TermMethodTable.Length)
                    fb.For(tmp5).InRange(tmp4).Block(forb)

        tmpi = rpy.gen_pyid_temporaries(1, symgen)
        fb.AssignTo(tmpi).New('Sequence', lst)
        fb.Return(tmpi)

        self.modulebuilder.SingleLineComment(repr(termsequence))
        self.modulebuilder.Function(seqfuncname).WithParameters(
            match, *parameters).Block(fb)

        for t in terms2codegen:
            self.transform(t)
        return termsequence