示例#1
0
    def visit_Assign(self, node: ast.Assign) -> str:
        assign: List[str] = []
        use_temp: bool = len(node.targets) > 1 and isinstance(
            node.value, ast.Call)
        if use_temp:
            assign.append(f"mut tmp := {self.visit(node.value)}")
        for target in node.targets:
            kw: str = "mut " if is_mutable(node.scopes, get_id(target)) else ""
            if use_temp:
                value: str = "tmp"
            else:
                value: str = self.visit(node.value)

            if isinstance(target, (ast.Tuple, ast.List)):
                value = value[1:-1]
                subtargets: List[str] = []
                op: str = ":="
                for subtarget in target.elts:
                    subkw: str = ("mut " if is_mutable(
                        node.scopes, get_id(subtarget)) else "")
                    subtargets.append(f"{subkw}{self.visit(subtarget)}")
                    definition: Optional[
                        ast.AST] = node.scopes.parent_scopes.find(
                            get_id(subtarget)) or node.scopes.find(
                                get_id(subtarget))
                    if definition is not None and defined_before(
                            definition, subtarget):
                        op = "="
                    elif op == "=":
                        raise AstNotImplementedError(
                            "Mixing declarations and assignment in the same statement is unsupported.",
                            node,
                        )
                assign.append(f"{', '.join(subtargets)} {op} {value}")
            elif isinstance(target, (ast.Subscript, ast.Attribute)):
                target: str = self.visit(target)
                assign.append(f"{target} = {value}")
            elif isinstance(target, ast.Name) and defined_before(
                    node.scopes.parent_scopes.find(target.id)
                    or node.scopes.find(target.id),
                    node,
            ):
                target: str = self.visit(target)
                assign.append(f"{target} = {value}")
            else:
                target: str = self.visit(target)

                assign.append(f"{kw}{target} := {value}")
        return "\n".join(assign)
示例#2
0
    def visit_ClassDef(self, node):
        extractor = DeclarationExtractor(KotlinTranspiler())
        extractor.visit(node)
        declarations = node.declarations = extractor.get_declarations()
        node.class_assignments = extractor.class_assignments
        ret = super().visit_ClassDef(node)
        if ret is not None:
            return ret

        fields = []
        index = 0
        for declaration, typename in declarations.items():
            if typename == None:
                typename = "ST{0}".format(index)
                index += 1
            mut = is_mutable(node.scopes, get_id(declaration))
            mut = "var" if mut else "val"
            fields.append(f"{mut} {declaration}: {typename}")

        for b in node.body:
            if isinstance(b, ast.FunctionDef):
                b.self_type = node.name

        if node.is_dataclass:
            fields = ", ".join(fields)
            body = [self.visit(b) for b in node.body]
            body = "\n".join(body)
            return f"data class {node.name}({fields}) {{\n{body}\n}}\n"
        else:
            fields = "\n".join(fields)
            body = [self.visit(b) for b in node.body]
            body = "\n".join(body)
            return f"class {node.name} {{\n{fields}\n\n {body}\n}}\n"
示例#3
0
    def _visit_AssignOne(self, node, target) -> str:
        kw = "var" if is_mutable(node.scopes, get_id(target)) else "let"

        if isinstance(target, ast.Tuple):
            elts = [self.visit(e) for e in target.elts]
            elts_str = ", ".join(elts)
            value = self.visit(node.value)
            return f"{kw} ({elts_str}) = {value}"

        if isinstance(node.scopes[-1], ast.If):
            outer_if = node.scopes[-1]
            target_id = self.visit(target)
            if target_id in outer_if.common_vars:
                value = self.visit(node.value)
                return f"{kw} {target_id} = {value}"

        if isinstance(target, ast.Subscript) or isinstance(
                target, ast.Attribute):
            target = self.visit(target)
            value = self.visit(node.value)
            return f"{target} = {value}"

        definition = node.scopes.parent_scopes.find(get_id(target))
        if definition is None:
            definition = node.scopes.find(get_id(target))
        if isinstance(target, ast.Name) and defined_before(definition, node):
            target = self.visit(target)
            value = self.visit(node.value)
            return f"{target} = {value}"
        else:
            target = self.visit(target)
            value = self.visit(node.value)

            return f"{kw} {target} = {value}"
