示例#1
0
    def dire_expose_cmeth(self, name, parm, body):
        if body is None:
            body = 'return `concat`(`deleg_prefix,`name)((PyType)getSelf(),`all);'
        parm, prefix, body = self.expose_meth_body(name, parm, body)
        expose = self.get_aux('expose_narrow_cmeth')
        type_class = getattr(self, 'type_class', None)

        parms = parm.strip().split(None, 1)
        if len(parms) not in (1, 2):
            self.invalid(name, parm)
        if len(parms) == 1:
            parms.append('')
        expose_bindings = {}
        expose_bindings['typ'] = type_class
        expose_bindings['name'] = JavaTemplate(parms[0])
        expose_bindings['deleg_prefix'] = make_name(prefix)

        # !!!
        call_meths_bindings = expose_bindings.copy()

        body_bindings = self.global_bindings.copy()
        body_bindings.update(expose_bindings)

        call_meths_bindings['call_meths'] = self.get_aux('call_cmeths').tbind(
            {'typ': type_class})

        inst_call_meths, minargs, maxargs = self.handle_expose_meth_sig(
            parms[1], call_meths_bindings, body, body_bindings)

        expose_bindings['call_meths'] = inst_call_meths
        expose_bindings['minargs'] = JavaTemplate(str(minargs))
        expose_bindings['maxargs'] = JavaTemplate(str(maxargs))

        self.statements.append(expose.tbind(expose_bindings))
示例#2
0
    def dire_ctr(self, name, parm, body):
        if self.ctr_done:
            return
        if body is not None:
            self.invalid(name, "non-empty body")
        if self.want_dict:
            self.add_decl(self.get_aux('userdict'))
            ctr = self.get_aux('ctr_userdict')
        else:
            ctr = self.get_aux('ctr')
        extraargs = JavaTemplate(parm.strip(), start="FormalParameterListOpt")

        def visit(node):
            if isinstance(node, jast.VariableDeclaratorId):
                yield node.Identifier
            elif hasattr(node, 'children'):
                for child in node.children:
                    for x in visit(child):
                        yield x

        extra = jast_make(jast.Expressions, [
            jast_make(jast.Primary, Identifier=x, ArgumentsOpt=None)
            for x in visit(extraargs.fragment)
        ])
        extra = JavaTemplate(extra)
        self.add_decl(
            ctr.tbind({
                'base': self.base_class,
                'extraargs': extraargs,
                'extra': extra
            }))
        self.ctr_done = 1
示例#3
0
 def dire_unary1(self, name, parm, body):
     if body is not None:
         self.invalid(name, 'non-empty body')
     parms = parm.split()
     if len(parms) not in (1, 2, 3):
         self.invalid(name, parm)
     meth_name = parms[0]
     if len(parms) == 1:
         unary_body = self.get_aux('unary')
         self.add_decl(unary_body.tbind({'unary': JavaTemplate(meth_name)}))
     else:
         rettype_name = parms[1]
         if len(parms) == 3:
             rettype_class = parms[2]
         else:
             rettype_class = 'Py' + rettype_name[0].upper(
             ) + rettype_name[1:]
         unary_body = self.get_aux('typed_unary')
         self.add_decl(
             unary_body.tbind({
                 'unary':
                 JavaTemplate(meth_name),
                 'rettype_name':
                 JavaTemplate(java_parser.make_qualid(rettype_name)),
                 'rettype':
                 JavaTemplate(rettype_class)
             }))
示例#4
0
    def generate(self):
        typeinfo0 = self.get_aux("typeinfo0")

        basic = JavaTemplate("", start="ClassBodyDeclarations")

        bindings = self.global_bindings.copy()
        if hasattr(self, "type_as"):
            basic = basic + JavaTemplate(
                "public static final Class exposed_as = `as.class;", start="ClassBodyDeclarations"
            )
            bindings["as"] = self.type_as
        else:
            basic = basic + JavaTemplate(
                "public static final String exposed_name = `strfy`(`name);", start="ClassBodyDeclarations"
            )
            bindings["name"] = self.type_name
            if hasattr(self, "type_base_class"):
                basic = basic + JavaTemplate(
                    "public static final Class exposed_base = `base.class;", start="ClassBodyDeclarations"
                )
                bindings["base"] = self.type_base_class

        typeinfo = typeinfo0

        setup = JavaTemplate("", start="BlockStatements")
        if not self.no_setup:
            typeinfo1 = self.get_aux("typeinfo1")

            pair = self.get_aux("pair")
            for statement in self.statements:
                setup = pair.tbind({"trailer": setup, "last": statement})

            typeinfo = typeinfo.tfree() + typeinfo1.tfree()

        return typeinfo.tnaked().texpand({"basic": basic.tbind(bindings), "setup": setup}, nindent=1)
示例#5
0
    def dire_expose_getset(self, name, parm, body):
        if body is not None:
            self.invalid(name, 'non-empty body')

        parms = parm.strip().split()

        if len(parms) not in (2, 3, 4):
            self.invalid(name, parm)

        name = parms[0]
        get = '"%s"' % parms[1]

        if len(parms) >= 3:
            set = '"%s"' % parms[2]
        else:
            set = "null"

        if len(parms) == 4:
            del_meth = '"%s"' % parms[3]
        else:
            del_meth = "null"

        getset_bindings = self.global_bindings.copy()

        getset_bindings['name'] = JavaTemplate(make_id(name))
        getset_bindings['get'] = JavaTemplate(make_literal(get))
        getset_bindings['set'] = JavaTemplate(make_literal(set))
        getset_bindings['del'] = JavaTemplate(make_literal(del_meth))

        getset = self.get_aux('getset')

        self.statements.append(getset.tbind(getset_bindings))
