def transform_constructor(self, node, in_block=False, assignment=None): simple_initializer = True simple_args = [] for e, a in zip(node.block, self.current_class.attrs): if e.type == 'assignment' and e.target.type == 'instance_variable' and e.target.name == a.name: simple_args.append(e.value) if e.value.type != 'local' or e.value.name != a.name: simple_initializer = False else: break if simple_initializer: self.classes_with_simple_initializers.add(self.current_class.name) return [] else: if len(simple_args) < len(node.block): ass = assi(Node('this', pseudo_type=node.this.name), Node('simple_initializer', name=typename(node.this.name, node.this.name), args=simple_args, pseudo_type=node.this.name)) node.block = [ass] + node.block[len(simple_args):] + [Node('implicit_return', value=Node('_go_ref', value= local('this', node.this.name), pseudo_type=node.this.name), pseudo_type=node.this.name)] else: node.block = [Node('implicit_return', value=Node('_go_ref', value= Node('simple_initializer', name=typename(node.this.name, node.this.name), args=simple_args, pseudo_type=node.this.name), pseudo_type=node.this.name), pseudo_type=node.this.name)] return node
def as_expression(self): return [Node('static_call', receiver=typename('Console', 'Library'), message='WriteLine', args=[arg], pseudo_type='Void') for arg in self.args], None
def split(f, delimiter, pseudo_type): if delimiter.type == 'string' and (len(delimiter.value) == 1 or delimiter.value == '\\n'): return method_call(f, 'Split', [Node('char', value=delimiter.value, pseudo_type='Char')], ['List', 'String']) else: return method_call(f, 'Split', [Node('array', elements=[delimiter]), attr(typename('StringSplitOptions', 'Library'), 'None', 'CSharpNone')], pseudo_type=['List', 'String'])
def transform_constructor(self, node, in_block=False, assignment=None): simple_initializer = True simple_args = [] for e, a in zip(node.block, self.current_class.attrs): if e.type == 'assignment' and e.target.type == 'instance_variable' and e.target.name == a.name: simple_args.append(e.value) if e.value.type != 'local' or e.value.name != a.name: simple_initializer = False else: break if simple_initializer: self.classes_with_simple_initializers.add(self.current_class.name) return [] else: if len(simple_args) < len(node.block): ass = assi( Node('this', pseudo_type=node.this.name), Node('simple_initializer', name=typename(node.this.name, node.this.name), args=simple_args, pseudo_type=node.this.name)) node.block = [ass] + node.block[len(simple_args):] + [ Node('implicit_return', value=Node('_go_ref', value=local('this', node.this.name), pseudo_type=node.this.name), pseudo_type=node.this.name) ] else: node.block = [ Node('implicit_return', value=Node('_go_ref', value=Node('simple_initializer', name=typename( node.this.name, node.this.name), args=simple_args, pseudo_type=node.this.name), pseudo_type=node.this.name), pseudo_type=node.this.name) ] return node
def transform_new_instance(self, node, in_block=False, assignment=None): if isinstance( node.pseudo_type, str ) and node.pseudo_type in self.classes_with_simple_initializers: return Node('_go_simple_initializer', name=typename(node.pseudo_type, node.pseudo_type), args=node.args) else: return node
def object_len(l, _): return attr( method_call( typename('Object', 'Type'), 'keys', [l], ['List', l.pseudo_type[1]]), 'length', 'Int')
def with_constructor(self, t): t = t[1] t.name = camel_case(t.name) if self.all == False: t.constructor = Node('constructor', params=[local(field.name, field.pseudo_type) for field in t.attrs], this=typename(t.name), pseudo_type = ['Function'] + [field.pseudo_type for field in t.attrs] + [t.name], return_type=t.name, block=[ assignment( Node('instance_variable', name=field.name, pseudo_type=field.pseudo_type), local(field.name, field.pseudo_type), first_mention=False) for field in t.attrs]) return t
def with_constructor(self, t): t = t[1] t.name = camel_case(t.name) if self.all == False: t.constructor = Node( 'constructor', params=[ local(field.name, field.pseudo_type) for field in t.attrs ], this=typename(t.name), pseudo_type=['Function'] + [field.pseudo_type for field in t.attrs] + [t.name], return_type=t.name, block=[ assignment(Node('instance_variable', name=field.name, pseudo_type=field.pseudo_type), local(field.name, field.pseudo_type), first_mention=False) for field in t.attrs ]) return t
Module = [Node('module', constants=[], code=[])] Int = [to_node(42)] Float = [to_node(42.420)] String = [to_node('la')] Boolean = [Node('boolean', value='true', pseudo_type='Boolean')] Null = [Node('null')] Dictionary = [ Node('dictionary', pairs=[Node('pair', key=to_node('la'), value=to_node(0))], pseudo_type=['Dictionary', 'String', 'Int']) ] List = [Node('list', elements=[to_node('la')], pseudo_type=['List', 'String'])] Local = [local('egg')] Typename = [typename('Egg')] InstanceVariable = [Node('instance_variable', name='egg')] Attr = [Node('attr', object=local('e'), attr='egg')] Assignment = [ Node('assignment', target=local('egg', pseudo_type='Int'), value=local('ham', pseudo_type='Int')), Node('assignment', target=Node('instance_variable', name='egg', pseudo_type='Int'), value=local('ham', pseudo_type='Int')), Node('assignment', target=Node('attr', object=Node('typename', name='T'), attr='egg', pseudo_type='String'), value=local('ham', pseudo_type='String')),
def object_len(l, _): return attr( method_call(typename('Object', 'Type'), 'keys', [l], ['List', l.pseudo_type[1]]), 'length', 'Int')
namespace['gen_with_imports'] = TestHelpers.gen_with_imports namespace['maxDiff'] = None return super().__new__(cls, name, bases, namespace) Module = [Node('module', constants=[], code=[])] Int = [to_node(42)] Float = [to_node(42.420)] String = [to_node('la')] Boolean = [Node('boolean', value='true', pseudo_type='Boolean')] Null = [Node('null')] Dictionary = [Node('dictionary', pairs=[ Node('pair', key=to_node('la'), value=to_node(0))], pseudo_type=['Dictionary', 'String', 'Int'])] List = [Node('list', elements=[to_node('la')], pseudo_type=['List', 'String'])] Local = [local('egg')] Typename = [typename('Egg')] InstanceVariable = [Node('instance_variable', name='egg')] Attr = [Node('attr', object=local('e'), attr='egg')] Assignment = [ Node('assignment', target=local('egg', pseudo_type='Int'), value=local('ham', pseudo_type='Int')), Node('assignment', target=Node('instance_variable', name='egg', pseudo_type='Int'), value=local('ham', pseudo_type='Int')), Node('assignment', target=Node('attr', object=Node('typename', name='T'), attr='egg', pseudo_type='String'), value=local('ham', pseudo_type='String')), Node('assignment', target=Node('index', sequence=local('x', pseudo_type=['List', 'String']), index=to_node(4), pseudo_type='String'), value=to_node('String')) ] Call = [call('map', [local('x')])]
def transform_new_instance(self, node, in_block=False, assignment=None): if isinstance(node.pseudo_type, str) and node.pseudo_type in self.classes_with_simple_initializers: return Node('_go_simple_initializer', name=typename(node.pseudo_type, node.pseudo_type), args=node.args) else: return node
def transform_general_call(self, n, in_block=False, assignment=None): for j, arg in enumerate(n.args): if (arg.type == 'local' or arg.type == 'instance_variable' or arg.type == 'attr' or arg.type == 'typename') and general_type( arg.pseudo_type) == 'Tuple': name = arg.name if arg.type != 'attr' else arg.attr pseudo_type = arg.pseudo_type elif arg.type == 'index' and arg.sequence.type in { 'local', 'instance_variable', 'attr', 'typename' } and general_type(arg.sequence.pseudo_type) == 'Tuple': name = arg.sequence.name if arg.sequence.type != 'attr' else arg.sequence.attr pseudo_type = arg.sequence.pseudo_type else: n.args[j] = self.transform(n.args[j]) continue z = safe_serialize_type(pseudo_type) if z not in self.tuple_definition.tuple_definitions: self.tuple_definition.tuple_definitions[z] = name, Node( 'class_definition', name=name, base=None, constructor=None, this=typename(name), attrs=[ Node('immutable_class_attr', name='item%d' % k, is_public=True, pseudo_type=t) for k, t in enumerate(pseudo_type[1:]) ], methods=[]) else: self.tuple_definition.tuple_definitions[ z] = name, self.tuple_definition.tuple_definitions[z][1] for l in self.tuple_definition.params: l.name = name if n.type == 'call': if n.function.type != 'local': return n namespace, name = 'functions', n.function.name elif n.type == 'method_call': n.receiver = self.transform(n.receiver) namespace, name = general_type(n.receiver.pseudo_type), n.message elif n.type == 'new_instance': namespace, name = general_type(n.class_name), '__init__' else: return n if hasattr(namespace, 'y'): input(namespace.y) if namespace not in self.tuple_definition.function_index or name not in self.tuple_definition.function_index[ namespace]: return n if self.tuple_index(n): pseudo_type = n.args[-1].sequence.pseudo_type sequence = n.args[-1].sequence if len(n.args) >= len(pseudo_type) - 1 and all( self.successive(sequence, j, a) for j, a in enumerate(n.args[-len(pseudo_type) + 1:])): # s(a, b[0], b[1]) -> s(a, b) and def s(a, x, y) -> s(a, k_name) t = safe_serialize_type(pseudo_type) tuple_class_name, class_node = self.tuple_definition.tuple_definitions[ t] old_params = self.tuple_definition.function_index[namespace][ name].params[-len(pseudo_type) + 1:] l = local( tuple_class_name, pseudo_type) # referencable if we find another tuple name self.tuple_definition.params.append(l) self.tuple_definition.function_index[namespace][name].params[ -len(pseudo_type) + 1:] = [l] self.tuple_definition.function_index[namespace][ name] = BlockRewriter( {old_param.name for old_param in old_params}, l).transform( self.tuple_definition.function_index[namespace] [name]) self.tuple_definition.function_index[namespace][ name].pseudo_type[-len(pseudo_type):-1] = [ camel_case(tuple_class_name) ] for class_attr, name in zip(class_node.attrs, old_params): class_attr.name = name.name n.args[-len(pseudo_type) + 1:] = [sequence] return n return n
def transform_general_call(self, n, in_block=False, assignment=None): for j, arg in enumerate(n.args): if (arg.type == 'local' or arg.type == 'instance_variable' or arg.type == 'attr' or arg.type == 'typename') and general_type(arg.pseudo_type) == 'Tuple': name = arg.name if arg.type != 'attr' else arg.attr pseudo_type = arg.pseudo_type elif arg.type == 'index' and arg.sequence.type in {'local', 'instance_variable', 'attr', 'typename'} and general_type(arg.sequence.pseudo_type) == 'Tuple': name = arg.sequence.name if arg.sequence.type != 'attr' else arg.sequence.attr pseudo_type = arg.sequence.pseudo_type else: n.args[j] = self.transform(n.args[j]) continue z = safe_serialize_type(pseudo_type) if z not in self.tuple_definition.tuple_definitions: self.tuple_definition.tuple_definitions[z] = name, Node('class_definition', name=name, base=None, constructor=None, this=typename(name), attrs=[Node('immutable_class_attr', name='item%d' % k, is_public=True, pseudo_type=t) for k, t in enumerate(pseudo_type[1:])], methods=[]) else: self.tuple_definition.tuple_definitions[z] = name, self.tuple_definition.tuple_definitions[z][1] for l in self.tuple_definition.params: l.name = name if n.type == 'call': if n.function.type != 'local': return n namespace, name = 'functions', n.function.name elif n.type == 'method_call': n.receiver = self.transform(n.receiver) namespace, name = general_type(n.receiver.pseudo_type), n.message elif n.type == 'new_instance': namespace, name = general_type(n.class_name), '__init__' else: return n if hasattr(namespace, 'y'): input(namespace.y) if namespace not in self.tuple_definition.function_index or name not in self.tuple_definition.function_index[namespace]: return n if self.tuple_index(n): pseudo_type = n.args[-1].sequence.pseudo_type sequence = n.args[-1].sequence if len(n.args) >= len(pseudo_type) - 1 and all(self.successive(sequence, j, a) for j, a in enumerate(n.args[-len(pseudo_type) + 1:])): # s(a, b[0], b[1]) -> s(a, b) and def s(a, x, y) -> s(a, k_name) t = safe_serialize_type(pseudo_type) tuple_class_name, class_node = self.tuple_definition.tuple_definitions[t] old_params = self.tuple_definition.function_index[namespace][name].params[-len(pseudo_type) + 1:] l = local(tuple_class_name, pseudo_type) # referencable if we find another tuple name self.tuple_definition.params.append(l) self.tuple_definition.function_index[namespace][name].params[-len(pseudo_type) + 1:] = [l] self.tuple_definition.function_index[namespace][name] = BlockRewriter({old_param.name for old_param in old_params}, l).transform(self.tuple_definition.function_index[namespace][name]) self.tuple_definition.function_index[namespace][name].pseudo_type[-len(pseudo_type):-1] = [camel_case(tuple_class_name)] for class_attr, name in zip(class_node.attrs, old_params): class_attr.name = name.name n.args[-len(pseudo_type) + 1:] = [sequence] return n return n
class RubyTranslator(ApiTranslator): ''' Ruby api translator The DSL is explained in the ApiTranslator docstring ''' methods = { 'List': { '@equivalent': 'Array', 'push': '#push', 'pop': '#pop', 'length': '#length', 'insert': '#insert', 'remove_at': '#delete_at', 'remove': '#delete', 'slice': expand_slice, 'slice_from': expand_slice, 'slice_to': lambda receiver, to, pseudo_type: expand_slice( receiver, to_node(0), to, pseudo_type), 'join': '#join', 'map': to_method_rb_block('map'), 'filter': to_method_rb_block('select'), 'reduce': to_method_rb_block('reduce'), 'any?': to_method_rb_block('any?'), 'all?': to_method_rb_block('all?'), 'sort': '#sort!', 'present?': lambda receiver, _: Node('unary_op', op='not', value=method_call(receiver, 'empty?', [], 'Boolean'), pseudo_type='Boolean'), 'empty?': '#empty?', 'find': '#index', 'contains?': '#include?' }, 'Dictionary': { '@equivalent': 'Hash', 'length': '#length', 'keys': '#keys', 'values': '#values', 'contains?': '#include?', 'present?': lambda receiver, _: Node('unary_op', op='not', value=method_call(receiver, 'empty?', [], 'Boolean'), pseudo_type='Boolean'), 'empty?': '#empty?' }, 'Set': { '@equivalent': 'Set', 'length': '#length', 'contains?': '#include?', 'union': to_op('|'), 'intersection': '#intersection', 'present?': lambda receiver, _: Node('unary_op', op='not', value=method_call(receiver, 'empty?', [], 'Boolean'), pseudo_type='Boolean'), 'empty?': '#empty?' }, 'Tuple': { '@equivalent': 'Array', 'length': '#length' }, 'Array': { '@equivalent': 'Array', 'length': '#length' }, 'String': { '@equivalent': 'String', 'substr': expand_slice, 'substr_from': expand_slice, 'substr_to': lambda receiver, to, _: expand_slice(receiver, None, to, 'String'), 'length': '#length', 'concat': to_op('+'), 'find': '#index', 'find_from': '#index', 'count': '#count', 'partition': '#partition', 'split': '#split', 'trim': '#trim', 'reversed': '#reverse', 'center': '#center', 'present?': lambda receiver, _: Node('unary_op', op='not', value=method_call(receiver, 'empty?', [], 'Boolean'), pseudo_type='Boolean'), 'empty?': '#empty?', 'contains?': '#include?', 'to_int': '#to_i', 'pad_left': '#ljust', 'pad_right': '#rjust' }, 'Regexp': { '@equivalent': 'Regexp', 'match': '%{0}#scan(%{self})' }, 'Int': { 'to_float': '#to_f' }, 'Float': { 'to_int': '#to_i' }, 'RegexpMatch': { '@equivalent': 'Regexp_', 'group': lambda receiver, index, _: Node('index', sequence=Node('index', sequence=receiver, index=index, pseudo_type= ['List', 'String']), index=to_node(0), pseudo_type='String'), 'has_match': lambda receiver, _: Node('unary_op', op='not', value=method_call(receiver, 'empty?', [], 'Boolean'), pseudo_type='Boolean') } } functions = { 'global': { 'wat': lambda _: Node('block', block=[]), 'exit': lambda status, _: call('exit', [status]) }, 'io': { 'display': display, 'read': 'gets', 'read_file': 'File.read', 'write_file': 'File.write' }, 'math': { 'ln': 'Math.log', 'log': 'Math.log', 'tan': 'Math.tan', 'sin': 'Math.sin', 'cos': 'Math.cos', 'pow': lambda left, right, pseudo_type: Node('binary_op', op='**', left=left, right=right, pseudo_type=pseudo_type) }, 'regexp': { 'compile': lambda value, _: Node( '_rb_regex_interpolation', value=value, pseudo_type='Regexp'), 'escape': 'Regexp.escape' }, 'system': { 'args': lambda _: typename('ARGV', ['List', 'String']), 'arg_count': lambda _: Node('binary_op', op='+', left=method_call(local('ARGV', ['List', 'String']), 'length', [], 'Int'), right=to_node(1), pseudo_type='Int'), 'index': lambda value, _: Node('index', sequence=local('ARGV', ['List', 'String']), index=to_node(value.value - 1) if value.type == 'int' else Node('binary_op', op='-', left=value, right=to_node(1), pseudo_type='Int'), pseudo_type='String') # in ruby args counting starts from 0, not 1 } } dependencies = {'http': {'@all': 'Requests'}, 'Set': {'@all': 'set'}}