summaryrefslogtreecommitdiff
path: root/tools/libdol2asm/types/function.py
blob: b4574d0c10b28b74f4c25d123345884b7172e449 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
from dataclasses import dataclass, field
from typing import List, Set

from .base import *
from .named import *


@dataclass(frozen=True, eq=True)
class FunctionType(Type):
    inner: Type
    return_type: Type
    argument_types: List[Type] = field(default_factory=list)
    inner_class: NamedType = None

    def __hash__(self):
        return hash((self.inner, self.return_type, tuple(self.argument_types), self.inner_class))

    def type(self,
             specialize_templates: bool = False,
             without_template: bool = False) -> str:
        return self.decl("",
                         specialize_templates=specialize_templates,
                         without_template=without_template)

    def traverse(self, callback, depth):
        should_exit = callback(self, depth)
        if not should_exit:
            self.inner.traverse(callback, depth + 1)
            self.return_type.traverse(callback, depth + 1)
            for arg in self.argument_types:
                arg.traverse(callback, depth + 1)
            if self.inner_class:
                self.inner_class.traverse(callback, depth + 1)

    def decl(self,
             label: str,
             specialize_templates: bool = False,
             without_template: bool = False) -> str:
        class_name = ""
        if self.inner_class:
            inner = self.inner_class.type(specialize_templates=specialize_templates,
                                          without_template=without_template)
            class_name = f"{inner}::"

        return_type = self.return_type.type(specialize_templates=specialize_templates,
                                            without_template=without_template)
        inner_type = self.inner.type(specialize_templates=specialize_templates,
                                     without_template=without_template)
        args = ", ".join([x.type(specialize_templates=specialize_templates,
                                 without_template=without_template) for x in self.argument_types])
        return f"{return_type} ({class_name}{inner_type}{label})({args})"