示例#6
0
    def dire_expose_meth(self, name, parm, body):  # !!!
        parm, prefix, body = self.expose_meth_body(name, parm, body)
        expose = self.get_aux('expose_narrow_meth')

        type_class = getattr(self, 'type_class', None)
        type_name = getattr(self, 'type_name', None)
        if type_class is None or type_name is None:
            raise Exception, "type_class or type_name not defined"
        parms = parm.strip().split(None, 1)
        if len(parms) not in (1, 2):
            self.invalid(name, parm)
        if len(parms) == 1:
            parms.append('')
        expose_bindings = {}
        expose_bindings['typ'] = type_class
        expose_bindings['name'] = JavaTemplate(parms[0])
        expose_bindings['deleg_prefix'] = make_name(prefix)

        # !!!
        call_meths_bindings = expose_bindings.copy()

        body_bindings = self.global_bindings.copy()
        body_bindings.update(expose_bindings)

        call_meths_bindings['call_meths'] = self.get_aux('call_meths').tbind(
            {'typ': type_class})

        inst_call_meths, minargs, maxargs = self.handle_expose_meth_sig(
            parms[1], call_meths_bindings, body, body_bindings)

        expose_bindings['call_meths'] = inst_call_meths
        expose_bindings['minargs'] = JavaTemplate(str(minargs))
        expose_bindings['maxargs'] = JavaTemplate(str(maxargs))

        self.statements.append(expose.tbind(expose_bindings))
示例#7
0
    def handle_expose_meth_sig(self, sig, call_meths_bindings, body, body_bindings):
        proto_body_jt = JavaTemplate(body)
        everything, dfls = self.parse_sig("expose_meth", sig)

        dfls = map(JavaTemplate, dfls)

        tot = len(everything)
        rng = len(dfls) + 1

        for dflc in range(rng):
            new_body_bindings = body_bindings.copy()
            args = self.NOARGS
            all = self.EMPTYALL
            j = 0
            conv_errors = {}
            for k, tg in everything[: tot - dflc]:
                argj = "arg%d" % j
                args += JavaTemplate("void(PyObject %s)" % argj)
                new_body_bindings[argj], err = getattr(self, "arg_%s" % k)(argj, j, tg)
                all += JavaTemplate(jast_make(jast.Expressions, [new_body_bindings[argj].fragment]))
                if err:
                    conv_errors.setdefault(err, []).append(j)
                j += 1
            new_body_bindings["all"] = all
            for dv in dfls[rng - 1 - dflc :]:
                new_body_bindings["arg%d" % j] = dv
                j += 1
            for deleg_templ_name in (
                "void",
                "deleg",
                "vdeleg",
                "rdeleg",
                "ideleg",
                "ldeleg",
                "bdeleg",
                "sdeleg",
                "udeleg",
            ):
                deleg_templ = self.get_aux(deleg_templ_name)
                new_body_bindings[deleg_templ_name] = deleg_templ.tbind(new_body_bindings)
            body_jt = proto_body_jt.tbind(new_body_bindings)
            if conv_errors:
                cases = JavaTemplate(jast_make(jast.SwitchBlockStatementGroups))
                for err, indexes in conv_errors.items():
                    suite = JavaTemplate('msg = "%s"; break; ' % err).fragment.BlockStatements
                    cases += java_templating.switchgroup(indexes, suite)
                bindings = {"cases": cases, "unsafe_body": body_jt}
                body_jt = self.get_aux("conv_error_handling").tbind(bindings)

            call_meths_bindings["body%d" % dflc] = body_jt
            call_meths_bindings["args%d" % dflc] = args

        inst_call_meths = self.make_call_meths(rng, call_meths_bindings)

        return inst_call_meths, tot - rng + 1, tot
示例#8
0
 def make_call_meths(self, n, bindings):
     try:
         return self.call_meths_cache[n].tbind(bindings)
     except KeyError:
         templ = "`call_meths`(`args%d,`body%d);"
         defs = []
         for i in range(n):
             defs.append(templ % (i, i))
         defs = '\n'.join(defs)
         jtempl = JavaTemplate(defs, start='ClassBodyDeclarations')
         self.call_meths_cache[n] = jtempl
         return jtempl.tbind(bindings)
示例#9
0
 def make_call_meths(self,n,bindings):
     try:
         return self.call_meths_cache[n].tbind(bindings)
     except KeyError:
         templ = "`call_meths`(`args%d,`body%d);"
         defs = []
         for i in range(n):
             defs.append(templ % (i,i))
         defs = '\n'.join(defs)
         jtempl = JavaTemplate(defs,start='ClassBodyDeclarations')
         self.call_meths_cache[n] = jtempl
         return jtempl.tbind(bindings)
示例#10
0
 def dire_ibinary(self, name, parm, body):
     if body is not None:
         self.invalid(name, 'non-empty body')
     meth_names = parm.split()
     binary_body = self.get_aux('ibinary')
     for meth_name in meth_names:
         self.add_decl(binary_body.tbind({'binary': JavaTemplate(meth_name)}))