示例#4
0
    def visit_Call(self, node: ast.Call) -> str:
        fname: str = self.visit(node.func)
        fndef: ast.AST = node.scopes.find(fname)

        if isinstance(fndef, ast.ClassDef):
            return self._visit_object_literal(node, fname, fndef)

        vargs: List[str] = []

        for idx, arg in enumerate(node.args):
            if hasattr(fndef, "args") and is_mutable(fndef.scopes,
                                                     fndef.args.args[idx].arg):
                vargs.append(f"mut {self.visit(arg)}")
            else:
                vargs.append(self.visit(arg))
        if node.keywords:
            vargs += [self.visit(kw.value) for kw in node.keywords]

        ret: Optional[str] = self._dispatch(node, fname, vargs)
        if ret is not None:
            return ret
        if vargs:
            args = ", ".join(vargs)
        else:
            args = ""
        return f"{fname}({args})"
示例#5
0
 def _compute_kw(self, node, target) -> str:
     kw = "let"
     mut = is_mutable(node.scopes, get_id(target))
     if is_global(node) or getattr(node, "class_assignment", False):
         # Note that static are not really supported, as modifying them requires adding
         # "unsafe" blocks, which pyrs does not do.
         kw = "pub static" if mut else "pub const"
     elif mut:
         kw = "let mut"
     return kw
示例#6
0
 def visit_arg(self, node) -> Tuple[Optional[str], str]:
     id = get_id(node)
     if id == "self":
         return (None, "self")
     typename = ""
     if node.annotation:
         typename = self._typename_from_annotation(node)
     if is_mutable(node.scopes, id):
         id = f"mut {id}"
     return (typename, id)
示例#7
0
    def _visit_AssignOne(self, node, target):
        kw = "var" if is_mutable(node.scopes, get_id(target)) else "final"

        if isinstance(target, ast.Tuple):
            self._usings.add("package:tuple/tuple.dart")
            elts = [self.visit(e) for e in target.elts]
            value = self.visit(node.value)
            value_types = "int, int"
            count = len(elts)
            tmp_var = self._get_temp()
            buf = [f"{kw} {tmp_var} = Tuple{count}<{value_types}>{value};"]
            for i, elt in enumerate(elts):
                buf.extend([f"{elt} = {tmp_var}.item{i+1};"])
            return "\n".join(buf)

        if isinstance(node.scopes[-1], ast.If):
            outer_if = node.scopes[-1]
            target_id = self.visit(target)
            if target_id in outer_if.common_vars:
                value = self.visit(node.value)
                return f"{kw} {target_id} = {value};"

        if isinstance(target, ast.Subscript) or isinstance(
                target, ast.Attribute):
            target = self.visit(target)
            value = self.visit(node.value)
            return f"{target} = {value};"

        definition = node.scopes.find(target.id)
        if isinstance(target, ast.Name) and defined_before(definition, node):
            target = self.visit(target)
            value = self.visit(node.value)
            return f"{target} = {value};"
        elif isinstance(node.value, ast.List):
            elements = [self.visit(e) for e in node.value.elts]
            elements = ", ".join(elements)
            target = self.visit(target)

            return f"{kw} {target} = [{elements}];"
        else:
            typename = self._typename_from_annotation(target)
            target = self.visit(target)
            value = self.visit(node.value)

            if typename != self._default_type:
                if kw == self._default_type:
                    return f"{typename} {target} = {value};"
            else:
                return f"{kw} {target} = {value};"

            return f"{kw} {typename} {target} = {value};"
