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 clean_tuple_class_type(self, t): if isinstance(t, list): if t[0] == 'Tuple': a = self.tuple_definitions.get(safe_serialize_type(t)) if a: return camel_case(a[0]) t[1:] = [self.clean_tuple_class_type(child) for child in t[1:]] return t
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_tuple(self, node, in_block=False, assignment=None): name = safe_serialize_type(node.pseudo_type) if name in self.tuple_definitions: return Node('simple_initializer', name=camel_case(self.tuple_definitions[name][0]), args=node.elements) else: if self.all: # go: we have to change all tuples self.tuple_definitions[name] = Node('class_definition', name=name, base=None, constructor=None, attrs=[Node('immutable_class_attr', name='item%d' % j, is_public=True, pseudo_type=q) for j, q in enumerate(node.pseudo_type[1:])], methods=[]) else: # c#: we can just use tuples return node
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
def transform_tuple(self, node, in_block=False, assignment=None): name = safe_serialize_type(node.pseudo_type) if name in self.tuple_definitions: return Node('simple_initializer', name=camel_case(self.tuple_definitions[name][0]), args=node.elements) else: if self.all: # go: we have to change all tuples self.tuple_definitions[name] = Node( 'class_definition', name=name, base=None, constructor=None, attrs=[ Node('immutable_class_attr', name='item%d' % j, is_public=True, pseudo_type=q) for j, q in enumerate(node.pseudo_type[1:]) ], methods=[]) else: # c#: we can just use tuples 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_local(self, node, in_block=False, assignment=None): if node.name in self.old_params: return attr(self.l, camel_case(node.name)) # aware of tuple name updates 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