示例#11
0
 def dire_expose_new_immutable(self, name, parm, body):
     expose_new = self.get_aux('expose_new')
     parms = parm.split()
     body_bindings = self.global_bindings.copy()
     if body is not None:
         self.invalid(name, "non-empty body")
     body = self.get_aux('immutable_new_body')
     if not parms:
         parms = ['-1', '-1']
     else:
         if len(parms) != 2:
             self.invalid(name, parm)
     body_bindings['minargs'] = JavaTemplate(parms[0])
     body_bindings['maxargs'] = JavaTemplate(parms[1])
     body = body.tbind(body_bindings)
     templ = expose_new.tbind(body_bindings)
     self.statements.append(templ.tbind({'body': body}))
示例#12
0
 def dire_expose_new_mutable(self,name,parm,body):
     expose_new = self.get_aux('expose_new')
     parms = parm.split()
     body_bindings = self.global_bindings.copy()
     if body is None:
         body = self.get_aux('mutable_new_body')
     else:
         body = JavaTemplate(body)
     if not parms:
         parms = ['-1','-1']
     else:
         if len(parms) != 2:
             self.invalid(name,parm)
     body_bindings['minargs'] = JavaTemplate(parms[0])
     body_bindings['maxargs'] = JavaTemplate(parms[1])
     body = body.tbind(body_bindings)
     templ = expose_new.tbind(body_bindings)
     self.statements.append(templ.tbind({'body': body}))
示例#13
0
 def dire_expose_new_mutable(self, name, parm, body):
     expose_new = self.get_aux("expose_new")
     parms = parm.split()
     body_bindings = self.global_bindings.copy()
     if body is None:
         body = self.get_aux("mutable_new_body")
     else:
         body = JavaTemplate(body)
     if not parms:
         parms = ["-1", "-1"]
     else:
         if len(parms) != 2:
             self.invalid(name, parm)
     body_bindings["minargs"] = JavaTemplate(parms[0])
     body_bindings["maxargs"] = JavaTemplate(parms[1])
     body = body.tbind(body_bindings)
     templ = expose_new.tbind(body_bindings)
     self.statements.append(templ.tbind({"body": body}))
示例#14
0
 def dire_type_as(self, name, parm, body):
     if body is not None:
         self.invalid(name, 'non-empty body')
     parms = parm.split()
     if len(parms) not in (1, 2):
         self.invalid(name, parm)
     self.type_as = JavaTemplate(parms[0])
     if len(parms) == 2:
         if parms[1] == 'no-setup':
             self.no_setup = True
         else:
             self.invalid(name, parm)
示例#15
0
    def handle_expose_meth_sig(self, sig, call_meths_bindings, body,
                               body_bindings):
        proto_body_jt = JavaTemplate(body)
        everything, dfls = self.parse_sig('expose_meth', sig)

        dfls = map(JavaTemplate, dfls)

        tot = len(everything)
        rng = len(dfls) + 1

        for dflc in range(rng):
            new_body_bindings = body_bindings.copy()
            args = self.NOARGS
            all = self.EMPTYALL
            j = 0
            conv_errors = {}
            for k, tg in everything[:tot - dflc]:
                argj = "arg%d" % j
                args += JavaTemplate("void(PyObject %s)" % argj)
                new_body_bindings[argj], err = getattr(self,
                                                       'arg_%s' % k)(argj, j,
                                                                     tg)
                all += JavaTemplate(
                    jast_make(jast.Expressions,
                              [new_body_bindings[argj].fragment]))
                if err:
                    conv_errors.setdefault(err, []).append(j)
                j += 1
            new_body_bindings['all'] = all
            for dv in dfls[rng - 1 - dflc:]:
                new_body_bindings["arg%d" % j] = dv
                j += 1
            for deleg_templ_name in ('void', 'deleg', 'vdeleg', 'rdeleg',
                                     'ideleg', 'ldeleg', 'bdeleg', 'sdeleg',
                                     'udeleg'):
                deleg_templ = self.get_aux(deleg_templ_name)
                new_body_bindings[deleg_templ_name] = deleg_templ.tbind(
                    new_body_bindings)
            body_jt = proto_body_jt.tbind(new_body_bindings)
            if conv_errors:
                cases = JavaTemplate(jast_make(
                    jast.SwitchBlockStatementGroups))
                for err, indexes in conv_errors.items():
                    suite = JavaTemplate('msg = "%s"; break; ' %
                                         err).fragment.BlockStatements
                    cases += java_templating.switchgroup(indexes, suite)
                bindings = {'cases': cases, 'unsafe_body': body_jt}
                body_jt = self.get_aux('conv_error_handling').tbind(bindings)

            call_meths_bindings['body%d' % dflc] = body_jt
            call_meths_bindings['args%d' % dflc] = args

        inst_call_meths = self.make_call_meths(rng, call_meths_bindings)

        return inst_call_meths, tot - rng + 1, tot