示例#8
0
 def visit_arg(self, node):
     id = get_id(node)
     if id == "self":
         return (None, "self")
     typename = "T"
     if node.annotation:
         typename = self._typename_from_annotation(node)
         mut = "mut " if is_mutable(node.scopes, id) else ""
         # TODO: Should we make this if not primitive instead of checking
         # for container types? That way we cover user defined structs too.
         if hasattr(node, "container_type"):
             # Python passes by reference by default. Rust needs explicit borrowing
             typename = f"&{mut}{typename}"
     return (typename, id)
示例#9
0
 def visit_Return(self, node):
     self.generic_visit(node)
     if node.value:
         fndef = None
         for scope in node.scopes:
             if isinstance(scope, ast.FunctionDef):
                 fndef = scope
                 break
         if fndef:
             if is_reference(node.value):
                 mut = is_mutable(node.scopes, get_id(node.value))
                 fndef.returns.rust_needs_reference = not mut
                 fndef.rust_return_needs_reference = (
                     fndef.returns.rust_needs_reference)
     return node
示例#10
0
 def visit_arg(self, node):
     id = get_id(node)
     if id == "self":
         return (None, "self")
     typename = "T"
     if node.annotation:
         # This works only for arguments, for all other cases, use container_types
         mutable = is_mutable(node.scopes, id)
         use_open_array = isinstance(node.annotation, ast.Subscript) and not mutable
         typename = self._typename_from_annotation(node)
         if use_open_array:
             typename = typename.replace("seq", "openArray")
         if mutable:
             typename = f"var {typename}"
     return (typename, id)
示例#11
0
 def visit_AnnAssign(self, node: ast.AnnAssign) -> str:
     target, type_str, val = super().visit_AnnAssign(node)
     kw: str = "mut " if is_mutable(node.scopes, target) else ""
     if isinstance(node.value, ast.List):
         if node.value.elts:
             elts: List[str] = []
             if type_str[2:] in V_WIDTH_RANK:
                 elts.append(
                     f"{type_str[2:]}({self.visit(node.value.elts[0])})")
             else:
                 elts.append(self.visit(node.value.elts[0]))
             elts.extend(map(self.visit, node.value.elts[1:]))
             return f"{kw}{target} := [{', '.join(elts)}]"
         return f"{kw}{target} := {type_str}{{}}"
     else:
         return f"{kw}{target} := {val}"
示例#12
0
    def _visit_AssignOne(self, node, target):
        kw = "var" if is_mutable(node.scopes, get_id(target)) else "val"

        if isinstance(target, ast.Tuple):
            elts = [self.visit(e) for e in target.elts]
            elts_str = ", ".join(elts)
            value = self.visit(node.value)
            if isinstance(node.value, ast.Tuple):
                value = f"Pair{value}"
            return f"{kw} ({elts_str}) = {value}"

        if isinstance(node.scopes[-1], ast.If):
            outer_if = node.scopes[-1]
            target_id = self.visit(target)
            if target_id in outer_if.common_vars:
                value = self.visit(node.value)
                return f"{kw} {target_id} = {value}"

        if isinstance(target, ast.Subscript) or isinstance(
                target, ast.Attribute):
            target = self.visit(target)
            value = self.visit(node.value)
            return f"{target} = {value}"

        definition = node.scopes.find(target.id)
        if isinstance(target, ast.Name) and defined_before(definition, node):
            target = self.visit(target)
            value = self.visit(node.value)
            return f"{target} = {value}"
        elif isinstance(node.value, ast.List):
            elements = [self.visit(e) for e in node.value.elts]
            elements = ", ".join(elements)
            target = self.visit(target)

            return f"{kw} {target} = arrayOf({elements})"
        else:
            target = self.visit(target)
            value = self.visit(node.value)

            return f"{kw} {target} = {value}"
