pycforge 0.15.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. pycforge/__init__.py +8 -0
  2. pycforge/__main__.py +2 -0
  3. pycforge/_version.py +1 -0
  4. pycforge/converter/__init__.py +0 -0
  5. pycforge/converter/analysis/__init__.py +5 -0
  6. pycforge/converter/analysis/functions.py +723 -0
  7. pycforge/converter/analysis/model.py +158 -0
  8. pycforge/converter/analysis/planning.py +464 -0
  9. pycforge/converter/analysis/stage.py +1976 -0
  10. pycforge/converter/analysis/symbols.py +237 -0
  11. pycforge/converter/analysis/validation.py +2166 -0
  12. pycforge/converter/c_output/__init__.py +2 -0
  13. pycforge/converter/c_output/conformance.py +297 -0
  14. pycforge/converter/c_output/renderer.py +220 -0
  15. pycforge/converter/conditional_regions/__init__.py +71 -0
  16. pycforge/converter/conditional_regions/analysis.py +481 -0
  17. pycforge/converter/conditional_regions/lowering.py +579 -0
  18. pycforge/converter/conditional_regions/model.py +243 -0
  19. pycforge/converter/conditional_regions/validation.py +690 -0
  20. pycforge/converter/containers/__init__.py +19 -0
  21. pycforge/converter/containers/analysis.py +542 -0
  22. pycforge/converter/containers/lowering.py +290 -0
  23. pycforge/converter/containers/model.py +146 -0
  24. pycforge/converter/contracts/__init__.py +0 -0
  25. pycforge/converter/contracts/configuration.py +178 -0
  26. pycforge/converter/contracts/identifiers.py +68 -0
  27. pycforge/converter/contracts/versions.py +71 -0
  28. pycforge/converter/core/__init__.py +0 -0
  29. pycforge/converter/core/artifact_io.py +87 -0
  30. pycforge/converter/core/cancellation.py +7 -0
  31. pycforge/converter/core/canonicalization.py +254 -0
  32. pycforge/converter/core/context.py +13 -0
  33. pycforge/converter/core/diagnostics.py +95 -0
  34. pycforge/converter/core/enums.py +23 -0
  35. pycforge/converter/core/fingerprint.py +22 -0
  36. pycforge/converter/core/pipeline.py +8 -0
  37. pycforge/converter/core/progress.py +25 -0
  38. pycforge/converter/core/request.py +50 -0
  39. pycforge/converter/core/resource_policy.py +31 -0
  40. pycforge/converter/core/result.py +23 -0
  41. pycforge/converter/core/serialization.py +36 -0
  42. pycforge/converter/core/stage.py +10 -0
  43. pycforge/converter/core/stage_artifact.py +80 -0
  44. pycforge/converter/core/stage_outcome.py +15 -0
  45. pycforge/converter/decision_trace/__init__.py +0 -0
  46. pycforge/converter/decision_trace/recorder.py +52 -0
  47. pycforge/converter/facade.py +459 -0
  48. pycforge/converter/frontend/__init__.py +4 -0
  49. pycforge/converter/frontend/normalizer.py +59 -0
  50. pycforge/converter/frontend/parser.py +20 -0
  51. pycforge/converter/frontend/source_document.py +93 -0
  52. pycforge/converter/frontend/stages.py +518 -0
  53. pycforge/converter/frontend/validation.py +76 -0
  54. pycforge/converter/io/__init__.py +0 -0
  55. pycforge/converter/io/atomic_writer.py +33 -0
  56. pycforge/converter/ir/__init__.py +1 -0
  57. pycforge/converter/ir/c_ir/__init__.py +4 -0
  58. pycforge/converter/ir/c_ir/builder.py +26 -0
  59. pycforge/converter/ir/c_ir/model.py +318 -0
  60. pycforge/converter/ir/c_ir/serialization.py +88 -0
  61. pycforge/converter/ir/c_ir/validation.py +834 -0
  62. pycforge/converter/ir/python_ir/__init__.py +17 -0
  63. pycforge/converter/ir/python_ir/nodes.py +86 -0
  64. pycforge/converter/keyword_calls/__init__.py +68 -0
  65. pycforge/converter/keyword_calls/analysis.py +458 -0
  66. pycforge/converter/keyword_calls/lowering.py +271 -0
  67. pycforge/converter/keyword_calls/model.py +304 -0
  68. pycforge/converter/keyword_calls/validation.py +802 -0
  69. pycforge/converter/keyword_only_calls/__init__.py +68 -0
  70. pycforge/converter/keyword_only_calls/analysis.py +640 -0
  71. pycforge/converter/keyword_only_calls/lowering.py +376 -0
  72. pycforge/converter/keyword_only_calls/model.py +328 -0
  73. pycforge/converter/keyword_only_calls/validation.py +1357 -0
  74. pycforge/converter/lowering.py +1000 -0
  75. pycforge/converter/modules/__init__.py +13 -0
  76. pycforge/converter/modules/analysis.py +1250 -0
  77. pycforge/converter/modules/lowering.py +200 -0
  78. pycforge/converter/modules/model.py +73 -0
  79. pycforge/converter/modules/stage.py +192 -0
  80. pycforge/converter/numeric_semantics/__init__.py +23 -0
  81. pycforge/converter/numeric_semantics/analysis.py +420 -0
  82. pycforge/converter/numeric_semantics/lowering.py +153 -0
  83. pycforge/converter/numeric_semantics/model.py +123 -0
  84. pycforge/converter/records/__init__.py +34 -0
  85. pycforge/converter/records/analysis.py +1394 -0
  86. pycforge/converter/records/lowering.py +393 -0
  87. pycforge/converter/records/model.py +319 -0
  88. pycforge/converter/rules/__init__.py +3 -0
  89. pycforge/converter/support_templates/__init__.py +49 -0
  90. pycforge/converter/support_templates/assembly.py +106 -0
  91. pycforge/converter/support_templates/factories.py +348 -0
  92. pycforge/converter/support_templates/model.py +159 -0
  93. pycforge/converter/support_templates/registry.py +388 -0
  94. pycforge/converter/telemetry/__init__.py +0 -0
  95. pycforge/converter/telemetry/sink.py +39 -0
  96. pycforge/ide/__init__.py +19 -0
  97. pycforge/ide/__main__.py +5 -0
  98. pycforge/ide/_worker_event_codec.py +276 -0
  99. pycforge/ide/_worker_protocol_json.py +197 -0
  100. pycforge/ide/_worker_protocol_types.py +90 -0
  101. pycforge/ide/_worker_request_codec.py +200 -0
  102. pycforge/ide/_worker_request_data.py +260 -0
  103. pycforge/ide/_worker_result_data.py +343 -0
  104. pycforge/ide/action_contract.py +469 -0
  105. pycforge/ide/action_validation.py +229 -0
  106. pycforge/ide/command_palette.py +223 -0
  107. pycforge/ide/controller.py +904 -0
  108. pycforge/ide/controller_conversion.py +546 -0
  109. pycforge/ide/controller_io.py +205 -0
  110. pycforge/ide/editor.py +951 -0
  111. pycforge/ide/editor_commands_qt.py +274 -0
  112. pycforge/ide/editor_lexical.py +43 -0
  113. pycforge/ide/editor_sidebars.py +236 -0
  114. pycforge/ide/editor_syntax.py +243 -0
  115. pycforge/ide/find_replace.py +535 -0
  116. pycforge/ide/icons.py +91 -0
  117. pycforge/ide/io_service.py +196 -0
  118. pycforge/ide/model.py +164 -0
  119. pycforge/ide/panels.py +903 -0
  120. pycforge/ide/positions.py +220 -0
  121. pycforge/ide/process_worker.py +130 -0
  122. pycforge/ide/qt.py +230 -0
  123. pycforge/ide/qt_actions.py +418 -0
  124. pycforge/ide/qt_close.py +169 -0
  125. pycforge/ide/qt_command_palette.py +297 -0
  126. pycforge/ide/qt_contract.py +220 -0
  127. pycforge/ide/qt_documents.py +590 -0
  128. pycforge/ide/qt_editor_buffers.py +113 -0
  129. pycforge/ide/qt_editor_surfaces.py +112 -0
  130. pycforge/ide/qt_menus.py +324 -0
  131. pycforge/ide/qt_projection.py +500 -0
  132. pycforge/ide/qt_shell.py +348 -0
  133. pycforge/ide/qt_shell_interactions.py +320 -0
  134. pycforge/ide/qt_state.py +393 -0
  135. pycforge/ide/qt_workspace_features.py +398 -0
  136. pycforge/ide/qt_workspace_navigation.py +208 -0
  137. pycforge/ide/qt_workspace_observers.py +173 -0
  138. pycforge/ide/qt_workspace_panels.py +545 -0
  139. pycforge/ide/qt_workspace_widgets.py +228 -0
  140. pycforge/ide/resources/icons/about.svg +1 -0
  141. pycforge/ide/resources/icons/add-document.svg +1 -0
  142. pycforge/ide/resources/icons/brand-mark.svg +1 -0
  143. pycforge/ide/resources/icons/bundle-search.svg +1 -0
  144. pycforge/ide/resources/icons/cancel.svg +1 -0
  145. pycforge/ide/resources/icons/check.svg +1 -0
  146. pycforge/ide/resources/icons/chevron-right.svg +1 -0
  147. pycforge/ide/resources/icons/close.svg +1 -0
  148. pycforge/ide/resources/icons/collapse-all.svg +1 -0
  149. pycforge/ide/resources/icons/command-palette.svg +1 -0
  150. pycforge/ide/resources/icons/convert.svg +1 -0
  151. pycforge/ide/resources/icons/copy.svg +1 -0
  152. pycforge/ide/resources/icons/cut.svg +1 -0
  153. pycforge/ide/resources/icons/decision-trace.svg +1 -0
  154. pycforge/ide/resources/icons/details.svg +1 -0
  155. pycforge/ide/resources/icons/diagnostics.svg +1 -0
  156. pycforge/ide/resources/icons/duplicate-line.svg +1 -0
  157. pycforge/ide/resources/icons/exit.svg +1 -0
  158. pycforge/ide/resources/icons/expand-all.svg +1 -0
  159. pycforge/ide/resources/icons/export.svg +1 -0
  160. pycforge/ide/resources/icons/find.svg +1 -0
  161. pycforge/ide/resources/icons/go-to-line.svg +1 -0
  162. pycforge/ide/resources/icons/go-to-output.svg +1 -0
  163. pycforge/ide/resources/icons/go-to-source.svg +1 -0
  164. pycforge/ide/resources/icons/history.svg +1 -0
  165. pycforge/ide/resources/icons/indent.svg +1 -0
  166. pycforge/ide/resources/icons/link-c.svg +1 -0
  167. pycforge/ide/resources/icons/mappings.svg +1 -0
  168. pycforge/ide/resources/icons/module.svg +1 -0
  169. pycforge/ide/resources/icons/move-down.svg +1 -0
  170. pycforge/ide/resources/icons/move-line-down.svg +1 -0
  171. pycforge/ide/resources/icons/move-line-up.svg +1 -0
  172. pycforge/ide/resources/icons/move-up.svg +1 -0
  173. pycforge/ide/resources/icons/next.svg +1 -0
  174. pycforge/ide/resources/icons/open.svg +1 -0
  175. pycforge/ide/resources/icons/outdent.svg +1 -0
  176. pycforge/ide/resources/icons/outline.svg +1 -0
  177. pycforge/ide/resources/icons/paste.svg +1 -0
  178. pycforge/ide/resources/icons/previous.svg +1 -0
  179. pycforge/ide/resources/icons/primary-module.svg +1 -0
  180. pycforge/ide/resources/icons/redo.svg +1 -0
  181. pycforge/ide/resources/icons/remove-document.svg +1 -0
  182. pycforge/ide/resources/icons/replace.svg +1 -0
  183. pycforge/ide/resources/icons/save-as.svg +1 -0
  184. pycforge/ide/resources/icons/save.svg +1 -0
  185. pycforge/ide/resources/icons/select-all.svg +1 -0
  186. pycforge/ide/resources/icons/settings.svg +1 -0
  187. pycforge/ide/resources/icons/show-c.svg +1 -0
  188. pycforge/ide/resources/icons/split-view.svg +1 -0
  189. pycforge/ide/resources/icons/summary.svg +1 -0
  190. pycforge/ide/resources/icons/telemetry.svg +1 -0
  191. pycforge/ide/resources/icons/toggle-comment.svg +1 -0
  192. pycforge/ide/resources/icons/toggle-fold.svg +1 -0
  193. pycforge/ide/resources/icons/undo.svg +1 -0
  194. pycforge/ide/resources/icons/whitespace.svg +1 -0
  195. pycforge/ide/revisions.py +400 -0
  196. pycforge/ide/search_service.py +280 -0
  197. pycforge/ide/session_history.py +150 -0
  198. pycforge/ide/source_editing.py +417 -0
  199. pycforge/ide/source_structure.py +558 -0
  200. pycforge/ide/source_structure_async.py +191 -0
  201. pycforge/ide/supervisor.py +503 -0
  202. pycforge/ide/theme.py +119 -0
  203. pycforge/ide/theme_stylesheet.py +598 -0
  204. pycforge/ide/theme_workspace_stylesheet.py +155 -0
  205. pycforge/ide/visual_tokens.py +142 -0
  206. pycforge/ide/worker_protocol.py +80 -0
  207. pycforge/ide/workspace_search.py +462 -0
  208. pycforge/ide/workspace_session.py +256 -0
  209. pycforge/laboratory/__init__.py +6 -0
  210. pycforge/laboratory/audits.py +2244 -0
  211. pycforge/laboratory/checkpoint_e.py +2685 -0
  212. pycforge/laboratory/cli.py +119 -0
  213. pycforge/laboratory/exit_codes.py +11 -0
  214. pycforge/laboratory/keyword_audit.py +661 -0
  215. pycforge/laboratory/keyword_only_audit.py +481 -0
  216. pycforge-0.15.2.dist-info/METADATA +209 -0
  217. pycforge-0.15.2.dist-info/RECORD +221 -0
  218. pycforge-0.15.2.dist-info/WHEEL +5 -0
  219. pycforge-0.15.2.dist-info/entry_points.txt +5 -0
  220. pycforge-0.15.2.dist-info/licenses/LICENSE +674 -0
  221. pycforge-0.15.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,290 @@