示例#16
0
    def generate(self):
        typeinfo0 = self.get_aux('typeinfo0')

        basic = JavaTemplate("",start='ClassBodyDeclarations')
        
        bindings = self.global_bindings.copy()
        if hasattr(self,'type_as'):
            basic = (basic + 
              JavaTemplate("public static final Class exposed_as = `as.class;",
                           start = 'ClassBodyDeclarations'))
            bindings['as'] = self.type_as
        else:
            basic = (basic + 
              JavaTemplate(
                "public static final String exposed_name = `strfy`(`name);",
                start='ClassBodyDeclarations'))
            bindings['name'] = self.type_name
            if hasattr(self,'type_base_class'):
               basic = (basic + 
                 JavaTemplate(
                   "public static final Class exposed_base = `base.class;",
                   start='ClassBodyDeclarations'))
               bindings['base'] = self.type_base_class

        typeinfo = typeinfo0
        
        setup = JavaTemplate("",start='BlockStatements')
        if not self.no_setup:
            typeinfo1 = self.get_aux('typeinfo1')
            
            pair = self.get_aux('pair')
            for statement in self.statements:
                setup = pair.tbind({'trailer': setup, 'last': statement})
            
            typeinfo = typeinfo.tfree() + typeinfo1.tfree()

        return typeinfo.tnaked().texpand({'basic': basic.tbind(bindings),
                                         'setup': setup},nindent=1)
示例#17
0
 def dire_define(self, name, parm, body):
     parms = parm.split()
     if not parms:
         self.invalid('define', parm)
     parsed_name = modif_re.match(parms[0])
     if not parsed_name:
         self.invalid('define', parm)
     templ_kind = parsed_name.group(1)
     templ_name = parsed_name.group(2)
     if templ_kind is None:
         templ_kind = 'Fragment'
     
     templ = JavaTemplate(body,
                                          parms=':'.join(parms[1:]),
                                          bindings = self.global_bindings,
                                          start = templ_kind)
     self.global_bindings[templ_name] = templ
示例#18
0
    def __init__(self,bindings=None,priority_order=None):
        if bindings is None:
            self.global_bindings = { 'csub': java_templating.csub,
                                     'concat': java_templating.concat,
                                     'strfy': java_templating.strfy }
        else:
            self.global_bindings = bindings
            
        if priority_order:
            self.priority_order = priority_order

        self.decls = JavaTemplate("")

        self.auxiliary = None

        self.base_class = None
        self.want_dict = None
        self.no_toString = False
        self.ctr_done = 0
示例#19
0
    def generate(self):
        typeinfo0 = self.get_aux('typeinfo0')

        basic = JavaTemplate("", start='ClassBodyDeclarations')

        bindings = self.global_bindings.copy()
        if hasattr(self, 'type_as'):
            basic = (basic + JavaTemplate(
                "public static final Class exposed_as = `as.class;",
                start='ClassBodyDeclarations'))
            bindings['as'] = self.type_as
        else:
            basic = (basic + JavaTemplate(
                "public static final String exposed_name = `strfy`(`name);",
                start='ClassBodyDeclarations'))
            bindings['name'] = self.type_name
            if hasattr(self, 'type_base_class'):
                basic = (basic + JavaTemplate(
                    "public static final Class exposed_base = `base.class;",
                    start='ClassBodyDeclarations'))
                bindings['base'] = self.type_base_class

        typeinfo = typeinfo0

        setup = JavaTemplate("", start='BlockStatements')
        if not self.no_setup:
            typeinfo1 = self.get_aux('typeinfo1')

            pair = self.get_aux('pair')
            for statement in self.statements:
                setup = pair.tbind({'trailer': setup, 'last': statement})

            typeinfo = typeinfo.tfree() + typeinfo1.tfree()

        return typeinfo.tnaked().texpand(
            {
                'basic': basic.tbind(bindings),
                'setup': setup
            }, nindent=1)
示例#20
0
 def dire_expose_wide_meth(self, name, parm, body):  # !!!
     parm, prefix, body = self.expose_meth_body(name, parm, body)
     parms = parm.split()
     args = JavaTemplate("void(PyObject[] args,String[] keywords)")
     all = JavaTemplate("args, keywords", start='Expressions')
     bindings = self.global_bindings.copy()
     if len(parms) not in (1, 3):
         self.invalid(name, parm)
     bindings['name'] = JavaTemplate(parms[0])
     bindings['deleg_prefix'] = make_name(prefix)
     bindings['all'] = all
     bindings['args'] = args
     for deleg_templ_name in ('void', 'deleg', 'vdeleg', 'rdeleg'):
         deleg_templ = self.get_aux(deleg_templ_name)
         bindings[deleg_templ_name] = deleg_templ.tbind(bindings)
     body = JavaTemplate(body).tbind(bindings)
     bindings['body'] = body
     call_meths = self.get_aux('call_meths').tbind(bindings)
     bindings['call_meths'] = call_meths
     parms = (parms + [-1, -1])[1:3]
     bindings['minargs'] = JavaTemplate(parms[0])
     bindings['maxargs'] = JavaTemplate(parms[1])
     expose = self.get_aux('expose_wide_meth').tbind(bindings)
     self.statements.append(expose)
示例#21
0
 def arg_i(self, argj, j, tg):
     if tg:
         err = "%s must be an integer" % tg
     else:
         err = "expected an integer"
     return JavaTemplate("%s.asInt(%s)" % (argj, j)), err  # !!!
示例#22
0
 def dire_rest(self, name, parm, body):
     if parm:
         self.invalid(name, 'non-empty parm')
     if body is None:
         return
     self.add_decl(JavaTemplate(body, start='ClassBodyDeclarations'))   
示例#23
0
 def arg_b(self, argj, j, tg):
     return JavaTemplate("%s.__bool__()" % (argj)), None
