Has to implement both functions as arguments and type place holders (variables) for type constructors.
292 lines
6.7 KiB
Python
292 lines
6.7 KiB
Python
"""
|
|
The prelude are all the builtin types, type classes and methods
|
|
"""
|
|
|
|
from ..type3.typeclasses import (
|
|
Type3Class,
|
|
TypeConstructorVariable,
|
|
TypeVariable,
|
|
instance_type_class,
|
|
)
|
|
from ..type3.types import (
|
|
Type3,
|
|
TypeConstructor_StaticArray,
|
|
TypeConstructor_Struct,
|
|
TypeConstructor_Tuple,
|
|
)
|
|
|
|
none = Type3('none', [])
|
|
"""
|
|
The none type, for when functions simply don't return anything. e.g., IO().
|
|
"""
|
|
|
|
bool_ = Type3('bool', [])
|
|
"""
|
|
The bool type, either True or False
|
|
|
|
Suffixes with an underscores, as it's a Python builtin
|
|
"""
|
|
|
|
u8 = Type3('u8', [])
|
|
"""
|
|
The unsigned 8-bit integer type.
|
|
|
|
Operations on variables employ modular arithmetic, with modulus 2^8.
|
|
"""
|
|
|
|
u32 = Type3('u32', [])
|
|
"""
|
|
The unsigned 32-bit integer type.
|
|
|
|
Operations on variables employ modular arithmetic, with modulus 2^32.
|
|
"""
|
|
|
|
u64 = Type3('u64', [])
|
|
"""
|
|
The unsigned 64-bit integer type.
|
|
|
|
Operations on variables employ modular arithmetic, with modulus 2^64.
|
|
"""
|
|
|
|
i8 = Type3('i8', [])
|
|
"""
|
|
The signed 8-bit integer type.
|
|
|
|
Operations on variables employ modular arithmetic, with modulus 2^8, but
|
|
with the middel point being 0.
|
|
"""
|
|
|
|
i32 = Type3('i32', [])
|
|
"""
|
|
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', [])
|
|
"""
|
|
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', [])
|
|
"""
|
|
A 32-bits IEEE 754 float, of 32 bits width.
|
|
"""
|
|
|
|
f64 = Type3('f64', [])
|
|
"""
|
|
A 32-bits IEEE 754 float, of 64 bits width.
|
|
"""
|
|
|
|
bytes_ = Type3('bytes', [])
|
|
"""
|
|
This is a runtime-determined length piece of memory that can be indexed at runtime.
|
|
"""
|
|
|
|
static_array = TypeConstructor_StaticArray('static_array', [], [])
|
|
"""
|
|
A type constructor.
|
|
|
|
Any static array is a fixed length piece of memory that can be indexed at runtime.
|
|
|
|
It should be applied with one argument. It has a runtime-dynamic length
|
|
of the same type repeated.
|
|
"""
|
|
|
|
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.
|
|
"""
|
|
|
|
struct = TypeConstructor_Struct('struct', [], [])
|
|
"""
|
|
This is like a tuple, but each argument is named, so that developers
|
|
can get and set fields by name.
|
|
"""
|
|
|
|
PRELUDE_TYPES: dict[str, Type3] = {
|
|
'none': none,
|
|
'bool': bool_,
|
|
'u8': u8,
|
|
'u32': u32,
|
|
'u64': u64,
|
|
'i8': i8,
|
|
'i32': i32,
|
|
'i64': i64,
|
|
'f32': f32,
|
|
'f64': f64,
|
|
'bytes': bytes_,
|
|
}
|
|
|
|
a = TypeVariable('a')
|
|
b = TypeVariable('b')
|
|
t = TypeConstructorVariable('t')
|
|
|
|
InternalPassAsPointer = Type3Class('InternalPassAsPointer', [a], methods={}, operators={})
|
|
"""
|
|
Internal type class to keep track which types we pass arounds as a pointer.
|
|
"""
|
|
|
|
instance_type_class(InternalPassAsPointer, bytes_)
|
|
instance_type_class(InternalPassAsPointer, static_array)
|
|
instance_type_class(InternalPassAsPointer, tuple_)
|
|
instance_type_class(InternalPassAsPointer, struct)
|
|
|
|
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)
|
|
instance_type_class(Eq, u32)
|
|
instance_type_class(Eq, u64)
|
|
instance_type_class(Eq, i8)
|
|
instance_type_class(Eq, i32)
|
|
instance_type_class(Eq, i64)
|
|
instance_type_class(Eq, f32)
|
|
instance_type_class(Eq, f64)
|
|
instance_type_class(Eq, static_array)
|
|
|
|
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)
|
|
instance_type_class(Ord, u32)
|
|
instance_type_class(Ord, u64)
|
|
instance_type_class(Ord, i8)
|
|
instance_type_class(Ord, i32)
|
|
instance_type_class(Ord, i64)
|
|
instance_type_class(Ord, f32)
|
|
instance_type_class(Ord, f64)
|
|
|
|
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)
|
|
instance_type_class(Bits, u32)
|
|
instance_type_class(Bits, u64)
|
|
|
|
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)
|
|
instance_type_class(NatNum, u64)
|
|
instance_type_class(NatNum, i32)
|
|
instance_type_class(NatNum, i64)
|
|
instance_type_class(NatNum, f32)
|
|
instance_type_class(NatNum, f64)
|
|
|
|
IntNum = Type3Class('IntNum', [a], methods={
|
|
'abs': [a, a],
|
|
'neg': [a, a],
|
|
}, operators={}, inherited_classes=[NatNum])
|
|
|
|
instance_type_class(IntNum, i32)
|
|
instance_type_class(IntNum, i64)
|
|
instance_type_class(IntNum, f32)
|
|
instance_type_class(IntNum, f64)
|
|
|
|
Integral = Type3Class('Eq', [a], methods={
|
|
}, operators={
|
|
'//': [a, a, a],
|
|
'%': [a, a, a],
|
|
}, inherited_classes=[NatNum])
|
|
|
|
instance_type_class(Integral, u32)
|
|
instance_type_class(Integral, u64)
|
|
instance_type_class(Integral, i32)
|
|
instance_type_class(Integral, i64)
|
|
|
|
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)
|
|
instance_type_class(Fractional, f64)
|
|
|
|
Floating = Type3Class('Floating', [a], methods={
|
|
'sqrt': [a, a],
|
|
}, operators={}, inherited_classes=[Fractional])
|
|
|
|
# FIXME: Do we want to expose copysign?
|
|
|
|
instance_type_class(Floating, f32)
|
|
instance_type_class(Floating, f64)
|
|
|
|
Sized_ = Type3Class('Sized', [a], methods={
|
|
'len': [a, u32],
|
|
}, operators={}) # FIXME: Once we get type class families, add [] here
|
|
|
|
instance_type_class(Sized_, bytes_)
|
|
|
|
Foldable = Type3Class('Foldable', [t], methods={
|
|
'foldl': [[a, b, b], b, t(a), b],
|
|
}, operators={})
|
|
|
|
PRELUDE_TYPE_CLASSES = {
|
|
'Eq': Eq,
|
|
'Ord': Ord,
|
|
'Bits': Bits,
|
|
'NatNum': NatNum,
|
|
'IntNum': IntNum,
|
|
'Integral': Integral,
|
|
'Fractional': Fractional,
|
|
'Floating': Floating,
|
|
}
|
|
|
|
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,
|
|
}
|