Helper for C code generation.
| 201 | |
| 202 | |
| 203 | class Emitter: |
| 204 | """Helper for C code generation.""" |
| 205 | |
| 206 | def __init__( |
| 207 | self, |
| 208 | context: EmitterContext, |
| 209 | value_names: dict[Value, str] | None = None, |
| 210 | capi_version: tuple[int, int] | None = None, |
| 211 | filepath: str | None = None, |
| 212 | ) -> None: |
| 213 | self.context = context |
| 214 | self.capi_version = capi_version or sys.version_info[:2] |
| 215 | self.names = context.names |
| 216 | self.value_names = value_names or {} |
| 217 | self.fragments: list[str] = [] |
| 218 | self._indent = 0 |
| 219 | self.filepath = filepath |
| 220 | |
| 221 | # Low-level operations |
| 222 | |
| 223 | def indent(self) -> None: |
| 224 | self._indent += 4 |
| 225 | |
| 226 | def dedent(self) -> None: |
| 227 | self._indent -= 4 |
| 228 | assert self._indent >= 0 |
| 229 | |
| 230 | def label(self, label: BasicBlock) -> str: |
| 231 | return "CPyL%s" % label.label |
| 232 | |
| 233 | def reg(self, reg: Value) -> str: |
| 234 | return REG_PREFIX + self.value_names[reg] |
| 235 | |
| 236 | def attr(self, name: str) -> str: |
| 237 | return ATTR_PREFIX + name |
| 238 | |
| 239 | def object_annotation(self, obj: object, line: str) -> str: |
| 240 | """Build a C comment with an object's string representation. |
| 241 | |
| 242 | If the comment exceeds the line length limit, it's wrapped into a |
| 243 | multiline string (with the extra lines indented to be aligned with |
| 244 | the first line's comment). |
| 245 | |
| 246 | If it contains illegal characters, an empty string is returned.""" |
| 247 | line_width = self._indent + len(line) |
| 248 | formatted = pprint.pformat(obj, compact=True, width=max(90 - line_width, 20)) |
| 249 | if any(x in formatted for x in ("/*", "*/", "\0")): |
| 250 | return "" |
| 251 | |
| 252 | if "\n" in formatted: |
| 253 | first_line, rest = formatted.split("\n", maxsplit=1) |
| 254 | comment_continued = textwrap.indent(rest, (line_width + 3) * " ") |
| 255 | return f" /* {first_line}\n{comment_continued} */" |
| 256 | else: |
| 257 | return f" /* {formatted} */" |
| 258 | |
| 259 | def emit_line(self, line: str = "", *, ann: object = None) -> None: |
| 260 | if line.startswith("}"): |
no outgoing calls
searching dependent graphs…