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,348 @@
1
+ """Project-owned structured C IR factories for accepted Phase 10 fixtures."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+
7
+ from pycforge.converter.ir.c_ir import (
8
+ CAssignmentStatement,
9
+ CBinaryExpr,
10
+ CBinaryOp,
11
+ CBlock,
12
+ CFunctionDefinition,
13
+ CFunctionPrototype,
14
+ CIdentifier,
15
+ CIdentifierRef,
16
+ CIfStatement,
17
+ CInclude,
18
+ CIntegerLiteral,
19
+ CParameter,
20
+ CProvenance,
21
+ CReturnStatement,
22
+ CStorage,
23
+ CType,
24
+ CVariableDeclaration,
25
+ )
26
+
27
+ from .model import (
28
+ HELPER_INTERFACE_ID,
29
+ HelperCIRAsset,
30
+ HelperDefinition,
31
+ HelperFailureContract,
32
+ HelperOwnershipContract,
33
+ HelperReference,
34
+ )
35
+
36
+
37
+ FLOOR_DIV_REFERENCE = HelperReference("pycf.i64.floor_div", "1.0.0")
38
+ FLOOR_MOD_REFERENCE = HelperReference("pycf.i64.floor_mod", "1.0.0")
39
+
40
+ _TARGETS = ("c11-portable-fixed-v1",)
41
+ _OWNERSHIP = HelperOwnershipContract(
42
+ parameter_ownership="scalar values passed by value",
43
+ return_ownership="scalar value returned by value",
44
+ allocation="none",
45
+ lifetime="automatic call lifetime only",
46
+ cleanup="none",
47
+ )
48
+ _FAILURE = HelperFailureContract(
49
+ strategy="caller-proved preconditions",
50
+ preconditions=(
51
+ "divisor is nonzero",
52
+ "dividend is not INT64_MIN when divisor is -1",
53
+ ),
54
+ violation_policy=(
55
+ "the prospective RulePlan must reject conversion or select a separately "
56
+ "approved checked-failure contract before helper lowering"
57
+ ),
58
+ runtime_failure_channel="none",
59
+ )
60
+
61
+
62
+ def _sid(reference: HelperReference, role: str) -> str:
63
+ digest = hashlib.sha256(f"{reference.canonical}\x1f{role}".encode("utf-8")).hexdigest()[:20]
64
+ return f"c-helper-{role}-{digest}"
65
+
66
+
67
+ def _binding(reference: HelperReference, role: str) -> str:
68
+ return f"helper-binding:{reference.canonical}:{role}"
69
+
70
+
71
+ def _ref(
72
+ reference: HelperReference,
73
+ binding_role: str,
74
+ occurrence: str,
75
+ provenance: CProvenance,
76
+ ) -> CIdentifierRef:
77
+ return CIdentifierRef(
78
+ _sid(reference, f"ref-{occurrence}"),
79
+ _binding(reference, binding_role),
80
+ provenance,
81
+ )
82
+
83
+
84
+ def _zero(reference: HelperReference, role: str, provenance: CProvenance) -> CIntegerLiteral:
85
+ return CIntegerLiteral(_sid(reference, f"zero-{role}"), 0, "LL", provenance)
86
+
87
+
88
+ def _one(reference: HelperReference, role: str, provenance: CProvenance) -> CIntegerLiteral:
89
+ return CIntegerLiteral(_sid(reference, f"one-{role}"), 1, "LL", provenance)
90
+
91
+
92
+ def _common_parts(reference: HelperReference, spelling: str):
93
+ provenance = CProvenance("support-template")
94
+ function_id = CIdentifier(_binding(reference, "function"), spelling, provenance)
95
+ dividend_id = CIdentifier(_binding(reference, "dividend"), "pycf_dividend", provenance)
96
+ divisor_id = CIdentifier(_binding(reference, "divisor"), "pycf_divisor", provenance)
97
+ quotient_id = CIdentifier(_binding(reference, "quotient"), "pycf_quotient", provenance)
98
+ remainder_id = CIdentifier(_binding(reference, "remainder"), "pycf_remainder", provenance)
99
+ value_type = CType("int64_t")
100
+ prototype_parameters = (
101
+ CParameter(_sid(reference, "prototype-param-dividend"), dividend_id, value_type, provenance),
102
+ CParameter(_sid(reference, "prototype-param-divisor"), divisor_id, value_type, provenance),
103
+ )
104
+ definition_parameters = (
105
+ CParameter(_sid(reference, "definition-param-dividend"), dividend_id, value_type, provenance),
106
+ CParameter(_sid(reference, "definition-param-divisor"), divisor_id, value_type, provenance),
107
+ )
108
+ prototype = CFunctionPrototype(
109
+ _sid(reference, "prototype"),
110
+ function_id,
111
+ value_type,
112
+ prototype_parameters,
113
+ CStorage.STATIC,
114
+ provenance,
115
+ )
116
+ include = CInclude(_sid(reference, "include-stdint"), "stdint.h", True, provenance)
117
+ return (
118
+ provenance,
119
+ function_id,
120
+ dividend_id,
121
+ divisor_id,
122
+ quotient_id,
123
+ remainder_id,
124
+ value_type,
125
+ prototype,
126
+ definition_parameters,
127
+ include,
128
+ )
129
+
130
+
131
+ def _adjustment_condition(reference: HelperReference, provenance: CProvenance) -> CBinaryExpr:
132
+ remainder_nonzero = CBinaryExpr(
133
+ _sid(reference, "condition-remainder-nonzero"),
134
+ CBinaryOp.NOT_EQUAL,
135
+ _ref(reference, "remainder", "condition-nonzero-remainder", provenance),
136
+ _zero(reference, "condition-remainder", provenance),
137
+ provenance,
138
+ )
139
+ remainder_negative = CBinaryExpr(
140
+ _sid(reference, "condition-remainder-negative"),
141
+ CBinaryOp.LESS,
142
+ _ref(reference, "remainder", "condition-negative-remainder", provenance),
143
+ _zero(reference, "condition-remainder-sign", provenance),
144
+ provenance,
145
+ )
146
+ divisor_negative = CBinaryExpr(
147
+ _sid(reference, "condition-divisor-negative"),
148
+ CBinaryOp.LESS,
149
+ _ref(reference, "divisor", "condition-negative-divisor", provenance),
150
+ _zero(reference, "condition-divisor-sign", provenance),
151
+ provenance,
152
+ )
153
+ signs_differ = CBinaryExpr(
154
+ _sid(reference, "condition-signs-differ"),
155
+ CBinaryOp.NOT_EQUAL,
156
+ remainder_negative,
157
+ divisor_negative,
158
+ provenance,
159
+ )
160
+ return CBinaryExpr(
161
+ _sid(reference, "condition-adjustment"),
162
+ CBinaryOp.LOGICAL_AND,
163
+ remainder_nonzero,
164
+ signs_differ,
165
+ provenance,
166
+ )
167
+
168
+
169
+ def floor_div_asset() -> HelperCIRAsset:
170
+ reference = FLOOR_DIV_REFERENCE
171
+ (
172
+ provenance,
173
+ function_id,
174
+ _dividend_id,
175
+ _divisor_id,
176
+ quotient_id,
177
+ remainder_id,
178
+ value_type,
179
+ prototype,
180
+ parameters,
181
+ include,
182
+ ) = _common_parts(reference, "pycf_i64_floor_div_v1")
183
+ quotient = CVariableDeclaration(
184
+ _sid(reference, "declaration-quotient"),
185
+ quotient_id,
186
+ value_type,
187
+ CBinaryExpr(
188
+ _sid(reference, "expression-quotient"),
189
+ CBinaryOp.DIVIDE,
190
+ _ref(reference, "dividend", "quotient-dividend", provenance),
191
+ _ref(reference, "divisor", "quotient-divisor", provenance),
192
+ provenance,
193
+ ),
194
+ CStorage.NONE,
195
+ provenance,
196
+ )
197
+ remainder = CVariableDeclaration(
198
+ _sid(reference, "declaration-remainder"),
199
+ remainder_id,
200
+ value_type,
201
+ CBinaryExpr(
202
+ _sid(reference, "expression-remainder"),
203
+ CBinaryOp.REMAINDER,
204
+ _ref(reference, "dividend", "remainder-dividend", provenance),
205
+ _ref(reference, "divisor", "remainder-divisor", provenance),
206
+ provenance,
207
+ ),
208
+ CStorage.NONE,
209
+ provenance,
210
+ )
211
+ adjustment = CAssignmentStatement(
212
+ _sid(reference, "assignment-adjustment"),
213
+ _ref(reference, "quotient", "adjustment-target", provenance),
214
+ CBinaryExpr(
215
+ _sid(reference, "expression-adjustment"),
216
+ CBinaryOp.SUBTRACT,
217
+ _ref(reference, "quotient", "adjustment-left", provenance),
218
+ _one(reference, "adjustment", provenance),
219
+ provenance,
220
+ ),
221
+ provenance,
222
+ )
223
+ condition = CIfStatement(
224
+ _sid(reference, "if-adjustment"),
225
+ _adjustment_condition(reference, provenance),
226
+ CBlock(_sid(reference, "if-adjustment-body"), (adjustment,), provenance),
227
+ None,
228
+ provenance,
229
+ )
230
+ result = CReturnStatement(
231
+ _sid(reference, "return"),
232
+ _ref(reference, "quotient", "return-quotient", provenance),
233
+ provenance,
234
+ )
235
+ definition = CFunctionDefinition(
236
+ _sid(reference, "definition"),
237
+ function_id,
238
+ value_type,
239
+ parameters,
240
+ CBlock(_sid(reference, "body"), (quotient, remainder, condition, result), provenance),
241
+ CStorage.STATIC,
242
+ provenance,
243
+ )
244
+ return HelperCIRAsset(reference, (include,), prototype, definition)
245
+
246
+
247
+ def floor_mod_asset() -> HelperCIRAsset:
248
+ reference = FLOOR_MOD_REFERENCE
249
+ (
250
+ provenance,
251
+ function_id,
252
+ _dividend_id,
253
+ _divisor_id,
254
+ _quotient_id,
255
+ remainder_id,
256
+ value_type,
257
+ prototype,
258
+ parameters,
259
+ include,
260
+ ) = _common_parts(reference, "pycf_i64_floor_mod_v1")
261
+ remainder = CVariableDeclaration(
262
+ _sid(reference, "declaration-remainder"),
263
+ remainder_id,
264
+ value_type,
265
+ CBinaryExpr(
266
+ _sid(reference, "expression-remainder"),
267
+ CBinaryOp.REMAINDER,
268
+ _ref(reference, "dividend", "remainder-dividend", provenance),
269
+ _ref(reference, "divisor", "remainder-divisor", provenance),
270
+ provenance,
271
+ ),
272
+ CStorage.NONE,
273
+ provenance,
274
+ )
275
+ adjustment = CAssignmentStatement(
276
+ _sid(reference, "assignment-adjustment"),
277
+ _ref(reference, "remainder", "adjustment-target", provenance),
278
+ CBinaryExpr(
279
+ _sid(reference, "expression-adjustment"),
280
+ CBinaryOp.ADD,
281
+ _ref(reference, "remainder", "adjustment-left", provenance),
282
+ _ref(reference, "divisor", "adjustment-divisor", provenance),
283
+ provenance,
284
+ ),
285
+ provenance,
286
+ )
287
+ condition = CIfStatement(
288
+ _sid(reference, "if-adjustment"),
289
+ _adjustment_condition(reference, provenance),
290
+ CBlock(_sid(reference, "if-adjustment-body"), (adjustment,), provenance),
291
+ None,
292
+ provenance,
293
+ )
294
+ result = CReturnStatement(
295
+ _sid(reference, "return"),
296
+ _ref(reference, "remainder", "return-remainder", provenance),
297
+ provenance,
298
+ )
299
+ definition = CFunctionDefinition(
300
+ _sid(reference, "definition"),
301
+ function_id,
302
+ value_type,
303
+ parameters,
304
+ CBlock(_sid(reference, "body"), (remainder, condition, result), provenance),
305
+ CStorage.STATIC,
306
+ provenance,
307
+ )
308
+ return HelperCIRAsset(reference, (include,), prototype, definition)
309
+
310
+
311
+ def builtin_definitions() -> tuple[HelperDefinition, ...]:
312
+ common = {
313
+ "interface_id": HELPER_INTERFACE_ID,
314
+ "target_contracts": _TARGETS,
315
+ "dependencies": (),
316
+ "earliest_eligible_phase": "separate numeric-semantics mini-phase no earlier than Phase 14",
317
+ "ownership": _OWNERSHIP,
318
+ "failure": _FAILURE,
319
+ "cancellation_policy": "bounded factory and resolver work checks the conversion cancellation token",
320
+ }
321
+ return (
322
+ HelperDefinition(
323
+ reference=FLOOR_DIV_REFERENCE,
324
+ prospective_consumer="future bounded-int Python floor-division RulePlan",
325
+ summary="Correct C truncating signed division to Python floor-division semantics.",
326
+ semantic_obligations=(
327
+ "bounded-int64-representation-proved",
328
+ "divisor-nonzero-proved",
329
+ "int64-minimum-divided-by-negative-one-excluded",
330
+ "python-floor-rounding-preserved",
331
+ ),
332
+ factory=floor_div_asset,
333
+ **common,
334
+ ),
335
+ HelperDefinition(
336
+ reference=FLOOR_MOD_REFERENCE,
337
+ prospective_consumer="future bounded-int Python modulo RulePlan",
338
+ summary="Correct C signed remainder to Python divisor-sign modulo semantics.",
339
+ semantic_obligations=(
340
+ "bounded-int64-representation-proved",
341
+ "divisor-nonzero-proved",
342
+ "int64-minimum-divided-by-negative-one-excluded",
343
+ "python-modulo-sign-preserved",
344
+ ),
345
+ factory=floor_mod_asset,
346
+ **common,
347
+ ),
348
+ )
@@ -0,0 +1,159 @@
1
+ """Immutable contracts for trusted, versioned support-template assets.
2
+
3
+ Support templates are project-owned structured C IR factories. They are not a
4
+ runtime subsystem and Python input can never provide or select arbitrary text.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import re
10
+ from dataclasses import dataclass
11
+ from typing import Callable
12
+
13
+ from pycforge.converter.contracts.configuration import DEFAULT_HELPER_POLICY
14
+ from pycforge.converter.ir.c_ir import (
15
+ CFunctionDefinition,
16
+ CFunctionPrototype,
17
+ CInclude,
18
+ )
19
+
20
+
21
+ HELPER_INTERFACE_ID = "pycforge-helper/1"
22
+ HELPER_REGISTRY_VERSION = DEFAULT_HELPER_POLICY
23
+
24
+ _HELPER_ID = re.compile(r"^pycf(?:\.[a-z][a-z0-9_]*)+$")
25
+ _VERSION = re.compile(r"^(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)$")
26
+
27
+
28
+ @dataclass(frozen=True, slots=True, order=True)
29
+ class HelperReference:
30
+ """An exact helper identity; ranges and implicit latest versions are forbidden."""
31
+
32
+ helper_id: str
33
+ version: str
34
+
35
+ def __post_init__(self) -> None:
36
+ if not _HELPER_ID.fullmatch(self.helper_id):
37
+ raise ValueError(f"invalid helper ID: {self.helper_id}")
38
+ if not _VERSION.fullmatch(self.version):
39
+ raise ValueError(f"invalid exact helper version: {self.version}")
40
+
41
+ @property
42
+ def canonical(self) -> str:
43
+ return f"{self.helper_id}@{self.version}"
44
+
45
+ @classmethod
46
+ def parse(cls, value: str) -> "HelperReference":
47
+ if not isinstance(value, str) or value.count("@") != 1:
48
+ raise ValueError("helper requirement must be helper-id@exact-version")
49
+ helper_id, version = value.split("@", 1)
50
+ return cls(helper_id, version)
51
+
52
+
53
+ @dataclass(frozen=True, slots=True)
54
+ class HelperOwnershipContract:
55
+ parameter_ownership: str
56
+ return_ownership: str
57
+ allocation: str
58
+ lifetime: str
59
+ cleanup: str
60
+
61
+ def to_dict(self) -> dict[str, str]:
62
+ return {
63
+ "parameter_ownership": self.parameter_ownership,
64
+ "return_ownership": self.return_ownership,
65
+ "allocation": self.allocation,
66
+ "lifetime": self.lifetime,
67
+ "cleanup": self.cleanup,
68
+ }
69
+
70
+
71
+ @dataclass(frozen=True, slots=True)
72
+ class HelperFailureContract:
73
+ strategy: str
74
+ preconditions: tuple[str, ...]
75
+ violation_policy: str
76
+ runtime_failure_channel: str
77
+
78
+ def to_dict(self) -> dict[str, object]:
79
+ return {
80
+ "strategy": self.strategy,
81
+ "preconditions": list(self.preconditions),
82
+ "violation_policy": self.violation_policy,
83
+ "runtime_failure_channel": self.runtime_failure_channel,
84
+ }
85
+
86
+
87
+ @dataclass(frozen=True, slots=True)
88
+ class HelperCIRAsset:
89
+ reference: HelperReference
90
+ includes: tuple[CInclude, ...]
91
+ prototype: CFunctionPrototype
92
+ definition: CFunctionDefinition
93
+
94
+
95
+ HelperFactory = Callable[[], HelperCIRAsset]
96
+
97
+
98
+ @dataclass(frozen=True, slots=True)
99
+ class HelperDefinition:
100
+ reference: HelperReference
101
+ interface_id: str
102
+ target_contracts: tuple[str, ...]
103
+ dependencies: tuple[HelperReference, ...]
104
+ prospective_consumer: str
105
+ earliest_eligible_phase: str
106
+ summary: str
107
+ semantic_obligations: tuple[str, ...]
108
+ ownership: HelperOwnershipContract
109
+ failure: HelperFailureContract
110
+ cancellation_policy: str
111
+ factory: HelperFactory
112
+
113
+ def contract_dict(self) -> dict[str, object]:
114
+ return {
115
+ "reference": self.reference.canonical,
116
+ "helper_id": self.reference.helper_id,
117
+ "version": self.reference.version,
118
+ "interface_id": self.interface_id,
119
+ "target_contracts": list(self.target_contracts),
120
+ "dependencies": [item.canonical for item in self.dependencies],
121
+ "prospective_consumer": self.prospective_consumer,
122
+ "earliest_eligible_phase": self.earliest_eligible_phase,
123
+ "summary": self.summary,
124
+ "semantic_obligations": list(self.semantic_obligations),
125
+ "ownership": self.ownership.to_dict(),
126
+ "failure": self.failure.to_dict(),
127
+ "cancellation_policy": self.cancellation_policy,
128
+ "factory_kind": "structured-c-ir",
129
+ }
130
+
131
+
132
+ @dataclass(frozen=True, slots=True)
133
+ class HelperManifestEntry:
134
+ contract: HelperDefinition
135
+ asset_fingerprint: str
136
+
137
+ @property
138
+ def reference(self) -> HelperReference:
139
+ return self.contract.reference
140
+
141
+ def to_dict(self) -> dict[str, object]:
142
+ return {
143
+ **self.contract.contract_dict(),
144
+ "asset_fingerprint": self.asset_fingerprint,
145
+ }
146
+
147
+
148
+ @dataclass(frozen=True, slots=True)
149
+ class ResolvedHelperPlan:
150
+ target_contract: str
151
+ registry_version: str
152
+ requirements: tuple[HelperReference, ...]
153
+ assets: tuple[HelperCIRAsset, ...]
154
+ manifest: tuple[HelperManifestEntry, ...]
155
+ registry_fingerprint: str
156
+ manifest_fingerprint: str
157
+
158
+ def manifest_dicts(self) -> tuple[dict[str, object], ...]:
159
+ return tuple(item.to_dict() for item in self.manifest)