示例#13
0
    def _visit_AssignOne(self, node, target):
        kw = "let"
        mut = is_mutable(node.scopes, get_id(target))
        if is_global(node):
            # Note that static are not really supported, as modifying them requires adding
            # "unsafe" blocks, which pyrs does not do.
            kw = "pub static" if mut else "pub const"
        elif mut:
            kw = "let mut"

        if isinstance(target, ast.Tuple):
            elts = ", ".join([self.visit(e) for e in target.elts])
            value = self.visit(node.value)
            return f"{kw} ({elts}) = {value};"

        if isinstance(node.scopes[-1], ast.If):
            outer_if = node.scopes[-1]
            target_id = self.visit(target)
            if target_id in outer_if.common_vars:
                value = self.visit(node.value)
                return "{0} = {1};".format(target_id, value)

        if isinstance(target, ast.Subscript) or isinstance(
                target, ast.Attribute):
            target = self.visit(target)
            value = self.visit(node.value)
            if value == None:
                value = "None"
            return "{0} = {1};".format(target, value)

        definition = node.scopes.find(target.id)
        if isinstance(target, ast.Name) and defined_before(definition, node):
            needs_cast = self._needs_cast(target, node.value)
            target_str = self.visit(target)
            value = self.visit(node.value)
            if needs_cast:
                target_type = self._typename_from_annotation(target)
                value = self._assign_cast(value, target_type,
                                          target.annotation,
                                          node.value.rust_annotation)
            return f"{target_str} = {value};"
        elif isinstance(node.value, ast.List):
            count = len(node.value.elts)
            target = self.visit(target)
            value = self.visit(node.value)
            typename = self._typename_from_annotation(node.value)

            if kw.startswith("pub "):
                # Use arrays instead of Vec as globals must have fixed size
                if value.startswith("vec!"):
                    value = value.replace("vec!", "&")
                element_type = self._default_type
                if hasattr(node.value, "container_type"):
                    container_type, element_type = node.value.container_type
                return f"{kw} {target}: &[{element_type}; {count}] = {value};"

            mut = "mut " if is_mutable(node.scopes, target) else ""
            if hasattr(node.value, "container_type"):
                return f"{kw} {target}: &{mut}{typename} = &{mut}{value};"

            return f"{kw} {target}: {typename} = {value};"
        elif isinstance(node.value, ast.Set):
            target = self.visit(target)
            value = self.visit(node.value)
            typename = self._typename_from_annotation(node.value)

            if kw.startswith("pub "):
                self._usings.add("lazy_static::lazy_static")
                if "str" in typename:
                    typename = typename.replace("str", "'static str")
                return (
                    f"lazy_static! {{ pub static ref {target}: {typename} = {value}; }}"
                )

            mut = "mut " if is_mutable(node.scopes, target) else ""
            if hasattr(node.value, "container_type"):
                return f"{kw} {target}: &{mut}{typename} = &{mut}{value};"

            return f"{kw} {target}: {typename} = {value};"
        elif isinstance(node.value, ast.Dict):
            target = self.visit(target)
            value = self.visit(node.value)
            typename = self._typename_from_annotation(node.value)

            if kw.startswith("pub "):
                if hasattr(node.value, "container_type"):
                    container_type, element_type = node.value.container_type
                    key_typename, value_typename = element_type
                    if key_typename == "&str":
                        key_typename = "&'static str"
                    if value_typename == "&str":
                        value_typename = "&'static str"
                    typename = f"{key_typename}, {value_typename}"

                return f"lazy_static! {{ pub static ref {target}: HashMap<{typename}> = {value}; }}"

            mut = "mut " if is_mutable(node.scopes, target) else ""
            if hasattr(node.value, "container_type"):
                return f"{kw} {target}: &{mut}{typename} = &{mut}{value};"

            return f"{kw} {target}: {typename} = {value};"
        else:
            typename = self._typename_from_annotation(target)
            needs_cast = self._needs_cast(target, node.value)
            target_str = self.visit(target)
            value = self.visit(node.value)
            if needs_cast:
                value = self._assign_cast(value, typename, target.annotation,
                                          node.value.annotation)
            return f"{kw} {target_str}: {typename} = {value};"
