示例#1
0
class DefineLanguage_IdRewriter(pattern.PatternTransformer):
    def __init__(self, definelanguage):
        assert isinstance(definelanguage, tlform.DefineLanguage)
        super().__init__()
        self.definelanguage = definelanguage
        self.symgen = SymGen()

    def run(self):
        ntdefs = []
        for nt, ntdef in self.definelanguage.nts.items():
            npats = []
            for pat in ntdef.patterns:
                npat = self.transform(pat)
                npat.copyattributesfrom(pat)
                npats.append(npat)
            ntdefs.append(tlform.DefineLanguage.NtDefinition(ntdef.nt, npats))
        return tlform.DefineLanguage(self.definelanguage.name, ntdefs)

    def transformBuiltInPat(self, node):
        assert isinstance(node, pattern.BuiltInPat)
        nsym = self.symgen.get(node.prefix+'_')
        return pattern.BuiltInPat(node.kind, node.prefix, nsym).copyattributesfrom(node)

    def transformNt(self, node):
        assert isinstance(node, pattern.Nt)
        nsym = self.symgen.get(node.prefix+'_')
        return pattern.Nt(node.prefix, nsym).copyattributesfrom(node)
示例#2
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 = []
示例#3
0
    def __init__(self, variables, idof, context):
        self.idof = idof
        self.path = []
        self.context = context
        self.variables = variables
        self.symgen = SymGen()

        # stores annotations that will be injected into term-template after
        # visiting all the children.
        self.annotations = {
            term.TermAttribute.MatchRead: {},
            term.TermAttribute.InArg: {},
            term.TermAttribute.ForEach: {},
        }
示例#4
0
    def __init__(self, module, context, debug_dump_ntgraph=False):
        assert isinstance(module, tlform.Module)
        assert isinstance(context, CompilationContext)
        self.module = module
        self.context = context
        self.symgen = SymGen() 

        self.debug_dump_ntgraph = debug_dump_ntgraph

        # store reference to definelanguage structure for use by redex-match form
        self.definelanguages = {}
        self.definelanguageclosures = {}
        self.reductionrelations = {}
        self.metafunctions = {}
示例#5
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
示例#6
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)
示例#7
0
    def __init__(self):
        self.__variables_mentioned = {}
        self.__isa_functions = {}
        self.__pattern_code = {}
        self.__term_template_funcs = {}

        self._litterms = {}

        self.__toplevel_patterns = {}

        self.__reductionrelations = {}
        self.__metafuctions = {}

        self.__redexmatches = {}

        self.symgen = SymGen()
示例#8
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
示例#9
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)
示例#10
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())
示例#11
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)
示例#12
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
示例#13
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)
示例#14
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
示例#15
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)
示例#16
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
示例#17
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
示例#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
示例#19
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)
示例#20
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)
示例#21
0
 def __init__(self, pattern):
     self.pattern = pattern
     self.symgen = SymGen()
     self.symstoremove = []
示例#22
0
class Pattern_ConstraintCheckInserter(pattern.PatternTransformer):
    def __init__(self, pattern):
        self.pattern = pattern
        self.symgen = SymGen()
        self.symstoremove = []

    def run(self):
        pat, _ = self.transform(self.pattern)
        pat.addattribute(pattern.PatternAttribute.PatternVariablesToRemove,
                         self.symstoremove)
        return pat

    def _merge_variable_maps(self, m1, m2):
        m1k = set(list(m1.keys()))
        m2k = set(list(m2.keys()))
        intersection = m1k.intersection(m2k)
        nmap, syms2check = {}, []
        for k in intersection:
            syms2check.append((m1[k], m2[k]))
            nmap[k] = m2[k]
        for k in m1k:
            if k not in intersection:
                nmap[k] = m1[k]
        for k in m2k:
            nmap[k] = m2[k]
        return nmap, syms2check

    def transformInHole(self, node):
        assert isinstance(node, pattern.InHole)
        npat1, syms1 = self.transform(node.pat1)
        npat2, syms2 = self.transform(node.pat2)
        constraintchecks = []
        syms, syms2check = self._merge_variable_maps(syms1, syms2)
        for sym1, sym2 in syms2check:
            constraintchecks.append(pattern.CheckConstraint(sym1, sym2))
        return pattern.InHole(npat1, npat2,
                              constraintchecks).copyattributesfrom(node), syms

    def transformPatSequence(self, node):
        assert isinstance(node, pattern.PatSequence)
        if len(node.seq) == 0:
            return node, {}
        nseq = []
        npat, syms = self.transform(node.seq[0])
        nseq.append(npat)
        for pat in node.seq[1:]:
            npat, nsyms = self.transform(pat)
            nseq.append(npat)
            syms, syms2check = self._merge_variable_maps(syms, nsyms)
            for sym1, sym2 in syms2check:
                nseq.append(pattern.CheckConstraint(sym1, sym2))
        return pattern.PatSequence(nseq).copyattributesfrom(node), syms

    def transformRepeat(self, node):
        assert isinstance(node, pattern.Repeat)
        pat, syms = self.transform(node.pat)
        return pattern.Repeat(pat,
                              node.matchmode).copyattributesfrom(node), syms

    def transformNt(self, node):
        assert isinstance(node, pattern.Nt)
        # First time we see desired symbol we do not rename it - we will keep it in the end.
        nsym = self.symgen.get('{}#'.format(node.sym))
        if nsym == '{}#0'.format(node.sym):
            nsym = node.sym
        else:
            self.symstoremove.append(nsym)
        return pattern.Nt(node.prefix, nsym).copyattributesfrom(node), {
            node.sym: nsym
        }

    def transformBuiltInPat(self, node):
        assert isinstance(node, pattern.BuiltInPat)
        # First time we see desired symbol we do not rename it - we will keep it in the end.
        # Also we never bind holes.
        if node.kind != pattern.BuiltInPatKind.Hole:
            nsym = self.symgen.get('{}#'.format(node.sym))
            if nsym == '{}#0'.format(node.sym):
                nsym = node.sym
            else:
                self.symstoremove.append(nsym)
            return pattern.BuiltInPat(node.kind, node.prefix,
                                      nsym).copyattributesfrom(node), {
                                          node.sym: nsym
                                      }
        return node, {}

    def transformLit(self, pat):
        return pat, {}

    def transformCheckConstraint(self, node):
        return node, {}
