From 04d02c1593eafb82a55cc55eae8673e6b41cde07 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Thu, 12 Feb 2015 10:48:41 -0800 Subject: [PATCH 1/3] new option `j2py --rusthon` outputs Rusthon syntax. --- bin/j2py | 19 ++++++++++--------- java2python/compiler/template.py | 8 +++++++- java2python/compiler/visitor.py | 14 ++++++++++++-- readme.md | 16 ++++++++++++---- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/bin/j2py b/bin/j2py index 6eb1a40..f4a8eac 100755 --- a/bin/j2py +++ b/bin/j2py @@ -17,8 +17,7 @@ from java2python.compiler import Module, buildAST, transformAST from java2python.config import Config from java2python.lib import escapes - -version = '0.5.1' +version = '0.5.2' def logLevel(value): @@ -87,7 +86,6 @@ def runTransform(options): """ Compile the indicated java source with the given options. """ timed = defaultdict(time) timed['overall'] - filein = fileout = filedefault = '-' if options.inputfile and not isinstance(options.inputfile, file): filein = options.inputfile @@ -116,11 +114,12 @@ def runTransform(options): return code timed['comp'] - try: - tree = buildAST(source) - except (Exception, ), exc: - exception('exception while parsing') - return 1 + tree = buildAST(source) + #try: + # tree = buildAST(source) + #except (Exception, ), exc: + # exception('exception while parsing') + # return 1 timed['comp_finish'] config = Config(configs) @@ -130,6 +129,7 @@ def runTransform(options): timed['visit'] module = Module(config) + module.set_global_options(options) module.sourceFilename = path.abspath(filein) if filein != '-' else None module.name = path.splitext(path.basename(filein))[0] if filein != '-' else '' module.walk(tree) @@ -161,7 +161,7 @@ def runTransform(options): module.name = path.splitext(filein)[0] if filein != '-' else '' print >> output, source - if not options.skipcompile: + if not options.skipcompile and not options.rusthon: try: compile(source, '', 'exec') except (SyntaxError, ), ex: @@ -243,6 +243,7 @@ def configScript(argv): help='Print lexer tokens to stderr.', default=False, action='store_true') add('-v', '--version', action='version', version='%(prog)s ' + version) + add('--rusthon', help='output rusthon code', action='store_true') ns = parser.parse_args(argv) if ns.inputfile == '-': diff --git a/java2python/compiler/template.py b/java2python/compiler/template.py index 4f4dfe1..e9632d3 100644 --- a/java2python/compiler/template.py +++ b/java2python/compiler/template.py @@ -20,6 +20,7 @@ from java2python.lang import tokens from java2python.lib import FS, colors +OPTIONS = None class Factory(object): """ Factory -> creates pre-configured callables for new block instances. @@ -162,6 +163,8 @@ def altIdent(self, name): return name if name in method.variables: return name + if OPTIONS and OPTIONS.rusthon: + raise RuntimeError('ooookkk') return ('cls' if method.isStatic else 'self') + '.' + name return name @@ -480,7 +483,10 @@ def iterDecl(self): def formatParam(p): if 'default' in p: return '{0}={1}'.format(p['name'], p['default']) - return p['name'] + if OPTIONS and OPTIONS.rusthon: + return '%s:%s' %(p['name'],p['type']) + else: + return p['name'] params = ', '.join(formatParam(param) for param in self.iterParams()) yield 'def {0}({1}):'.format(self.name, params) diff --git a/java2python/compiler/visitor.py b/java2python/compiler/visitor.py index f62e53e..dd413d5 100644 --- a/java2python/compiler/visitor.py +++ b/java2python/compiler/visitor.py @@ -20,6 +20,7 @@ from java2python.lang import tokens from java2python.lib import FS +OPTIONS = None class Memo(object): """ Memo -> AST walking luggage. """ @@ -33,6 +34,12 @@ class Base(object): commentSubs = map(recompile, ['^\s*/(\*)+', '(\*)+/\s*$', '^\s*//']) + def set_global_options(self, cfg): + global OPTIONS + OPTIONS = cfg + import java2python.compiler.template + java2python.compiler.template.OPTIONS = cfg + def accept(self, node, memo): """ Accept a node, possibly creating a child visitor. """ tokType = tokens.map.get(node.token.type) @@ -139,7 +146,6 @@ def acceptInterface(self, node, memo): class Module(TypeAcceptor, Base): """ Module -> accepts AST branches for module-level objects. """ - def makeAcceptHandledDecl(part): """ Creates an accept function for a decl to be processed by a handler. """ def acceptDecl(self, node, memo): @@ -169,6 +175,7 @@ def acceptModifierList(self, node, memo): def nodesToAnnos(self, branch, memo): """ Convert the annotations in the given branch to a decorator. """ + raise RuntimeError('nodesToAnnos') name = branch.firstChildOfType(tokens.IDENT).text init = branch.firstChildOfType(tokens.ANNOTATION_INIT_BLOCK) if not init: @@ -196,7 +203,10 @@ def nodesToModifiers(self, branch, root): if root.parentType in tokens.methodTypes: self.modifiers.extend(n.text for n in root.children) if self.isStatic and self.parameters: - self.parameters[0]['name'] = 'cls' + name = 'cls' + #if OPTIONS and OPTIONS.rusthon: + # name = 'cls:self' + self.parameters[0]['name'] = name self.modifiers.append(branch.text) diff --git a/readme.md b/readme.md index f38d91a..9eb7c31 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ ## java2python -Simple but effective tool to translate Java source code into Python. +Simple but effective tool to translate Java source code into Python and Rusthon. The java2python package can translate any syntactically valid Java source code @@ -30,12 +30,14 @@ class HelloWorld { } ``` -Next we run our program: - - +Convert Java Program To Python +----------------------------- ```bash $ j2py HelloWorld.java ``` + +Python Output +------------- ```python #!/usr/bin/env python """ generated source for module HelloWorld """ @@ -54,6 +56,12 @@ if __name__ == '__main__': HelloWorld.main(sys.argv) ``` +Convert to Rusthon +-------------- +```bash +$ j2py --rusthon HelloWorld.java +``` + [downloads]: https://github.com/natural/java2python/downloads [installation]: https://github.com/natural/java2python/tree/master/doc/install.md From dca878b65cf3d8886fa6593b790219c3a60e5f0d Mon Sep 17 00:00:00 2001 From: hartsantler Date: Thu, 12 Feb 2015 12:35:05 -0800 Subject: [PATCH 2/3] return `str` as `string` --- java2python/compiler/template.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java2python/compiler/template.py b/java2python/compiler/template.py index e9632d3..b4ade16 100644 --- a/java2python/compiler/template.py +++ b/java2python/compiler/template.py @@ -484,7 +484,9 @@ def formatParam(p): if 'default' in p: return '{0}={1}'.format(p['name'], p['default']) if OPTIONS and OPTIONS.rusthon: - return '%s:%s' %(p['name'],p['type']) + T = p['type'] + if T=='str': T = 'string' + return '%s:%s' %(p['name'],T) else: return p['name'] params = ', '.join(formatParam(param) for param in self.iterParams()) From adb46efac3d371f862b329a19ef5a8f0920de37e Mon Sep 17 00:00:00 2001 From: hartsantler Date: Wed, 18 Feb 2015 18:42:35 -0800 Subject: [PATCH 3/3] continue translation even if CommonNodeError is hit. --- java2python/compiler/template.py | 2 +- java2python/compiler/visitor.py | 17 +++++++++++------ java2python/lang/selector.py | 4 +++- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/java2python/compiler/template.py b/java2python/compiler/template.py index b4ade16..0dc3a11 100644 --- a/java2python/compiler/template.py +++ b/java2python/compiler/template.py @@ -164,7 +164,7 @@ def altIdent(self, name): if name in method.variables: return name if OPTIONS and OPTIONS.rusthon: - raise RuntimeError('ooookkk') + pass return ('cls' if method.isStatic else 'self') + '.' + name return name diff --git a/java2python/compiler/visitor.py b/java2python/compiler/visitor.py index dd413d5..836457e 100644 --- a/java2python/compiler/visitor.py +++ b/java2python/compiler/visitor.py @@ -42,6 +42,7 @@ def set_global_options(self, cfg): def accept(self, node, memo): """ Accept a node, possibly creating a child visitor. """ + if node.token is None: return None ## bug? tokType = tokens.map.get(node.token.type) missing = lambda node, memo:self call = getattr(self, 'accept{0}'.format(tokens.title(tokType)), missing) @@ -51,6 +52,9 @@ def accept(self, node, memo): def insertComments(self, tmpl, tree, index, memo): """ Add comments to the template from tokens in the tree. """ + if not hasattr(tree, 'parser'): + ## see: lang/selector.py class Type, method __call__ + return prefix = self.config.last('commentPrefix', '# ') cache, parser, comTypes = memo.comments, tree.parser, tokens.commentTypes comNew = lambda t:t.type in comTypes and (t.index not in cache) @@ -93,12 +97,13 @@ def walk(self, tree, memo=None): visitor.walk(child, memo) comIns(visitor, child, child.tokenStopIndex, memo) comIns(self, tree, tree.tokenStopIndex, memo) - if tree.isJavaSource: - comIns(self, tree, len(tree.parser.input.tokens), memo) - # fixme: we're calling the mutators far too frequently instead - # of only once per object after its walk is finished. - for handler in self.configHandlers('PostWalk', suffix='Mutators'): - handler(self) + if hasattr(tree, 'isJavaSource'): ## else CommonNodeError + if tree.isJavaSource: + comIns(self, tree, len(tree.parser.input.tokens), memo) + # fixme: we're calling the mutators far too frequently instead + # of only once per object after its walk is finished. + for handler in self.configHandlers('PostWalk', suffix='Mutators'): + handler(self) def zipWalk(self, nodes, visitors, memo): """ Walk the given nodes zipped with the given visitors. """ diff --git a/java2python/lang/selector.py b/java2python/lang/selector.py index 22b531a..4e0ce23 100644 --- a/java2python/lang/selector.py +++ b/java2python/lang/selector.py @@ -160,7 +160,9 @@ def __init__(self, key, value=None): self.value = value def __call__(self, tree): - if tree.token.type == self.key: + if tree.token is None: ## bug? + pass + elif tree.token.type == self.key: if self.value is None or self.value == tree.token.text: yield tree