示例#14
0
 def visit_AnnAssign(self, node):
     target, type_str, val = super().visit_AnnAssign(node)
     mut = "mut " if is_mutable(node.scopes, get_id(node.target)) else ""
     return f"let {mut}{target}: {type_str} = {val};"
示例#15
0
    def _visit_AssignOne(self, node, target):
        kw = self._compute_kw(node, target)

        if isinstance(node.scopes[-1], ast.If):
            outer_if = node.scopes[-1]
            target_id = self.visit(target)
            if target_id in outer_if.common_vars:
                value = self.visit(node.value)
                return "{0} = {1};".format(target_id, value)

        if isinstance(target, ast.Subscript) or isinstance(
                target, ast.Attribute):
            target = self.visit(target)
            value = self.visit(node.value)
            if value == None:
                value = "None"
            return "{0} = {1};".format(target, value)

        definition = node.scopes.parent_scopes.find(get_id(target))
        if definition is None:
            definition = node.scopes.find(get_id(target))
        if isinstance(target, ast.Name) and defined_before(definition, node):
            needs_cast = self._needs_cast(target, node.value)
            target_str = self.visit(target)
            value = self.visit(node.value)
            if needs_cast:
                target_type = self._typename_from_annotation(target)
                value = self._assign_cast(value, target_type,
                                          target.annotation,
                                          node.value.rust_annotation)
            return f"{target_str} = {value};"
        elif isinstance(node.value, ast.List) and kw.startswith("pub "):
            count = len(node.value.elts)
            target = self.visit(target)
            value = self.visit(node.value)
            # populate node.value.container_type
            self._typename_from_annotation(node.value)
            # Use arrays instead of Vec as globals must have fixed size
            if value.startswith("vec!"):
                value = value.replace("vec!", "&")
            element_type = self._default_type
            if hasattr(node.value, "container_type"):
                container_type, element_type = node.value.container_type
            return f"{kw} {target}: &[{element_type}; {count}] = {value};"
        elif isinstance(node.value, ast.Set) and kw.startswith("pub "):
            target = self.visit(target)
            value = self.visit(node.value)
            typename = self._typename_from_annotation(node.value)

            self._usings.add("lazy_static::lazy_static")
            if "str" in typename:
                typename = typename.replace("str", "'static str")
            return f"lazy_static! {{ pub static ref {target}: {typename} = {value}; }}"
        elif isinstance(node.value, ast.Dict) and kw.startswith("pub "):
            target = self.visit(target)
            value = self.visit(node.value)
            typename = self._typename_from_annotation(node.value)

            self._usings.add("lazy_static::lazy_static")
            if hasattr(node.value, "container_type"):
                container_type, element_type = node.value.container_type
                key_typename, value_typename = element_type
                if key_typename == "&str":
                    key_typename = "&'static str"
                if value_typename == "&str":
                    value_typename = "&'static str"
                typename = f"{key_typename}, {value_typename}"

            return f"lazy_static! {{ pub static ref {target}: HashMap<{typename}> = {value}; }}"
        else:
            typename = self._typename_from_annotation(target)
            needs_cast = self._needs_cast(target, node.value)
            target_str = self.visit(target)
            value = self.visit(node.value)
            if needs_cast:
                value = self._assign_cast(value, typename, target.annotation,
                                          node.value.annotation)
            if hasattr(node.value, "container_type"):
                mut = "mut " if is_mutable(node.scopes, target_str) else ""
                typename = f"&{mut}{typename}"
                value = f"&{mut}{value}"
            optional_typename = (f": {typename}"
                                 if typename != self._default_type else "")
            return f"{kw} {target_str}{optional_typename} = {value};"
示例#16
0
 def visit_AnnAssign(self, node) -> str:
     target, type_str, val = super().visit_AnnAssign(node)
     kw = "var" if is_mutable(node.scopes, target) else "let"
     if type_str == self._default_type:
         return f"{kw} {target} = {val}"
     return f"{kw} {target}: {type_str} = {val}"