示例#23
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
示例#24
0
class Term_EllipsisDepthChecker(term.TermTransformer):
    def __init__(self, variables, idof, context):
        self.idof = idof
        self.path = []
        self.context = context
        self.variables = variables
        self.symgen = SymGen()

        # stores annotations that will be injected into term-template after
        # visiting all the children.
        self.annotations = {
            term.TermAttribute.MatchRead: {},
            term.TermAttribute.InArg: {},
            term.TermAttribute.ForEach: {},
        }

    def add_annotation_to(self, node, attribute, value):
        attributedict = self.annotations[attribute]
        if node not in attributedict:
            attributedict[node] = []
        attributedict[node].append(value)

    def complete_annotation(self, oldnode, newnode):
        if isinstance(oldnode, term.Repeat):
            attributedict = self.annotations[term.TermAttribute.ForEach]
            contents = attributedict.get(oldnode, [])
            return newnode.addattribute(term.TermAttribute.ForEach, contents)

        attributedict = self.annotations[term.TermAttribute.MatchRead]
        contents = attributedict.get(oldnode, [])
        newnode.addattribute(term.TermAttribute.MatchRead, contents)
        attributedict = self.annotations[term.TermAttribute.InArg]
        contents = attributedict.get(oldnode, [])
        return newnode.addattribute(term.TermAttribute.InArg, contents)

    def contains_nonzero_foreach_annotations(self, node):
        assert isinstance(node, term.Repeat)
        attributedict = self.annotations[term.TermAttribute.ForEach]
        contents = attributedict.get(node, [])
        return len(contents) != 0

    def transform(self, element):
        assert isinstance(element, term.Term)
        method_name = 'transform' + element.__class__.__name__
        method_ref = getattr(self, method_name)
        self.path.append(element)
        result = method_ref(element)
        assert isinstance(result, term.Term)
        self.path.pop()
        return result

    def transformTermLiteral(self, literal):
        assert isinstance(literal, term.TermLiteral)
        #self.context.add_lit_term(literal)
        return literal

    def transformPyCall(self, pycall):
        assert isinstance(pycall, term.PyCall)
        terms = []
        for t in pycall.termargs:
            transformer = Term_EllipsisDepthChecker(self.variables, '',
                                                    self.context)
            terms.append(transformer.transform(t))
        return self.complete_annotation(
            pycall, term.PyCall(pycall.mode, pycall.functionname, terms))

    def transformRepeat(self, repeat):
        assert isinstance(repeat, term.Repeat)
        nrepeat = term.Repeat(self.transform(
            repeat.term)).copyattributesfrom(repeat)
        if not self.contains_nonzero_foreach_annotations(repeat):
            raise Exception('too many ellipses in template {}'.format(
                repr(nrepeat)))
        return self.complete_annotation(repeat, nrepeat)

    def transformTermSequence(self, termsequence):
        ntermsequence = super().transformTermSequence(termsequence)
        return self.complete_annotation(termsequence, ntermsequence)

    def transformInHole(self, inhole):
        ninhole = super().transformInHole(inhole)
        return self.complete_annotation(inhole, ninhole)

    def transformUnresolvedSym(self, node):
        assert isinstance(node, term.UnresolvedSym)
        if node.sym not in self.variables:
            t = term.TermLiteral(term.TermLiteralKind.Variable, node.sym)
            #self.context.add_lit_term(t)
            return t
        expecteddepth = self.variables[node.sym]
        actualdepth = 0

        param = self.symgen.get(node.sym)
        # definitely a pattern variable now, topmost entry on the stack is this node.
        for t in reversed(self.path):
            if isinstance(t, term.UnresolvedSym):
                if expecteddepth == 0:
                    self.add_annotation_to(t, term.TermAttribute.MatchRead,
                                           (node.sym, param))
                    break
                self.add_annotation_to(t, term.TermAttribute.InArg, param)
            if isinstance(t, term.TermSequence) or isinstance(t, term.InHole):
                if expecteddepth == actualdepth:
                    self.add_annotation_to(t, term.TermAttribute.MatchRead,
                                           (node.sym, param))
                    break
                else:
                    self.add_annotation_to(t, term.TermAttribute.InArg, param)
            if isinstance(t, term.Repeat):
                actualdepth += 1
                self.add_annotation_to(t, term.TermAttribute.ForEach,
                                       (param, actualdepth))

        if actualdepth != expecteddepth:
            raise Exception(
                'inconsistent ellipsis depth for pattern variable {}: expected {} actual {}'
                .format(node.sym, expecteddepth, actualdepth))

        return self.complete_annotation(node, term.PatternVariable(node.sym))