1
+ """C IR lowering adapter for the approved fixed local-container profile.
2
+
3
+ The adapter owns only container representation mechanics. Scalar expression
4
+ evaluation, source binding, control-flow nesting, diagnostics, and provenance
5
+ remain services of the cumulative lowerer and are supplied explicitly.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import hashlib
11
+ from dataclasses import dataclass
12
+ from typing import Any, Callable
13
+
14
+ from pycforge.converter.ir.c_ir import (
15
+ CAssignmentStatement,
16
+ CBinaryExpr,
17
+ CBinaryOp,
18
+ CBlock,
19
+ CForStatement,
20
+ CIdentifier,
21
+ CIdentifierRef,
22
+ CInitializerList,
23
+ CIntegerLiteral,
24
+ CStorage,
25
+ CSubscriptExpr,
26
+ CType,
27
+ CVariableDeclaration,
28
+ )
29
+
30
+
31
+ def _sid(prefix: str, *parts: str) -> str:
32
+ return prefix + hashlib.sha256("\x1f".join(parts).encode()).hexdigest()[:20]
33
+
34
+
35
+ @dataclass(slots=True)
36
+ class ContainerLoweringServices:
37
+ nodes: dict[str, dict[str, Any]]
38
+ shapes: dict[str, dict[str, Any]]
39
+ bindings: dict[str, dict[str, Any]]
40
+ bindings_by_assignment: dict[str, dict[str, Any]]
41
+ accesses: dict[str, dict[str, Any]]
42
+ iterations: dict[str, dict[str, Any]]
43
+ source_bindings_by_id: dict[str, dict[str, Any]]
44
+ source_bindings_by_occurrence: dict[str, dict[str, Any]]
45
+ generated_names: dict[str, str]
46
+ generated_spellings: set[str]
47
+ expression: Callable[..., tuple[tuple[Any, ...], Any]]
48
+ temporary: Callable[..., tuple[CVariableDeclaration, CIdentifierRef]]
49
+ category_type: Callable[[str], CType]
50
+ identifier: Callable[[dict[str, Any], dict[str, Any]], CIdentifier]
51
+ provenance: Callable[..., Any]
52
+ synthetic_provenance: Callable[..., Any]
53
+ block_statements: Callable[..., tuple[Any, ...]]
54
+ temporary_spelling: Callable[[str, str], str]
55
+ reject: Callable[..., Any]
56
+ control_depth: Callable[[], int]
57
+
58
+
59
+ class ContainerCIRLowerer:
60
+ """Lower proved container facts without owning scalar or control semantics."""
61
+
62
+ def __init__(self, services: ContainerLoweringServices) -> None:
63
+ self.services = services
64
+ self.storage: dict[str, dict[str, Any]] = {}
65
+ self.component_spellings: dict[tuple[str, str], str] = {}
66
+
67
+ def declaration(self, node: dict[str, Any]) -> tuple[Any, ...]:
68
+ s = self.services
69
+ fact = s.bindings_by_assignment[node["node_id"]]
70
+ if not fact.get("valid"):
71
+ s.reject(fact.get("diagnostic_code") or "PYC3403", fact.get("reason") or "Invalid fixed container binding", node)
72
+ shape = s.shapes.get(fact["literal_node_id"])
73
+ if not shape or not shape.get("valid"):
74
+ s.reject(
75
+ (shape or {}).get("diagnostic_code") or "PYC3402",
76
+ (shape or {}).get("reason") or "Fixed container shape fact is absent or invalid",
77
+ s.nodes.get(fact["literal_node_id"], node),
78
+ )
79
+ target = s.nodes[fact["target_node_id"]]
80
+ binding = s.source_bindings_by_id.get(fact["binding_id"])
81
+ if not binding:
82
+ s.reject("PYC3403", "Fixed container binding cannot be resolved", target)
83
+ if s.control_depth():
84
+ s.reject("PYC3403", "A fixed container must be bound directly in a function body", node)
85
+
86
+ literal = s.nodes[fact["literal_node_id"]]
87
+ prelude: list[Any] = []
88
+ if fact["container_kind"] in {"list", "tuple"}:
89
+ element_refs: list[Any] = []
90
+ for ordinal, element_id in enumerate(shape["element_node_ids"]):
91
+ expression_prelude, expression = s.expression(s.nodes[element_id])
92
+ prelude.extend(expression_prelude)
93
+ declaration, reference = s.temporary(
94
+ "container_item",
95
+ literal,
96
+ ordinal,
97
+ s.category_type(fact["element_category"]),
98
+ expression,
99
+ (element_id, literal["node_id"]),
100
+ )
101
+ prelude.append(declaration)
102
+ element_refs.append(reference)
103
+ identifier = s.identifier(binding, target)
104
+ declaration = CVariableDeclaration(
105
+ _sid("c-container-array-", node["node_id"]),
106
+ identifier,
107
+ self._array_type(
108
+ fact["element_category"],
109
+ fact["capacity"],
110
+ readonly=fact["container_kind"] == "tuple",
111
+ ),
112
+ CInitializerList(
113
+ _sid("c-container-init-", literal["node_id"]),
114
+ tuple(element_refs),
115
+ s.provenance(literal),
116
+ ),
117
+ CStorage.NONE,
118
+ s.provenance(node),
119
+ )
120
+ self.storage[fact["binding_id"]] = {
121
+ "iteration": identifier,
122
+ "values": identifier,
123
+ "kind": fact["container_kind"],
124
+ }
125
+ return tuple(prelude) + (declaration,)
126
+
127
+ key_refs: list[Any] = []
128
+ value_refs: list[Any] = []
129
+ for ordinal, (key_id, value_id) in enumerate(zip(shape["key_node_ids"], shape["value_node_ids"])):
130
+ key_prelude, key_expression = s.expression(s.nodes[key_id])
131
+ prelude.extend(key_prelude)
132
+ key_declaration, key_reference = s.temporary(
133
+ "container_key",
134
+ literal,
135
+ ordinal,
136
+ s.category_type(fact["key_category"]),
137
+ key_expression,
138
+ (key_id, literal["node_id"]),
139
+ )
140
+ prelude.append(key_declaration)
141
+ key_refs.append(key_reference)
142
+
143
+ value_prelude, value_expression = s.expression(s.nodes[value_id])
144
+ prelude.extend(value_prelude)
145
+ value_declaration, value_reference = s.temporary(
146
+ "container_value",
147
+ literal,
148
+ ordinal,
149
+ s.category_type(fact["value_category"]),
150
+ value_expression,
151
+ (value_id, literal["node_id"]),
152
+ )
153
+ prelude.append(value_declaration)
154
+ value_refs.append(value_reference)
155
+
156
+ key_identifier = self._component_identifier(fact, literal, "keys")
157
+ value_identifier = self._component_identifier(fact, literal, "values")
158
+ key_declaration = CVariableDeclaration(
159
+ _sid("c-container-keys-", node["node_id"]),
160
+ key_identifier,
161
+ self._array_type(fact["key_category"], fact["capacity"], readonly=True),
162
+ CInitializerList(_sid("c-container-keys-init-", literal["node_id"]), tuple(key_refs), s.provenance(literal)),
163
+ CStorage.NONE,
164
+ s.provenance(node),
165
+ )
166
+ value_declaration = CVariableDeclaration(
167
+ _sid("c-container-values-", node["node_id"]),
168
+ value_identifier,
169
+ self._array_type(fact["value_category"], fact["capacity"], readonly=True),
170
+ CInitializerList(_sid("c-container-values-init-", literal["node_id"]), tuple(value_refs), s.provenance(literal)),
171
+ CStorage.NONE,
172
+ s.provenance(node),
173
+ )
174
+ self.storage[fact["binding_id"]] = {
175
+ "iteration": key_identifier,
176
+ "values": value_identifier,
177
+ "kind": "dict",
178
+ }
179
+ return tuple(prelude) + (key_declaration, value_declaration)
180
+
181
+ def access(self, node: dict[str, Any]) -> tuple[tuple[Any, ...], Any]:
182
+ s = self.services
183
+ fact = s.accesses.get(node["node_id"])
184
+ if not fact or not fact.get("supported"):
185
+ s.reject(
186
+ (fact or {}).get("diagnostic_code") or "PYC3404",
187
+ (fact or {}).get("reason") or "Container access lacks a static proof",
188
+ node,
189
+ )
190
+ storage = self.storage.get(fact["binding_id"])
191
+ if not storage:
192
+ s.reject("PYC3403", "Container access occurs before its fixed local declaration", node)
193
+ offset = fact.get("resolved_offset")
194
+ if not isinstance(offset, int) or isinstance(offset, bool):
195
+ s.reject("PYC3404", "Container access lacks a resolved integer offset", node)
196
+ provenance = s.provenance(node)
197
+ identifier = storage["values"]
198
+ container = CIdentifierRef(
199
+ _sid("c-container-ref-", node["node_id"], identifier.binding_id),
200
+ identifier.binding_id,
201
+ provenance,
202
+ )
203
+ index = CIntegerLiteral(
204
+ _sid("c-container-offset-", node["node_id"]),
205
+ offset,
206
+ "LL",
207
+ s.synthetic_provenance((node["node_id"],), node["node_id"]),
208
+ )
209
+ return (), CSubscriptExpr(_sid("c-subscript-", node["node_id"]), container, index, provenance)
210
+
211
+ def iteration(self, node: dict[str, Any]) -> tuple[Any, ...]:
212
+ s = self.services
213
+ fact = s.iterations[node["node_id"]]
214
+ if not fact.get("supported"):
215
+ s.reject(fact.get("diagnostic_code") or "PYC3407", fact.get("reason") or "Unsupported container iteration", node)
216
+ storage = self.storage.get(fact["binding_id"])
217
+ if not storage:
218
+ s.reject("PYC3403", "Container iteration occurs before its fixed local declaration", node)
219
+ target = s.nodes[node["fields"]["target"]]
220
+ target_binding = s.source_bindings_by_occurrence.get(target["node_id"])
221
+ if not target_binding:
222
+ s.reject("PYC3407", "Container loop target binding could not be resolved", target)
223
+
224
+ index_binding_id = _sid("bind-container-index-", node["node_id"])
225
+ index_provenance = s.synthetic_provenance((node["node_id"],), node["node_id"])
226
+ index_identifier = CIdentifier(
227
+ index_binding_id,
228
+ s.temporary_spelling("index", index_binding_id),
229
+ index_provenance,
230
+ )
231
+ zero = CIntegerLiteral(_sid("c-container-loop-zero-", node["node_id"]), 0, "LL", index_provenance)
232
+ one = CIntegerLiteral(_sid("c-container-loop-one-", node["node_id"]), 1, "LL", index_provenance)
233
+ capacity = CIntegerLiteral(_sid("c-container-loop-capacity-", node["node_id"]), fact["capacity"], "LL", index_provenance)
234
+ initializer = CVariableDeclaration(
235
+ _sid("c-container-loop-init-", node["node_id"]),
236
+ index_identifier,
237
+ CType("int64_t"),
238
+ zero,
239
+ CStorage.NONE,
240
+ index_provenance,
241
+ )
242
+ condition_ref = CIdentifierRef(_sid("c-container-loop-condition-ref-", node["node_id"]), index_binding_id, index_provenance)
243
+ condition = CBinaryExpr(_sid("c-container-loop-condition-", node["node_id"]), CBinaryOp.LESS, condition_ref, capacity, index_provenance)
244
+ update_left = CIdentifierRef(_sid("c-container-loop-update-left-", node["node_id"]), index_binding_id, index_provenance)
245
+ update_value = CBinaryExpr(_sid("c-container-loop-update-value-", node["node_id"]), CBinaryOp.ADD, update_left, one, index_provenance)
246
+ update_target = CIdentifierRef(_sid("c-container-loop-update-target-", node["node_id"]), index_binding_id, index_provenance)
247
+ update = CAssignmentStatement(_sid("c-container-loop-update-", node["node_id"]), update_target, update_value, index_provenance)
248
+
249
+ data_identifier = storage["iteration"]
250
+ data_ref = CIdentifierRef(_sid("c-container-loop-data-", node["node_id"]), data_identifier.binding_id, index_provenance)
251
+ element_index = CIdentifierRef(_sid("c-container-loop-element-index-", node["node_id"]), index_binding_id, index_provenance)
252
+ element = CSubscriptExpr(_sid("c-container-loop-element-", node["node_id"]), data_ref, element_index, index_provenance)
253
+ target_declaration = CVariableDeclaration(
254
+ _sid("c-container-loop-target-", node["node_id"]),
255
+ s.identifier(target_binding, target),
256
+ s.category_type(fact["target_category"]),
257
+ element,
258
+ CStorage.NONE,
259
+ s.provenance(target, fallback_plan_node=node["node_id"]),
260
+ )
261
+ source_body = s.block_statements(node["fields"].get("body", []), loop=True)
262
+ body = CBlock(
263
+ _sid("c-container-loop-body-", node["node_id"]),
264
+ (target_declaration,) + source_body,
265
+ s.provenance(node),
266
+ )
267
+ return (CForStatement(_sid("c-container-loop-", node["node_id"]), initializer, condition, update, body, s.provenance(node)),)
268
+
269
+ def _array_type(self, category: str, capacity: int, *, readonly: bool = False) -> CType:
270
+ scalar = self.services.category_type(category)
271
+ return CType(scalar.base, scalar.qualifiers, scalar.pointer_depth, (capacity,), readonly)
272
+
273
+ def _component_identifier(self, fact: dict[str, Any], node: dict[str, Any], component: str) -> CIdentifier:
274
+ s = self.services
275
+ binding_id = _sid("bind-container-component-", fact["binding_id"], component)
276
+ key = (fact["binding_id"], component)
277
+ spelling = self.component_spellings.get(key)
278
+ if spelling is None:
279
+ base = f"{s.generated_names[fact['binding_id']]}_{component}"
280
+ spelling = base
281
+ suffix = 1
282
+ while spelling in s.generated_spellings:
283
+ suffix += 1
284
+ spelling = f"{base}_{suffix}"
285
+ s.generated_spellings.add(spelling)
286
+ self.component_spellings[key] = spelling
287
+ return CIdentifier(binding_id, spelling, s.synthetic_provenance((node["node_id"],), fact["assignment_node_id"]))
288
+
289
+
290
+ __all__ = ["ContainerCIRLowerer", "ContainerLoweringServices"]
@@ -0,0 +1,146 @@
1
+ """Immutable facts for the Phase 11 fixed local-container profile."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Any
7
+
8
+ from pycforge.converter.analysis.model import ValueCategory
9
+ from pycforge.converter.contracts.configuration import MAX_CONTAINER_ELEMENTS
10
+
11
+
12
+
13
+ @dataclass(frozen=True, slots=True)
14
+ class ContainerShapeFact:
15
+ literal_node_id: str
16
+ container_kind: str
17
+ capacity: int
18
+ element_node_ids: tuple[str, ...]
19
+ key_node_ids: tuple[str, ...]
20
+ value_node_ids: tuple[str, ...]
21
+ element_category: ValueCategory
22
+ key_category: ValueCategory
23
+ value_category: ValueCategory
24
+ key_values: tuple[int | str, ...]
25
+ storage_model: str
26
+ mutable: bool
27
+ valid: bool
28
+ diagnostic_code: str | None
29
+ reason: str | None
30
+
31
+ def to_dict(self) -> dict[str, Any]:
32
+ return {
33
+ "literal_node_id": self.literal_node_id,
34
+ "container_kind": self.container_kind,
35
+ "capacity": self.capacity,
36
+ "element_node_ids": list(self.element_node_ids),
37
+ "key_node_ids": list(self.key_node_ids),
38
+ "value_node_ids": list(self.value_node_ids),
39
+ "element_category": self.element_category.value,
40
+ "key_category": self.key_category.value,
41
+ "value_category": self.value_category.value,
42
+ "key_values": list(self.key_values),
43
+ "storage_model": self.storage_model,
44
+ "mutable": self.mutable,
45
+ "valid": self.valid,
46
+ "diagnostic_code": self.diagnostic_code,
47
+ "reason": self.reason,
48
+ }
49
+
50
+
51
+ @dataclass(frozen=True, slots=True)
52
+ class ContainerBindingFact:
53
+ binding_id: str
54
+ source_name: str
55
+ assignment_node_id: str
56
+ target_node_id: str
57
+ literal_node_id: str
58
+ container_kind: str
59
+ capacity: int
60
+ element_category: ValueCategory
61
+ key_category: ValueCategory
62
+ value_category: ValueCategory
63
+ allowed_use_node_ids: tuple[str, ...]
64
+ invalid_use_node_ids: tuple[str, ...]
65
+ valid: bool
66
+ diagnostic_code: str | None
67
+ rejection_node_id: str | None
68
+ reason: str | None
69
+
70
+ def to_dict(self) -> dict[str, Any]:
71
+ return {
72
+ "binding_id": self.binding_id,
73
+ "source_name": self.source_name,
74
+ "assignment_node_id": self.assignment_node_id,
75
+ "target_node_id": self.target_node_id,
76
+ "literal_node_id": self.literal_node_id,
77
+ "container_kind": self.container_kind,
78
+ "capacity": self.capacity,
79
+ "element_category": self.element_category.value,
80
+ "key_category": self.key_category.value,
81
+ "value_category": self.value_category.value,
82
+ "allowed_use_node_ids": list(self.allowed_use_node_ids),
83
+ "invalid_use_node_ids": list(self.invalid_use_node_ids),
84
+ "valid": self.valid,
85
+ "diagnostic_code": self.diagnostic_code,
86
+ "rejection_node_id": self.rejection_node_id,
87
+ "reason": self.reason,
88
+ }
89
+
90
+
91
+ @dataclass(frozen=True, slots=True)
92
+ class ContainerAccessFact:
93
+ subscript_node_id: str
94
+ binding_id: str | None
95
+ container_kind: str | None
96
+ slice_node_id: str | None
97
+ result_category: ValueCategory
98
+ resolved_offset: int | None
99
+ source_index: int | None
100
+ key_value: int | str | None
101
+ supported: bool
102
+ diagnostic_code: str | None
103
+ reason: str | None
104
+
105
+ def to_dict(self) -> dict[str, Any]:
106
+ return {
107
+ "subscript_node_id": self.subscript_node_id,
108
+ "binding_id": self.binding_id,
109
+ "container_kind": self.container_kind,
110
+ "slice_node_id": self.slice_node_id,
111
+ "result_category": self.result_category.value,
112
+ "resolved_offset": self.resolved_offset,
113
+ "source_index": self.source_index,
114
+ "key_value": self.key_value,
115
+ "supported": self.supported,
116
+ "diagnostic_code": self.diagnostic_code,
117
+ "reason": self.reason,
118
+ }
119
+
120
+
121
+ @dataclass(frozen=True, slots=True)
122
+ class ContainerIterationFact:
123
+ for_node_id: str
124
+ binding_id: str | None
125
+ container_kind: str | None
126
+ target_node_id: str | None
127
+ target_category: ValueCategory
128
+ capacity: int
129
+ order_policy: str
130
+ supported: bool
131
+ diagnostic_code: str | None
132
+ reason: str | None
133
+
134
+ def to_dict(self) -> dict[str, Any]:
135
+ return {
136
+ "for_node_id": self.for_node_id,
137
+ "binding_id": self.binding_id,
138
+ "container_kind": self.container_kind,
139
+ "target_node_id": self.target_node_id,
140
+ "target_category": self.target_category.value,
141
+ "capacity": self.capacity,
142
+ "order_policy": self.order_policy,
143
+ "supported": self.supported,
144
+ "diagnostic_code": self.diagnostic_code,
145
+ "reason": self.reason,
146
+ }
File without changes
@@ -0,0 +1,178 @@
1
+ """Versioned public configuration identities for the promoted converter.
2
+
3
+ The constants in this module are deliberately data-only so the public request,
4
+ CLI, workspace, analysis, and lowering layers cannot drift to different phase
5
+ identities.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ DEFAULT_TARGET_CONTRACT = "c11-portable-fixed-v1"
11
+ DEFAULT_SEMANTIC_POLICY = "strict-source-v1"
12
+ PHASE9_RULE_SET = "phase9-functions-calls-v0.9"
13
+ PHASE11_RULE_SET = "phase11-bounded-containers-v0.11"
14
+ PHASE12_RULE_SET = "phase12-explicit-module-bundles-v0.12"
15
+ PHASE12_RENDERER = "c-renderer-v0.12"
16
+ PHASE12_MODULE_POLICY = "phase12-explicit-sourcebundle-modules-v0.12"
17
+ PHASE13_RULE_SET = "phase13-static-records-v0.13"
18
+ PHASE13_RENDERER = "c-renderer-v0.13"
19
+ # Phase 14A remains an explicit historical request profile after 14B becomes
20
+ # active. Keep these identities named rather than deriving them from the
21
+ # defaults so a historical request cannot be silently relabeled.
22
+ PHASE14A_RULE_SET = "phase14-bounded-numeric-v0.14"
23
+ PHASE14A_RENDERER = "c-renderer-v0.14"
24
+ PHASE14_RULE_SET = PHASE14A_RULE_SET
25
+ PHASE14_RENDERER = PHASE14A_RENDERER
26
+ PHASE14B_RULE_SET = "phase14-conditional-regions-v0.14.1"
27
+ PHASE14B_RENDERER = "c-renderer-v0.14.1"
28
+ PHASE14C_RULE_SET = "phase14-direct-keyword-calls-v0.14.2"
29
+ PHASE14C_RENDERER = "c-renderer-v0.14.2"
30
+ DEFAULT_RULE_SET = "phase14-required-keyword-only-calls-v0.14.3"
31
+ DEFAULT_RENDERER = "c-renderer-v0.14.3"
32
+ DEFAULT_HELPER_POLICY = "phase10-support-templates-v0.10"
33
+ DEFAULT_CONTAINER_POLICY = "phase11-fixed-local-containers-v0.11"
34
+ # Module, record, and numeric policies are deliberately unchanged in Phase 14B.
35
+ DEFAULT_MODULE_POLICY = "phase13-explicit-record-modules-v0.13"
36
+ DEFAULT_RECORD_POLICY = "phase13-immutable-automatic-records-v0.13"
37
+ PHASE14A_NUMERIC_POLICY = "phase14-proved-floor-arithmetic-v0.14"
38
+ DEFAULT_NUMERIC_POLICY = PHASE14A_NUMERIC_POLICY
39
+ MAX_CONTAINER_ELEMENTS = 64
40
+ MAX_SOURCE_DOCUMENTS = 64
41
+ MAX_IMPORT_ITEMS = 4_096
42
+
43
+ SUPPORTED_TARGET_CONTRACTS = frozenset(
44
+ {
45
+ DEFAULT_TARGET_CONTRACT,
46
+ # Read-compatible identity used by the earliest public request object.
47
+ "pycforge-c11-int64-v0.1",
48
+ }
49
+ )
50
+ SUPPORTED_SEMANTIC_POLICIES = frozenset(
51
+ {
52
+ DEFAULT_SEMANTIC_POLICY,
53
+ # Read-compatible identity used by the earliest public request object.
54
+ "strict-v0.1",
55
+ }
56
+ )
57
+ SUPPORTED_RULE_SETS = frozenset(
58
+ {
59
+ "phase3-frontend-v0.3",
60
+ "phase5-planning-v0.5",
61
+ "phase6-first-slice-v0.6",
62
+ "phase8-control-flow-v0.8",
63
+ PHASE9_RULE_SET,
64
+ PHASE11_RULE_SET,
65
+ PHASE12_RULE_SET,
66
+ PHASE13_RULE_SET,
67
+ PHASE14A_RULE_SET,
68
+ PHASE14B_RULE_SET,
69
+ PHASE14C_RULE_SET,
70
+ DEFAULT_RULE_SET,
71
+ }
72
+ )
73
+ SUPPORTED_RENDERERS = frozenset(
74
+ {
75
+ "phase3-none-v0.3",
76
+ "c-renderer-v0.6",
77
+ "c-renderer-v0.8",
78
+ "c-renderer-v0.9",
79
+ "c-renderer-v0.11",
80
+ PHASE12_RENDERER,
81
+ PHASE13_RENDERER,
82
+ PHASE14A_RENDERER,
83
+ PHASE14B_RENDERER,
84
+ PHASE14C_RENDERER,
85
+ DEFAULT_RENDERER,
86
+ }
87
+ )
88
+
89
+ # Rule-set and renderer identities are a paired compatibility profile. Phase 5
90
+ # is planning-only and therefore keeps the current request default renderer;
91
+ # every rendering phase requires its exact historical renderer.
92
+ COMPATIBLE_RENDERERS_BY_RULE_SET = {
93
+ "phase3-frontend-v0.3": frozenset({"phase3-none-v0.3"}),
94
+ "phase5-planning-v0.5": frozenset({DEFAULT_RENDERER}),
95
+ "phase6-first-slice-v0.6": frozenset({"c-renderer-v0.6"}),
96
+ "phase8-control-flow-v0.8": frozenset({"c-renderer-v0.8"}),
97
+ PHASE9_RULE_SET: frozenset({"c-renderer-v0.9"}),
98
+ PHASE11_RULE_SET: frozenset({"c-renderer-v0.11"}),
99
+ PHASE12_RULE_SET: frozenset({PHASE12_RENDERER}),
100
+ PHASE13_RULE_SET: frozenset({PHASE13_RENDERER}),
101
+ PHASE14A_RULE_SET: frozenset({PHASE14A_RENDERER}),
102
+ PHASE14B_RULE_SET: frozenset({PHASE14B_RENDERER}),
103
+ PHASE14C_RULE_SET: frozenset({PHASE14C_RENDERER}),
104
+ DEFAULT_RULE_SET: frozenset({DEFAULT_RENDERER}),
105
+ }
106
+
107
+ SUPPORTED_HELPER_POLICIES = frozenset({DEFAULT_HELPER_POLICY})
108
+ SUPPORTED_CONTAINER_POLICIES = frozenset({DEFAULT_CONTAINER_POLICY})
109
+ SUPPORTED_MODULE_POLICIES = frozenset({PHASE12_MODULE_POLICY, DEFAULT_MODULE_POLICY})
110
+ SUPPORTED_RECORD_POLICIES = frozenset({DEFAULT_RECORD_POLICY})
111
+ SUPPORTED_NUMERIC_POLICIES = frozenset({DEFAULT_NUMERIC_POLICY})
112
+
113
+
114
+ def supports_functions(rule_set: str) -> bool:
115
+ return rule_set in {
116
+ PHASE9_RULE_SET,
117
+ PHASE11_RULE_SET,
118
+ PHASE12_RULE_SET,
119
+ PHASE13_RULE_SET,
120
+ PHASE14A_RULE_SET,
121
+ PHASE14B_RULE_SET,
122
+ PHASE14C_RULE_SET,
123
+ DEFAULT_RULE_SET,
124
+ }
125
+
126
+
127
+ def supports_containers(rule_set: str) -> bool:
128
+ return rule_set in {
129
+ PHASE11_RULE_SET,
130
+ PHASE12_RULE_SET,
131
+ PHASE13_RULE_SET,
132
+ PHASE14A_RULE_SET,
133
+ PHASE14B_RULE_SET,
134
+ PHASE14C_RULE_SET,
135
+ DEFAULT_RULE_SET,
136
+ }
137
+
138
+
139
+ def supports_modules(rule_set: str) -> bool:
140
+ return rule_set in {
141
+ PHASE12_RULE_SET,
142
+ PHASE13_RULE_SET,
143
+ PHASE14A_RULE_SET,
144
+ PHASE14B_RULE_SET,
145
+ PHASE14C_RULE_SET,
146
+ DEFAULT_RULE_SET,
147
+ }
148
+
149
+
150
+ def supports_records(rule_set: str) -> bool:
151
+ return rule_set in {
152
+ PHASE13_RULE_SET,
153
+ PHASE14A_RULE_SET,
154
+ PHASE14B_RULE_SET,
155
+ PHASE14C_RULE_SET,
156
+ DEFAULT_RULE_SET,
157
+ }
158
+
159
+
160
+ def supports_numeric(rule_set: str) -> bool:
161
+ return rule_set in {
162
+ PHASE14A_RULE_SET,
163
+ PHASE14B_RULE_SET,
164
+ PHASE14C_RULE_SET,
165
+ DEFAULT_RULE_SET,
166
+ }
167
+
168
+
169
+ def supports_conditional_regions(rule_set: str) -> bool:
170
+ return rule_set in {PHASE14B_RULE_SET, PHASE14C_RULE_SET, DEFAULT_RULE_SET}
171
+
172
+
173
+ def supports_keyword_calls(rule_set: str) -> bool:
174
+ return rule_set in {PHASE14C_RULE_SET, DEFAULT_RULE_SET}
175
+
176
+
177
+ def supports_keyword_only_calls(rule_set: str) -> bool:
178
+ return rule_set == DEFAULT_RULE_SET
@@ -0,0 +1,68 @@
1
+ """Data-only ISO C11 identifier reservations shared by planning and validation."""
2
+
3
+ from __future__ import annotations
4
+
5
+
6
+ C_KEYWORDS = frozenset({
7
+ "auto", "break", "case", "char", "const", "continue", "default", "do",
8
+ "double", "else", "enum", "extern", "float", "for", "goto", "if",
9
+ "inline", "int", "long", "register", "restrict", "return", "short",
10
+ "signed", "sizeof", "static", "struct", "switch", "typedef", "union",
11
+ "unsigned", "void", "volatile", "while", "_Alignas", "_Alignof",
12
+ "_Atomic", "_Bool", "_Complex", "_Generic", "_Imaginary", "_Noreturn",
13
+ "_Static_assert", "_Thread_local",
14
+ })
15
+
16
+ TARGET_RESERVED_NAMES = {
17
+ "bool", "true", "false", "size_t",
18
+ "int8_t", "uint8_t", "int16_t", "uint16_t", "int32_t", "uint32_t",
19
+ "int64_t", "uint64_t",
20
+ }
21
+ for _width in (8, 16, 32, 64):
22
+ TARGET_RESERVED_NAMES.update({
23
+ f"int_least{_width}_t", f"uint_least{_width}_t", f"int_fast{_width}_t", f"uint_fast{_width}_t",
24
+ f"INT{_width}_MIN", f"INT{_width}_MAX", f"UINT{_width}_MAX", f"INT{_width}_C", f"UINT{_width}_C",
25
+ f"INT_LEAST{_width}_MIN", f"INT_LEAST{_width}_MAX", f"UINT_LEAST{_width}_MAX",
26
+ f"INT_FAST{_width}_MIN", f"INT_FAST{_width}_MAX", f"UINT_FAST{_width}_MAX",
27
+ })
28
+ TARGET_RESERVED_NAMES.update({
29
+ "intptr_t", "uintptr_t", "intmax_t", "uintmax_t", "INTPTR_MIN", "INTPTR_MAX", "UINTPTR_MAX",
30
+ "INTMAX_MIN", "INTMAX_MAX", "UINTMAX_MAX", "INTMAX_C", "UINTMAX_C", "PTRDIFF_MIN", "PTRDIFF_MAX",
31
+ "SIG_ATOMIC_MIN", "SIG_ATOMIC_MAX", "SIZE_MAX", "WCHAR_MIN", "WCHAR_MAX", "WINT_MIN", "WINT_MAX",
32
+ })
33
+ TARGET_RESERVED_NAMES = frozenset(TARGET_RESERVED_NAMES)
34
+
35
+ # ISO C library identifiers with external linkage are reserved even when their
36
+ # declaring header is not included. `main` is included as the hosted entry point.
37
+ C11_EXTERNAL_IDENTIFIERS = frozenset("""
38
+ main errno stdin stdout stderr
39
+ isalnum isalpha isblank iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper
40
+ feclearexcept fegetexceptflag feraiseexcept fesetexceptflag fetestexcept fegetround fesetround fegetenv feholdexcept fesetenv feupdateenv
41
+ imaxabs imaxdiv strtoimax strtoumax wcstoimax wcstoumax setlocale localeconv setjmp longjmp signal raise
42
+ remove rename tmpfile tmpnam fclose fflush fopen freopen setbuf setvbuf fprintf fscanf printf scanf snprintf sprintf sscanf
43
+ vfprintf vfscanf vprintf vscanf vsnprintf vsprintf vsscanf fgetc fgets fputc fputs getc getchar putc putchar puts ungetc
44
+ fread fwrite fgetpos fseek fsetpos ftell rewind clearerr feof ferror perror
45
+ atof atoi atol atoll strtod strtof strtold strtol strtoll strtoul strtoull rand srand aligned_alloc calloc free malloc realloc
46
+ abort atexit at_quick_exit exit _Exit getenv quick_exit system bsearch qsort abs labs llabs div ldiv lldiv
47
+ mblen mbtowc wctomb mbstowcs wcstombs
48
+ memcpy memmove strcpy strncpy strcat strncat memcmp strcmp strcoll strncmp strxfrm memchr strchr strcspn strpbrk strrchr strspn strstr strtok memset strerror strlen
49
+ call_once cnd_broadcast cnd_destroy cnd_init cnd_signal cnd_timedwait cnd_wait mtx_destroy mtx_init mtx_lock mtx_timedlock mtx_trylock mtx_unlock
50
+ thrd_create thrd_current thrd_detach thrd_equal thrd_exit thrd_join thrd_sleep thrd_yield tss_create tss_delete tss_get tss_set
51
+ clock difftime mktime time timespec_get asctime ctime gmtime localtime strftime
52
+ mbrtoc16 c16rtomb mbrtoc32 c32rtomb
53
+ fwprintf fwscanf swprintf swscanf vfwprintf vfwscanf vswprintf vswscanf vwprintf vwscanf wprintf wscanf
54
+ fgetwc fgetws fputwc fputws fwide getwc getwchar putwc putwchar ungetwc
55
+ wcstod wcstof wcstold wcstol wcstoll wcstoul wcstoull wcscpy wcsncpy wmemcpy wmemmove wcscat wcsncat
56
+ wmemcmp wcscmp wcscoll wcsncmp wcsxfrm wmemchr wcschr wcscspn wcspbrk wcsrchr wcsspn wcsstr wcstok wmemset wcslen wcsftime
57
+ btowc wctob mbsinit mbrlen mbrtowc wcrtomb mbsrtowcs wcsrtombs
58
+ iswalnum iswalpha iswblank iswcntrl iswctype iswdigit iswgraph iswlower iswprint iswpunct iswspace iswupper iswxdigit towlower towupper towctrans wctype wctrans
59
+ """.split())
60
+
61
+ _MATH_EXTERNAL_BASES = frozenset("""
62
+ acos asin atan atan2 cos sin tan acosh asinh atanh exp exp2 expm1 frexp ilogb ldexp log log10 log1p log2 logb modf scalbn scalbln
63
+ cbrt fabs hypot pow sqrt erf erfc lgamma tgamma ceil floor nearbyint rint lrint llrint round lround llround trunc
64
+ fmod remainder remquo copysign nan nextafter nexttoward fdim fmax fmin fma
65
+ cacos casin catan ccos csin ctan cacosh casinh catanh cexp clog cabs cpow csqrt carg cimag conj cproj creal
66
+ """.split())
67
+ C11_EXTERNAL_IDENTIFIERS |= frozenset(name + suffix for name in _MATH_EXTERNAL_BASES for suffix in ("", "f", "l"))
68
+