phasm/phasm/typing.py
2022-07-09 12:48:54 +02:00

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
)