""" The prelude are all the builtin types, type classes and methods """ from ..type3.functions import TypeVariable from ..type3.typeclasses import Type3Class from ..type3.types import ( Type3, TypeConstructor_StaticArray, TypeConstructor_Struct, TypeConstructor_Tuple, ) PRELUDE_TYPE_CLASS_INSTANCES_EXISTING: set[tuple[Type3Class, tuple[Type3, ...]]] = set() def instance_type_class(cls: Type3Class, *typ: Type3) -> None: global PRELUDE_TYPE_CLASS_INSTANCES_EXISTING # TODO: Check for required existing instantiations PRELUDE_TYPE_CLASS_INSTANCES_EXISTING.add((cls, tuple(typ), )) 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. """ def sa_on_create(typ: Type3) -> None: instance_type_class(InternalPassAsPointer, typ) static_array = TypeConstructor_StaticArray('static_array', on_create=sa_on_create) """ 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. """ def tp_on_create(typ: Type3) -> None: instance_type_class(InternalPassAsPointer, typ) tuple_ = TypeConstructor_Tuple('tuple', on_create=tp_on_create) """ 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. """ def st_on_create(typ: Type3) -> None: instance_type_class(InternalPassAsPointer, typ) struct = TypeConstructor_Struct('struct', on_create=st_on_create) """ 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') 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) 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_) Extendable = Type3Class('Extendable', [a, b], methods={ 'extend': [a, b], 'wrap': [b, a], }, operators={}) instance_type_class(Extendable, u8, u32) instance_type_class(Extendable, u8, u64) instance_type_class(Extendable, u32, u64) instance_type_class(Extendable, i8, i32) instance_type_class(Extendable, i8, i64) instance_type_class(Extendable, i32, i64) Promotable = Type3Class('Promotable', [a, b], methods={ 'promote': [a, b], 'demote': [b, a], }, operators={}) instance_type_class(Promotable, f32, f64) 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, }