207 lines
4.2 KiB
Python
207 lines
4.2 KiB
Python
"""
|
|
The phasm type system
|
|
"""
|
|
from typing import Optional, List
|
|
|
|
class TypeBase:
|
|
"""
|
|
TypeBase base class
|
|
"""
|
|
__slots__ = ()
|
|
|
|
def render(self) -> str:
|
|
"""
|
|
Renders the type back to source code format
|
|
|
|
This'll look like Python code.
|
|
"""
|
|
raise NotImplementedError(self, 'render')
|
|
|
|
def alloc_size(self) -> int:
|
|
"""
|
|
When allocating this type in memory, how many bytes do we need to reserve?
|
|
"""
|
|
raise NotImplementedError(self, 'alloc_size')
|
|
|
|
class TypeNone(TypeBase):
|
|
"""
|
|
The None (or Void) type
|
|
"""
|
|
__slots__ = ()
|
|
|
|
def render(self) -> str:
|
|
return 'None'
|
|
|
|
class TypeBool(TypeBase):
|
|
"""
|
|
The boolean type
|
|
"""
|
|
__slots__ = ()
|
|
|
|
def render(self) -> str:
|
|
return 'bool'
|
|
|
|
class TypeUInt8(TypeBase):
|
|
"""
|
|
The Integer type, unsigned and 8 bits wide
|
|
"""
|
|
__slots__ = ()
|
|
|
|
def render(self) -> str:
|
|
return 'u8'
|
|
|
|
def alloc_size(self) -> int:
|
|
return 4 # Int32 under the hood
|
|
|
|
class TypeInt32(TypeBase):
|
|
"""
|
|
The Integer type, signed and 32 bits wide
|
|
"""
|
|
__slots__ = ()
|
|
|
|
def render(self) -> str:
|
|
return 'i32'
|
|
|
|
def alloc_size(self) -> int:
|
|
return 4
|
|
|
|
class TypeInt64(TypeBase):
|
|
"""
|
|
The Integer type, signed and 64 bits wide
|
|
"""
|
|
__slots__ = ()
|
|
|
|
def render(self) -> str:
|
|
return 'i64'
|
|
|
|
def alloc_size(self) -> int:
|
|
return 8
|
|
|
|
class TypeFloat32(TypeBase):
|
|
"""
|
|
The Float type, 32 bits wide
|
|
"""
|
|
__slots__ = ()
|
|
|
|
def render(self) -> str:
|
|
return 'f32'
|
|
|
|
def alloc_size(self) -> int:
|
|
return 4
|
|
|
|
class TypeFloat64(TypeBase):
|
|
"""
|
|
The Float type, 64 bits wide
|
|
"""
|
|
__slots__ = ()
|
|
|
|
def render(self) -> str:
|
|
return 'f64'
|
|
|
|
def alloc_size(self) -> int:
|
|
return 8
|
|
|
|
class TypeBytes(TypeBase):
|
|
"""
|
|
The bytes type
|
|
"""
|
|
__slots__ = ()
|
|
|
|
def render(self) -> str:
|
|
return 'bytes'
|
|
|
|
class TypeTupleMember:
|
|
"""
|
|
Represents a tuple member
|
|
"""
|
|
def __init__(self, idx: int, type_: TypeBase, offset: int) -> None:
|
|
self.idx = idx
|
|
self.type = type_
|
|
self.offset = offset
|
|
|
|
class TypeTuple(TypeBase):
|
|
"""
|
|
The tuple type
|
|
"""
|
|
__slots__ = ('members', )
|
|
|
|
members: List[TypeTupleMember]
|
|
|
|
def __init__(self) -> None:
|
|
self.members = []
|
|
|
|
def render(self) -> str:
|
|
mems = ', '.join(x.type.render() for x in self.members)
|
|
return f'({mems}, )'
|
|
|
|
def render_internal_name(self) -> str:
|
|
mems = '@'.join(x.type.render() for x in self.members)
|
|
assert ' ' not in mems, 'Not implement yet: subtuples'
|
|
return f'tuple@{mems}'
|
|
|
|
def alloc_size(self) -> int:
|
|
return sum(
|
|
x.type.alloc_size()
|
|
for x in self.members
|
|
)
|
|
|
|
class TypeStructMember:
|
|
"""
|
|
Represents a struct member
|
|
"""
|
|
def __init__(self, name: str, type_: TypeBase, offset: int) -> None:
|
|
self.name = name
|
|
self.type = type_
|
|
self.offset = offset
|
|
|
|
class TypeStruct(TypeBase):
|
|
"""
|
|
A struct has named properties
|
|
"""
|
|
__slots__ = ('name', 'lineno', 'members', )
|
|
|
|
name: str
|
|
lineno: int
|
|
members: List[TypeStructMember]
|
|
|
|
def __init__(self, name: str, lineno: int) -> None:
|
|
self.name = name
|
|
self.lineno = lineno
|
|
self.members = []
|
|
|
|
def get_member(self, name: str) -> Optional[TypeStructMember]:
|
|
"""
|
|
Returns a member by name
|
|
"""
|
|
for mem in self.members:
|
|
if mem.name == name:
|
|
return mem
|
|
|
|
return None
|
|
|
|
def render(self) -> str:
|
|
"""
|
|
Renders the type back to source code format
|
|
|
|
This'll look like Python code.
|
|
"""
|
|
return self.name
|
|
|
|
def render_definition(self) -> str:
|
|
"""
|
|
Renders the definition back to source code format
|
|
|
|
This'll look like Python code.
|
|
"""
|
|
result = f'class {self.name}:\n'
|
|
for mem in self.members:
|
|
result += f' {mem.name}: {mem.type.render()}\n'
|
|
|
|
return result
|
|
|
|
def alloc_size(self) -> int:
|
|
return sum(
|
|
x.type.alloc_size()
|
|
for x in self.members
|
|
)
|