4Serialises a :class:`~phasor.Bytecode.Bytecode` object to the binary ``.phsb`` format.
7from __future__
import annotations
11from pathlib
import Path
12from typing
import Dict, List
14from .Bytecode
import Bytecode
15from .Instruction
import Instruction
16from .Metadata
import (
17 HEADER_SIZE, MAGIC, SEC_CONSTANTS, SEC_FUNCTIONS,
18 SEC_INSTRUCTIONS, SEC_VARIABLES, VERSION,
20from .Value
import Value, ValueType
24 """Converts a :class:`~phasor.Bytecode.Bytecode` object into its binary ``.phsb`` representation."""
27 """Initialise the serializer with an empty write buffer."""
28 self.
_buf: bytearray = bytearray()
32 """Serialise *bytecode* to the ``.phsb`` wire format.
34 Writes a 16-byte header (magic, version, flags, CRC-32 checksum) followed
35 by the constants, variables, functions, and instructions sections in order.
38 bytecode: The :class:`~phasor.Bytecode.Bytecode` object to serialise.
41 The complete ``.phsb`` binary as a :class:`bytes` object.
43 self.
_buf = bytearray()
45 self.
_buf.extend(bytes(HEADER_SIZE))
46 data_start = len(self.
_buf)
53 checksum = zlib.crc32(self.
_buf[data_start:]) & 0xFFFFFFFF
55 header = struct.pack(
"<IIII", MAGIC, VERSION, 0, checksum)
56 self.
_buf[:HEADER_SIZE] = header
58 return bytes(self.
_buf)
61 """Serialise *bytecode* and write the result to *path*.
63 Parent directories are created automatically if they do not exist.
66 bytecode: The :class:`~phasor.Bytecode.Bytecode` object to serialise.
67 path: Destination file path; typically ends with ``.phsb``.
70 path.parent.mkdir(parents=
True, exist_ok=
True)
71 path.write_bytes(self.
serialize(bytecode))
74 """Write the :data:`~phasor.Metadata.SEC_CONSTANTS` section: count followed by each :class:`~phasor.Value.Value`."""
77 for value
in constants:
81 self, variables: Dict[str, int], next_var_index: int
83 """Write the :data:`~phasor.Metadata.SEC_VARIABLES` section: count, :attr:`~phasor.Bytecode.Bytecode.next_var_index`, then each name→slot pair."""
87 for name, index
in variables.items():
92 """Write the :data:`~phasor.Metadata.SEC_FUNCTIONS` section: count then each name→instruction-index entry point."""
95 for name, address
in function_entries.items():
100 """Write the :data:`~phasor.Metadata.SEC_INSTRUCTIONS` section: count then each :class:`~phasor.Instruction.Instruction` as ``uint8`` opcode + five ``int32`` operands."""
103 for instr
in instructions:
110 """Write a :class:`~phasor.Value.Value` as a ``uint8`` type tag followed by its payload.
113 NotImplementedError: If :attr:`value.type <phasor.Value.Value.type>` is not one of
114 Null, Bool, Int, Float, or String.
117 if t == ValueType.Null:
119 elif t == ValueType.Bool:
122 elif t == ValueType.Int:
125 elif t == ValueType.Float:
128 elif t == ValueType.String:
132 raise NotImplementedError(f
"Serialization not implemented for {t!r}")
135 """Append a single unsigned byte to the buffer."""
136 self.
_buf.append(v & 0xFF)
139 """Append a little-endian unsigned 16-bit integer to the buffer."""
140 self.
_buf.extend(struct.pack(
"<H", v & 0xFFFF))
143 """Append a little-endian unsigned 32-bit integer to the buffer."""
144 self.
_buf.extend(struct.pack(
"<I", v & 0xFFFFFFFF))
147 """Append a little-endian signed 32-bit integer to the buffer."""
148 self.
_buf.extend(struct.pack(
"<i", v))
151 """Append a little-endian signed 64-bit integer to the buffer."""
152 self.
_buf.extend(struct.pack(
"<q", v))
155 """Append a little-endian IEEE 754 double to the buffer."""
156 self.
_buf.extend(struct.pack(
"<d", v))
159 """Append a length-prefixed UTF-8 string (uint16 length + bytes) to the buffer."""
160 encoded = s.encode(
"utf-8")
162 self.
_buf.extend(encoded)
None _write_uint16(self, int v)
None save_to_file(self, Bytecode bytecode, Path path)
None _write_double(self, float v)
None _write_constant_pool(self, List[Value] constants)
None _write_int32(self, int v)
None _write_uint8(self, int v)
None _write_variable_mapping(self, Dict[str, int] variables, int next_var_index)
None _write_instructions(self, List[Instruction] instructions)
None _write_value(self, Value value)
None _write_string(self, str s)
None _write_uint32(self, int v)
None _write_int64(self, int v)
bytes serialize(self, Bytecode bytecode)
None _write_function_entries(self, Dict[str, int] function_entries)