示例#24
0
 def dire_base_class(self, name, parm, body):
     if body is not None:
         self.invalid(name, 'non-empty body')
     if self.base_class is None:
         self.base_class = JavaTemplate(parm.strip())
         self.global_bindings['base'] = self.base_class
示例#25
0
 def arg_o(self, argj, j, tg):
     return JavaTemplate(argj), None
示例#26
0
 def dire_type_class(self, name, parm, body):
     if body is not None:
         self.invalid(name, 'non-empty body')
     self.type_class = JavaTemplate(parm.strip())
     self.global_bindings['typ'] = self.type_class
示例#27
0
 def arg_S(self, argj, j, tg):
     if tg:
         err = "%s must be a string or None" % tg
     else:
         err = "expected a string or None"
     return JavaTemplate("%s.asStringOrNull(%s)" % (argj, j)), err  # !!!
示例#28
0
 def arg_n(self, argj, j, tg):
     if tg:
         err = "%s must be a string" % tg
     else:
         err = "expected a string"
     return JavaTemplate("%s.asName(%s)" % (argj, j)), err  # !!!
示例#29
0
def make_name(n):
    return JavaTemplate(
        jast_make(jast.QualifiedIdentifier, [java_parser.make_id(n)]))
示例#30
0
 def dire_rest(self, name, parm, body):
     if parm:
         self.invalid(name, 'non-empty parm')
     if body is None:
         return
     self.statements.append(JavaTemplate(body, start='BlockStatements'))
示例#31
0
 def arg_l(self, argj, j, tg):
     if tg:
         err = "%s must be a long" % tg
     else:
         err = "expected a long"
     return JavaTemplate("%s.asLong(%s)" % (argj, j)), err  # !!!
示例#32
0
 def dire_type_base_class(self, name, parm, body):
     if body is not None:
         self.invalid(name, 'non-empty body')
     self.type_base_class = JavaTemplate(parm.strip())
