Moves the prelude to runtime
Previously, it was hardcoded at 'compile' time (in as much Python has that). This would make it more difficult to add stuff to it. Also, in a lot of places we made assumptions about prelude instead of checking properly.
This commit is contained in:
parent
d97be81828
commit
b83772e178
0
phasm/build/__init__.py
Normal file
0
phasm/build/__init__.py
Normal file
211
phasm/build/base.py
Normal file
211
phasm/build/base.py
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
"""
|
||||||
|
The base class for build environments.
|
||||||
|
|
||||||
|
Contains nothing but the explicit compiler builtins.
|
||||||
|
"""
|
||||||
|
from typing import Any, NamedTuple, Type
|
||||||
|
|
||||||
|
from ..type3.types import (
|
||||||
|
IntType3,
|
||||||
|
Type3,
|
||||||
|
TypeConstructor_Base,
|
||||||
|
TypeConstructor_DynamicArray,
|
||||||
|
TypeConstructor_StaticArray,
|
||||||
|
TypeConstructor_Struct,
|
||||||
|
TypeConstructor_Tuple,
|
||||||
|
)
|
||||||
|
from ..type3.typeclasses import Type3Class, Type3ClassMethod
|
||||||
|
from ..type3.routers import NoRouteForTypeException, TypeApplicationRouter
|
||||||
|
from ..wasm import WasmType, WasmTypeInt32
|
||||||
|
|
||||||
|
from . import builtins
|
||||||
|
|
||||||
|
|
||||||
|
TypeInfo = NamedTuple('TypeInfo', [
|
||||||
|
# Name of the type
|
||||||
|
('typ', str, ),
|
||||||
|
# What WebAssembly type to use when passing this value around
|
||||||
|
# For example in function arguments
|
||||||
|
('wasm_type', Type[WasmType]),
|
||||||
|
# What WebAssembly function to use when loading a value from memory
|
||||||
|
('wasm_load_func', str),
|
||||||
|
# What WebAssembly function to use when storing a value to memory
|
||||||
|
('wasm_store_func', str),
|
||||||
|
# When storing this value in memory, how many bytes do we use?
|
||||||
|
# Only valid for non-constructed types, see calculate_alloc_size
|
||||||
|
# Should match wasm_load_func / wasm_store_func
|
||||||
|
('alloc_size', int),
|
||||||
|
])
|
||||||
|
|
||||||
|
class BuildBase:
|
||||||
|
__slots__ = (
|
||||||
|
'dynamic_array',
|
||||||
|
'static_array',
|
||||||
|
'struct',
|
||||||
|
'tuple_',
|
||||||
|
|
||||||
|
'none_',
|
||||||
|
|
||||||
|
'type_info_map',
|
||||||
|
'type_info_constructed',
|
||||||
|
|
||||||
|
'types',
|
||||||
|
'type_class_instances',
|
||||||
|
'methods',
|
||||||
|
'operators',
|
||||||
|
|
||||||
|
'alloc_size_router',
|
||||||
|
)
|
||||||
|
|
||||||
|
dynamic_array: TypeConstructor_DynamicArray
|
||||||
|
"""
|
||||||
|
This is a dynamic length piece of memory.
|
||||||
|
|
||||||
|
It should be applied with two arguments. It has a runtime
|
||||||
|
determined length, and each argument is the same.
|
||||||
|
"""
|
||||||
|
|
||||||
|
static_array: TypeConstructor_StaticArray
|
||||||
|
"""
|
||||||
|
This is a fixed length piece of memory.
|
||||||
|
|
||||||
|
It should be applied with two arguments. It has a compile time
|
||||||
|
determined length, and each argument is the same.
|
||||||
|
"""
|
||||||
|
|
||||||
|
struct: TypeConstructor_Struct
|
||||||
|
"""
|
||||||
|
This is like a tuple, but each argument is named, so that developers
|
||||||
|
can get and set fields by name.
|
||||||
|
"""
|
||||||
|
|
||||||
|
tuple_: TypeConstructor_Tuple
|
||||||
|
"""
|
||||||
|
This is a fixed length piece of memory.
|
||||||
|
|
||||||
|
It should be applied with zero or more arguments. It has a compile time
|
||||||
|
determined length, and each argument can be different.
|
||||||
|
"""
|
||||||
|
|
||||||
|
none_: Type3
|
||||||
|
"""
|
||||||
|
The none type, for when functions simply don't return anything. e.g., IO().
|
||||||
|
"""
|
||||||
|
|
||||||
|
type_info_map: dict[str, TypeInfo]
|
||||||
|
"""
|
||||||
|
Map from type name to the info of that type
|
||||||
|
"""
|
||||||
|
|
||||||
|
type_info_constructed: TypeInfo
|
||||||
|
"""
|
||||||
|
By default, constructed types are passed as pointers
|
||||||
|
NOTE: ALLOC SIZE IN THIS STRUCT DOES NOT WORK FOR CONSTRUCTED TYPES
|
||||||
|
USE calculate_alloc_size FOR ACCURATE RESULTS
|
||||||
|
Functions count as constructed types - even though they are
|
||||||
|
not memory pointers but table addresses instead.
|
||||||
|
"""
|
||||||
|
|
||||||
|
types: dict[str, Type3]
|
||||||
|
"""
|
||||||
|
Types that are available without explicit import.
|
||||||
|
"""
|
||||||
|
|
||||||
|
type_class_instances: set[tuple[Type3Class, tuple[Type3 | TypeConstructor_Base[Any], ...]]]
|
||||||
|
"""
|
||||||
|
Type class instances that are available without explicit import.
|
||||||
|
"""
|
||||||
|
|
||||||
|
methods: dict[str, Type3ClassMethod]
|
||||||
|
"""
|
||||||
|
Methods that are available without explicit import.
|
||||||
|
"""
|
||||||
|
|
||||||
|
operators: dict[str, Type3ClassMethod]
|
||||||
|
"""
|
||||||
|
Operators that are available without explicit import.
|
||||||
|
"""
|
||||||
|
|
||||||
|
alloc_size_router: TypeApplicationRouter['BuildBase', int]
|
||||||
|
"""
|
||||||
|
Helper value for calculate_alloc_size.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.dynamic_array = builtins.dynamic_array
|
||||||
|
self.static_array = builtins.static_array
|
||||||
|
self.struct = builtins.struct
|
||||||
|
self.tuple_ = builtins.tuple_
|
||||||
|
|
||||||
|
self.none_ = builtins.none
|
||||||
|
|
||||||
|
self.type_info_map = {}
|
||||||
|
self.type_info_constructed = TypeInfo('t a', WasmTypeInt32, 'i32.load', 'i32.store', 4)
|
||||||
|
|
||||||
|
self.types = {
|
||||||
|
'None': self.none_,
|
||||||
|
}
|
||||||
|
self.type_class_instances = set()
|
||||||
|
self.methods = {}
|
||||||
|
self.operators = {}
|
||||||
|
|
||||||
|
self.alloc_size_router = TypeApplicationRouter['BuildBase', int]()
|
||||||
|
self.alloc_size_router.add(self.static_array, self.__class__.calculate_alloc_size_static_array)
|
||||||
|
self.alloc_size_router.add(self.struct, self.__class__.calculate_alloc_size_struct)
|
||||||
|
self.alloc_size_router.add(self.tuple_, self.__class__.calculate_alloc_size_tuple)
|
||||||
|
|
||||||
|
def calculate_alloc_size_static_array(self, args: tuple[Type3, IntType3]) -> int:
|
||||||
|
"""
|
||||||
|
Helper method for calculate_alloc_size - static_array
|
||||||
|
"""
|
||||||
|
sa_type, sa_len = args
|
||||||
|
|
||||||
|
return sa_len.value * self.calculate_alloc_size(sa_type, is_member=True)
|
||||||
|
|
||||||
|
def calculate_alloc_size_tuple(self, args: tuple[Type3, ...]) -> int:
|
||||||
|
"""
|
||||||
|
Helper method for calculate_alloc_size - tuple
|
||||||
|
"""
|
||||||
|
return sum(
|
||||||
|
self.calculate_alloc_size(x, is_member=True)
|
||||||
|
for x in args
|
||||||
|
)
|
||||||
|
|
||||||
|
def calculate_alloc_size_struct(self, args: tuple[tuple[str, Type3], ...]) -> int:
|
||||||
|
"""
|
||||||
|
Helper method for calculate_alloc_size - struct
|
||||||
|
"""
|
||||||
|
return sum(
|
||||||
|
self.calculate_alloc_size(x, is_member=True)
|
||||||
|
for _, x in args
|
||||||
|
)
|
||||||
|
|
||||||
|
def calculate_alloc_size(self, typ: Type3, is_member: bool = False) -> int:
|
||||||
|
"""
|
||||||
|
Calculates how much bytes you need to allocate when reserving memory for the given type.
|
||||||
|
"""
|
||||||
|
typ_info = self.type_info_map.get(typ.name)
|
||||||
|
if typ_info is not None:
|
||||||
|
return typ_info.alloc_size
|
||||||
|
|
||||||
|
if is_member:
|
||||||
|
return self.type_info_constructed.alloc_size
|
||||||
|
|
||||||
|
try:
|
||||||
|
return self.alloc_size_router(self, typ)
|
||||||
|
except NoRouteForTypeException:
|
||||||
|
raise NotImplementedError(typ)
|
||||||
|
|
||||||
|
def calculate_member_offset(self, st_name: str, st_args: tuple[tuple[str, Type3], ...], needle: str) -> int:
|
||||||
|
"""
|
||||||
|
Calculates the amount of bytes that should be skipped in memory befor reaching the struct's property with the given name.
|
||||||
|
"""
|
||||||
|
result = 0
|
||||||
|
|
||||||
|
for memnam, memtyp in st_args:
|
||||||
|
if needle == memnam:
|
||||||
|
return result
|
||||||
|
|
||||||
|
result += self.calculate_alloc_size(memtyp, is_member=True)
|
||||||
|
|
||||||
|
raise Exception(f'{needle} not in {st_name}')
|
||||||
22
phasm/build/builtins.py
Normal file
22
phasm/build/builtins.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
"""
|
||||||
|
Type (constructors) that are used integral to the compiler.
|
||||||
|
|
||||||
|
These cannot be changed as there is compiler logic depending on them.
|
||||||
|
|
||||||
|
For mode documentation, see base.py.
|
||||||
|
"""
|
||||||
|
from ..type3.types import (
|
||||||
|
Type3,
|
||||||
|
TypeApplication_Nullary,
|
||||||
|
TypeConstructor_DynamicArray,
|
||||||
|
TypeConstructor_StaticArray,
|
||||||
|
TypeConstructor_Struct,
|
||||||
|
TypeConstructor_Tuple,
|
||||||
|
)
|
||||||
|
|
||||||
|
dynamic_array = TypeConstructor_DynamicArray('dynamic_array')
|
||||||
|
static_array = TypeConstructor_StaticArray('static_array')
|
||||||
|
struct = TypeConstructor_Struct('struct')
|
||||||
|
tuple_ = TypeConstructor_Tuple('tuple')
|
||||||
|
|
||||||
|
none = Type3('none', TypeApplication_Nullary(None, None))
|
||||||
57
phasm/build/default.py
Normal file
57
phasm/build/default.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
"""
|
||||||
|
The default class for build environments.
|
||||||
|
|
||||||
|
Contains the compiler builtins as well as some sane defaults.
|
||||||
|
|
||||||
|
# Added types
|
||||||
|
|
||||||
|
f32: A 32-bits IEEE 754 float, of 32 bits width.
|
||||||
|
"""
|
||||||
|
from ..type3.functions import (
|
||||||
|
TypeVariable,
|
||||||
|
TypeVariableApplication_Nullary,
|
||||||
|
)
|
||||||
|
from ..type3.typeclasses import Type3Class
|
||||||
|
from ..type3.types import (
|
||||||
|
Type3,
|
||||||
|
TypeApplication_Nullary,
|
||||||
|
)
|
||||||
|
from ..wasm import (
|
||||||
|
WasmTypeFloat32,
|
||||||
|
WasmTypeInt32,
|
||||||
|
)
|
||||||
|
|
||||||
|
from .base import BuildBase, TypeInfo
|
||||||
|
|
||||||
|
class BuildDefault(BuildBase):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
u32 = Type3('f32', TypeApplication_Nullary(None, None))
|
||||||
|
|
||||||
|
self.type_info_map.update({
|
||||||
|
'u32': TypeInfo('u32', WasmTypeInt32, 'i32.load', 'i32.store', 4),
|
||||||
|
'f32': TypeInfo('f32', WasmTypeFloat32, 'f32.load', 'f32.store', 4),
|
||||||
|
})
|
||||||
|
|
||||||
|
self.types.update({
|
||||||
|
'u32': u32,
|
||||||
|
'f32': Type3('f32', TypeApplication_Nullary(None, None)),
|
||||||
|
})
|
||||||
|
|
||||||
|
a = TypeVariable('a', TypeVariableApplication_Nullary(None, None))
|
||||||
|
|
||||||
|
NatNum = Type3Class('NatNum', (a, ), methods={}, operators={
|
||||||
|
'+': [a, a, a],
|
||||||
|
'-': [a, a, a],
|
||||||
|
'*': [a, a, a],
|
||||||
|
'<<': [a, u32, a], # Arithmic shift left
|
||||||
|
'>>': [a, u32, a], # Arithmic shift right
|
||||||
|
})
|
||||||
|
|
||||||
|
self.methods.update({
|
||||||
|
**NatNum.methods,
|
||||||
|
})
|
||||||
|
self.operators.update({
|
||||||
|
**NatNum.operators,
|
||||||
|
})
|
||||||
@ -5,7 +5,7 @@ It's intented to be a "any color, as long as it's black" kind of renderer
|
|||||||
"""
|
"""
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
|
|
||||||
from . import ourlang, prelude
|
from . import ourlang
|
||||||
from .type3.types import Type3, TypeApplication_Struct
|
from .type3.types import Type3, TypeApplication_Struct
|
||||||
|
|
||||||
|
|
||||||
@ -21,9 +21,6 @@ def type3(inp: Type3) -> str:
|
|||||||
"""
|
"""
|
||||||
Render: type's name
|
Render: type's name
|
||||||
"""
|
"""
|
||||||
if inp is prelude.none:
|
|
||||||
return 'None'
|
|
||||||
|
|
||||||
return inp.name
|
return inp.name
|
||||||
|
|
||||||
def struct_definition(inp: ourlang.StructDefinition) -> str:
|
def struct_definition(inp: ourlang.StructDefinition) -> str:
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import struct
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from . import ourlang, prelude, wasm
|
from . import ourlang, prelude, wasm
|
||||||
from .runtime import calculate_alloc_size, calculate_member_offset
|
from .build import builtins
|
||||||
from .stdlib import alloc as stdlib_alloc
|
from .stdlib import alloc as stdlib_alloc
|
||||||
from .stdlib import types as stdlib_types
|
from .stdlib import types as stdlib_types
|
||||||
from .stdlib.types import TYPE_INFO_CONSTRUCTED, TYPE_INFO_MAP
|
from .stdlib.types import TYPE_INFO_CONSTRUCTED, TYPE_INFO_MAP
|
||||||
@ -187,9 +187,9 @@ def expression_subscript_tuple(
|
|||||||
wgn.add_statement(el_type_info.wasm_load_func, f'offset={offset}')
|
wgn.add_statement(el_type_info.wasm_load_func, f'offset={offset}')
|
||||||
|
|
||||||
SUBSCRIPT_ROUTER = TypeApplicationRouter[tuple[WasmGenerator, ourlang.Module, ourlang.Subscript], None]()
|
SUBSCRIPT_ROUTER = TypeApplicationRouter[tuple[WasmGenerator, ourlang.Module, ourlang.Subscript], None]()
|
||||||
SUBSCRIPT_ROUTER.add_n(prelude.bytes_, expression_subscript_bytes)
|
# SUBSCRIPT_ROUTER.add(builtins.dynamic_array, expression_subscript_dynamic_array)
|
||||||
SUBSCRIPT_ROUTER.add(prelude.static_array, expression_subscript_static_array)
|
SUBSCRIPT_ROUTER.add(builtins.static_array, expression_subscript_static_array)
|
||||||
SUBSCRIPT_ROUTER.add(prelude.tuple_, expression_subscript_tuple)
|
SUBSCRIPT_ROUTER.add(builtins.tuple_, expression_subscript_tuple)
|
||||||
|
|
||||||
def expression(wgn: WasmGenerator, mod: ourlang.Module, inp: ourlang.Expression) -> None:
|
def expression(wgn: WasmGenerator, mod: ourlang.Module, inp: ourlang.Expression) -> None:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -4,6 +4,7 @@ Contains the syntax tree for ourlang
|
|||||||
from typing import Dict, Iterable, List, Optional, Union
|
from typing import Dict, Iterable, List, Optional, Union
|
||||||
|
|
||||||
from . import prelude
|
from . import prelude
|
||||||
|
from .build.base import BuildBase
|
||||||
from .type3.functions import FunctionSignature, TypeVariableContext
|
from .type3.functions import FunctionSignature, TypeVariableContext
|
||||||
from .type3.typeclasses import Type3ClassMethod
|
from .type3.typeclasses import Type3ClassMethod
|
||||||
from .type3.types import Type3, TypeApplication_Struct
|
from .type3.types import Type3, TypeApplication_Struct
|
||||||
@ -288,14 +289,14 @@ class Function:
|
|||||||
returns_type3: Type3
|
returns_type3: Type3
|
||||||
posonlyargs: List[FunctionParam]
|
posonlyargs: List[FunctionParam]
|
||||||
|
|
||||||
def __init__(self, name: str, lineno: int) -> None:
|
def __init__(self, name: str, lineno: int, returns_type3: Type3) -> None:
|
||||||
self.name = name
|
self.name = name
|
||||||
self.lineno = lineno
|
self.lineno = lineno
|
||||||
self.exported = False
|
self.exported = False
|
||||||
self.imported = None
|
self.imported = None
|
||||||
self.statements = []
|
self.statements = []
|
||||||
self.signature = FunctionSignature(TypeVariableContext(), [])
|
self.signature = FunctionSignature(TypeVariableContext(), [])
|
||||||
self.returns_type3 = prelude.none # FIXME: This could be a placeholder
|
self.returns_type3 = returns_type3
|
||||||
self.posonlyargs = []
|
self.posonlyargs = []
|
||||||
|
|
||||||
class StructDefinition:
|
class StructDefinition:
|
||||||
@ -381,21 +382,26 @@ class Module:
|
|||||||
"""
|
"""
|
||||||
A module is a file and consists of functions
|
A module is a file and consists of functions
|
||||||
"""
|
"""
|
||||||
__slots__ = ('data', 'types', 'struct_definitions', 'constant_defs', 'functions', 'operators', 'functions_table', )
|
__slots__ = ('build', 'data', 'types', 'struct_definitions', 'constant_defs', 'functions', 'methods', 'operators', 'functions_table', )
|
||||||
|
|
||||||
|
build: BuildBase
|
||||||
data: ModuleData
|
data: ModuleData
|
||||||
types: dict[str, Type3]
|
types: dict[str, Type3]
|
||||||
struct_definitions: Dict[str, StructDefinition]
|
struct_definitions: Dict[str, StructDefinition]
|
||||||
constant_defs: Dict[str, ModuleConstantDef]
|
constant_defs: Dict[str, ModuleConstantDef]
|
||||||
functions: Dict[str, Function]
|
functions: Dict[str, Function]
|
||||||
|
methods: Dict[str, Type3ClassMethod]
|
||||||
operators: Dict[str, Type3ClassMethod]
|
operators: Dict[str, Type3ClassMethod]
|
||||||
functions_table: dict[Function, int]
|
functions_table: dict[Function, int]
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self, build: BuildBase) -> None:
|
||||||
|
self.build = build
|
||||||
|
|
||||||
self.data = ModuleData()
|
self.data = ModuleData()
|
||||||
self.types = {}
|
self.types = {}
|
||||||
self.struct_definitions = {}
|
self.struct_definitions = {}
|
||||||
self.constant_defs = {}
|
self.constant_defs = {}
|
||||||
self.functions = {}
|
self.functions = {}
|
||||||
|
self.methods = {}
|
||||||
self.operators = {}
|
self.operators = {}
|
||||||
self.functions_table = {}
|
self.functions_table = {}
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import ast
|
|||||||
from typing import Any, Dict, NoReturn, Union
|
from typing import Any, Dict, NoReturn, Union
|
||||||
|
|
||||||
from . import prelude
|
from . import prelude
|
||||||
|
from .build.base import BuildBase
|
||||||
|
from .build.default import BuildDefault
|
||||||
from .exceptions import StaticError
|
from .exceptions import StaticError
|
||||||
from .ourlang import (
|
from .ourlang import (
|
||||||
AccessStructMember,
|
AccessStructMember,
|
||||||
@ -31,7 +33,6 @@ from .ourlang import (
|
|||||||
TupleInstantiation,
|
TupleInstantiation,
|
||||||
VariableReference,
|
VariableReference,
|
||||||
)
|
)
|
||||||
from .prelude import PRELUDE_METHODS, PRELUDE_OPERATORS, PRELUDE_TYPES
|
|
||||||
from .type3.typeclasses import Type3ClassMethod
|
from .type3.typeclasses import Type3ClassMethod
|
||||||
from .type3.types import IntType3, Type3
|
from .type3.types import IntType3, Type3
|
||||||
|
|
||||||
@ -44,7 +45,8 @@ def phasm_parse(source: str) -> Module:
|
|||||||
|
|
||||||
res = OptimizerTransformer().visit(res)
|
res = OptimizerTransformer().visit(res)
|
||||||
|
|
||||||
our_visitor = OurVisitor()
|
build = BuildDefault()
|
||||||
|
our_visitor = OurVisitor(build)
|
||||||
return our_visitor.visit_Module(res)
|
return our_visitor.visit_Module(res)
|
||||||
|
|
||||||
OurLocals = Dict[str, Union[FunctionParam]] # FIXME: Does it become easier if we add ModuleConstantDef to this dict?
|
OurLocals = Dict[str, Union[FunctionParam]] # FIXME: Does it become easier if we add ModuleConstantDef to this dict?
|
||||||
@ -90,14 +92,14 @@ class OurVisitor:
|
|||||||
|
|
||||||
# pylint: disable=C0103,C0116,C0301,R0201,R0912
|
# pylint: disable=C0103,C0116,C0301,R0201,R0912
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self, build: BuildBase) -> None:
|
||||||
pass
|
self.build = build
|
||||||
|
|
||||||
def visit_Module(self, node: ast.Module) -> Module:
|
def visit_Module(self, node: ast.Module) -> Module:
|
||||||
module = Module()
|
module = Module(self.build)
|
||||||
|
|
||||||
module.operators.update(PRELUDE_OPERATORS)
|
module.operators.update(self.build.operators)
|
||||||
module.types.update(PRELUDE_TYPES)
|
module.types.update(self.build.types)
|
||||||
|
|
||||||
_not_implemented(not node.type_ignores, 'Module.type_ignores')
|
_not_implemented(not node.type_ignores, 'Module.type_ignores')
|
||||||
|
|
||||||
@ -153,7 +155,7 @@ class OurVisitor:
|
|||||||
raise NotImplementedError(f'{node} on Module')
|
raise NotImplementedError(f'{node} on Module')
|
||||||
|
|
||||||
def pre_visit_Module_FunctionDef(self, module: Module, node: ast.FunctionDef) -> Function:
|
def pre_visit_Module_FunctionDef(self, module: Module, node: ast.FunctionDef) -> Function:
|
||||||
function = Function(node.name, node.lineno)
|
function = Function(node.name, node.lineno, self.build.none_)
|
||||||
|
|
||||||
_not_implemented(not node.args.posonlyargs, 'FunctionDef.args.posonlyargs')
|
_not_implemented(not node.args.posonlyargs, 'FunctionDef.args.posonlyargs')
|
||||||
|
|
||||||
@ -477,8 +479,8 @@ class OurVisitor:
|
|||||||
|
|
||||||
func: Union[Function, FunctionParam, Type3ClassMethod]
|
func: Union[Function, FunctionParam, Type3ClassMethod]
|
||||||
|
|
||||||
if node.func.id in PRELUDE_METHODS:
|
if node.func.id in module.methods:
|
||||||
func = PRELUDE_METHODS[node.func.id]
|
func = module.methods[node.func.id]
|
||||||
elif node.func.id in our_locals:
|
elif node.func.id in our_locals:
|
||||||
func = our_locals[node.func.id]
|
func = our_locals[node.func.id]
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -1,772 +0,0 @@
|
|||||||
"""
|
|
||||||
The prelude are all the builtin types, type classes and methods
|
|
||||||
"""
|
|
||||||
from typing import Any, Callable
|
|
||||||
from warnings import warn
|
|
||||||
|
|
||||||
from phasm.stdlib import types as stdtypes
|
|
||||||
from phasm.wasmgenerator import Generator
|
|
||||||
|
|
||||||
from ..type3.functions import (
|
|
||||||
Constraint_TypeClassInstanceExists,
|
|
||||||
TypeConstructorVariable,
|
|
||||||
TypeVariable,
|
|
||||||
TypeVariableApplication_Nullary,
|
|
||||||
)
|
|
||||||
from ..type3.routers import TypeClassArgsRouter, TypeVariableLookup
|
|
||||||
from ..type3.typeclasses import Type3Class, Type3ClassMethod
|
|
||||||
from ..type3.types import (
|
|
||||||
Type3,
|
|
||||||
TypeApplication_Nullary,
|
|
||||||
TypeConstructor_Base,
|
|
||||||
TypeConstructor_DynamicArray,
|
|
||||||
TypeConstructor_Function,
|
|
||||||
TypeConstructor_StaticArray,
|
|
||||||
TypeConstructor_Struct,
|
|
||||||
TypeConstructor_Tuple,
|
|
||||||
)
|
|
||||||
|
|
||||||
PRELUDE_TYPE_CLASS_INSTANCES_EXISTING: set[tuple[Type3Class, tuple[Type3 | TypeConstructor_Base[Any], ...]]] = set()
|
|
||||||
|
|
||||||
PRELUDE_TYPE_CLASS_INSTANCE_METHODS: dict[Type3ClassMethod, TypeClassArgsRouter[Generator, None]] = {}
|
|
||||||
|
|
||||||
class MissingImplementationException(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class MissingImplementationWarning(Warning):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def instance_type_class(
|
|
||||||
cls: Type3Class,
|
|
||||||
*typ: Type3 | TypeConstructor_Base[Any],
|
|
||||||
methods: dict[str, Callable[[Generator, TypeVariableLookup], None]] = {},
|
|
||||||
operators: dict[str, Callable[[Generator, TypeVariableLookup], None]] = {},
|
|
||||||
) -> None:
|
|
||||||
global PRELUDE_TYPE_CLASS_INSTANCES_EXISTING
|
|
||||||
global PRELUDE_TYPE_CLASS_INSTANCE_METHODS
|
|
||||||
|
|
||||||
assert len(cls.args) == len(typ)
|
|
||||||
|
|
||||||
tv_map: dict[TypeVariable, Type3] = {}
|
|
||||||
tc_map: dict[TypeConstructorVariable, TypeConstructor_Base[Any]] = {}
|
|
||||||
for arg_tv, arg_tp in zip(cls.args, typ, strict=True):
|
|
||||||
if isinstance(arg_tv, TypeVariable):
|
|
||||||
assert isinstance(arg_tp, Type3)
|
|
||||||
tv_map[arg_tv] = arg_tp
|
|
||||||
elif isinstance(arg_tv, TypeConstructorVariable):
|
|
||||||
assert isinstance(arg_tp, TypeConstructor_Base)
|
|
||||||
tc_map[arg_tv] = arg_tp
|
|
||||||
else:
|
|
||||||
raise NotImplementedError(arg_tv, arg_tp)
|
|
||||||
|
|
||||||
# TODO: Check for required existing instantiations
|
|
||||||
|
|
||||||
PRELUDE_TYPE_CLASS_INSTANCES_EXISTING.add((cls, tuple(typ), ))
|
|
||||||
|
|
||||||
for method_name, method in cls.methods.items():
|
|
||||||
router = PRELUDE_TYPE_CLASS_INSTANCE_METHODS.get(method)
|
|
||||||
if router is None:
|
|
||||||
router = TypeClassArgsRouter[Generator, None](cls.args)
|
|
||||||
PRELUDE_TYPE_CLASS_INSTANCE_METHODS[method] = router
|
|
||||||
|
|
||||||
try:
|
|
||||||
generator = methods[method_name]
|
|
||||||
except KeyError:
|
|
||||||
warn(MissingImplementationWarning(str(method), cls.name + ' ' + ' '.join(x.name for x in typ)))
|
|
||||||
continue
|
|
||||||
|
|
||||||
router.add(tv_map, tc_map, generator)
|
|
||||||
|
|
||||||
for operator_name, operator in cls.operators.items():
|
|
||||||
router = PRELUDE_TYPE_CLASS_INSTANCE_METHODS.get(operator)
|
|
||||||
if router is None:
|
|
||||||
router = TypeClassArgsRouter[Generator, None](cls.args)
|
|
||||||
PRELUDE_TYPE_CLASS_INSTANCE_METHODS[operator] = router
|
|
||||||
|
|
||||||
try:
|
|
||||||
generator = operators[operator_name]
|
|
||||||
except KeyError:
|
|
||||||
warn(MissingImplementationWarning(str(operator), cls.name + ' ' + ' '.join(x.name for x in typ)))
|
|
||||||
continue
|
|
||||||
|
|
||||||
router.add(tv_map, tc_map, generator)
|
|
||||||
|
|
||||||
none = Type3('none', TypeApplication_Nullary(None, None))
|
|
||||||
"""
|
|
||||||
The none type, for when functions simply don't return anything. e.g., IO().
|
|
||||||
"""
|
|
||||||
|
|
||||||
bool_ = Type3('bool', TypeApplication_Nullary(None, None))
|
|
||||||
"""
|
|
||||||
The bool type, either True or False
|
|
||||||
|
|
||||||
Suffixes with an underscores, as it's a Python builtin
|
|
||||||
"""
|
|
||||||
|
|
||||||
u8 = Type3('u8', TypeApplication_Nullary(None, None))
|
|
||||||
"""
|
|
||||||
The unsigned 8-bit integer type.
|
|
||||||
|
|
||||||
Operations on variables employ modular arithmetic, with modulus 2^8.
|
|
||||||
"""
|
|
||||||
|
|
||||||
u16 = Type3('u16', TypeApplication_Nullary(None, None))
|
|
||||||
"""
|
|
||||||
The unsigned 16-bit integer type.
|
|
||||||
|
|
||||||
Operations on variables employ modular arithmetic, with modulus 2^16.
|
|
||||||
"""
|
|
||||||
|
|
||||||
u32 = Type3('u32', TypeApplication_Nullary(None, None))
|
|
||||||
"""
|
|
||||||
The unsigned 32-bit integer type.
|
|
||||||
|
|
||||||
Operations on variables employ modular arithmetic, with modulus 2^32.
|
|
||||||
"""
|
|
||||||
|
|
||||||
u64 = Type3('u64', TypeApplication_Nullary(None, None))
|
|
||||||
"""
|
|
||||||
The unsigned 64-bit integer type.
|
|
||||||
|
|
||||||
Operations on variables employ modular arithmetic, with modulus 2^64.
|
|
||||||
"""
|
|
||||||
|
|
||||||
i8 = Type3('i8', TypeApplication_Nullary(None, None))
|
|
||||||
"""
|
|
||||||
The signed 8-bit integer type.
|
|
||||||
|
|
||||||
Operations on variables employ modular arithmetic, with modulus 2^8, but
|
|
||||||
with the middel point being 0.
|
|
||||||
"""
|
|
||||||
|
|
||||||
i16 = Type3('i16', TypeApplication_Nullary(None, None))
|
|
||||||
"""
|
|
||||||
The signed 16-bit integer type.
|
|
||||||
|
|
||||||
Operations on variables employ modular arithmetic, with modulus 2^16, but
|
|
||||||
with the middel point being 0.
|
|
||||||
"""
|
|
||||||
|
|
||||||
i32 = Type3('i32', TypeApplication_Nullary(None, None))
|
|
||||||
"""
|
|
||||||
The unsigned 32-bit integer type.
|
|
||||||
|
|
||||||
Operations on variables employ modular arithmetic, with modulus 2^32, but
|
|
||||||
with the middel point being 0.
|
|
||||||
"""
|
|
||||||
|
|
||||||
i64 = Type3('i64', TypeApplication_Nullary(None, None))
|
|
||||||
"""
|
|
||||||
The unsigned 64-bit integer type.
|
|
||||||
|
|
||||||
Operations on variables employ modular arithmetic, with modulus 2^64, but
|
|
||||||
with the middel point being 0.
|
|
||||||
"""
|
|
||||||
|
|
||||||
f32 = Type3('f32', TypeApplication_Nullary(None, None))
|
|
||||||
"""
|
|
||||||
A 32-bits IEEE 754 float, of 32 bits width.
|
|
||||||
"""
|
|
||||||
|
|
||||||
f64 = Type3('f64', TypeApplication_Nullary(None, None))
|
|
||||||
"""
|
|
||||||
A 32-bits IEEE 754 float, of 64 bits width.
|
|
||||||
"""
|
|
||||||
|
|
||||||
dynamic_array = TypeConstructor_DynamicArray('dynamic_array')
|
|
||||||
"""
|
|
||||||
This is a dynamic length piece of memory.
|
|
||||||
|
|
||||||
It should be applied with two arguments. It has a runtime
|
|
||||||
determined length, and each argument is the same.
|
|
||||||
"""
|
|
||||||
|
|
||||||
static_array = TypeConstructor_StaticArray('static_array')
|
|
||||||
"""
|
|
||||||
This is a fixed length piece of memory.
|
|
||||||
|
|
||||||
It should be applied with two arguments. It has a compile time
|
|
||||||
determined length, and each argument is the same.
|
|
||||||
"""
|
|
||||||
|
|
||||||
tuple_ = TypeConstructor_Tuple('tuple')
|
|
||||||
"""
|
|
||||||
This is a fixed length piece of memory.
|
|
||||||
|
|
||||||
It should be applied with zero or more arguments. It has a compile time
|
|
||||||
determined length, and each argument can be different.
|
|
||||||
"""
|
|
||||||
|
|
||||||
function = TypeConstructor_Function('function')
|
|
||||||
"""
|
|
||||||
This is a function.
|
|
||||||
|
|
||||||
It should be applied with one or more arguments. The last argument is the 'return' type.
|
|
||||||
"""
|
|
||||||
|
|
||||||
struct = TypeConstructor_Struct('struct')
|
|
||||||
"""
|
|
||||||
This is like a tuple, but each argument is named, so that developers
|
|
||||||
can get and set fields by name.
|
|
||||||
"""
|
|
||||||
|
|
||||||
a = TypeVariable('a', TypeVariableApplication_Nullary(None, None))
|
|
||||||
b = TypeVariable('b', TypeVariableApplication_Nullary(None, None))
|
|
||||||
|
|
||||||
t = TypeConstructorVariable('t')
|
|
||||||
|
|
||||||
Eq = Type3Class('Eq', (a, ), methods={}, operators={
|
|
||||||
'==': [a, a, bool_],
|
|
||||||
'!=': [a, a, bool_],
|
|
||||||
# FIXME: Do we want to expose 'eqz'? Or is that a compiler optimization?
|
|
||||||
})
|
|
||||||
|
|
||||||
instance_type_class(Eq, u8, operators={
|
|
||||||
'==': stdtypes.u8_eq_equals,
|
|
||||||
'!=': stdtypes.u8_eq_not_equals,
|
|
||||||
})
|
|
||||||
instance_type_class(Eq, u16, operators={
|
|
||||||
'==': stdtypes.u16_eq_equals,
|
|
||||||
'!=': stdtypes.u16_eq_not_equals,
|
|
||||||
})
|
|
||||||
instance_type_class(Eq, u32, operators={
|
|
||||||
'==': stdtypes.u32_eq_equals,
|
|
||||||
'!=': stdtypes.u32_eq_not_equals,
|
|
||||||
})
|
|
||||||
instance_type_class(Eq, u64, operators={
|
|
||||||
'==': stdtypes.u64_eq_equals,
|
|
||||||
'!=': stdtypes.u64_eq_not_equals,
|
|
||||||
})
|
|
||||||
instance_type_class(Eq, i8, operators={
|
|
||||||
'==': stdtypes.i8_eq_equals,
|
|
||||||
'!=': stdtypes.i8_eq_not_equals,
|
|
||||||
})
|
|
||||||
instance_type_class(Eq, i16, operators={
|
|
||||||
'==': stdtypes.i16_eq_equals,
|
|
||||||
'!=': stdtypes.i16_eq_not_equals,
|
|
||||||
})
|
|
||||||
instance_type_class(Eq, i32, operators={
|
|
||||||
'==': stdtypes.i32_eq_equals,
|
|
||||||
'!=': stdtypes.i32_eq_not_equals,
|
|
||||||
})
|
|
||||||
instance_type_class(Eq, i64, operators={
|
|
||||||
'==': stdtypes.i64_eq_equals,
|
|
||||||
'!=': stdtypes.i64_eq_not_equals,
|
|
||||||
})
|
|
||||||
instance_type_class(Eq, f32, operators={
|
|
||||||
'==': stdtypes.f32_eq_equals,
|
|
||||||
'!=': stdtypes.f32_eq_not_equals,
|
|
||||||
})
|
|
||||||
instance_type_class(Eq, f64, operators={
|
|
||||||
'==': stdtypes.f64_eq_equals,
|
|
||||||
'!=': stdtypes.f64_eq_not_equals,
|
|
||||||
})
|
|
||||||
|
|
||||||
Ord = Type3Class('Ord', (a, ), methods={
|
|
||||||
'min': [a, a, a],
|
|
||||||
'max': [a, a, a],
|
|
||||||
}, operators={
|
|
||||||
'<': [a, a, bool_],
|
|
||||||
'<=': [a, a, bool_],
|
|
||||||
'>': [a, a, bool_],
|
|
||||||
'>=': [a, a, bool_],
|
|
||||||
}, inherited_classes=[Eq])
|
|
||||||
|
|
||||||
instance_type_class(Ord, u8, methods={
|
|
||||||
'min': stdtypes.u8_ord_min,
|
|
||||||
'max': stdtypes.u8_ord_max,
|
|
||||||
}, operators={
|
|
||||||
'<': stdtypes.u8_ord_less_than,
|
|
||||||
'<=': stdtypes.u8_ord_less_than_or_equal,
|
|
||||||
'>': stdtypes.u8_ord_greater_than,
|
|
||||||
'>=': stdtypes.u8_ord_greater_than_or_equal,
|
|
||||||
})
|
|
||||||
instance_type_class(Ord, u16, methods={
|
|
||||||
'min': stdtypes.u16_ord_min,
|
|
||||||
'max': stdtypes.u16_ord_max,
|
|
||||||
}, operators={
|
|
||||||
'<': stdtypes.u16_ord_less_than,
|
|
||||||
'<=': stdtypes.u16_ord_less_than_or_equal,
|
|
||||||
'>': stdtypes.u16_ord_greater_than,
|
|
||||||
'>=': stdtypes.u16_ord_greater_than_or_equal,
|
|
||||||
})
|
|
||||||
instance_type_class(Ord, u32, methods={
|
|
||||||
'min': stdtypes.u32_ord_min,
|
|
||||||
'max': stdtypes.u32_ord_max,
|
|
||||||
}, operators={
|
|
||||||
'<': stdtypes.u32_ord_less_than,
|
|
||||||
'<=': stdtypes.u32_ord_less_than_or_equal,
|
|
||||||
'>': stdtypes.u32_ord_greater_than,
|
|
||||||
'>=': stdtypes.u32_ord_greater_than_or_equal,
|
|
||||||
})
|
|
||||||
instance_type_class(Ord, u64, methods={
|
|
||||||
'min': stdtypes.u64_ord_min,
|
|
||||||
'max': stdtypes.u64_ord_max,
|
|
||||||
}, operators={
|
|
||||||
'<': stdtypes.u64_ord_less_than,
|
|
||||||
'<=': stdtypes.u64_ord_less_than_or_equal,
|
|
||||||
'>': stdtypes.u64_ord_greater_than,
|
|
||||||
'>=': stdtypes.u64_ord_greater_than_or_equal,
|
|
||||||
})
|
|
||||||
instance_type_class(Ord, i8, methods={
|
|
||||||
'min': stdtypes.i8_ord_min,
|
|
||||||
'max': stdtypes.i8_ord_max,
|
|
||||||
}, operators={
|
|
||||||
'<': stdtypes.i8_ord_less_than,
|
|
||||||
'<=': stdtypes.i8_ord_less_than_or_equal,
|
|
||||||
'>': stdtypes.i8_ord_greater_than,
|
|
||||||
'>=': stdtypes.i8_ord_greater_than_or_equal,
|
|
||||||
})
|
|
||||||
instance_type_class(Ord, i16, methods={
|
|
||||||
'min': stdtypes.i16_ord_min,
|
|
||||||
'max': stdtypes.i16_ord_max,
|
|
||||||
}, operators={
|
|
||||||
'<': stdtypes.i16_ord_less_than,
|
|
||||||
'<=': stdtypes.i16_ord_less_than_or_equal,
|
|
||||||
'>': stdtypes.i16_ord_greater_than,
|
|
||||||
'>=': stdtypes.i16_ord_greater_than_or_equal,
|
|
||||||
})
|
|
||||||
instance_type_class(Ord, i32, methods={
|
|
||||||
'min': stdtypes.i32_ord_min,
|
|
||||||
'max': stdtypes.i32_ord_max,
|
|
||||||
}, operators={
|
|
||||||
'<': stdtypes.i32_ord_less_than,
|
|
||||||
'<=': stdtypes.i32_ord_less_than_or_equal,
|
|
||||||
'>': stdtypes.i32_ord_greater_than,
|
|
||||||
'>=': stdtypes.i32_ord_greater_than_or_equal,
|
|
||||||
})
|
|
||||||
instance_type_class(Ord, i64, methods={
|
|
||||||
'min': stdtypes.i64_ord_min,
|
|
||||||
'max': stdtypes.i64_ord_max,
|
|
||||||
}, operators={
|
|
||||||
'<': stdtypes.i64_ord_less_than,
|
|
||||||
'<=': stdtypes.i64_ord_less_than_or_equal,
|
|
||||||
'>': stdtypes.i64_ord_greater_than,
|
|
||||||
'>=': stdtypes.i64_ord_greater_than_or_equal,
|
|
||||||
})
|
|
||||||
instance_type_class(Ord, f32, methods={
|
|
||||||
'min': stdtypes.f32_ord_min,
|
|
||||||
'max': stdtypes.f32_ord_max,
|
|
||||||
}, operators={
|
|
||||||
'<': stdtypes.f32_ord_less_than,
|
|
||||||
'<=': stdtypes.f32_ord_less_than_or_equal,
|
|
||||||
'>': stdtypes.f32_ord_greater_than,
|
|
||||||
'>=': stdtypes.f32_ord_greater_than_or_equal,
|
|
||||||
})
|
|
||||||
instance_type_class(Ord, f64, methods={
|
|
||||||
'min': stdtypes.f64_ord_min,
|
|
||||||
'max': stdtypes.f64_ord_max,
|
|
||||||
}, operators={
|
|
||||||
'<': stdtypes.f64_ord_less_than,
|
|
||||||
'<=': stdtypes.f64_ord_less_than_or_equal,
|
|
||||||
'>': stdtypes.f64_ord_greater_than,
|
|
||||||
'>=': stdtypes.f64_ord_greater_than_or_equal,
|
|
||||||
})
|
|
||||||
|
|
||||||
Bits = Type3Class('Bits', (a, ), methods={
|
|
||||||
'shl': [a, u32, a], # Logical shift left
|
|
||||||
'shr': [a, u32, a], # Logical shift right
|
|
||||||
'rotl': [a, u32, a], # Rotate bits left
|
|
||||||
'rotr': [a, u32, a], # Rotate bits right
|
|
||||||
# FIXME: Do we want to expose clz, ctz, popcnt?
|
|
||||||
}, operators={
|
|
||||||
'&': [a, a, a], # Bit-wise and
|
|
||||||
'|': [a, a, a], # Bit-wise or
|
|
||||||
'^': [a, a, a], # Bit-wise xor
|
|
||||||
})
|
|
||||||
|
|
||||||
instance_type_class(Bits, u8, methods={
|
|
||||||
'shl': stdtypes.u8_bits_logical_shift_left,
|
|
||||||
'shr': stdtypes.u8_bits_logical_shift_right,
|
|
||||||
'rotl': stdtypes.u8_bits_rotate_left,
|
|
||||||
'rotr': stdtypes.u8_bits_rotate_right,
|
|
||||||
}, operators={
|
|
||||||
'&': stdtypes.u8_bits_bitwise_and,
|
|
||||||
'|': stdtypes.u8_bits_bitwise_or,
|
|
||||||
'^': stdtypes.u8_bits_bitwise_xor,
|
|
||||||
})
|
|
||||||
instance_type_class(Bits, u16, methods={
|
|
||||||
'shl': stdtypes.u16_bits_logical_shift_left,
|
|
||||||
'shr': stdtypes.u16_bits_logical_shift_right,
|
|
||||||
'rotl': stdtypes.u16_bits_rotate_left,
|
|
||||||
'rotr': stdtypes.u16_bits_rotate_right,
|
|
||||||
}, operators={
|
|
||||||
'&': stdtypes.u16_bits_bitwise_and,
|
|
||||||
'|': stdtypes.u16_bits_bitwise_or,
|
|
||||||
'^': stdtypes.u16_bits_bitwise_xor,
|
|
||||||
})
|
|
||||||
instance_type_class(Bits, u32, methods={
|
|
||||||
'shl': stdtypes.u32_bits_logical_shift_left,
|
|
||||||
'shr': stdtypes.u32_bits_logical_shift_right,
|
|
||||||
'rotl': stdtypes.u32_bits_rotate_left,
|
|
||||||
'rotr': stdtypes.u32_bits_rotate_right,
|
|
||||||
}, operators={
|
|
||||||
'&': stdtypes.u32_bits_bitwise_and,
|
|
||||||
'|': stdtypes.u32_bits_bitwise_or,
|
|
||||||
'^': stdtypes.u32_bits_bitwise_xor,
|
|
||||||
})
|
|
||||||
instance_type_class(Bits, u64, methods={
|
|
||||||
'shl': stdtypes.u64_bits_logical_shift_left,
|
|
||||||
'shr': stdtypes.u64_bits_logical_shift_right,
|
|
||||||
'rotl': stdtypes.u64_bits_rotate_left,
|
|
||||||
'rotr': stdtypes.u64_bits_rotate_right,
|
|
||||||
}, operators={
|
|
||||||
'&': stdtypes.u64_bits_bitwise_and,
|
|
||||||
'|': stdtypes.u64_bits_bitwise_or,
|
|
||||||
'^': stdtypes.u64_bits_bitwise_xor,
|
|
||||||
})
|
|
||||||
|
|
||||||
NatNum = Type3Class('NatNum', (a, ), methods={}, operators={
|
|
||||||
'+': [a, a, a],
|
|
||||||
'-': [a, a, a],
|
|
||||||
'*': [a, a, a],
|
|
||||||
'<<': [a, u32, a], # Arithmic shift left
|
|
||||||
'>>': [a, u32, a], # Arithmic shift right
|
|
||||||
})
|
|
||||||
|
|
||||||
instance_type_class(NatNum, u32, operators={
|
|
||||||
'+': stdtypes.u32_natnum_add,
|
|
||||||
'-': stdtypes.u32_natnum_sub,
|
|
||||||
'*': stdtypes.u32_natnum_mul,
|
|
||||||
'<<': stdtypes.u32_natnum_arithmic_shift_left,
|
|
||||||
'>>': stdtypes.u32_natnum_arithmic_shift_right,
|
|
||||||
})
|
|
||||||
instance_type_class(NatNum, u64, operators={
|
|
||||||
'+': stdtypes.u64_natnum_add,
|
|
||||||
'-': stdtypes.u64_natnum_sub,
|
|
||||||
'*': stdtypes.u64_natnum_mul,
|
|
||||||
'<<': stdtypes.u64_natnum_arithmic_shift_left,
|
|
||||||
'>>': stdtypes.u64_natnum_arithmic_shift_right,
|
|
||||||
})
|
|
||||||
instance_type_class(NatNum, i32, operators={
|
|
||||||
'+': stdtypes.i32_natnum_add,
|
|
||||||
'-': stdtypes.i32_natnum_sub,
|
|
||||||
'*': stdtypes.i32_natnum_mul,
|
|
||||||
'<<': stdtypes.i32_natnum_arithmic_shift_left,
|
|
||||||
'>>': stdtypes.i32_natnum_arithmic_shift_right,
|
|
||||||
})
|
|
||||||
instance_type_class(NatNum, i64, operators={
|
|
||||||
'+': stdtypes.i64_natnum_add,
|
|
||||||
'-': stdtypes.i64_natnum_sub,
|
|
||||||
'*': stdtypes.i64_natnum_mul,
|
|
||||||
'<<': stdtypes.i64_natnum_arithmic_shift_left,
|
|
||||||
'>>': stdtypes.i64_natnum_arithmic_shift_right,
|
|
||||||
})
|
|
||||||
instance_type_class(NatNum, f32, operators={
|
|
||||||
'+': stdtypes.f32_natnum_add,
|
|
||||||
'-': stdtypes.f32_natnum_sub,
|
|
||||||
'*': stdtypes.f32_natnum_mul,
|
|
||||||
'<<': stdtypes.f32_natnum_arithmic_shift_left,
|
|
||||||
'>>': stdtypes.f32_natnum_arithmic_shift_right,
|
|
||||||
})
|
|
||||||
instance_type_class(NatNum, f64, operators={
|
|
||||||
'+': stdtypes.f64_natnum_add,
|
|
||||||
'-': stdtypes.f64_natnum_sub,
|
|
||||||
'*': stdtypes.f64_natnum_mul,
|
|
||||||
'<<': stdtypes.f64_natnum_arithmic_shift_left,
|
|
||||||
'>>': stdtypes.f64_natnum_arithmic_shift_right,
|
|
||||||
})
|
|
||||||
|
|
||||||
IntNum = Type3Class('IntNum', (a, ), methods={
|
|
||||||
'abs': [a, a],
|
|
||||||
'neg': [a, a],
|
|
||||||
}, operators={}, inherited_classes=[NatNum])
|
|
||||||
|
|
||||||
instance_type_class(IntNum, i32, methods={
|
|
||||||
'abs': stdtypes.i32_intnum_abs,
|
|
||||||
'neg': stdtypes.i32_intnum_neg,
|
|
||||||
})
|
|
||||||
instance_type_class(IntNum, i64, methods={
|
|
||||||
'abs': stdtypes.i64_intnum_abs,
|
|
||||||
'neg': stdtypes.i64_intnum_neg,
|
|
||||||
})
|
|
||||||
instance_type_class(IntNum, f32, methods={
|
|
||||||
'abs': stdtypes.f32_intnum_abs,
|
|
||||||
'neg': stdtypes.f32_intnum_neg,
|
|
||||||
})
|
|
||||||
instance_type_class(IntNum, f64, methods={
|
|
||||||
'abs': stdtypes.f64_intnum_abs,
|
|
||||||
'neg': stdtypes.f64_intnum_neg,
|
|
||||||
})
|
|
||||||
|
|
||||||
Integral = Type3Class('Integral', (a, ), methods={
|
|
||||||
}, operators={
|
|
||||||
'//': [a, a, a],
|
|
||||||
'%': [a, a, a],
|
|
||||||
}, inherited_classes=[NatNum])
|
|
||||||
|
|
||||||
instance_type_class(Integral, u32, operators={
|
|
||||||
'//': stdtypes.u32_integral_div,
|
|
||||||
'%': stdtypes.u32_integral_rem,
|
|
||||||
})
|
|
||||||
instance_type_class(Integral, u64, operators={
|
|
||||||
'//': stdtypes.u64_integral_div,
|
|
||||||
'%': stdtypes.u64_integral_rem,
|
|
||||||
})
|
|
||||||
instance_type_class(Integral, i32, operators={
|
|
||||||
'//': stdtypes.i32_integral_div,
|
|
||||||
'%': stdtypes.i32_integral_rem,
|
|
||||||
})
|
|
||||||
instance_type_class(Integral, i64, operators={
|
|
||||||
'//': stdtypes.i64_integral_div,
|
|
||||||
'%': stdtypes.i64_integral_rem,
|
|
||||||
})
|
|
||||||
|
|
||||||
Fractional = Type3Class('Fractional', (a, ), methods={
|
|
||||||
'ceil': [a, a],
|
|
||||||
'floor': [a, a],
|
|
||||||
'trunc': [a, a],
|
|
||||||
'nearest': [a, a],
|
|
||||||
}, operators={
|
|
||||||
'/': [a, a, a],
|
|
||||||
}, inherited_classes=[NatNum])
|
|
||||||
|
|
||||||
instance_type_class(Fractional, f32, methods={
|
|
||||||
'ceil': stdtypes.f32_fractional_ceil,
|
|
||||||
'floor': stdtypes.f32_fractional_floor,
|
|
||||||
'trunc': stdtypes.f32_fractional_trunc,
|
|
||||||
'nearest': stdtypes.f32_fractional_nearest,
|
|
||||||
}, operators={
|
|
||||||
'/': stdtypes.f32_fractional_div,
|
|
||||||
})
|
|
||||||
instance_type_class(Fractional, f64, methods={
|
|
||||||
'ceil': stdtypes.f64_fractional_ceil,
|
|
||||||
'floor': stdtypes.f64_fractional_floor,
|
|
||||||
'trunc': stdtypes.f64_fractional_trunc,
|
|
||||||
'nearest': stdtypes.f64_fractional_nearest,
|
|
||||||
}, operators={
|
|
||||||
'/': stdtypes.f64_fractional_div,
|
|
||||||
})
|
|
||||||
|
|
||||||
Floating = Type3Class('Floating', (a, ), methods={
|
|
||||||
'sqrt': [a, a],
|
|
||||||
}, operators={}, inherited_classes=[Fractional])
|
|
||||||
|
|
||||||
# FIXME: Do we want to expose copysign?
|
|
||||||
|
|
||||||
instance_type_class(Floating, f32, methods={
|
|
||||||
'sqrt': stdtypes.f32_floating_sqrt,
|
|
||||||
})
|
|
||||||
instance_type_class(Floating, f64, methods={
|
|
||||||
'sqrt': stdtypes.f64_floating_sqrt,
|
|
||||||
})
|
|
||||||
|
|
||||||
Sized_ = Type3Class('Sized', (t, ), methods={
|
|
||||||
'len': [t(a), u32],
|
|
||||||
}, operators={}) # FIXME: Once we get type class families, add [] here
|
|
||||||
|
|
||||||
instance_type_class(Sized_, dynamic_array, methods={
|
|
||||||
'len': stdtypes.dynamic_array_sized_len,
|
|
||||||
})
|
|
||||||
instance_type_class(Sized_, static_array, methods={
|
|
||||||
'len': stdtypes.static_array_sized_len,
|
|
||||||
})
|
|
||||||
|
|
||||||
Extendable = Type3Class('Extendable', (a, b, ), methods={
|
|
||||||
'extend': [a, b],
|
|
||||||
'wrap': [b, a],
|
|
||||||
}, operators={})
|
|
||||||
|
|
||||||
instance_type_class(Extendable, u8, u16, methods={
|
|
||||||
'extend': stdtypes.u8_u16_extend,
|
|
||||||
'wrap': stdtypes.u8_u16_wrap,
|
|
||||||
})
|
|
||||||
instance_type_class(Extendable, u8, u32, methods={
|
|
||||||
'extend': stdtypes.u8_u32_extend,
|
|
||||||
'wrap': stdtypes.u8_u32_wrap,
|
|
||||||
})
|
|
||||||
instance_type_class(Extendable, u8, u64, methods={
|
|
||||||
'extend': stdtypes.u8_u64_extend,
|
|
||||||
'wrap': stdtypes.u8_u64_wrap,
|
|
||||||
})
|
|
||||||
instance_type_class(Extendable, u16, u32, methods={
|
|
||||||
'extend': stdtypes.u16_u32_extend,
|
|
||||||
'wrap': stdtypes.u16_u32_wrap,
|
|
||||||
})
|
|
||||||
instance_type_class(Extendable, u16, u64, methods={
|
|
||||||
'extend': stdtypes.u16_u64_extend,
|
|
||||||
'wrap': stdtypes.u16_u64_wrap,
|
|
||||||
})
|
|
||||||
instance_type_class(Extendable, u32, u64, methods={
|
|
||||||
'extend': stdtypes.u32_u64_extend,
|
|
||||||
'wrap': stdtypes.u32_u64_wrap,
|
|
||||||
})
|
|
||||||
instance_type_class(Extendable, i8, i16, methods={
|
|
||||||
'extend': stdtypes.i8_i16_extend,
|
|
||||||
'wrap': stdtypes.i8_i16_wrap,
|
|
||||||
})
|
|
||||||
instance_type_class(Extendable, i8, i32, methods={
|
|
||||||
'extend': stdtypes.i8_i32_extend,
|
|
||||||
'wrap': stdtypes.i8_i32_wrap,
|
|
||||||
})
|
|
||||||
instance_type_class(Extendable, i8, i64, methods={
|
|
||||||
'extend': stdtypes.i8_i64_extend,
|
|
||||||
'wrap': stdtypes.i8_i64_wrap,
|
|
||||||
})
|
|
||||||
instance_type_class(Extendable, i16, i32, methods={
|
|
||||||
'extend': stdtypes.i16_i32_extend,
|
|
||||||
'wrap': stdtypes.i16_i32_wrap,
|
|
||||||
})
|
|
||||||
instance_type_class(Extendable, i16, i64, methods={
|
|
||||||
'extend': stdtypes.i16_i64_extend,
|
|
||||||
'wrap': stdtypes.i16_i64_wrap,
|
|
||||||
})
|
|
||||||
instance_type_class(Extendable, i32, i64, methods={
|
|
||||||
'extend': stdtypes.i32_i64_extend,
|
|
||||||
'wrap': stdtypes.i32_i64_wrap,
|
|
||||||
})
|
|
||||||
|
|
||||||
Promotable = Type3Class('Promotable', (a, b, ), methods={
|
|
||||||
'promote': [a, b],
|
|
||||||
'demote': [b, a],
|
|
||||||
}, operators={})
|
|
||||||
|
|
||||||
instance_type_class(Promotable, f32, f64, methods={
|
|
||||||
'promote': stdtypes.f32_f64_promote,
|
|
||||||
'demote': stdtypes.f32_f64_demote,
|
|
||||||
})
|
|
||||||
|
|
||||||
Reinterpretable = Type3Class('Reinterpretable', (a, b, ), methods={
|
|
||||||
'reinterpret': [a, b]
|
|
||||||
}, operators={})
|
|
||||||
|
|
||||||
instance_type_class(Reinterpretable, u32, f32, methods={
|
|
||||||
'reinterpret': stdtypes.u32_f32_reinterpret,
|
|
||||||
})
|
|
||||||
instance_type_class(Reinterpretable, u64, f64, methods={
|
|
||||||
'reinterpret': stdtypes.u64_f64_reinterpret,
|
|
||||||
})
|
|
||||||
instance_type_class(Reinterpretable, i32, f32, methods={
|
|
||||||
'reinterpret': stdtypes.i32_f32_reinterpret,
|
|
||||||
})
|
|
||||||
instance_type_class(Reinterpretable, i64, f64, methods={
|
|
||||||
'reinterpret': stdtypes.i64_f64_reinterpret,
|
|
||||||
})
|
|
||||||
instance_type_class(Reinterpretable, f32, u32, methods={
|
|
||||||
'reinterpret': stdtypes.f32_u32_reinterpret,
|
|
||||||
})
|
|
||||||
instance_type_class(Reinterpretable, f64, u64, methods={
|
|
||||||
'reinterpret': stdtypes.f64_u64_reinterpret,
|
|
||||||
})
|
|
||||||
instance_type_class(Reinterpretable, f32, i32, methods={
|
|
||||||
'reinterpret': stdtypes.f32_i32_reinterpret,
|
|
||||||
})
|
|
||||||
instance_type_class(Reinterpretable, f64, i64, methods={
|
|
||||||
'reinterpret': stdtypes.f64_i64_reinterpret,
|
|
||||||
})
|
|
||||||
|
|
||||||
Convertable = Type3Class('Convertable', (a, b, ), methods={
|
|
||||||
'convert': [a, b],
|
|
||||||
'truncate': [b, a], # To prevent name clas with Fractional
|
|
||||||
}, operators={})
|
|
||||||
|
|
||||||
instance_type_class(Convertable, u32, f32, methods={
|
|
||||||
'convert': stdtypes.u32_f32_convert,
|
|
||||||
'truncate': stdtypes.u32_f32_truncate,
|
|
||||||
})
|
|
||||||
instance_type_class(Convertable, u32, f64, methods={
|
|
||||||
'convert': stdtypes.u32_f64_convert,
|
|
||||||
'truncate': stdtypes.u32_f64_truncate,
|
|
||||||
})
|
|
||||||
instance_type_class(Convertable, u64, f32, methods={
|
|
||||||
'convert': stdtypes.u64_f32_convert,
|
|
||||||
'truncate': stdtypes.u64_f32_truncate,
|
|
||||||
})
|
|
||||||
instance_type_class(Convertable, u64, f64, methods={
|
|
||||||
'convert': stdtypes.u64_f64_convert,
|
|
||||||
'truncate': stdtypes.u64_f64_truncate,
|
|
||||||
})
|
|
||||||
instance_type_class(Convertable, i32, f32, methods={
|
|
||||||
'convert': stdtypes.i32_f32_convert,
|
|
||||||
'truncate': stdtypes.i32_f32_truncate,
|
|
||||||
})
|
|
||||||
instance_type_class(Convertable, i32, f64, methods={
|
|
||||||
'convert': stdtypes.i32_f64_convert,
|
|
||||||
'truncate': stdtypes.i32_f64_truncate,
|
|
||||||
})
|
|
||||||
instance_type_class(Convertable, i64, f32, methods={
|
|
||||||
'convert': stdtypes.i64_f32_convert,
|
|
||||||
'truncate': stdtypes.i64_f32_truncate,
|
|
||||||
})
|
|
||||||
instance_type_class(Convertable, i64, f64, methods={
|
|
||||||
'convert': stdtypes.i64_f64_convert,
|
|
||||||
'truncate': stdtypes.i64_f64_truncate,
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
Foldable = Type3Class('Foldable', (t, ), methods={
|
|
||||||
'sum': [t(a), a],
|
|
||||||
'foldl': [[b, a, b], b, t(a), b],
|
|
||||||
'foldr': [[a, b, b], b, t(a), b],
|
|
||||||
}, operators={}, additional_context={
|
|
||||||
'sum': [Constraint_TypeClassInstanceExists(NatNum, (a, ))],
|
|
||||||
})
|
|
||||||
|
|
||||||
instance_type_class(Foldable, dynamic_array, methods={
|
|
||||||
'sum': stdtypes.dynamic_array_sum,
|
|
||||||
'foldl': stdtypes.dynamic_array_foldl,
|
|
||||||
'foldr': stdtypes.dynamic_array_foldr,
|
|
||||||
})
|
|
||||||
instance_type_class(Foldable, static_array, methods={
|
|
||||||
'sum': stdtypes.static_array_sum,
|
|
||||||
'foldl': stdtypes.static_array_foldl,
|
|
||||||
'foldr': stdtypes.static_array_foldr,
|
|
||||||
})
|
|
||||||
|
|
||||||
bytes_ = dynamic_array(u8)
|
|
||||||
|
|
||||||
PRELUDE_TYPES: dict[str, Type3] = {
|
|
||||||
'none': none,
|
|
||||||
'bool': bool_,
|
|
||||||
'u8': u8,
|
|
||||||
'u16': u16,
|
|
||||||
'u32': u32,
|
|
||||||
'u64': u64,
|
|
||||||
'i8': i8,
|
|
||||||
'i16': i16,
|
|
||||||
'i32': i32,
|
|
||||||
'i64': i64,
|
|
||||||
'f32': f32,
|
|
||||||
'f64': f64,
|
|
||||||
'bytes': bytes_,
|
|
||||||
}
|
|
||||||
|
|
||||||
PRELUDE_TYPE_CLASSES = {
|
|
||||||
'Eq': Eq,
|
|
||||||
'Ord': Ord,
|
|
||||||
'Bits': Bits,
|
|
||||||
'NatNum': NatNum,
|
|
||||||
'IntNum': IntNum,
|
|
||||||
'Integral': Integral,
|
|
||||||
'Fractional': Fractional,
|
|
||||||
'Floating': Floating,
|
|
||||||
'Extendable': Extendable,
|
|
||||||
'Promotable': Promotable,
|
|
||||||
}
|
|
||||||
|
|
||||||
PRELUDE_OPERATORS = {
|
|
||||||
**Bits.operators,
|
|
||||||
**Eq.operators,
|
|
||||||
**Ord.operators,
|
|
||||||
**Fractional.operators,
|
|
||||||
**Integral.operators,
|
|
||||||
**IntNum.operators,
|
|
||||||
**NatNum.operators,
|
|
||||||
}
|
|
||||||
|
|
||||||
PRELUDE_METHODS = {
|
|
||||||
**Bits.methods,
|
|
||||||
**Eq.methods,
|
|
||||||
**Ord.methods,
|
|
||||||
**Floating.methods,
|
|
||||||
**Fractional.methods,
|
|
||||||
**Integral.methods,
|
|
||||||
**IntNum.methods,
|
|
||||||
**NatNum.methods,
|
|
||||||
**Sized_.methods,
|
|
||||||
**Extendable.methods,
|
|
||||||
**Promotable.methods,
|
|
||||||
**Reinterpretable.methods,
|
|
||||||
**Convertable.methods,
|
|
||||||
**Foldable.methods,
|
|
||||||
}
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
from . import prelude
|
|
||||||
from .stdlib.types import TYPE_INFO_CONSTRUCTED, TYPE_INFO_MAP
|
|
||||||
from .type3.routers import NoRouteForTypeException, TypeApplicationRouter
|
|
||||||
from .type3.types import IntType3, Type3
|
|
||||||
|
|
||||||
|
|
||||||
def calculate_alloc_size_static_array(is_member: bool, args: tuple[Type3, IntType3]) -> int:
|
|
||||||
if is_member:
|
|
||||||
return TYPE_INFO_CONSTRUCTED.alloc_size
|
|
||||||
|
|
||||||
sa_type, sa_len = args
|
|
||||||
|
|
||||||
return sa_len.value * calculate_alloc_size(sa_type, is_member=True)
|
|
||||||
|
|
||||||
def calculate_alloc_size_tuple(is_member: bool, args: tuple[Type3, ...]) -> int:
|
|
||||||
if is_member:
|
|
||||||
return TYPE_INFO_CONSTRUCTED.alloc_size
|
|
||||||
|
|
||||||
return sum(
|
|
||||||
calculate_alloc_size(x, is_member=True)
|
|
||||||
for x in args
|
|
||||||
)
|
|
||||||
|
|
||||||
def calculate_alloc_size_struct(is_member: bool, args: tuple[tuple[str, Type3], ...]) -> int:
|
|
||||||
if is_member:
|
|
||||||
return TYPE_INFO_CONSTRUCTED.alloc_size
|
|
||||||
|
|
||||||
return sum(
|
|
||||||
calculate_alloc_size(x, is_member=True)
|
|
||||||
for _, x in args
|
|
||||||
)
|
|
||||||
|
|
||||||
ALLOC_SIZE_ROUTER = TypeApplicationRouter[bool, int]()
|
|
||||||
ALLOC_SIZE_ROUTER.add(prelude.static_array, calculate_alloc_size_static_array)
|
|
||||||
ALLOC_SIZE_ROUTER.add(prelude.struct, calculate_alloc_size_struct)
|
|
||||||
ALLOC_SIZE_ROUTER.add(prelude.tuple_, calculate_alloc_size_tuple)
|
|
||||||
|
|
||||||
def calculate_alloc_size(typ: Type3, is_member: bool = False) -> int:
|
|
||||||
typ_info = TYPE_INFO_MAP.get(typ.name)
|
|
||||||
if typ_info is not None:
|
|
||||||
return typ_info.alloc_size
|
|
||||||
|
|
||||||
try:
|
|
||||||
return ALLOC_SIZE_ROUTER(is_member, typ)
|
|
||||||
except NoRouteForTypeException:
|
|
||||||
if is_member:
|
|
||||||
# By default, 'boxed' or 'constructed' types are
|
|
||||||
# stored as pointers when a member of a struct or tuple
|
|
||||||
return TYPE_INFO_CONSTRUCTED.alloc_size
|
|
||||||
|
|
||||||
raise NotImplementedError(typ)
|
|
||||||
|
|
||||||
def calculate_member_offset(st_name: str, st_args: tuple[tuple[str, Type3], ...], needle: str) -> int:
|
|
||||||
result = 0
|
|
||||||
|
|
||||||
for memnam, memtyp in st_args:
|
|
||||||
if needle == memnam:
|
|
||||||
return result
|
|
||||||
|
|
||||||
result += calculate_alloc_size(memtyp, is_member=True)
|
|
||||||
|
|
||||||
raise Exception(f'{needle} not in {st_name}')
|
|
||||||
@ -1,13 +1,13 @@
|
|||||||
"""
|
"""
|
||||||
stdlib: Standard types that are not wasm primitives
|
stdlib: Standard types that are not wasm primitives
|
||||||
"""
|
"""
|
||||||
from typing import Mapping, NamedTuple, Type
|
from typing import Mapping
|
||||||
|
|
||||||
|
from phasm.build.base import TypeInfo
|
||||||
from phasm.stdlib import alloc
|
from phasm.stdlib import alloc
|
||||||
from phasm.type3.routers import TypeVariableLookup
|
from phasm.type3.routers import TypeVariableLookup
|
||||||
from phasm.type3.types import IntType3, Type3
|
from phasm.type3.types import IntType3, Type3
|
||||||
from phasm.wasm import (
|
from phasm.wasm import (
|
||||||
WasmType,
|
|
||||||
WasmTypeFloat32,
|
WasmTypeFloat32,
|
||||||
WasmTypeFloat64,
|
WasmTypeFloat64,
|
||||||
WasmTypeInt32,
|
WasmTypeInt32,
|
||||||
@ -18,22 +18,6 @@ from phasm.wasmgenerator import Generator, func_wrapper
|
|||||||
from phasm.wasmgenerator import VarType_i32 as i32
|
from phasm.wasmgenerator import VarType_i32 as i32
|
||||||
from phasm.wasmgenerator import VarType_i64 as i64
|
from phasm.wasmgenerator import VarType_i64 as i64
|
||||||
|
|
||||||
TypeInfo = NamedTuple('TypeInfo', [
|
|
||||||
# Name of the type
|
|
||||||
('typ', str, ),
|
|
||||||
# What WebAssembly type to use when passing this value around
|
|
||||||
# For example in function arguments
|
|
||||||
('wasm_type', Type[WasmType]),
|
|
||||||
# What WebAssembly function to use when loading a value from memory
|
|
||||||
('wasm_load_func', str),
|
|
||||||
# What WebAssembly function to use when storing a value to memory
|
|
||||||
('wasm_store_func', str),
|
|
||||||
# When storing this value in memory, how many bytes do we use?
|
|
||||||
# Only valid for non-constructed types, see calculate_alloc_size
|
|
||||||
# Should match wasm_load_func / wasm_store_func
|
|
||||||
('alloc_size', int),
|
|
||||||
])
|
|
||||||
|
|
||||||
TYPE_INFO_MAP: Mapping[str, TypeInfo] = {
|
TYPE_INFO_MAP: Mapping[str, TypeInfo] = {
|
||||||
'none': TypeInfo('none', WasmTypeNone, 'nop', 'nop', 0),
|
'none': TypeInfo('none', WasmTypeNone, 'nop', 'nop', 0),
|
||||||
'bool': TypeInfo('bool', WasmTypeInt32, 'i32.load8_u', 'i32.store8', 1),
|
'bool': TypeInfo('bool', WasmTypeInt32, 'i32.load8_u', 'i32.store8', 1),
|
||||||
|
|||||||
@ -5,7 +5,8 @@ These need to be resolved before the program can be compiled.
|
|||||||
"""
|
"""
|
||||||
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union
|
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union
|
||||||
|
|
||||||
from .. import ourlang, prelude
|
from .. import ourlang
|
||||||
|
from ..build import builtins
|
||||||
from .functions import FunctionArgument, TypeVariable
|
from .functions import FunctionArgument, TypeVariable
|
||||||
from .placeholders import PlaceholderForType, Type3OrPlaceholder
|
from .placeholders import PlaceholderForType, Type3OrPlaceholder
|
||||||
from .routers import NoRouteForTypeException, TypeApplicationRouter
|
from .routers import NoRouteForTypeException, TypeApplicationRouter
|
||||||
@ -271,7 +272,7 @@ class SameFunctionArgumentConstraint(ConstraintBase):
|
|||||||
return [
|
return [
|
||||||
SameTypeConstraint(
|
SameTypeConstraint(
|
||||||
typ,
|
typ,
|
||||||
prelude.function(*exp_type_arg_list),
|
builtins.function(*exp_type_arg_list),
|
||||||
comment=self.comment,
|
comment=self.comment,
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
@ -326,9 +327,9 @@ class TupleMatchConstraint(ConstraintBase):
|
|||||||
]
|
]
|
||||||
|
|
||||||
GENERATE_ROUTER = TypeApplicationRouter['TupleMatchConstraint', CheckResult]()
|
GENERATE_ROUTER = TypeApplicationRouter['TupleMatchConstraint', CheckResult]()
|
||||||
GENERATE_ROUTER.add(prelude.dynamic_array, _generate_dynamic_array)
|
GENERATE_ROUTER.add(builtins.dynamic_array, _generate_dynamic_array)
|
||||||
GENERATE_ROUTER.add(prelude.static_array, _generate_static_array)
|
GENERATE_ROUTER.add(builtins.static_array, _generate_static_array)
|
||||||
GENERATE_ROUTER.add(prelude.tuple_, _generate_tuple)
|
GENERATE_ROUTER.add(builtins.tuple_, _generate_tuple)
|
||||||
|
|
||||||
def check(self) -> CheckResult:
|
def check(self) -> CheckResult:
|
||||||
exp_type = self.exp_type
|
exp_type = self.exp_type
|
||||||
@ -530,10 +531,10 @@ class LiteralFitsConstraint(ConstraintBase):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
GENERATE_ROUTER = TypeApplicationRouter['LiteralFitsConstraint', CheckResult]()
|
GENERATE_ROUTER = TypeApplicationRouter['LiteralFitsConstraint', CheckResult]()
|
||||||
GENERATE_ROUTER.add(prelude.dynamic_array, _generate_dynamic_array)
|
GENERATE_ROUTER.add(builtins.dynamic_array, _generate_dynamic_array)
|
||||||
GENERATE_ROUTER.add(prelude.static_array, _generate_static_array)
|
GENERATE_ROUTER.add(builtins.static_array, _generate_static_array)
|
||||||
GENERATE_ROUTER.add(prelude.struct, _generate_struct)
|
GENERATE_ROUTER.add(builtins.struct, _generate_struct)
|
||||||
GENERATE_ROUTER.add(prelude.tuple_, _generate_tuple)
|
GENERATE_ROUTER.add(builtins.tuple_, _generate_tuple)
|
||||||
|
|
||||||
def check(self) -> CheckResult:
|
def check(self) -> CheckResult:
|
||||||
int_table: Dict[str, Tuple[int, bool]] = {
|
int_table: Dict[str, Tuple[int, bool]] = {
|
||||||
@ -581,7 +582,7 @@ class LiteralFitsConstraint(ConstraintBase):
|
|||||||
|
|
||||||
return Error('Must be real', comment=self.comment) # FIXME: Add line information
|
return Error('Must be real', comment=self.comment) # FIXME: Add line information
|
||||||
|
|
||||||
if self.type3 is prelude.bytes_:
|
if self.type3 is builtins.bytes_:
|
||||||
if isinstance(self.literal.value, bytes):
|
if isinstance(self.literal.value, bytes):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -666,9 +667,9 @@ class CanBeSubscriptedConstraint(ConstraintBase):
|
|||||||
]
|
]
|
||||||
|
|
||||||
GENERATE_ROUTER = TypeApplicationRouter['CanBeSubscriptedConstraint', CheckResult]()
|
GENERATE_ROUTER = TypeApplicationRouter['CanBeSubscriptedConstraint', CheckResult]()
|
||||||
GENERATE_ROUTER.add_n(prelude.bytes_, _generate_bytes)
|
# GENERATE_ROUTER.add_n(builtins.bytes_, _generate_bytes)
|
||||||
GENERATE_ROUTER.add(prelude.static_array, _generate_static_array)
|
GENERATE_ROUTER.add(builtins.static_array, _generate_static_array)
|
||||||
GENERATE_ROUTER.add(prelude.tuple_, _generate_tuple)
|
GENERATE_ROUTER.add(builtins.tuple_, _generate_tuple)
|
||||||
|
|
||||||
def check(self) -> CheckResult:
|
def check(self) -> CheckResult:
|
||||||
if self.type3.resolve_as is None:
|
if self.type3.resolve_as is None:
|
||||||
|
|||||||
@ -32,7 +32,7 @@ ConstraintGenerator = Generator[ConstraintBase, None, None]
|
|||||||
|
|
||||||
def phasm_type3_generate_constraints(inp: ourlang.Module) -> List[ConstraintBase]:
|
def phasm_type3_generate_constraints(inp: ourlang.Module) -> List[ConstraintBase]:
|
||||||
ctx = Context()
|
ctx = Context()
|
||||||
ctx.type_class_instances_existing.update(prelude.PRELUDE_TYPE_CLASS_INSTANCES_EXISTING)
|
ctx.type_class_instances_existing.update(inp.build.type_class_instances)
|
||||||
|
|
||||||
return [*module(ctx, inp)]
|
return [*module(ctx, inp)]
|
||||||
|
|
||||||
|
|||||||
@ -4,13 +4,8 @@ import sys
|
|||||||
from typing import Any, Callable, Generator, Iterable, List, TextIO, Union
|
from typing import Any, Callable, Generator, Iterable, List, TextIO, Union
|
||||||
|
|
||||||
from phasm import compiler, prelude
|
from phasm import compiler, prelude
|
||||||
|
from phasm.build import builtins
|
||||||
from phasm.codestyle import phasm_render
|
from phasm.codestyle import phasm_render
|
||||||
from phasm.runtime import (
|
|
||||||
calculate_alloc_size,
|
|
||||||
calculate_alloc_size_static_array,
|
|
||||||
calculate_alloc_size_struct,
|
|
||||||
calculate_alloc_size_tuple,
|
|
||||||
)
|
|
||||||
from phasm.stdlib.types import TYPE_INFO_CONSTRUCTED, TYPE_INFO_MAP
|
from phasm.stdlib.types import TYPE_INFO_CONSTRUCTED, TYPE_INFO_MAP
|
||||||
from phasm.type3 import types as type3types
|
from phasm.type3 import types as type3types
|
||||||
from phasm.type3.routers import NoRouteForTypeException, TypeApplicationRouter
|
from phasm.type3.routers import NoRouteForTypeException, TypeApplicationRouter
|
||||||
@ -285,11 +280,11 @@ def _allocate_memory_stored_tuple(attrs: tuple[runners.RunnerBase, Any], tp_args
|
|||||||
return adr
|
return adr
|
||||||
|
|
||||||
ALLOCATE_MEMORY_STORED_ROUTER = TypeApplicationRouter[tuple[runners.RunnerBase, Any], Any]()
|
ALLOCATE_MEMORY_STORED_ROUTER = TypeApplicationRouter[tuple[runners.RunnerBase, Any], Any]()
|
||||||
ALLOCATE_MEMORY_STORED_ROUTER.add_n(prelude.bytes_, _allocate_memory_stored_bytes)
|
# ALLOCATE_MEMORY_STORED_ROUTER.add_n(prelude.bytes_, _allocate_memory_stored_bytes)
|
||||||
ALLOCATE_MEMORY_STORED_ROUTER.add(prelude.dynamic_array, _allocate_memory_stored_dynamic_array)
|
ALLOCATE_MEMORY_STORED_ROUTER.add(builtins.dynamic_array, _allocate_memory_stored_dynamic_array)
|
||||||
ALLOCATE_MEMORY_STORED_ROUTER.add(prelude.static_array, _allocate_memory_stored_static_array)
|
ALLOCATE_MEMORY_STORED_ROUTER.add(builtins.static_array, _allocate_memory_stored_static_array)
|
||||||
ALLOCATE_MEMORY_STORED_ROUTER.add(prelude.struct, _allocate_memory_stored_struct)
|
ALLOCATE_MEMORY_STORED_ROUTER.add(builtins.struct, _allocate_memory_stored_struct)
|
||||||
ALLOCATE_MEMORY_STORED_ROUTER.add(prelude.tuple_, _allocate_memory_stored_tuple)
|
ALLOCATE_MEMORY_STORED_ROUTER.add(builtins.tuple_, _allocate_memory_stored_tuple)
|
||||||
|
|
||||||
def _load_memory_stored_returned_value(
|
def _load_memory_stored_returned_value(
|
||||||
runner: runners.RunnerBase,
|
runner: runners.RunnerBase,
|
||||||
@ -479,8 +474,8 @@ def _load_tuple_from_address(attrs: tuple[runners.RunnerBase, int], tp_args: tup
|
|||||||
)
|
)
|
||||||
|
|
||||||
LOAD_FROM_ADDRESS_ROUTER = TypeApplicationRouter[tuple[runners.RunnerBase, int], Any]()
|
LOAD_FROM_ADDRESS_ROUTER = TypeApplicationRouter[tuple[runners.RunnerBase, int], Any]()
|
||||||
LOAD_FROM_ADDRESS_ROUTER.add_n(prelude.bytes_, _load_bytes_from_address)
|
# LOAD_FROM_ADDRESS_ROUTER.add_n(prelude.bytes_, _load_bytes_from_address)
|
||||||
LOAD_FROM_ADDRESS_ROUTER.add(prelude.dynamic_array, _load_dynamic_array_from_address)
|
LOAD_FROM_ADDRESS_ROUTER.add(builtins.dynamic_array, _load_dynamic_array_from_address)
|
||||||
LOAD_FROM_ADDRESS_ROUTER.add(prelude.static_array, _load_static_array_from_address)
|
LOAD_FROM_ADDRESS_ROUTER.add(builtins.static_array, _load_static_array_from_address)
|
||||||
LOAD_FROM_ADDRESS_ROUTER.add(prelude.struct, _load_struct_from_address)
|
LOAD_FROM_ADDRESS_ROUTER.add(builtins.struct, _load_struct_from_address)
|
||||||
LOAD_FROM_ADDRESS_ROUTER.add(prelude.tuple_, _load_tuple_from_address)
|
LOAD_FROM_ADDRESS_ROUTER.add(builtins.tuple_, _load_tuple_from_address)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user