示例#25
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)
示例#26
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
示例#27
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
示例#28
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)
示例#29
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)
示例#30
0
class CompilationContext:
    def __init__(self):
        self.__variables_mentioned = {}
        self.__isa_functions = {}
        self.__pattern_code = {}
        self.__term_template_funcs = {}

        self._litterms = {}

        self.__toplevel_patterns = {}

        self.__reductionrelations = {}
        self.__metafuctions = {}

        self.__redexmatches = {}

        self.symgen = SymGen()

    def add_variables_mentioned(self, languagename, variables):
        assert languagename not in self.__variables_mentioned
        self.__variables_mentioned[languagename] = (
            '{}_variables_mentioned'.format(languagename), variables)

    def get_variables_mentioned(self, languagename):
        assert languagename in self.__variables_mentioned
        return self.__variables_mentioned[languagename]

    def get_variables_mentioned_all(self):
        return self.__variables_mentioned.values()

    def add_lit_term(self, term):
        self._litterms[term] = self.symgen.get('literal_term_')

    def add_isa_function_name(self, languagename, patrepr, functionname):
        k = (languagename, patrepr)
        assert k not in self.__isa_functions
        self.__isa_functions[k] = functionname

    def get_isa_function_name(self, languagename, patrepr):
        k = (languagename, patrepr)
        if k in self.__isa_functions:
            return self.__isa_functions[k]
        return None

    def get_sym_for_lit_term(self, term):
        return self._litterms[term]

    def add_function_for_pattern(self, languagename, patrepr, functionname):
        k = (languagename, patrepr)
        assert k not in self.__pattern_code, 'function for {}-{}  is present'.format(
            languagename, patrepr)
        self.__pattern_code[k] = functionname

    def get_function_for_pattern(self, languagename, patrepr):
        k = (languagename, patrepr)
        if k in self.__pattern_code:
            return self.__pattern_code[k]
        return None

    # generated and returns procedurename, boolean for given pattern. If boolean is True - the code for
    # pattern has already been generated.
    def get_function_for_pattern_2(self, languagename, patrepr):
        k = (languagename, patrepr)
        if k in self.__pattern_code:
            return self.__pattern_code[k], True
        self.__pattern_code[k] = self.symgen.get('pattern_match')
        return self.__pattern_code[k], False

    def add_toplevel_function_for_pattern(self, languagename, patrepr,
                                          functionname):
        k = (languagename, patrepr)
        assert k not in self.__toplevel_patterns, 'function for {}-{} is present'.format(
            languagename, patrepr)
        self.__toplevel_patterns[k] = functionname

    def get_toplevel_function_for_pattern(self, languagename, patrepr):
        k = (languagename, patrepr)
        if k in self.__toplevel_patterns:
            return self.__toplevel_patterns[k]
        return None

    def get_function_for_term_template(self, term_template):
        assert isinstance(term_template, term.Term)
        if term_template not in self.__term_template_funcs:
            name = self.symgen.get('gen_term')
            self.__term_template_funcs[term_template] = name
        return self.__term_template_funcs[term_template]

    def add_reduction_relation(self, reductionrelationname, function):
        k = reductionrelationname
        assert k not in self.__reductionrelations
        self.__reductionrelations[k] = function

    def get_reduction_relation(self, reductionrelationname):
        k = reductionrelationname
        if k in self.__reductionrelations:
            return self.__reductionrelations[k]
        return None

    def add_metafunction(self, mfname, function):
        k = mfname
        assert k not in self.__metafuctions
        self.__metafuctions[k] = function

    def get_metafunction(self, mfname):
        k = mfname
        if k in self.__metafuctions:
            return self.__metafuctions[k]
        return None

    def get_redexmatch_for(self, form):
        return self.__redexmatches[form]

    def add_redexmatch_for(self, form, name):
        self.__redexmatches[form] = name