summaryrefslogtreecommitdiff
path: root/tools/libdol2asm/types/array.py
blob: 1a9353821699cbaeac363b362dc6ad1f38887d43 (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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
from dataclasses import dataclass, field
from typing import List
from .base import *
from .empty import *


@dataclass(frozen=True, eq=True)
class ArrayType(Type):
    base: Type
    inner: Type
    sizes: List[int] = field(default_factory=list)

    def __hash__(self):
        return hash((self.base, self.inner, tuple(self.sizes)))

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

    def decl(self,
             label: str,
             specialize_templates: bool = False,
             without_template: bool = False) -> str:
        size = ''.join(f'[{i}]' for i in self.sizes)
        base = self.base.type(specialize_templates=specialize_templates,without_template=without_template)
        if isinstance(self.inner, EmptyType):
            return f"{base} {label}{size}"
        else:
            inner = self.inner.decl(label,specialize_templates=specialize_templates,without_template=without_template)
            return f"{base} ({inner}){size}"

    def traverse(self, callback, depth):
        should_exit = callback(self, depth)
        if not should_exit:
            self.base.traverse(callback, depth + 1)
            self.inner.traverse(callback, depth + 1)

    @staticmethod
    def create(base: Type, count: int) -> "ArrayType":
        return ArrayType(base, EmptyType(), [count])


@dataclass(frozen=True, eq=True)
class PaddingArrayType(Type):
    """
        Type which is used for exporting symbols of raw data with padding.
        Should never be used by the typing system.
    """

    base: Type
    size: int
    padding: int

    def __hash__(self):
        return hash((self.base, self.size, self.padding))

    def type(self) -> str:
        assert False

    def dependencies(self) -> Set["Type"]:
        assert False

    def decl(self, label: str) -> str:
        padding_size = ""
        if self.padding > 0:
            padding_size = f" + {self.padding} /* padding */"
        return f"{self.base.type()} {label}[{self.size}{padding_size}]"

    @staticmethod
    def create(base: Type, size: int, padding: int) -> "PaddingArrayType":
        return PaddingArrayType(base, size, padding)

@dataclass(frozen=True, eq=True)
class ZeroArrayType(Type):    
    """ Array Type with zero/unknown length """

    base: Type

    def __hash__(self):
        return hash((self.base, "ZERO_ARRAY_TYPE"))

    def type(self) -> str:
        assert False

    def dependencies(self) -> Set["Type"]:
        assert False

    def decl(self, label: str) -> str:
        return f"{self.base.type()} {label}[]"

    @staticmethod
    def create(base: Type) -> "ZeroArrayType":
        return ZeroArrayType(base)