#!/usr/bin/env python # -*- coding: utf-8 -*- from typing import Optional, NamedTuple import textwrap class ElementType(NamedTuple): name: str rep_ty: str desc: str width: Optional[int] MACH_WORD = None element_types = [ # (name, representation type, human description, width) # # width in bytes. # width == None denotes machine word ElementType("Char", "Char#", "8-bit character", 1), ElementType("WideChar", "Char#", "32-bit character", 4), ElementType("Int", "Int#", "word-sized integer", MACH_WORD), ElementType("Word", "Word#", "word-sized unsigned integer", MACH_WORD), ElementType("Addr", "Addr#", "machine address", MACH_WORD), ElementType("Float", "Float#", "single-precision floating-point value", 4), ElementType("Double", "Double#", "double-precision floating-point value", 8), ElementType("StablePtr", "StablePtr# a", "'StablePtr#' value", MACH_WORD), ] # TODO: Eventually when the sized integer primops use proper unboxed types we # should rather do: # #for n in [8,16,32,64]: # element_types += [ ElementType(f"Int{n}", f"Int{n}#", f"{n}-bit signed integer", n // 8) ] # #for n in [8,16,32,64]: # element_types += [ ElementType(f"Word{n}", f"Word{n}#", f"{n}-bit unsigned integer", n // 8) ] element_types += [ ElementType("Int8", "Int8#", "8-bit signed integer", 1), ElementType("Int16", "Int16#", "16-bit signed integer", 2), ElementType("Int32", "Int32#", "32-bit signed integer", 4), ElementType("Int64", "Int64#", "64-bit signed integer", 8), ElementType("Word8", "Word8#", "8-bit unsigned integer", 1), ElementType("Word16", "Word16#", "16-bit unsigned integer", 2), ElementType("Word32", "Word32#", "32-bit unsigned integer", 4), ElementType("Word64", "Word64#", "64-bit unsigned integer", 8), ] def pretty_offset(n: Optional[int]) -> str: if n == MACH_WORD: return 'machine words' elif n == 1: return 'bytes' else: return f'{n}-byte words' def print_block(template: str, **kwargs) -> None: print(textwrap.dedent(template.format(**kwargs)).lstrip()) def header(s: str): print('') print_block(''' ------------------------------------ -- {s} ------------------------------------ ''', s=s) header("ByteArray# operations") print(''' -- Do not edit. This file is generated by utils/genprimopcode/gen_bytearray_ops.py. -- To regenerate run, -- -- python3 utils/genprimops/gen_bytearray_ops.py > compiler/GHC/Builtin/bytearray-ops.txt.pp ''') header('aligned index operations') for t in element_types: offset = pretty_offset(t.width) print_block(''' primop IndexByteArrayOp_{name} "index{name}Array#" GenPrimOp ByteArray# -> Int# -> {rep_ty} {{Read a {desc}; offset in {offset}.}} with can_fail = True ''', offset = offset, **t._asdict()) header('unaligned index operations') for t in element_types: if t.name in ['Int8', 'Word8']: continue print_block(''' primop IndexByteArrayOp_Word8As{name} "indexWord8ArrayAs{name}#" GenPrimOp ByteArray# -> Int# -> {rep_ty} {{Read a {desc}; offset in bytes.}} with can_fail = True ''', **t._asdict()) header('aligned read operations') for t in element_types: offset = pretty_offset(t.width) print_block(''' primop ReadByteArrayOp_{name} "read{name}Array#" GenPrimOp MutableByteArray# s -> Int# -> State# s -> (# State# s, {rep_ty} #) {{Read a {desc}; offset in {offset}.}} with has_side_effects = True can_fail = True ''', offset = offset, **t._asdict()) header('unaligned read operations') for t in element_types: if t.name in ['Int8', 'Word8']: continue print_block(''' primop ReadByteArrayOp_Word8As{name} "readWord8ArrayAs{name}#" GenPrimOp MutableByteArray# s -> Int# -> State# s -> (# State# s, {rep_ty} #) {{Read a {desc}; offset in bytes.}} with has_side_effects = True can_fail = True ''', **t._asdict()) header('aligned write operations') for t in element_types: offset = pretty_offset(t.width) print_block(''' primop WriteByteArrayOp_{name} "write{name}Array#" GenPrimOp MutableByteArray# s -> Int# -> {rep_ty} -> State# s -> State# s {{Write a {desc}; offset in {offset}.}} with has_side_effects = True can_fail = True ''', offset = offset, **t._asdict()) header('unaligned write operations') for t in element_types: if t.name in ['Int8', 'Word8']: continue print_block(''' primop WriteByteArrayOp_Word8As{name} "writeWord8ArrayAs{name}#" GenPrimOp MutableByteArray# s -> Int# -> {rep_ty} -> State# s -> State# s {{Write a {desc}; offset in bytes.}} with has_side_effects = True can_fail = True ''', **t._asdict())