Source code for hawk.embedded.profile

# Copyright 2026 Alessandro Masat
# SPDX-License-Identifier: Apache-2.0

"""The C target's profile: the opt-in caps and policies one export runs under.

Every cap defaults to ``None`` (no cap) and every policy to the permissive
value, so the default profile refuses only what the C target cannot build.
``repr()`` is a term of the unit key, so it stays the dataclass default:
deterministic, field order fixed."""

from __future__ import annotations

from dataclasses import dataclass

from ..ir import HawkError

#: The cap fields: ``None`` (no cap) or a non-negative ``int``.
_CAPS = ("max_trips", "max_ops", "max_stack_bytes")

#: The allowed values of each policy field, in the order a refusal lists them.
_CHOICES = {
    "fp_domain": ("record", "refuse"),
    "index_policy": ("clamp", "refuse"),
    "c_std": ("c99", "c11"),
}


[docs] @dataclass(frozen=True) class EmbeddedProfile: """Caps and policies for one C export (see :mod:`hawk.embedded.verify`).""" max_trips: int | None = None # worst-case loop trips per sample max_ops: int | None = None # arith + special ops per sample (kernel_cost) max_stack_bytes: int | None = None # tapes + carries + named temporaries fp_domain: str = "record" # "record" | "refuse" index_policy: str = "clamp" # "clamp" | "refuse" require_cppcheck: bool = False c_std: str = "c99" # the dialect the consumer compiles under def __post_init__(self) -> None: for field in _CAPS: value = getattr(self, field) if value is not None and (isinstance(value, bool) or not isinstance(value, int) or value < 0): raise HawkError( f"EmbeddedProfile({field}={value!r}): {field} is None (no cap) " "or a non-negative int") for field, allowed in _CHOICES.items(): value = getattr(self, field) if value not in allowed: raise HawkError( f"EmbeddedProfile({field}={value!r}): {field} is one of " f"{', '.join(repr(a) for a in allowed)}")