def as_expression(self, target=None): t = self.temp_name(target or self.default) element = '_%sElement' % extract_name(self.args[0], t) element = local(element, self.args[0].pseudo_type[1]) if target is None: target = local(t, 'Int') return [ assignment(target, Node('boolean', value='false', pseudo_type='Boolean')), Node('for_statement', sequences=Node('for_sequence', sequence=self.args[0]), iterators=Node('for_iterator', iterator=element), block=[ Node('if_statement', test=Node('comparison', op='==', pseudo_type='Boolean', left=element, right=self.args[1]), block=[ assignment( target, Node('boolean', value='true', pseudo_type='Boolean')), Node('break_') ], otherwise=None, pseudo_type='Void') ]), target ], None
def as_expression(self, target=None): _index = local('_index', 'Int') name = self.temp_name(target or self.default) z = local(name, pseudo_type=self.args[0].pseudo_type) if self.args[1].type == 'anonymous_function': block_test = self.args[1].block[-1].value initial = self.args[1].block[:-1] z_arg = self.args[1].params[0] else: z_arg = local('_value', z.pseudo_type[1]) block_test = call(self.args[1], z_arg, 'Boolean') initial = [] return [Node('_go_declaration', decl=name, decl_type=z.pseudo_type), Node('for_statement', sequences=Node('for_sequence_with_index', sequence=self.args[0]), iterators=Node('for_iterator_with_index', index=_index, iterator=z_arg), block=initial + [ Node('if_statement', test=block_test, block=[assignment( z, call('append', [z, z_arg], z.pseudo_type))], otherwise=None)]), z], None
def as_expression(self, target=None): t = self.temp_name(target or 'accumulator') if self.args[1].type == 'anonymous_function': initial = self.args[1].block[:-1] element = self.args[1].params[1] if target is None: target = self.args[1].params[0] elif target.name != self.args[1].params[0].name: self.args[1].block = ReduceRewriter( self.args[1].params[0].name, target.name).transform(self.args[1].block) self.args[1].params[0] = target block_result = self.args[1].block[-1].value else: initial = [] element = local('_element', self.args[0].pseudo_type[1]) if target is None: target = local(t, self.args[1].pseudo_type[-1]) block_result = call(self.args[1], [element, target], target.pseudo_type) return [ assignment(target, self.args[2]), Node('for_statement', sequences=Node('for_sequence', sequence=self.args[0]), iterators=Node('for_iterator', iterator=element), block=initial + [assignment(target, block_result)]), target ], None
def as_expression(self, target=None): t = self.temp_name(target or self.default) element = '_%sElement' % extract_name(self.args[0], t) j = '_%sIndex' % extract_name(self.args[0], t) element = local(element, self.args[0].pseudo_type[1]) j = local(j, 'Int') if target is None: target = local(t, 'Int') return [ assignment(target, to_node(-1)), Node('for_statement', sequences=Node('for_sequence_with_index', sequence=self.args[0]), iterators=Node('for_iterator_with_index', index=j, iterator=element), block=[ Node('if_statement', test=Node('comparison', op='==', pseudo_type='Boolean', left=element, right=self.args[1]), block=[assignment(target, j), Node('break_')], otherwise=None) ]), target ], None
def as_expression(self, target=None): _index = local('_index', 'Int') name = self.temp_name(target or self.default) z = local(name, pseudo_type=['List', self.args[-1].pseudo_type[2]]) z_arg = local('_value', z.pseudo_type[1]) return [ assignment( z, Node('_go_make_slice', slice_type=z.pseudo_type, length=call('len', [self.args[0]], 'Int'))), Node( 'for_statement', sequences=Node('for_sequence_with_index', sequence=self.args[0]), iterators=Node( 'for_iterator_with_index', index=_index, iterator=self.args[1].params[0] if self.args[1].type == 'anonymous_function' else z_arg), block=self.args[1].block[:-1] + [ assignment( Node('index', sequence=z, index=_index, pseudo_type=z.pseudo_type[1]), self.args[1].block[-1].value) ] if self.args[1].type == 'anonymous_function' else assignment( Node('index', sequence=z, index=_index, pseudo_type=z.pseudo_type[1]), call(self.args[1], z_arg, z.pseudo_type[1]))), z ], None
def as_expression(self, target=None): _index = local('_index', 'Int') name = self.temp_name(target or self.default) z = local(name, pseudo_type=self.args[0].pseudo_type) if self.args[1].type == 'anonymous_function': block_test = self.args[1].block[-1].value initial = self.args[1].block[:-1] z_arg = self.args[1].params[0] else: z_arg = local('_value', z.pseudo_type[1]) block_test = call(self.args[1], z_arg, 'Boolean') initial = [] return [ Node('_go_declaration', decl=name, decl_type=z.pseudo_type), Node('for_statement', sequences=Node('for_sequence_with_index', sequence=self.args[0]), iterators=Node('for_iterator_with_index', index=_index, iterator=z_arg), block=initial + [ Node('if_statement', test=block_test, block=[ assignment( z, call('append', [z, z_arg], z.pseudo_type)) ], otherwise=None) ]), z ], None
def as_expression(self, target=None): t = self.temp_name(target or 'accumulator') if self.args[1].type == 'anonymous_function': initial = self.args[1].block[:-1] element = self.args[1].params[1] if target is None: target = self.args[1].params[0] elif target.name != self.args[1].params[0].name: self.args[1].block = ReduceRewriter(self.args[1].params[0].name, target.name).transform(self.args[1].block) self.args[1].params[0] = target block_result = self.args[1].block[-1].value else: initial = [] element = local('_element', self.args[0].pseudo_type[1]) if target is None: target = local(t, self.args[1].pseudo_type[-1]) block_result = call(self.args[1], [element, target], target.pseudo_type) return [assignment(target, self.args[2]), Node('for_statement', sequences=Node('for_sequence', sequence=self.args[0]), iterators=Node('for_iterator', iterator=element), block=initial + [ assignment(target, block_result) ]), target], None
def as_expression(self, target=None): t = self.temp_name(target or self.default) element = '_%sElement' % extract_name(self.args[0], t) j = '_%sIndex' % extract_name(self.args[0], t) element = local(element, self.args[0].pseudo_type[1]) j = local(j, 'Int') if target is None: target = local(t, 'Int') return [assignment(target, to_node(-1)), Node('for_statement', sequences=Node('for_sequence_with_index', sequence=self.args[0]), iterators=Node('for_iterator_with_index', index=j, iterator=element), block=[ Node('if_statement', test=Node('comparison', op='==', pseudo_type='Boolean', left=element, right=self.args[1]), block=[assignment(target, j), Node('break_')], otherwise=None)]), target], None
def as_expression(self): l = local(self.temp_name(''), 'String') return [Node('_go_multi_assignment', targets=[l, local('_', 'Error')], values=[Node('static_call', message='ReadFile', receiver=local('ioutil', 'Library'), args=self.args, pseudo_type='MaybeBytez')]), call('string', [l], 'String')], None
def x(receiver, test, pseudo_type): return call( local(method, ['Function', test.pseudo_type, 'Boolean']), [Node('_py_generatorcomp', sequences=Node('for_sequence', sequence=receiver), iterators=Node('for_iterator', iterator=local(test.params[0].name, test.pseudo_type[1])), block=test.block[0].value, test=None, pseudo_type=['PyGenerator', 'Boolean'])], pseudo_type='Boolean')
def as_expression(self): t = self.temp_name('', False) target = local(t, 'Int') return [Node('_go_multi_assignment', targets=[target, local('_', 'Error')], values=[Node('static_call', receiver=local('strconv', 'Library'), message='Atoi', args=[self.args[0]], pseudo_type=['GoResultWithError', 'Int'])]), target], None
def x(receiver, test, pseudo_type): return call(local(method, ['Function', test.pseudo_type, 'Boolean']), [ Node('_py_generatorcomp', sequences=Node('for_sequence', sequence=receiver), iterators=Node('for_iterator', iterator=local(test.params[0].name, test.pseudo_type[1])), block=test.block[0].value, test=None, pseudo_type=['PyGenerator', 'Boolean']) ], pseudo_type='Boolean')
def as_expression(self): return [ Node('_go_multi_assignment', targets=[local('reader', 'Reader'), local('err', 'Error')], values=[call(attr(local('bufio', 'GoLibrary'), 'NewReader', ['Function', 'IO', 'Reader']), [attr(local('os', 'GoLibrary'), 'Stdin', 'IO')], pseudo_type='Reader')]), call( attr(local('reader', 'Reader'), 'ReadString', ['Function', 'String', 'String']), [to_node('\\n')], pseudo_type='String')], None
def as_expression(self): return [ Node('_go_multi_assignment', targets=[ local('_', self.args[0].pseudo_type[1]), local(self.temp_name(''), pseudo_type='Boolean') ], values=[ Node('index', sequence=self.args[0], index=self.args[1], pseudo_type='MaybeElement') ]), local(self.temp_name(''), pseudo_type='Boolean')], None
def as_expression(self): l = local(self.temp_name(''), 'String') return [ Node('_go_multi_assignment', targets=[l, local('_', 'Error')], values=[ Node('static_call', message='ReadFile', receiver=local('ioutil', 'Library'), args=self.args, pseudo_type='MaybeBytez') ]), call('string', [l], 'String') ], None
def as_expression(self): t = self.temp_name('', False) target = local(t, 'Int') return [ Node('_go_multi_assignment', targets=[target, local('_', 'Error')], values=[ Node('static_call', receiver=local('strconv', 'Library'), message='Atoi', args=[self.args[0]], pseudo_type=['GoResultWithError', 'Int']) ]), target ], None
def as_expression(self): return [ Node('_go_multi_assignment', targets=[ local('_', self.args[0].pseudo_type[1]), local(self.temp_name(''), pseudo_type='Boolean') ], values=[ Node('index', sequence=self.args[0], index=self.args[1], pseudo_type='MaybeElement') ]), local(self.temp_name(''), pseudo_type='Boolean') ], None
def as_expression(self): return [ Node('_go_multi_assignment', targets=[local('reader', 'Reader'), local('err', 'Error')], values=[ call(attr(local('bufio', 'GoLibrary'), 'NewReader', ['Function', 'IO', 'Reader']), [attr(local('os', 'GoLibrary'), 'Stdin', 'IO')], pseudo_type='Reader') ]), call(attr(local('reader', 'Reader'), 'ReadString', ['Function', 'String', 'String']), [to_node('\\n')], pseudo_type='String') ], None
def transform_index(self, n, in_block=False, assignment=None): if general_type(n.sequence.pseudo_type) == 'Tuple': class_name, class_node = self.tuple_definitions.get(safe_serialize_type(n.sequence.pseudo_type), (None, None)) # we can have only literal int index of tuple because typecheck if class_name: return attr(local(n.sequence, class_name), camel_case(class_node.attrs[n.index.value].name), pseudo_type=n.pseudo_type) return n
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 leaking(self, z, module, name, node, context, *data): ''' an expression leaking ... assignment nodes into the nearest block list of nodes c++ guys, stay calm ''' # input(node.y) args = [node.receiver] + node.args if node.type == 'standard_method_call' else node.args z = z(module, name, args) if context == 'expression': if isinstance(z, NormalLeakingNode): leaked_nodes, exp = z.as_expression() else: leaked_nodes = z.as_assignment(z.temp_name(data[0])) exp = local(z.temp_name(data[0]), node.pseudo_type) if exp is None or exp.pseudo_type == 'Void': raise PseudoTypeError("pseudo can't handle values with void type in expression: %s?%s" % (module, name)) self.leaked_nodes += leaked_nodes return exp elif context == 'assignment': if isinstance(z, NormalLeakingNode): leaked_nodes, exp = z.as_expression() if exp is None or exp.pseudo_type == 'Void': raise PseudoTypeError("pseudo can't handle values with void type in expression: %s?%s" % (module, name)) self.leaked_nodes += leaked_nodes return assignment(data[0], exp) else: self.leaked_nodes += z.as_assignment(data[0]) return None elif context == 'block': leaked_nodes, exp = z.as_expression() self.leaked_nodes += leaked_nodes return exp
def as_expression(self): return [Node( '_py_with', call=call('open', [self.args[0], to_node('r')], 'File'), context='_f', block=[method_call(local('_f', 'File'), 'read', [], 'String')], pseudo_type='Void')], None
def as_expression(self): return [], Node( '_py_with', call=call('open', [self.args[0], to_node('w')], 'File'), context='_f', block=[method_call(local('_f', 'File'), 'write', [self.args[1]], 'Void')], pseudo_type='Void')
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 as_expression(self, target=None): _index = local('_index', 'Int') name = self.temp_name(target or self.default) z = local(name, pseudo_type=['List', self.args[-1].pseudo_type[2]]) z_arg = local('_value', z.pseudo_type[1]) return [assignment(z, Node('_go_make_slice', slice_type=z.pseudo_type, length=call('len', [self.args[0]], 'Int'))), Node('for_statement', sequences=Node('for_sequence_with_index', sequence=self.args[0]), iterators=Node('for_iterator_with_index', index=_index, iterator=self.args[1].params[0] if self.args[1].type == 'anonymous_function' else z_arg), block=self.args[1].block[:-1] + [ assignment(Node('index', sequence=z, index=_index, pseudo_type=z.pseudo_type[1]), self.args[1].block[-1].value)] if self.args[1].type == 'anonymous_function' else assignment(Node('index', sequence=z, index=_index, pseudo_type=z.pseudo_type[1]), call(self.args[1], z_arg, z.pseudo_type[1]))), z], None
def index(self): if self.args[0].type in ['local', 'instance_variable', 'typename']: name = self.args[0].name elif self.args[0].type == 'attr': name = self.args[0].attr else: name = '' return local('_%sIndex' % name, 'Int')
def as_expression(self): return [ Node( '_py_with', call=call('open', [self.args[0], to_node('r')], 'File'), context='_f', block=[method_call(local('_f', 'File'), 'read', [], 'String')], pseudo_type='Void') ], None
def index(self): if self.args[0].type in ['local', 'instance_variable', 'typename']: name = self.args[0].name elif self.args[0].type == 'attr': name = self.args[0].attr else: name = '' return local('_%sIndex' % name, 'Int')
def leaking(self, z, module, name, node, context, *data): ''' an expression leaking ... assignment nodes into the nearest block list of nodes c++ guys, stay calm ''' # input(node.y) args = [ node.receiver ] + node.args if node.type == 'standard_method_call' else node.args z = z(module, name, args) if context == 'expression': if isinstance(z, NormalLeakingNode): leaked_nodes, exp = z.as_expression() else: leaked_nodes, exp = z.as_expression() zz = local(z.temp_name(getattr(z, 'default', '')), node.pseudo_type) leaked_nodes = z.as_assignment(zz) exp = local(zz, node.pseudo_type) if exp is None or exp.pseudo_type == 'Void': raise PseudoTypeError( "pseudo can't handle values with void type in expression: %s?%s" % (module, name)) self.leaked_nodes += leaked_nodes return exp elif context == 'assignment': if isinstance(z, NormalLeakingNode): leaked_nodes, exp = z.as_expression() if exp is None or exp.pseudo_type == 'Void': raise PseudoTypeError( "pseudo can't handle values with void type in expression: %s?%s" % (module, name)) self.leaked_nodes += leaked_nodes return assignment(data[0], exp) else: self.leaked_nodes += z.as_assignment(data[0]) return None elif context == 'block': leaked_nodes, exp = z.as_expression() self.leaked_nodes += leaked_nodes return exp
def transform_index(self, n, in_block=False, assignment=None): if general_type(n.sequence.pseudo_type) == 'Tuple': class_name, class_node = self.tuple_definitions.get( safe_serialize_type(n.sequence.pseudo_type), (None, None)) # we can have only literal int index of tuple because typecheck if class_name: return attr(local(n.sequence, class_name), camel_case(class_node.attrs[n.index.value].name), pseudo_type=n.pseudo_type) return n
def as_expression(self): return [], Node('_py_with', call=call('open', [self.args[0], to_node('w')], 'File'), context='_f', block=[ method_call(local('_f', 'File'), 'write', [self.args[1]], 'Void') ], pseudo_type='Void')
def zip_iterators(self, node, depth): return '\n'.join( '%sauto %s = %s;' % (self.offset(depth) if j else '', q.name, self._generate_node( Node('index', sequence=node.sequences.sequences[j], index=local('_index', 'Int'), pseudo_type=node.sequences.sequences[j].pseudo_type[1]))) for j, q in enumerate(node.iterators.iterators))
def as_expression(self): return [ Node('_cpp_declaration', name='_dummy', args=[], decl_type='String', pseudo_type='Void'), Node('_cpp_cin', args=[local('_dummy', 'String')]) ], None
def zip_iterators(self, node, depth): return '\n'.join( '%sauto %s = %s;' % ( self.offset(depth) if j else '', q.name, self._generate_node( Node('index', sequence=node.sequences.sequences[j], index=local('_index', 'Int'), pseudo_type=node.sequences.sequences[j].pseudo_type[1]))) for j, q in enumerate(node.iterators.iterators))
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 as_expression(self): e = self.temp_name('') e_singular = self.singular_name() e_index = self.index() if self.field == 'keys': field_type = self.args[0].pseudo_type[1] first = local(e_singular, field_type) second = local('_', self.args[0].pseudo_type[2]) else: field_type = self.args[0].pseudo_type[2] first = local('_', self.args[0].pseudo_type[1]) second = local(e_singular, field_type) e = local(e, field_type) e_singular = local(e_singular, field_type) return [assignment(e, Node('_go_make_slice', slice_type=['List', field_type], length=call('len', [self.args[0]], 'Int'), pseudo_type=['List', field_type])), assignment(e_index, to_node(0)), Node('for_statement', sequences=Node('for_sequence_with_items', sequence=self.args[0]), iterators=Node('for_iterator_with_items', key=first, value=second), block=[ assignment( Node('index', sequence=e, index=e_index, pseudo_type=field_type), e_singular), Node('aug_assignment', op='+', target=e_index, value=to_node(1))]), e], None def as_assignment(self, target): e = self.as_expression()[0] e[3] = assignment(target, e) return e
def as_expression(self, target=None): t = self.temp_name(target or self.default) element = '_%sElement' % extract_name(self.args[0], t) element = local(element, self.args[0].pseudo_type[1]) if target is None: target = local(t, 'Int') return [assignment(target, Node('boolean', value='false', pseudo_type='Boolean')), Node('for_statement', sequences=Node('for_sequence', sequence=self.args[0]), iterators=Node('for_iterator', iterator=element), block=[ Node('if_statement', test=Node('comparison', op='==', pseudo_type='Boolean', left=element, right=self.args[1]), block=[assignment(target, Node('boolean', value='true', pseudo_type='Boolean')), Node('break_')], otherwise=None, pseudo_type='Void')]), target], None
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 _parse_part(self, part, receiver, args, equivalent): if part[0] == '%': # %{v} inside = part[2:-1] if inside.isnumeric(): inside = int(inside) return args[inside] elif inside == 'self': if receiver: return receiver else: raise PseudoDSLError( '%{self} not working for functions with api dsl') elif inside == 'equivalent': return typename(equivalent) else: return getattr(self, '%s_placeholder' % inside)(receiver, *args, equivalent=equivalent) else: return local(part)
def _parse_part(self, part, receiver, args, equivalent): if part[0] == '%': # %{v} inside = part[2:-1] if inside.isnumeric(): inside = int(inside) return args[inside] elif inside == 'self': if receiver: return receiver else: raise PseudoDSLError( '%{self} not working for functions with api dsl') elif inside == 'equivalent': return typename(equivalent) else: return getattr(self, '%s_placeholder' % inside)( receiver, *args, equivalent=equivalent) else: return local(part)
def as_expression(self): return [Node('_cpp_declaration', name='ifs', args=[to_node('f.py')], decl_type='ifstream', pseudo_type='Void'), Node('_cpp_declaration', name=self.temp_name(None), args=[Node('_cpp_group', value=Node('_cpp_anon_declaration', args=[local('ifs', 'ifstream')], decl_type='istreambuf_iterator<char>', pseudo_type='Void')), Node('_cpp_group', value=Node('_cpp_anon_declaration', args=[], decl_type='istreambuf_iterator<char>', pseudo_type='Void'))], decl_type='String', pseudo_type='Void')], None
def as_expression(self): e = self.temp_name('') e_singular = self.singular_name() e_index = self.index() if self.field == 'keys': field_type = self.args[0].pseudo_type[1] first = local(e_singular, field_type) second = local('_', self.args[0].pseudo_type[2]) else: field_type = self.args[0].pseudo_type[2] first = local('_', self.args[0].pseudo_type[1]) second = local(e_singular, field_type) e = local(e, field_type) e_singular = local(e_singular, field_type) return [ assignment( e, Node('_go_make_slice', slice_type=['List', field_type], length=call('len', [self.args[0]], 'Int'), pseudo_type=['List', field_type])), assignment(e_index, to_node(0)), Node('for_statement', sequences=Node('for_sequence_with_items', sequence=self.args[0]), iterators=Node('for_iterator_with_items', key=first, value=second), block=[ assignment( Node('index', sequence=e, index=e_index, pseudo_type=field_type), e_singular), Node('aug_assignment', op='+', target=e_index, value=to_node(1)) ]), e ], None def as_assignment(self, target): e = self.as_expression()[0] e[3] = assignment(target, e) return e
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'}}
from pseudo.api_translator import ApiTranslator, to_op from pseudo.pseudo_tree import Node, method_call, call, to_node, attr, local from pseudo.api_translators.js_api_handlers import empty, present, object_len LODASH = local('_', 'Library') class JSTranslator(ApiTranslator): ''' JS api translator The DSL is explained in the ApiTranslator docstring ''' methods = { 'List': { '@equivalent': 'Array', 'push': '#push', 'pop': '#pop', 'length': '.length!', 'insert': '#splice(%{self}, 0, %{0})', 'remove_at': lambda receiver, index, _: method_call( receiver, 'splice', [index, to_node(index.value + 1) if index.type == 'int' else Node('binary_op', op='+', left=index, right=to_node(1), pseudo_type='Int')], pseudo_type='Void'), 'remove': '_.pull(%{self}, %{0})',
class CSharpTranslator(ApiTranslator): ''' CSharp api translator The DSL is explained in the ApiTranslator docstring ''' methods = { 'List': { '@equivalent': 'List', 'push': '#Insert', 'pop': lambda l, _: method_call(l, 'RemoveAt', [ Node('binary_op', op='-', left=attr(l, 'Length', 'Int'), right=to_node(1), pseudo_type='Int') ], pseudo_type='Void'), 'insert': '#Insert', 'remove_at': '#RemoveAt', 'remove': '#Remove', 'length': '.Length!', 'slice': expand_slice, 'slice_from': lambda l, from_, pseudo_type: method_call( l, 'Drop', [ Node('binary_op', op='-', left=attr(l, 'Length', 'Int'), right=to_node(-from_.value), pseudo_type='Int') if from_.type == 'int' and from_.value < 0 else from_ ], pseudo_type=pseudo_type), 'slice_to': lambda l, to, pseudo_type: method_call( l, 'Take', [ Node('binary_op', op='-', left=attr(l, 'Length', 'Int'), right=to_node(-to.value), pseudo_type='Int') if to.type == 'int' and to.value < 0 else to ], pseudo_type=pseudo_type), 'slice_': '#Slice', 'join': lambda l, delimiter, _: method_call(delimiter, 'Join', [receiver], 'String'), 'map': linq('Select'), 'filter': linq('Where'), 'reduce': linq('Aggregate', False, swap=True), 'all?': linq('All'), 'any?': linq('Any'), 'concat': '#AddRange', 'present?': '#Any', 'empty?': empty, 'find': '#IndexOf', 'contains?': '#Contains', 'sort': '#Sort' }, 'Dictionary': { '@equivalent': 'Dictionary', 'length': '.Length!', 'keys': '#Keys', 'values': '#Values', 'contains?': '#Contains', 'present?': '#Any', 'empty?': empty }, 'String': { '@equivalent': 'String', 'length': '.Length!', 'substr': lambda f, from_, to, pseudo_type: method_call( f, 'Substring', [from_, normalize(f, from_, to)], pseudo_type), 'substr_from': '#Substring', 'substr_to': lambda f, to, pseudo_type: method_call(f, 'Substring', [ to_node(0), normalize(f, to_node(0), to) ], pseudo_type), 'find_from': '#IndexOf', 'find': '#IndexOf', 'count': lambda f, element, pseudo_type: method_call( f, 'Count', [ Node('anonymous_function', params=[local('sub', 'String')], block=[ Node('comparison', op='==', left=local('sub', 'String'), right=local('s', 'String'), pseudo_type='Boolean') ], return_type='Boolean', pseudo_type=['Function', 'String', 'Boolean']) ], pseudo_type='Int'), 'concat': to_op('+'), 'split': split, 'trim': '#Trim', 'center': pad, 'present?': lambda f, _: Node('comparison', op='!=', left=attr(f, 'Length', 'Int'), right=to_node(0), pseudo_type='Boolean'), 'empty?': lambda f, _: Node('comparison', op='==', left=attr(f, 'Length', 'Int'), right=to_node(0), pseudo_type='Boolean'), 'contains?': '#Contains', 'to_int': 'Int32.Parse(%{self})', 'pad_left': '#PadLeft', 'pad_right': '#PadRight' }, 'Set': { '@equivalent': 'HashSet', 'length': '.Length!', 'contains?': '#Contains', 'union': '#Union', 'intersection': '#Intersection', 'present?': '#Any', 'empty?': empty }, 'Regexp': { '@equivalent': 'Regexp', 'match': '#match' }, 'RegexpMatch': { '@equivalent': 'RegexpMatch', 'group': lambda receiver, index, _: Node( 'index', sequence=attr( Node('index', sequence=attr(receiver, 'Groups', ['List', 'CSharpRegexGroup']), index=to_node(1 + index.value) if index.type == 'int' else Node('binary_op', op='+', left=to_node(1), right=index, pseudo_type='Int'), pseudo_type='CSharpRegexGroup'), 'Captures', ['List', 'RegexpMatch']), index=to_node(0), pseudo_type='RegexpMatch'), 'has_match': '.Success!' }, 'Array': { '@equivalent': 'Any[]', 'length': lambda receiver, _: to_node(receiver.pseudo_type[2]) }, 'Tuple': { '@equivalent': 'Tuple', 'length': lambda _, pseudo_type: to_node(len(pseudo_type) - 1) } } functions = { 'io': { 'display': Display, 'read': 'Console.ReadLine', 'read_file': 'File.ReadAllText', 'write_file': 'File.WriteAllText' }, 'math': { 'ln': 'Math.Log', 'log': 'Math.Log', 'tan': 'Math.Tan', 'sin': 'Math.Sin', 'cos': 'Math.Cos', 'pow': 'Math.Pow' }, 'http': {}, 'system': { 'args': lambda _: local('args', ['List', 'String']), 'index': lambda index, _: Node('index', sequence=local('args', ['List', 'String']), index=to_node(index.value - 1) if index.type == 'int' else Node('binary_op', op='-', left=index, right=to_node(1), pseudo_type='Int'), pseudo_type='String'), 'arg_count': lambda _: Node('binary_op', op='+', left=attr(local('args', ['List', 'String']), 'Length', 'Int'), right=to_node(1), pseudo_type='Int') }, 'regexp': { 'compile': lambda value, _: Node('new_instance', class_name='Regex', args=[value], pseudo_type='Regexp'), 'escape': 'Regex.Escape' } } dependencies = { 'List': { '@all': 'System.Collections.Generic', 'map': 'System.Linq', 'filter': 'System.Linq', 'any?': 'System.Linq', 'all?': 'System.Linq', 'reduce': 'System.Linq' }, 'String': { '@all': 'System.Text' }, 'Dictionary': { '@all': 'System.Collections.Generic', }, 'io': { 'read_file': 'System.IO', 'write_file': 'System.IO' }, 'regexp': { '@all': 'System.Text.RegularExpressions' } }
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
from pseudo.api_translator import ApiTranslator, to_op from pseudo.pseudo_tree import Node, method_call, call, to_node, attr, local from pseudo.api_translators.js_api_handlers import empty, present, object_len LODASH = local('_', 'Library') class JSTranslator(ApiTranslator): ''' JS api translator The DSL is explained in the ApiTranslator docstring ''' methods = { 'List': { '@equivalent': 'Array', 'push': '#push', 'pop': '#pop', 'length': '.length!', 'insert': '#splice(%{self}, 0, %{0})', 'remove_at': lambda receiver, index, _: method_call( receiver, 'splice', [ index,
class GolangTranslator(ApiTranslator): ''' Go api translator The DSL is explained in the ApiTranslator docstring ''' methods = { 'List': { '@equivalent': 'slice', 'push': lambda receiver, element, _: assignment( receiver, call('append', [receiver, element], receiver.pseudo_type)), 'pop': lambda receiver, _: assignment( receiver, Node('_go_slice_to', sequence=receiver, to=Node('binary_op', op='-', left=call('len', [receiver], 'Int'), right=to_node(1), pseudo_type='Int'), pseudo_type=receiver.pseudo_type)), 'length': 'len', 'insert': expand_insert, 'slice': expand_slice, 'slice_from': expand_slice, 'slice_to': lambda receiver, to, pseudo_type: expand_slice( receiver, None, to, pseudo_type), 'join': 'strings.Join(%{self}, %{0})', 'map': expand_map, 'filter': expand_filter, 'find': Find, 'reduce': expand_reduce, 'contains?': ListContains, 'present?': present, 'empty?': empty }, 'Dictionary': { '@equivalent': 'map', 'length': 'len', 'contains?': Contains, 'keys': DictKeys, 'values': DictValues, 'present?': present, 'empty?': empty }, 'String': { '@equivalent': 'str', 'substr': expand_slice, 'substr_from': expand_slice, 'length': 'len', 'substr_to': lambda receiver, to, _: expand_slice( receiver, None, to, pseudo_type='String'), 'find': 'strings.Index(%{self}, %{0})', 'count': 'strings.Count(%{self}, %{0})', 'split': 'strings.Split(%{self}, %{0})', 'concat': to_op('+'), 'contains?': 'strings.Contains(%{self}, %{0})', 'present?': present, 'empty?': empty, 'find_from': lambda f, value, index, _: Node( 'binary_op', op='+', pseudo_type='Int', left=index, right=Node('static_call', receiver=local('strings', 'Library'), message='Index', args=[ Node('_go_slice_from', sequence=f, from_=index, pseudo_type='String'), value ], pseudo_type='Int')), 'to_int': Int }, 'Regexp': { '@equivalent': 'Regexp', 'match': lambda receiver, word, _: method_call( receiver, 'FindAllSubmatch', [ Node('_go_bytes', value=word, pseudo_type='Bytes'), to_node(-1) ], pseudo_type='RegexpMatch') }, 'RegexpMatch': { '@equivalent': 'R', 'group': lambda receiver, index, _: Node('index', sequence=receiver, index=Node('binary_op', op='+', left=index, right=to_node(1), pseudo_type='Int'), pseudo_type='String'), 'has_match': lambda receiver, _: Node('comparison', op='!=', left=receiver, right=Node('null', pseudo_type='None'), pseudo_type='Boolean') }, 'Set': { '@equivalent': 'map[bool]struct{}', 'length': 'len', 'contains?': Contains, 'present?': present, 'empty?': empty }, 'Tuple': { '@equivalent': 'L', 'length': lambda receiver, _: to_node(len(receiver.pseudo_type) - 1) }, 'Array': { '@equivalent': 'int[]', 'length': lambda receiver, _: to_node(receiver.pseudo_type[2]) } } functions = { 'regexp': { 'compile': 'regexp.MustCompile', 'escape': 'regexp.QuoteMeta' }, 'io': { 'display': 'fmt.Println', 'read': Read, 'read_file': ReadFile, 'write_file': 'ioutil.WriteFile' }, 'math': { 'ln': 'math.Log', 'log': 'math.Log', 'tan': 'math.Tan', 'sin': 'math.Sin', 'cos': 'math.Cos', 'pow': 'math.Pow' }, 'system': { 'args': 'os.Args!', 'arg_count': lambda _: call('len', [ attr(local('os', 'Library'), 'Args', ['List', 'String']) ], 'Int'), 'index': lambda value, _: Node('index', sequence=attr(local('os', 'Library'), 'Args', ['List', 'String']), index=value, pseudo_type='String') } } dependencies = { 'regexp': { '@all': 'regexp' }, 'io': { 'display': 'fmt', 'read': ['bufio', 'os'], 'read_file': ['io/ioutil'], 'write_file': ['io/ioutil'] }, 'math': { '@all': 'math' }, 'List': { 'join': 'strings' }, 'String': { 'find': 'strings', 'count': 'strings', 'split': 'strings', 'contains?': 'strings', 'find_from': 'strings', 'to_int': 'strconv' }, 'system': { '@all': 'os' } } errors = {}
if 'gen_with_imports' not in namespace: 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')) ]
class PythonTranslator(ApiTranslator): ''' Python api translator The DSL is explained in the ApiTranslator docstring ''' methods = { 'List': { '@equivalent': 'list', 'push': '#append', 'pop': '#pop', 'length': 'len', 'insert': '#insert', 'remove_at': lambda receiver, index, _: Node( '_py_del', value=Node('index', sequence=receiver, index=index), pseudo_type='Void'), 'remove': '#remove', 'slice': expand_slice, 'slice_from': expand_slice, 'slice_to': lambda receiver, to, pseudo_type: expand_slice( receiver, None, to, pseudo_type), 'repeat': to_op('*'), 'set_slice': expand_set_slice, 'set_slice_from': expand_set_slice, 'set_slice_to': lambda receiver, to, value, pseudo_type: expand_set_slice( receiver, None, to, value, pseudo_type), 'find': '#index', 'join': lambda receiver, delimiter, _: method_call( delimiter, 'join', [receiver], pseudo_type='String'), # map and filter have implicit or explicit return because otherwise they wouldnt type check 'map': lambda receiver, f, pseudo_type: Node( '_py_listcomp', sequences=Node('for_sequence', sequence=receiver), iterators=Node('for_iterator', iterator=local(f.params[0].name, f.pseudo_type[ 1])), block=f.block[0].value, test=None, pseudo_type=['List', f.pseudo_type[2]]), 'filter': lambda receiver, test, pseudo_type: Node( '_py_listcomp', sequences=Node('for_sequence', sequence=receiver), iterators=Node('for_iterator', iterator=local(test.params[0].name, test. pseudo_type[1])), block=local(test.params[0].name, test.pseudo_type[1]), test=test.block[0].value, pseudo_type=['List', test.pseudo_type[1]]), 'reduce': lambda receiver, aggregator, initial, pseudo_type: Node( 'static_call', receiver=local('functools', 'Library'), message='reduce', args=[aggregator, receiver, initial], pseudo_type=pseudo_type), 'any?': to_py_generatorcomp('any'), 'all?': to_py_generatorcomp('all'), 'sort': '#sort', 'present?': lambda receiver, _: receiver, 'empty?': lambda receiver, _: Node( 'unary_op', op='not', value=receiver, pseudo_type='Boolean'), 'contains?': contains }, 'Dictionary': { '@equivalent': 'dict', 'length': 'len', 'keys': '#keys', 'values': '#values', 'contains?': contains, 'keys': lambda receiver, pseudo_type: call(local( 'list', ['Function', 'Any', 'List']), [ method_call(receiver, 'keys', [], ['dict_keys', pseudo_type[1]]) ], pseudo_type=pseudo_type), 'values': lambda receiver, pseudo_type: call(local( 'list', ['Function', 'Any', 'List']), [ method_call(receiver, 'values', [], ['dict_values', pseudo_type[1]]) ], pseudo_type=pseudo_type), 'present?': lambda receiver, _: receiver, 'empty?': lambda receiver, _: Node( 'unary_op', op='not', value=receiver, pseudo_type='Boolean') }, 'String': { '@equivalent': 'str', 'substr': expand_slice, 'substr_from': expand_slice, 'length': 'len', 'substr_to': lambda receiver, to, _: expand_slice(receiver, None, to, 'String'), 'find': '#index', 'find_from': '#index', 'count': '#count', 'partition': '#partition', 'split': '#split', 'trim': '#strip', 'format': '#format', 'concat': to_op('+'), 'c_format': to_op('%'), 'center': '#center', 'reversed': 'reversed', 'empty?': lambda receiver, _: Node( 'unary_op', op='not', value=receiver, pseudo_type='Boolean'), 'present?': lambda receiver, _: receiver, 'contains?': lambda receiver, element, _: Node('_py_in', sequence=receiver, value=element, pseudo_type='Boolean'), 'to_int': 'int', 'pad_left': '#ljust', 'pad_right': '#rjust' }, 'Int': { 'to_float': 'float(%{self})' }, 'Float': { 'to_int': 'int(%{self})' }, 'Set': { '@equivalent': 'set', 'length': 'len', 'contains?': contains, 'union': to_op('|'), 'intersection': to_op('-'), 'present?': lambda receiver, _: receiver, 'empty?': lambda receiver, _: Node( 'unary_op', op='not', value=receiver, pseudo_type='Boolean') }, 'Tuple': { '@equivalent': 'tuple', 'length': 'len' }, 'Array': { '@equivalent': 'tuple', 'length': 'len' }, 'Regexp': { '@equivalent': '_sre.SRE_Pattern', 'match': '#match' }, 'RegexpMatch': { '@equivalent': '_sre.SRE_Match', 'group': '#group', 'has_match': lambda receiver, _: receiver } } functions = { 'global': { 'wat': lambda _: Node('block', block=[]), 'exit': lambda status, _: call('exit', [status]) }, 'io': { 'display': 'print', 'read': 'input', 'write_file': WriteFile, 'read_file': ReadFile }, 'system': { 'args': 'sys.argv!', 'arg_count': lambda _: call('len', [ attr(local('sys', 'Library'), 'argv', ['List', 'String']) ], 'Int'), 'index': lambda value, _: Node('index', sequence=attr(local('sys', 'Library'), 'argv', ['List', 'String']), index=value, pseudo_type='String') }, 'http': { 'get': 'requests.get', 'post': 'requests.post', }, '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': 're.compile', 'escape': 're.escape' } } dependencies = { 'Regexp': { '@all': 're' }, 'List': { 'reduce': 'functools' }, 'http': { '@all': 'requests' }, 'math': { '@all': 'math' }, 'regexp': { '@all': 're' }, 'system': { '@all': 'sys' } }
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'),
class JSTranslator(ApiTranslator): ''' JS api translator The DSL is explained in the ApiTranslator docstring ''' methods = { 'List': { '@equivalent': 'Array', 'push': '#push', 'pop': '#pop', 'length': '.length!', 'insert': '#splice(%{self}, 0, %{0})', 'remove_at': lambda receiver, index, _: method_call( receiver, 'splice', [ index, to_node(index.value + 1) if index.type == 'int' else Node('binary_op', op='+', left=index, right=to_node(1), pseudo_type='Int') ], pseudo_type='Void'), 'remove': '_.pull(%{self}, %{0})', 'slice': '#slice', 'slice_from': '#slice', 'slice_to': '#slice(0, %{0})', 'map': '_.map(%{self}, %{0})', 'filter': '_.filter(%{self}, %{0})', 'reduce': '_.reduce(%{self}, %{0}, %{1})', 'any?': '_.any(%{self}, %{0})', 'all?': '_.all(%{self}, %{0})', 'sort': '#sort', 'empty?': empty, 'present?': present, 'find': '#indexOf', 'contains?': '_.contains(%{self}, %{0})' }, 'Dictionary': { '@equivalent': 'Object', 'length': object_len, 'keys': 'Object.keys(%{self})', 'values': 'Object.values(%{self})', 'contains?': '#hasOwnProperty', 'present?': present, 'empty?': empty }, 'String': { '@equivalent': 'String', 'substr': '#slice', 'substr_from': '#slice', 'length': '.length!', 'substr_to': '#slice(0, %{0})', 'find': '#search', 'find_from': lambda f, value, index, _: Node( 'binary_op', op='+', pseudo_type='Int', left=index, right=method_call(method_call(f, 'slice', [index], 'String'), 'search', [value], 'Int')), 'count': lambda f, count, _: attr( method_call(LODASH, 'where', [count], ['List', 'String']), 'length', 'Int'), 'concat': to_op('+'), 'partition': lambda f, delimiter, _: Node( 'index', sequence=method_call(LODASH, 'partition', [delimiter], 'String' ), index=to_node(1), pseudo_type=['Tuple', 'String', 'String', 'String']), 'split': '#split', 'trim': '#trim', 'reversed': lambda f, _: method_call( method_call( method_call(f, 'split', [to_node('')], ['List', 'String']), 'reverse', [], ['List', 'String']), 'join', [to_node('')], 'String'), 'center': '_.pad(%{self}, %{0}, %{1})', 'present?': lambda f, _: f, 'empty?': lambda f, _: Node( 'unary_op', op='not', value=f, pseudo_type='Boolean'), 'contains?': '_.contains(%{self}, %{0})', 'to_int': 'parseInt', 'pad_left': '_.padLeft(%{self}, %{0}, %{1})', 'pad_right': '_.padRight(%{self}, %{0}, %{1})' }, 'Tuple': { '@equivalent': 'Array', 'length': '.length!' }, 'Array': { '@equivalent': 'Array', 'length': '.length!' }, 'Set': { '@equivalent': 'Object', 'length': object_len, 'contains?': '_.contains(%{self}, %{0})', 'intersection': '_.intersection(%{self}, %{0})', 'union': '_.union(%{self}, %{0})', 'present?': present, 'empty?': empty }, 'RegexpMatch': { '@equivalent': 'Array', 'group': lambda receiver, index, _: Node('index', sequence=receiver, index=to_node(1 + index.value) if index.type == 'int' else Node( 'binary_op', op='+', left=to_node(1), right=index, pseudo_type='Int'), pseudo_type='String'), 'has_match': lambda receiver, _: receiver }, 'Regexp': { '@equivalent': 'Regexp', 'match': '#exec' } } functions = { 'global': { 'wat': lambda _: Node('block', block=[]), 'exit': lambda status, _: call('exit', [status]) }, 'system': { 'args': 'process.argv!', 'arg_count': lambda _: Node('binary_op', op='-', left=attr( attr(local('process', 'Library'), 'argv', ['List', 'String']), 'length', 'Int'), right=to_node(1), pseudo_type='Int'), 'index': lambda value, _: Node('index', sequence=attr(local('process', 'Library'), 'argv', ['List', 'String']), index=to_node(value.value + 1) if value.type == 'int' else Node('binary_op', op='+', left=value, right=value, pseudo_type='Int'), pseudo_type='String') }, 'io': { 'display': 'console.log', 'read_file': "fs.readFileSync(%{0}, 'utf8')", 'write_file': "fs.writeFileSync(%{0}, %{1}, 'utf8')", }, 'math': { 'ln': 'Math.log', 'log': 'Math.log', 'tan': 'Math.tan', 'sin': 'Math.sin', 'cos': 'Math.cos', 'pow': 'Math.pow' }, 'regexp': { 'compile': lambda value, _: Node('new_instance', class_name='RegExp', args=[value], pseudo_type='Regexp'), 'escape': '_.escapeRegExp' } } js_dependencies = {'_': 'lodash'} dependencies = { 'io': { 'read_file': 'fs', 'write_file': 'fs' }, 'regexp': { 'escape': 'lodash' } }
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