示例#33
0
class Gen:

    priority_order = [
        'require', 'define', 'type_as', 'type_name', 'type_class',
        'type_base_class', 'incl', 'expose_getset', 'expose_unary',
        'expose_binary', 'expose_vanilla_cmp', 'expose_vanilla_pow',
        'expose_key_getitem', 'expose_index_getitem', 'expose_cmeth',
        'expose_meth', 'expose_wide_meth', 'expose_new_mutable',
        'expose_new_immutable', 'rest'
    ]

    def __init__(self, bindings=None, priority_order=None):
        if bindings is None:
            self.global_bindings = {
                'csub': java_templating.csub,
                'concat': java_templating.concat,
                'strfy': java_templating.strfy
            }
        else:
            self.global_bindings = bindings

        if priority_order:
            self.priority_order = priority_order

        self.call_meths_cache = {}
        self.auxiliary = None

        self.no_setup = False
        self.statements = []

    def debug(self, bindings):
        for name, val in bindings.items():
            if isinstance(val, JavaTemplate):
                print "%s:" % name
                print val.texpand({})

    def invalid(self, dire, value):
        raise Exception, "invalid '%s': %s" % (dire, value)

    def get_aux(self, name):
        if self.auxiliary is None:
            aux_gen = Gen(priority_order=['require', 'define'])
            directives.execute(
                directives.load(os.path.join(scriptdir, 'gexpose-defs')),
                aux_gen)
            self.auxiliary = aux_gen.global_bindings
        return self.auxiliary[name]

    def dire_require(self, name, parm, body):
        if body is not None:
            self.invalid('require', 'non-empty body')
        sub_gen = Gen(bindings=self.global_bindings,
                      priority__order=['require', 'define'])
        directives.execute(directives.load(parm.strip()), sub_gen)

    def dire_define(self, name, parm, body):
        parms = parm.split()
        if not parms:
            self.invalid('define', parm)
        parsed_name = modif_re.match(parms[0])
        if not parsed_name:
            self.invalid('define', parm)
        templ_kind = parsed_name.group(1)
        templ_name = parsed_name.group(2)
        naked = False
        if templ_kind is None:
            templ_kind = 'Fragment'
        templ = JavaTemplate(body,
                             parms=':'.join(parms[1:]),
                             bindings=self.global_bindings,
                             start=templ_kind)
        self.global_bindings[templ_name] = templ

    def dire_type_as(self, name, parm, body):
        if body is not None:
            self.invalid(name, 'non-empty body')
        parms = parm.split()
        if len(parms) not in (1, 2):
            self.invalid(name, parm)
        self.type_as = JavaTemplate(parms[0])
        if len(parms) == 2:
            if parms[1] == 'no-setup':
                self.no_setup = True
            else:
                self.invalid(name, parm)

    def dire_type_name(self, name, parm, body):
        if body is not None:
            self.invalid(name, 'non-empty body')
        self.type_name_plain = parm.strip()
        self.type_name = make_name(self.type_name_plain)
        self.global_bindings['typname'] = self.type_name

    def dire_type_class(self, name, parm, body):
        if body is not None:
            self.invalid(name, 'non-empty body')
        self.type_class = JavaTemplate(parm.strip())
        self.global_bindings['typ'] = self.type_class

    def dire_type_base_class(self, name, parm, body):
        if body is not None:
            self.invalid(name, 'non-empty body')
        self.type_base_class = JavaTemplate(parm.strip())

    def dire_incl(self, name, parm, body):
        if body is not None:
            self.invalid(name, 'non-empty body')
        directives.execute(directives.load(parm.strip() + '.expose'), self)

    def dire_expose_getset(self, name, parm, body):
        if body is not None:
            self.invalid(name, 'non-empty body')

        parms = parm.strip().split()

        if len(parms) not in (2, 3, 4):
            self.invalid(name, parm)

        name = parms[0]
        get = '"%s"' % parms[1]

        if len(parms) >= 3:
            set = '"%s"' % parms[2]
        else:
            set = "null"

        if len(parms) == 4:
            del_meth = '"%s"' % parms[3]
        else:
            del_meth = "null"

        getset_bindings = self.global_bindings.copy()

        getset_bindings['name'] = JavaTemplate(make_id(name))
        getset_bindings['get'] = JavaTemplate(make_literal(get))
        getset_bindings['set'] = JavaTemplate(make_literal(set))
        getset_bindings['del'] = JavaTemplate(make_literal(del_meth))

        getset = self.get_aux('getset')

        self.statements.append(getset.tbind(getset_bindings))

    NOARGS = JavaTemplate("void()")
    EMPTYALL = JavaTemplate(jast_make(jast.Expressions))

    def parse_sig(self, name, sig):
        argspecs = []
        some_opt = 0
        for m in ktg_re.finditer(sig):
            k = m.group('k')
            opt = m.group('opt') and 1 or 0
            if opt:
                some_opt = 1
            if opt != some_opt:
                self.invalid(name,
                             "cannot interleave opt and non-opt arguments")
            dfl = m.group('dfl')
            if opt and dfl is None:
                dfl = ''
            tg = m.group('tg')
            argspecs.append((k, opt, dfl, tg))
        everything = [(k, tg) for k, opt, dfl, tg in argspecs]
        dfls = [dfl for k, opt, dfl, tg in argspecs if opt]
        return everything, dfls

    def arg_i(self, argj, j, tg):
        if tg:
            err = "%s must be an integer" % tg
        else:
            err = "expected an integer"
        return JavaTemplate("%s.asInt(%s)" % (argj, j)), err  # !!!

    def arg_l(self, argj, j, tg):
        if tg:
            err = "%s must be a long" % tg
        else:
            err = "expected a long"
        return JavaTemplate("%s.asLong(%s)" % (argj, j)), err  # !!!

    def arg_b(self, argj, j, tg):
        return JavaTemplate("%s.__bool__()" % (argj)), None

    def arg_o(self, argj, j, tg):
        return JavaTemplate(argj), None

    def arg_S(self, argj, j, tg):
        if tg:
            err = "%s must be a string or None" % tg
        else:
            err = "expected a string or None"
        return JavaTemplate("%s.asStringOrNull(%s)" % (argj, j)), err  # !!!

    def arg_s(self, argj, j, tg):
        if tg:
            err = "%s must be a string" % tg
        else:
            err = "expected a string"
        return JavaTemplate("%s.asString(%s)" % (argj, j)), err  # !!!

    def arg_n(self, argj, j, tg):
        if tg:
            err = "%s must be a string" % tg
        else:
            err = "expected a string"
        return JavaTemplate("%s.asName(%s)" % (argj, j)), err  # !!!

    def make_call_meths(self, n, bindings):
        try:
            return self.call_meths_cache[n].tbind(bindings)
        except KeyError:
            templ = "`call_meths`(`args%d,`body%d);"
            defs = []
            for i in range(n):
                defs.append(templ % (i, i))
            defs = '\n'.join(defs)
            jtempl = JavaTemplate(defs, start='ClassBodyDeclarations')
            self.call_meths_cache[n] = jtempl
            return jtempl.tbind(bindings)

    def handle_expose_meth_sig(self, sig, call_meths_bindings, body,
                               body_bindings):
        proto_body_jt = JavaTemplate(body)
        everything, dfls = self.parse_sig('expose_meth', sig)

        dfls = map(JavaTemplate, dfls)

        tot = len(everything)
        rng = len(dfls) + 1

        for dflc in range(rng):
            new_body_bindings = body_bindings.copy()
            args = self.NOARGS
            all = self.EMPTYALL
            j = 0
            conv_errors = {}
            for k, tg in everything[:tot - dflc]:
                argj = "arg%d" % j
                args += JavaTemplate("void(PyObject %s)" % argj)
                new_body_bindings[argj], err = getattr(self,
                                                       'arg_%s' % k)(argj, j,
                                                                     tg)
                all += JavaTemplate(
                    jast_make(jast.Expressions,
                              [new_body_bindings[argj].fragment]))
                if err:
                    conv_errors.setdefault(err, []).append(j)
                j += 1
            new_body_bindings['all'] = all
            for dv in dfls[rng - 1 - dflc:]:
                new_body_bindings["arg%d" % j] = dv
                j += 1
            for deleg_templ_name in ('void', 'deleg', 'vdeleg', 'rdeleg',
                                     'ideleg', 'ldeleg', 'bdeleg', 'sdeleg',
                                     'udeleg'):
                deleg_templ = self.get_aux(deleg_templ_name)
                new_body_bindings[deleg_templ_name] = deleg_templ.tbind(
                    new_body_bindings)
            body_jt = proto_body_jt.tbind(new_body_bindings)
            if conv_errors:
                cases = JavaTemplate(jast_make(
                    jast.SwitchBlockStatementGroups))
                for err, indexes in conv_errors.items():
                    suite = JavaTemplate('msg = "%s"; break; ' %
                                         err).fragment.BlockStatements
                    cases += java_templating.switchgroup(indexes, suite)
                bindings = {'cases': cases, 'unsafe_body': body_jt}
                body_jt = self.get_aux('conv_error_handling').tbind(bindings)

            call_meths_bindings['body%d' % dflc] = body_jt
            call_meths_bindings['args%d' % dflc] = args

        inst_call_meths = self.make_call_meths(rng, call_meths_bindings)

        return inst_call_meths, tot - rng + 1, tot

    def expose_meth_body(self, name, parm, body):
        parm = parm.strip()
        if parm.find('>') != -1:
            prefix, parm = parm.split('>', 1)
            parm = parm.strip()
        else:
            prefix = self.type_name_plain + '_'
        if body is not None:
            return parm, prefix, body
        if parm.startswith(':'):
            retk, rest = parm.split(None, 1)
            body = {
                ":i": "`ideleg;",
                ":l": "`ldeleg;",
                ":b": "`bdeleg;",
                ":s": "`sdeleg;",
                ":u": "`udeleg;",
                ":-": "`vdeleg; `void; ",
                ":o": "`rdeleg;"
            }.get(retk, None)
            if not body:
                self.invalid(name, retk)
            return rest, prefix, body
        else:
            return parm, prefix, "`rdeleg;"

    def dire_expose_meth(self, name, parm, body):  # !!!
        parm, prefix, body = self.expose_meth_body(name, parm, body)
        expose = self.get_aux('expose_narrow_meth')

        type_class = getattr(self, 'type_class', None)
        type_name = getattr(self, 'type_name', None)
        if type_class is None or type_name is None:
            raise Exception, "type_class or type_name not defined"
        parms = parm.strip().split(None, 1)
        if len(parms) not in (1, 2):
            self.invalid(name, parm)
        if len(parms) == 1:
            parms.append('')
        expose_bindings = {}
        expose_bindings['typ'] = type_class
        expose_bindings['name'] = JavaTemplate(parms[0])
        expose_bindings['deleg_prefix'] = make_name(prefix)

        # !!!
        call_meths_bindings = expose_bindings.copy()

        body_bindings = self.global_bindings.copy()
        body_bindings.update(expose_bindings)

        call_meths_bindings['call_meths'] = self.get_aux('call_meths').tbind(
            {'typ': type_class})

        inst_call_meths, minargs, maxargs = self.handle_expose_meth_sig(
            parms[1], call_meths_bindings, body, body_bindings)

        expose_bindings['call_meths'] = inst_call_meths
        expose_bindings['minargs'] = JavaTemplate(str(minargs))
        expose_bindings['maxargs'] = JavaTemplate(str(maxargs))

        self.statements.append(expose.tbind(expose_bindings))

    def dire_expose_cmeth(self, name, parm, body):
        if body is None:
            body = 'return `concat`(`deleg_prefix,`name)((PyType)getSelf(),`all);'
        parm, prefix, body = self.expose_meth_body(name, parm, body)
        expose = self.get_aux('expose_narrow_cmeth')
        type_class = getattr(self, 'type_class', None)

        parms = parm.strip().split(None, 1)
        if len(parms) not in (1, 2):
            self.invalid(name, parm)
        if len(parms) == 1:
            parms.append('')
        expose_bindings = {}
        expose_bindings['typ'] = type_class
        expose_bindings['name'] = JavaTemplate(parms[0])
        expose_bindings['deleg_prefix'] = make_name(prefix)

        # !!!
        call_meths_bindings = expose_bindings.copy()

        body_bindings = self.global_bindings.copy()
        body_bindings.update(expose_bindings)

        call_meths_bindings['call_meths'] = self.get_aux('call_cmeths').tbind(
            {'typ': type_class})

        inst_call_meths, minargs, maxargs = self.handle_expose_meth_sig(
            parms[1], call_meths_bindings, body, body_bindings)

        expose_bindings['call_meths'] = inst_call_meths
        expose_bindings['minargs'] = JavaTemplate(str(minargs))
        expose_bindings['maxargs'] = JavaTemplate(str(maxargs))

        self.statements.append(expose.tbind(expose_bindings))

    def dire_expose_unary(self, name, parm, body):
        if body is not None:
            self.invalid(name, 'non-empty body')
        meth_names = parm.split()
        if meth_names[0].endswith('>'):
            meth_names = ["%s %s" % (meth_names[0], n) for n in meth_names[1:]]
        unary_body = self.get_aux('unary').fragment
        for meth_name in meth_names:
            self.dire_expose_meth('expose_unary_1', meth_name, unary_body)

    def dire_expose_binary(self, name, parm, body):
        if body is not None:
            self.invalid(name, 'non-empty body')
        meth_names = parm.split()
        if meth_names[0].endswith('>'):
            meth_names = ["%s %s" % (meth_names[0], n) for n in meth_names[1:]]
        binary_body = self.get_aux('binary').fragment
        for meth_name in meth_names:
            self.dire_expose_meth('expose_binary_1', "%s o" % meth_name,
                                  binary_body)

    def dire_expose_key_getitem(self, name, parm, body):
        if body is not None:
            self.invalid(name, 'non-empty body')
        prefix = ""
        if parm.endswith('>'):
            prefix = parm
        key_getitem_body = self.get_aux('key_getitem').fragment
        self.dire_expose_meth('expose_key_getitem',
                              "%s __getitem__ o" % prefix, key_getitem_body)

    def dire_expose_index_getitem(self, name, parm, body):
        if body is not None:
            self.invalid(name, 'non-empty body')
        prefix = ""
        if parm.endswith('>'):
            prefix = parm
        index_getitem_body = self.get_aux('index_getitem').fragment
        self.dire_expose_meth('expose_index_getitem',
                              "%s __getitem__ o" % prefix, index_getitem_body)

    def dire_expose_vanilla_pow(self, name, parm, body):
        if body is not None:
            self.invalid(name, 'non-empty body')
        prefix = ""
        if parm.endswith('>'):
            prefix = parm
        vanilla_pow_body = self.get_aux('vanilla_pow').fragment
        self.dire_expose_meth('expose_vanilla_pow',
                              "%s __pow__ oo?(null)" % prefix,
                              vanilla_pow_body)

    def dire_expose_wide_meth(self, name, parm, body):  # !!!
        parm, prefix, body = self.expose_meth_body(name, parm, body)
        parms = parm.split()
        args = JavaTemplate("void(PyObject[] args,String[] keywords)")
        all = JavaTemplate("args, keywords", start='Expressions')
        bindings = self.global_bindings.copy()
        if len(parms) not in (1, 3):
            self.invalid(name, parm)
        bindings['name'] = JavaTemplate(parms[0])
        bindings['deleg_prefix'] = make_name(prefix)
        bindings['all'] = all
        bindings['args'] = args
        for deleg_templ_name in ('void', 'deleg', 'vdeleg', 'rdeleg'):
            deleg_templ = self.get_aux(deleg_templ_name)
            bindings[deleg_templ_name] = deleg_templ.tbind(bindings)
        body = JavaTemplate(body).tbind(bindings)
        bindings['body'] = body
        call_meths = self.get_aux('call_meths').tbind(bindings)
        bindings['call_meths'] = call_meths
        parms = (parms + [-1, -1])[1:3]
        bindings['minargs'] = JavaTemplate(parms[0])
        bindings['maxargs'] = JavaTemplate(parms[1])
        expose = self.get_aux('expose_wide_meth').tbind(bindings)
        self.statements.append(expose)

    def dire_expose_new_mutable(self, name, parm, body):
        expose_new = self.get_aux('expose_new')
        parms = parm.split()
        body_bindings = self.global_bindings.copy()
        if body is None:
            body = self.get_aux('mutable_new_body')
        else:
            body = JavaTemplate(body)
        if not parms:
            parms = ['-1', '-1']
        else:
            if len(parms) != 2:
                self.invalid(name, parm)
        body_bindings['minargs'] = JavaTemplate(parms[0])
        body_bindings['maxargs'] = JavaTemplate(parms[1])
        body = body.tbind(body_bindings)
        templ = expose_new.tbind(body_bindings)
        self.statements.append(templ.tbind({'body': body}))

    def dire_expose_new_immutable(self, name, parm, body):
        expose_new = self.get_aux('expose_new')
        parms = parm.split()
        body_bindings = self.global_bindings.copy()
        if body is not None:
            self.invalid(name, "non-empty body")
        body = self.get_aux('immutable_new_body')
        if not parms:
            parms = ['-1', '-1']
        else:
            if len(parms) != 2:
                self.invalid(name, parm)
        body_bindings['minargs'] = JavaTemplate(parms[0])
        body_bindings['maxargs'] = JavaTemplate(parms[1])
        body = body.tbind(body_bindings)
        templ = expose_new.tbind(body_bindings)
        self.statements.append(templ.tbind({'body': body}))

    def dire_rest(self, name, parm, body):
        if parm:
            self.invalid(name, 'non-empty parm')
        if body is None:
            return
        self.statements.append(JavaTemplate(body, start='BlockStatements'))

    def generate(self):
        typeinfo0 = self.get_aux('typeinfo0')

        basic = JavaTemplate("", start='ClassBodyDeclarations')

        bindings = self.global_bindings.copy()
        if hasattr(self, 'type_as'):
            basic = (basic + JavaTemplate(
                "public static final Class exposed_as = `as.class;",
                start='ClassBodyDeclarations'))
            bindings['as'] = self.type_as
        else:
            basic = (basic + JavaTemplate(
                "public static final String exposed_name = `strfy`(`name);",
                start='ClassBodyDeclarations'))
            bindings['name'] = self.type_name
            if hasattr(self, 'type_base_class'):
                basic = (basic + JavaTemplate(
                    "public static final Class exposed_base = `base.class;",
                    start='ClassBodyDeclarations'))
                bindings['base'] = self.type_base_class

        typeinfo = typeinfo0

        setup = JavaTemplate("", start='BlockStatements')
        if not self.no_setup:
            typeinfo1 = self.get_aux('typeinfo1')

            pair = self.get_aux('pair')
            for statement in self.statements:
                setup = pair.tbind({'trailer': setup, 'last': statement})

            typeinfo = typeinfo.tfree() + typeinfo1.tfree()

        return typeinfo.tnaked().texpand(
            {
                'basic': basic.tbind(bindings),
                'setup': setup
            }, nindent=1)