tddlog 0.1.0__tar.gz

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 (538) hide show
  1. tddlog-0.1.0/.github/CONTRIBUTING.md +80 -0
  2. tddlog-0.1.0/.github/scripts/check_release.py +67 -0
  3. tddlog-0.1.0/.github/workflows/binaries.yml +260 -0
  4. tddlog-0.1.0/.github/workflows/c-bindings.yml +251 -0
  5. tddlog-0.1.0/.github/workflows/ci.yml +37 -0
  6. tddlog-0.1.0/.github/workflows/pages.yml +175 -0
  7. tddlog-0.1.0/.github/workflows/wheels.yml +212 -0
  8. tddlog-0.1.0/.gitignore +7 -0
  9. tddlog-0.1.0/CITATION.cff +31 -0
  10. tddlog-0.1.0/Cargo.lock +151 -0
  11. tddlog-0.1.0/Cargo.toml +55 -0
  12. tddlog-0.1.0/LICENSE +201 -0
  13. tddlog-0.1.0/NOTICE +18 -0
  14. tddlog-0.1.0/PKG-INFO +165 -0
  15. tddlog-0.1.0/README.md +558 -0
  16. tddlog-0.1.0/THIRD-PARTY.md +126 -0
  17. tddlog-0.1.0/bindings/python/.gitignore +9 -0
  18. tddlog-0.1.0/bindings/python/Cargo.lock +275 -0
  19. tddlog-0.1.0/bindings/python/Cargo.toml +36 -0
  20. tddlog-0.1.0/bindings/python/README.md +143 -0
  21. tddlog-0.1.0/bindings/python/docs/conf.py +39 -0
  22. tddlog-0.1.0/bindings/python/docs/examples.md +24 -0
  23. tddlog-0.1.0/bindings/python/docs/index.md +18 -0
  24. tddlog-0.1.0/bindings/python/docs/reference.md +22 -0
  25. tddlog-0.1.0/bindings/python/docs/requirements.txt +3 -0
  26. tddlog-0.1.0/bindings/python/examples/alarm.py +39 -0
  27. tddlog-0.1.0/bindings/python/examples/graph.py +38 -0
  28. tddlog-0.1.0/bindings/python/src/lib.rs +234 -0
  29. tddlog-0.1.0/bindings/python/tddlog.pyi +46 -0
  30. tddlog-0.1.0/bindings/python/tests/test_tddlog.py +294 -0
  31. tddlog-0.1.0/bindings/sphinx/site-theme.js +30 -0
  32. tddlog-0.1.0/bindings/sphinx/site.css +9 -0
  33. tddlog-0.1.0/docs/design.md +3094 -0
  34. tddlog-0.1.0/docs/images/overview.svg +1270 -0
  35. tddlog-0.1.0/docs/images/results-all-programs.svg +9921 -0
  36. tddlog-0.1.0/docs/images/results-bayesian-networks.svg +4116 -0
  37. tddlog-0.1.0/docs/images/results-circuits.svg +2960 -0
  38. tddlog-0.1.0/docs/images/results-database-queries.svg +2394 -0
  39. tddlog-0.1.0/docs/images/results-functional-programs.svg +2362 -0
  40. tddlog-0.1.0/docs/images/results-logic-programs.svg +1433 -0
  41. tddlog-0.1.0/docs/images/results-markov-networks.svg +2288 -0
  42. tddlog-0.1.0/docs/logo.svg +11 -0
  43. tddlog-0.1.0/docs/papers/cheng-probprog21.md +49 -0
  44. tddlog-0.1.0/docs/papers/fierens-tplp15.md +175 -0
  45. tddlog-0.1.0/docs/papers/tp-compilation.md +259 -0
  46. tddlog-0.1.0/examples/README.md +83 -0
  47. tddlog-0.1.0/examples/adder.pl +30 -0
  48. tddlog-0.1.0/examples/alarm.pl +16 -0
  49. tddlog-0.1.0/examples/alea_dice.jl +22 -0
  50. tddlog-0.1.0/examples/alea_dice.pl +124 -0
  51. tddlog-0.1.0/examples/bn_cancer.pl +18 -0
  52. tddlog-0.1.0/examples/bn_car_evidence.pl +59 -0
  53. tddlog-0.1.0/examples/bn_split.pl +34 -0
  54. tddlog-0.1.0/examples/cancer.net +55 -0
  55. tddlog-0.1.0/examples/car.inst +9 -0
  56. tddlog-0.1.0/examples/car.net +149 -0
  57. tddlog-0.1.0/examples/chain.pl +12 -0
  58. tddlog-0.1.0/examples/cover.pl +43 -0
  59. tddlog-0.1.0/examples/cycle_graph.pl +21 -0
  60. tddlog-0.1.0/examples/dice.pl +15 -0
  61. tddlog-0.1.0/examples/dice_evidence.pl +13 -0
  62. tddlog-0.1.0/examples/dice_murder.pl +13 -0
  63. tddlog-0.1.0/examples/equal_atoms.pl +24 -0
  64. tddlog-0.1.0/examples/equal_functions.pl +74 -0
  65. tddlog-0.1.0/examples/equal_gates.pl +48 -0
  66. tddlog-0.1.0/examples/gearwheels.pl +18 -0
  67. tddlog-0.1.0/examples/larger/blood_types.pl +36 -0
  68. tddlog-0.1.0/examples/larger/dice_sum.pl +18 -0
  69. tddlog-0.1.0/examples/larger/grid_reliability.pl +15 -0
  70. tddlog-0.1.0/examples/larger/mastermind.pl +53 -0
  71. tddlog-0.1.0/examples/larger/robot.pl +42 -0
  72. tddlog-0.1.0/examples/larger/stones.pl +12 -0
  73. tddlog-0.1.0/examples/linear_path.pl +20 -0
  74. tddlog-0.1.0/examples/linear_target.pl +10 -0
  75. tddlog-0.1.0/examples/negcycle_sound.pl +11 -0
  76. tddlog-0.1.0/examples/query_beside_evidence.pl +22 -0
  77. tddlog-0.1.0/examples/row_classes.pl +41 -0
  78. tddlog-0.1.0/examples/shared_rows.pl +29 -0
  79. tddlog-0.1.0/examples/smokers.pl +14 -0
  80. tddlog-0.1.0/examples/solve.rs +70 -0
  81. tddlog-0.1.0/examples/sprinkler.rs +122 -0
  82. tddlog-0.1.0/examples/tpch_q2.pl +349 -0
  83. tddlog-0.1.0/examples/unsound.pl +12 -0
  84. tddlog-0.1.0/examples/uwcse.pl +137 -0
  85. tddlog-0.1.0/examples/views.pl +52 -0
  86. tddlog-0.1.0/examples/win.pl +10 -0
  87. tddlog-0.1.0/notices/LICENSE +201 -0
  88. tddlog-0.1.0/notices/NOTICE +18 -0
  89. tddlog-0.1.0/notices/THIRD-PARTY.md +126 -0
  90. tddlog-0.1.0/pyproject.toml +41 -0
  91. tddlog-0.1.0/src/auto/mod.rs +1103 -0
  92. tddlog-0.1.0/src/auto/policy.rs +439 -0
  93. tddlog-0.1.0/src/auto/tests.rs +2232 -0
  94. tddlog-0.1.0/src/auto/trial.rs +329 -0
  95. tddlog-0.1.0/src/bin/tddlog/alloc.rs +288 -0
  96. tddlog-0.1.0/src/bin/tddlog/budget.rs +336 -0
  97. tddlog-0.1.0/src/bin/tddlog/main.rs +664 -0
  98. tddlog-0.1.0/src/bin/tddlog/stats.rs +376 -0
  99. tddlog-0.1.0/src/by_hash.rs +128 -0
  100. tddlog-0.1.0/src/cnf.rs +787 -0
  101. tddlog-0.1.0/src/cubes.rs +544 -0
  102. tddlog-0.1.0/src/disjoint.rs +39 -0
  103. tddlog-0.1.0/src/eval/conjunction.rs +556 -0
  104. tddlog-0.1.0/src/eval/count.rs +1419 -0
  105. tddlog-0.1.0/src/eval/grid.rs +2047 -0
  106. tddlog-0.1.0/src/eval/kernel.rs +831 -0
  107. tddlog-0.1.0/src/eval/mod.rs +43 -0
  108. tddlog-0.1.0/src/eval/number.rs +639 -0
  109. tddlog-0.1.0/src/eval/tests.rs +1001 -0
  110. tddlog-0.1.0/src/eval/weights.rs +192 -0
  111. tddlog-0.1.0/src/evaluation.rs +332 -0
  112. tddlog-0.1.0/src/ground/aig.rs +1118 -0
  113. tddlog-0.1.0/src/ground/chain.rs +271 -0
  114. tddlog-0.1.0/src/ground/classes.rs +745 -0
  115. tddlog-0.1.0/src/ground/condition.rs +551 -0
  116. tddlog-0.1.0/src/ground/contexts.rs +327 -0
  117. tddlog-0.1.0/src/ground/cover.rs +816 -0
  118. tddlog-0.1.0/src/ground/deps.rs +770 -0
  119. tddlog-0.1.0/src/ground/detach.rs +246 -0
  120. tddlog-0.1.0/src/ground/eliminate.rs +567 -0
  121. tddlog-0.1.0/src/ground/encoding.rs +128 -0
  122. tddlog-0.1.0/src/ground/engine/lists.rs +422 -0
  123. tddlog-0.1.0/src/ground/engine/topdown.rs +1954 -0
  124. tddlog-0.1.0/src/ground/engine.rs +4054 -0
  125. tddlog-0.1.0/src/ground/exclusive.rs +1494 -0
  126. tddlog-0.1.0/src/ground/fact_copies.rs +258 -0
  127. tddlog-0.1.0/src/ground/guards.rs +1776 -0
  128. tddlog-0.1.0/src/ground/inline.rs +458 -0
  129. tddlog-0.1.0/src/ground/interned.rs +92 -0
  130. tddlog-0.1.0/src/ground/library.rs +631 -0
  131. tddlog-0.1.0/src/ground/linear.rs +442 -0
  132. tddlog-0.1.0/src/ground/magic.rs +1282 -0
  133. tddlog-0.1.0/src/ground/mod.rs +981 -0
  134. tddlog-0.1.0/src/ground/modes.rs +253 -0
  135. tddlog-0.1.0/src/ground/negation.rs +368 -0
  136. tddlog-0.1.0/src/ground/noisy_or.rs +1163 -0
  137. tddlog-0.1.0/src/ground/normalize.rs +801 -0
  138. tddlog-0.1.0/src/ground/preprocess/backbone.rs +559 -0
  139. tddlog-0.1.0/src/ground/preprocess/defined.rs +783 -0
  140. tddlog-0.1.0/src/ground/preprocess/implied.rs +356 -0
  141. tddlog-0.1.0/src/ground/preprocess/mod.rs +93 -0
  142. tddlog-0.1.0/src/ground/preprocess/sat.rs +1208 -0
  143. tddlog-0.1.0/src/ground/preprocess/support.rs +233 -0
  144. tddlog-0.1.0/src/ground/program.rs +725 -0
  145. tddlog-0.1.0/src/ground/propagation.rs +1201 -0
  146. tddlog-0.1.0/src/ground/relevant.rs +126 -0
  147. tddlog-0.1.0/src/ground/renormalize.rs +711 -0
  148. tddlog-0.1.0/src/ground/schedule.rs +494 -0
  149. tddlog-0.1.0/src/ground/shape.rs +281 -0
  150. tddlog-0.1.0/src/ground/share.rs +324 -0
  151. tddlog-0.1.0/src/ground/simplify.rs +827 -0
  152. tddlog-0.1.0/src/ground/steps.rs +304 -0
  153. tddlog-0.1.0/src/ground/structure.rs +133 -0
  154. tddlog-0.1.0/src/ground/table.rs +683 -0
  155. tddlog-0.1.0/src/ground/tables.rs +205 -0
  156. tddlog-0.1.0/src/ground/terms.rs +1053 -0
  157. tddlog-0.1.0/src/ground/unread.rs +176 -0
  158. tddlog-0.1.0/src/ground/values.rs +1836 -0
  159. tddlog-0.1.0/src/indicators/mod.rs +1557 -0
  160. tddlog-0.1.0/src/indicators/splits.rs +759 -0
  161. tddlog-0.1.0/src/indicators/tables.rs +778 -0
  162. tddlog-0.1.0/src/indicators/tests.rs +106 -0
  163. tddlog-0.1.0/src/input.rs +277 -0
  164. tddlog-0.1.0/src/lib.rs +238 -0
  165. tddlog-0.1.0/src/multisets.rs +133 -0
  166. tddlog-0.1.0/src/network/bif.rs +178 -0
  167. tddlog-0.1.0/src/network/hugin.rs +163 -0
  168. tddlog-0.1.0/src/network/mod.rs +700 -0
  169. tddlog-0.1.0/src/network/rows.rs +537 -0
  170. tddlog-0.1.0/src/network/scan.rs +170 -0
  171. tddlog-0.1.0/src/network/uai.rs +642 -0
  172. tddlog-0.1.0/src/network/xdsl.rs +121 -0
  173. tddlog-0.1.0/src/network/xml.rs +287 -0
  174. tddlog-0.1.0/src/query/mod.rs +1875 -0
  175. tddlog-0.1.0/src/query/sum_out.rs +651 -0
  176. tddlog-0.1.0/src/query/walk.rs +1860 -0
  177. tddlog-0.1.0/src/solve/mod.rs +475 -0
  178. tddlog-0.1.0/src/solve/split.rs +365 -0
  179. tddlog-0.1.0/src/solve/subquery.rs +377 -0
  180. tddlog-0.1.0/src/solve/tests.rs +389 -0
  181. tddlog-0.1.0/src/strategy.rs +251 -0
  182. tddlog-0.1.0/src/syntax/arguments.rs +169 -0
  183. tddlog-0.1.0/src/syntax/circulette.rs +1533 -0
  184. tddlog-0.1.0/src/syntax/dice/mod.rs +188 -0
  185. tddlog-0.1.0/src/syntax/dice/syntax.rs +603 -0
  186. tddlog-0.1.0/src/syntax/dice/tests.rs +315 -0
  187. tddlog-0.1.0/src/syntax/dice/tokens.rs +132 -0
  188. tddlog-0.1.0/src/syntax/dice/translate.rs +1770 -0
  189. tddlog-0.1.0/src/syntax/dice/values.rs +317 -0
  190. tddlog-0.1.0/src/syntax/lexer.rs +1241 -0
  191. tddlog-0.1.0/src/syntax/lpad.rs +1760 -0
  192. tddlog-0.1.0/src/syntax/mod.rs +1746 -0
  193. tddlog-0.1.0/src/syntax/parser.rs +1806 -0
  194. tddlog-0.1.0/src/tp/aft.rs +166 -0
  195. tddlog-0.1.0/src/tp/backend.rs +2225 -0
  196. tddlog-0.1.0/src/tp/clauses.rs +1143 -0
  197. tddlog-0.1.0/src/tp/compile.rs +2271 -0
  198. tddlog-0.1.0/src/tp/cone.rs +405 -0
  199. tddlog-0.1.0/src/tp/factoring.rs +980 -0
  200. tddlog-0.1.0/src/tp/mod.rs +242 -0
  201. tddlog-0.1.0/src/tp/none_of.rs +2141 -0
  202. tddlog-0.1.0/src/tp/projector.rs +243 -0
  203. tddlog-0.1.0/src/tp/rows.rs +601 -0
  204. tddlog-0.1.0/src/tp/scope.rs +213 -0
  205. tddlog-0.1.0/src/tp/settle.rs +966 -0
  206. tddlog-0.1.0/src/tp/stats.rs +276 -0
  207. tddlog-0.1.0/src/tp/template.rs +247 -0
  208. tddlog-0.1.0/src/tp/tests/clause_memo.rs +381 -0
  209. tddlog-0.1.0/src/tp/tests/dying.rs +245 -0
  210. tddlog-0.1.0/src/tp/tests/dynamic.rs +82 -0
  211. tddlog-0.1.0/src/tp/tests/primal_update.rs +149 -0
  212. tddlog-0.1.0/src/tp/tests/projection.rs +298 -0
  213. tddlog-0.1.0/src/tp/tests/resume.rs +467 -0
  214. tddlog-0.1.0/src/tp/tie.rs +219 -0
  215. tddlog-0.1.0/src/tp/trace.rs +159 -0
  216. tddlog-0.1.0/src/trace.rs +635 -0
  217. tddlog-0.1.0/src/vtree/closed.rs +376 -0
  218. tddlog-0.1.0/src/vtree/cost.rs +354 -0
  219. tddlog-0.1.0/src/vtree/decision.rs +700 -0
  220. tddlog-0.1.0/src/vtree/families.rs +2137 -0
  221. tddlog-0.1.0/src/vtree/forest.rs +185 -0
  222. tddlog-0.1.0/src/vtree/graph.rs +1533 -0
  223. tddlog-0.1.0/src/vtree/mod.rs +711 -0
  224. tddlog-0.1.0/src/vtree/naming.rs +1016 -0
  225. tddlog-0.1.0/src/vtree/nest.rs +746 -0
  226. tddlog-0.1.0/src/vtree/order.rs +893 -0
  227. tddlog-0.1.0/src/vtree/separators.rs +635 -0
  228. tddlog-0.1.0/src/vtree/td.rs +725 -0
  229. tddlog-0.1.0/src/vtree/tests/copies.rs +228 -0
  230. tddlog-0.1.0/tests/alea/tiny_expectation.jl +15 -0
  231. tddlog-0.1.0/tests/alea/tiny_expectation.pl +34 -0
  232. tddlog-0.1.0/tests/alea/tiny_pr.jl +15 -0
  233. tddlog-0.1.0/tests/alea/tiny_pr.pl +37 -0
  234. tddlog-0.1.0/tests/circulette/adder2.cql +25 -0
  235. tddlog-0.1.0/tests/circulette/counter.cql +27 -0
  236. tddlog-0.1.0/tests/circulette/voter.cql +17 -0
  237. tddlog-0.1.0/tests/compare.py +80 -0
  238. tddlog-0.1.0/tests/dice/arith.dice +10 -0
  239. tddlog-0.1.0/tests/dice/arith.pl +61 -0
  240. tddlog-0.1.0/tests/dice/caesar-recur.dice +17 -0
  241. tddlog-0.1.0/tests/dice/caesar-recur.pl +70 -0
  242. tddlog-0.1.0/tests/dice/compare.dice +8 -0
  243. tddlog-0.1.0/tests/dice/compare.pl +93 -0
  244. tddlog-0.1.0/tests/dice/counter.dice +11 -0
  245. tddlog-0.1.0/tests/dice/counter.pl +44 -0
  246. tddlog-0.1.0/tests/dice/diamond.dice +10 -0
  247. tddlog-0.1.0/tests/dice/diamond.pl +14 -0
  248. tddlog-0.1.0/tests/dice/geometric.dice +6 -0
  249. tddlog-0.1.0/tests/dice/geometric.pl +94 -0
  250. tddlog-0.1.0/tests/dice/ladder.dice +13 -0
  251. tddlog-0.1.0/tests/dice/ladder.pl +21 -0
  252. tddlog-0.1.0/tests/dice/loops.json +27 -0
  253. tddlog-0.1.0/tests/dice/nested.dice +8 -0
  254. tddlog-0.1.0/tests/dice/nested.pl +37 -0
  255. tddlog-0.1.0/tests/dice/recursion.dice +9 -0
  256. tddlog-0.1.0/tests/dice/recursion.pl +6 -0
  257. tddlog-0.1.0/tests/dice/steps.dice +9 -0
  258. tddlog-0.1.0/tests/dice/steps.pl +54 -0
  259. tddlog-0.1.0/tests/dice/walk.dice +8 -0
  260. tddlog-0.1.0/tests/dice/walk.pl +54 -0
  261. tddlog-0.1.0/tests/fuzz_problog.py +709 -0
  262. tddlog-0.1.0/tests/it/ad_tails.rs +350 -0
  263. tddlog-0.1.0/tests/it/binary.rs +575 -0
  264. tddlog-0.1.0/tests/it/binary_parent.rs +188 -0
  265. tddlog-0.1.0/tests/it/circulette.rs +233 -0
  266. tddlog-0.1.0/tests/it/class_spines.rs +221 -0
  267. tddlog-0.1.0/tests/it/cli.rs +566 -0
  268. tddlog-0.1.0/tests/it/cnf.rs +463 -0
  269. tddlog-0.1.0/tests/it/common/mod.rs +137 -0
  270. tddlog-0.1.0/tests/it/contexts.rs +142 -0
  271. tddlog-0.1.0/tests/it/dense_count.rs +154 -0
  272. tddlog-0.1.0/tests/it/evidence_probability.rs +906 -0
  273. tddlog-0.1.0/tests/it/evidence_walk.rs +243 -0
  274. tddlog-0.1.0/tests/it/examples.rs +2622 -0
  275. tddlog-0.1.0/tests/it/flexible.rs +140 -0
  276. tddlog-0.1.0/tests/it/front_pages.rs +64 -0
  277. tddlog-0.1.0/tests/it/guards.rs +1106 -0
  278. tddlog-0.1.0/tests/it/implicit_levels.rs +207 -0
  279. tddlog-0.1.0/tests/it/indicators.rs +530 -0
  280. tddlog-0.1.0/tests/it/input.rs +318 -0
  281. tddlog-0.1.0/tests/it/layouts/block.rs +113 -0
  282. tddlog-0.1.0/tests/it/layouts/flat.rs +106 -0
  283. tddlog-0.1.0/tests/it/layouts/grid.rs +119 -0
  284. tddlog-0.1.0/tests/it/layouts/hub.rs +66 -0
  285. tddlog-0.1.0/tests/it/layouts/mod.rs +8 -0
  286. tddlog-0.1.0/tests/it/layouts/split.rs +498 -0
  287. tddlog-0.1.0/tests/it/link_reuse.rs +74 -0
  288. tddlog-0.1.0/tests/it/long_bodies.rs +102 -0
  289. tddlog-0.1.0/tests/it/main.rs +53 -0
  290. tddlog-0.1.0/tests/it/naming.rs +945 -0
  291. tddlog-0.1.0/tests/it/narrowed.rs +128 -0
  292. tddlog-0.1.0/tests/it/negations.rs +250 -0
  293. tddlog-0.1.0/tests/it/networks.rs +649 -0
  294. tddlog-0.1.0/tests/it/observed_query.rs +251 -0
  295. tddlog-0.1.0/tests/it/or_route.rs +92 -0
  296. tddlog-0.1.0/tests/it/out_of_memory.rs +123 -0
  297. tddlog-0.1.0/tests/it/problog_suite.rs +253 -0
  298. tddlog-0.1.0/tests/it/query_count.rs +175 -0
  299. tddlog-0.1.0/tests/it/query_rules.rs +54 -0
  300. tddlog-0.1.0/tests/it/renormalize.rs +333 -0
  301. tddlog-0.1.0/tests/it/separator_copies.rs +277 -0
  302. tddlog-0.1.0/tests/it/share.rs +216 -0
  303. tddlog-0.1.0/tests/it/shared_operand.rs +128 -0
  304. tddlog-0.1.0/tests/it/subquery.rs +120 -0
  305. tddlog-0.1.0/tests/it/table_models.rs +87 -0
  306. tddlog-0.1.0/tests/it/templates.rs +107 -0
  307. tddlog-0.1.0/tests/it/terms.rs +889 -0
  308. tddlog-0.1.0/tests/it/ties.rs +176 -0
  309. tddlog-0.1.0/tests/it/topdown.rs +321 -0
  310. tddlog-0.1.0/tests/it/trace.rs +691 -0
  311. tddlog-0.1.0/tests/it/undefined.rs +180 -0
  312. tddlog-0.1.0/tests/it/underflow.rs +522 -0
  313. tddlog-0.1.0/tests/it/writings.rs +1325 -0
  314. tddlog-0.1.0/tests/lit/biomine.pl +26 -0
  315. tddlog-0.1.0/tests/lit/biomine3.pl +23 -0
  316. tddlog-0.1.0/tests/lit/biomine_toy.bmg +22 -0
  317. tddlog-0.1.0/tests/lit/mastermind.pl +44 -0
  318. tddlog-0.1.0/tests/lit/mnist_sum.pl +26 -0
  319. tddlog-0.1.0/tests/lit/noisyor.pl +55 -0
  320. tddlog-0.1.0/tests/lit/pdb.pl +24 -0
  321. tddlog-0.1.0/tests/lit/pedigree.pl +59 -0
  322. tddlog-0.1.0/tests/lit/sickness.pl +32 -0
  323. tddlog-0.1.0/tests/lit/tpch.pl +3476 -0
  324. tddlog-0.1.0/tests/lit/tpch_views.pl +3501 -0
  325. tddlog-0.1.0/tests/lit/wcnf.pl +14 -0
  326. tddlog-0.1.0/tests/lit/wcnf_factors_bn.pl +18 -0
  327. tddlog-0.1.0/tests/lit/wcnf_factors_mn.pl +22 -0
  328. tddlog-0.1.0/tests/lpad/coin.cplint.pl +25 -0
  329. tddlog-0.1.0/tests/lpad/coin.pl +9 -0
  330. tddlog-0.1.0/tests/lpad/database.cplint.pl +39 -0
  331. tddlog-0.1.0/tests/lpad/database.pl +13 -0
  332. tddlog-0.1.0/tests/lpad/depth_bound.cplint.pl +28 -0
  333. tddlog-0.1.0/tests/lpad/msw.cplint.pl +39 -0
  334. tddlog-0.1.0/tests/lpad/msw_memo.cplint.pl +33 -0
  335. tddlog-0.1.0/tests/networks/as_written.uai +23 -0
  336. tddlog-0.1.0/tests/networks/as_written.uai.evid +1 -0
  337. tddlog-0.1.0/tests/networks/as_written_markov.uai +23 -0
  338. tddlog-0.1.0/tests/networks/asia.net +88 -0
  339. tddlog-0.1.0/tests/networks/asia_leaves.inst +6 -0
  340. tddlog-0.1.0/tests/networks/bn_asia_evidence.pl +36 -0
  341. tddlog-0.1.0/tests/networks/chain.pl +22 -0
  342. tddlog-0.1.0/tests/networks/chain.uai +16 -0
  343. tddlog-0.1.0/tests/networks/local_structure.uai +24 -0
  344. tddlog-0.1.0/tests/networks/local_structure.uai.evid +1 -0
  345. tddlog-0.1.0/tests/networks/local_structure_bayes.uai +19 -0
  346. tddlog-0.1.0/tests/networks/local_structure_bayes.uai.evid +1 -0
  347. tddlog-0.1.0/tests/networks/local_structure_wide.uai +10 -0
  348. tddlog-0.1.0/tests/networks/local_structure_wide.uai.evid +1 -0
  349. tddlog-0.1.0/tests/networks/noisy.pl +16 -0
  350. tddlog-0.1.0/tests/networks/noisy.xdsl +28 -0
  351. tddlog-0.1.0/tests/networks/percent.hugin +37 -0
  352. tddlog-0.1.0/tests/networks/percent.pl +11 -0
  353. tddlog-0.1.0/tests/networks/restored_scope.uai +36 -0
  354. tddlog-0.1.0/tests/networks/rounded.uai +12 -0
  355. tddlog-0.1.0/tests/networks/single.uai +12 -0
  356. tddlog-0.1.0/tests/networks/sprinkler.bif +34 -0
  357. tddlog-0.1.0/tests/networks/sprinkler.inst +4 -0
  358. tddlog-0.1.0/tests/networks/sprinkler.xdsl +33 -0
  359. tddlog-0.1.0/tests/networks/sprinkler_bif.pl +13 -0
  360. tddlog-0.1.0/tests/networks/sprinkler_xdsl.pl +14 -0
  361. tddlog-0.1.0/tests/problog/00_nested_conjunction.pl +24 -0
  362. tddlog-0.1.0/tests/problog/00_trivial_and.pl +17 -0
  363. tddlog-0.1.0/tests/problog/00_trivial_duplicate.pl +11 -0
  364. tddlog-0.1.0/tests/problog/00_trivial_fact.pl +9 -0
  365. tddlog-0.1.0/tests/problog/00_trivial_fail.pl +6 -0
  366. tddlog-0.1.0/tests/problog/00_trivial_not.pl +8 -0
  367. tddlog-0.1.0/tests/problog/00_trivial_not_and.pl +10 -0
  368. tddlog-0.1.0/tests/problog/00_trivial_or.pl +18 -0
  369. tddlog-0.1.0/tests/problog/00_trivial_true.pl +6 -0
  370. tddlog-0.1.0/tests/problog/00_trivial_undefined2_failed.pl +8 -0
  371. tddlog-0.1.0/tests/problog/00_trivial_undefined_failed.pl +6 -0
  372. tddlog-0.1.0/tests/problog/01_logic_implicit_equal.pl +7 -0
  373. tddlog-0.1.0/tests/problog/10_cards.pl +24 -0
  374. tddlog-0.1.0/tests/problog/11_ads_numerical.pl +17 -0
  375. tddlog-0.1.0/tests/problog/3_tossing_coin.pl +18 -0
  376. tddlog-0.1.0/tests/problog/4_1_bayesian_net.pl +23 -0
  377. tddlog-0.1.0/tests/problog/4_bayesian_net.pl +25 -0
  378. tddlog-0.1.0/tests/problog/5_bayesian_net.pl +30 -0
  379. tddlog-0.1.0/tests/problog/7_probabilistic_graph.pl +23 -0
  380. tddlog-0.1.0/tests/problog/8_smokers_network.pl +62 -0
  381. tddlog-0.1.0/tests/problog/README.md +3 -0
  382. tddlog-0.1.0/tests/problog/ad_fact.pl +7 -0
  383. tddlog-0.1.0/tests/problog/add.pl +20 -0
  384. tddlog-0.1.0/tests/problog/advars.pl +20 -0
  385. tddlog-0.1.0/tests/problog/advars_smokers.pl +56 -0
  386. tddlog-0.1.0/tests/problog/advars_smokers_alt.pl +55 -0
  387. tddlog-0.1.0/tests/problog/aggregate_builtins.pl +45 -0
  388. tddlog-0.1.0/tests/problog/aggregate_builtins_scoped.pl +45 -0
  389. tddlog-0.1.0/tests/problog/aggregate_custom.pl +88 -0
  390. tddlog-0.1.0/tests/problog/aggregate_satisfy.pl +46 -0
  391. tddlog-0.1.0/tests/problog/basic_scope_use.pl +15 -0
  392. tddlog-0.1.0/tests/problog/bug_keep_order.pl +63 -0
  393. tddlog-0.1.0/tests/problog/call_return_fail.pl +8 -0
  394. tddlog-0.1.0/tests/problog/clause2_basic_tests.pl +21 -0
  395. tddlog-0.1.0/tests/problog/coin.pl +14 -0
  396. tddlog-0.1.0/tests/problog/consult.pl +9 -0
  397. tddlog-0.1.0/tests/problog/consult_nested.pl +11 -0
  398. tddlog-0.1.0/tests/problog/evidence_bug.pl +18 -0
  399. tddlog-0.1.0/tests/problog/evidence_bug_alt.pl +18 -0
  400. tddlog-0.1.0/tests/problog/findall.pl +19 -0
  401. tddlog-0.1.0/tests/problog/findall1.pl +28 -0
  402. tddlog-0.1.0/tests/problog/findall2.pl +31 -0
  403. tddlog-0.1.0/tests/problog/findall3.pl +29 -0
  404. tddlog-0.1.0/tests/problog/findall6.pl +14 -0
  405. tddlog-0.1.0/tests/problog/findall_check.pl +9 -0
  406. tddlog-0.1.0/tests/problog/findall_duplicates.pl +38 -0
  407. tddlog-0.1.0/tests/problog/findall_nested.pl +6 -0
  408. tddlog-0.1.0/tests/problog/findall_with_anonymous.pl +10 -0
  409. tddlog-0.1.0/tests/problog/forall.pl +17 -0
  410. tddlog-0.1.0/tests/problog/generated.pl +251 -0
  411. tddlog-0.1.0/tests/problog/negation.pl +25 -0
  412. tddlog-0.1.0/tests/problog/negative_head_lits.pl +24 -0
  413. tddlog-0.1.0/tests/problog/negative_query.pl +6 -0
  414. tddlog-0.1.0/tests/problog/non_ground_query.pl +19 -0
  415. tddlog-0.1.0/tests/problog/query_same.pl +13 -0
  416. tddlog-0.1.0/tests/problog/same_var.pl +8 -0
  417. tddlog-0.1.0/tests/problog/scope_variable_manipulations.pl +16 -0
  418. tddlog-0.1.0/tests/problog/smokers_or.pl +45 -0
  419. tddlog-0.1.0/tests/problog/some_cycles.pl +27 -0
  420. tddlog-0.1.0/tests/problog/tc_1.pl +12 -0
  421. tddlog-0.1.0/tests/problog/tc_2.pl +10 -0
  422. tddlog-0.1.0/tests/problog/tc_3.pl +17 -0
  423. tddlog-0.1.0/tests/problog_suite.py +154 -0
  424. tddlog-0.1.0/tests/regress/aggregate_worlds.pl +36 -0
  425. tddlog-0.1.0/tests/regress/alias_evidence.pl +10 -0
  426. tddlog-0.1.0/tests/regress/alias_evidence_inconsistent.pl +8 -0
  427. tddlog-0.1.0/tests/regress/alias_query.pl +8 -0
  428. tddlog-0.1.0/tests/regress/alias_undirected.pl +13 -0
  429. tddlog-0.1.0/tests/regress/alias_undirected_ev.pl +12 -0
  430. tddlog-0.1.0/tests/regress/backbone_clauses.pl +24 -0
  431. tddlog-0.1.0/tests/regress/bound_end_chain.pl +21 -0
  432. tddlog-0.1.0/tests/regress/bound_end_demand.pl +17 -0
  433. tddlog-0.1.0/tests/regress/certain_closure.pl +31 -0
  434. tddlog-0.1.0/tests/regress/chain_mixed.pl +27 -0
  435. tddlog-0.1.0/tests/regress/chain_source.pl +16 -0
  436. tddlog-0.1.0/tests/regress/chain_target.pl +16 -0
  437. tddlog-0.1.0/tests/regress/coin_bias_mux.pl +128 -0
  438. tddlog-0.1.0/tests/regress/condition_bn.pl +26 -0
  439. tddlog-0.1.0/tests/regress/condition_copies.pl +23 -0
  440. tddlog-0.1.0/tests/regress/condition_copies_units.pl +22 -0
  441. tddlog-0.1.0/tests/regress/condition_cyclic.pl +17 -0
  442. tddlog-0.1.0/tests/regress/condition_equal.pl +23 -0
  443. tddlog-0.1.0/tests/regress/condition_inconsistent.pl +8 -0
  444. tddlog-0.1.0/tests/regress/condition_settled.pl +23 -0
  445. tddlog-0.1.0/tests/regress/condition_shared.pl +15 -0
  446. tddlog-0.1.0/tests/regress/decision_bits_read_alone.pl +105 -0
  447. tddlog-0.1.0/tests/regress/defined_facts.pl +38 -0
  448. tddlog-0.1.0/tests/regress/delta_first.pl +21 -0
  449. tddlog-0.1.0/tests/regress/delta_own_order.pl +27 -0
  450. tddlog-0.1.0/tests/regress/demand_after_guard.pl +20 -0
  451. tddlog-0.1.0/tests/regress/demand_test_on_guard.pl +42 -0
  452. tddlog-0.1.0/tests/regress/detach.pl +21 -0
  453. tddlog-0.1.0/tests/regress/detach_inconsistent.pl +17 -0
  454. tddlog-0.1.0/tests/regress/detach_no_query.pl +7 -0
  455. tddlog-0.1.0/tests/regress/facts_evidence.pl +20 -0
  456. tddlog-0.1.0/tests/regress/facts_twice.pl +27 -0
  457. tddlog-0.1.0/tests/regress/facts_unread.pl +21 -0
  458. tddlog-0.1.0/tests/regress/facts_unread_ground.pl +23 -0
  459. tddlog-0.1.0/tests/regress/false_observation.pl +9 -0
  460. tddlog-0.1.0/tests/regress/findall_demand_loop.pl +21 -0
  461. tddlog-0.1.0/tests/regress/gate_and_read.pl +19 -0
  462. tddlog-0.1.0/tests/regress/gate_backbone.pl +26 -0
  463. tddlog-0.1.0/tests/regress/gate_cyclic.pl +26 -0
  464. tddlog-0.1.0/tests/regress/gate_nested.pl +29 -0
  465. tddlog-0.1.0/tests/regress/gate_nested_unread.pl +24 -0
  466. tddlog-0.1.0/tests/regress/gate_not_half.pl +18 -0
  467. tddlog-0.1.0/tests/regress/gate_or_unread.pl +19 -0
  468. tddlog-0.1.0/tests/regress/gate_read_by_clause.pl +21 -0
  469. tddlog-0.1.0/tests/regress/growing_head.pl +21 -0
  470. tddlog-0.1.0/tests/regress/growing_negation.pl +52 -0
  471. tddlog-0.1.0/tests/regress/implied_clause.pl +20 -0
  472. tddlog-0.1.0/tests/regress/keyed.pl +30 -0
  473. tddlog-0.1.0/tests/regress/levels.pl +38 -0
  474. tddlog-0.1.0/tests/regress/levels_count.pl +37 -0
  475. tddlog-0.1.0/tests/regress/levels_successor.pl +32 -0
  476. tddlog-0.1.0/tests/regress/magic_bearing.pl +19 -0
  477. tddlog-0.1.0/tests/regress/magic_facts_read.pl +15 -0
  478. tddlog-0.1.0/tests/regress/magic_negation_given.pl +19 -0
  479. tddlog-0.1.0/tests/regress/magic_switch_after_recursion.pl +25 -0
  480. tddlog-0.1.0/tests/regress/markov.pl +30 -0
  481. tddlog-0.1.0/tests/regress/markov.uai +16 -0
  482. tddlog-0.1.0/tests/regress/markov.uai.evid +1 -0
  483. tddlog-0.1.0/tests/regress/markov_ev.pl +24 -0
  484. tddlog-0.1.0/tests/regress/markov_pr.pl +50 -0
  485. tddlog-0.1.0/tests/regress/markov_pr.uai +29 -0
  486. tddlog-0.1.0/tests/regress/markov_pr.uai.evid +1 -0
  487. tddlog-0.1.0/tests/regress/markov_pr_ev.pl +51 -0
  488. tddlog-0.1.0/tests/regress/mastermind3_4_3.pl +66 -0
  489. tddlog-0.1.0/tests/regress/memberchk_free_element.pl +17 -0
  490. tddlog-0.1.0/tests/regress/negation_bounds_walk.pl +40 -0
  491. tddlog-0.1.0/tests/regress/negation_in_demand_cycle.pl +40 -0
  492. tddlog-0.1.0/tests/regress/noisy_or_chain.pl +44 -0
  493. tddlog-0.1.0/tests/regress/noisy_or_shared.pl +83 -0
  494. tddlog-0.1.0/tests/regress/noisyor15_22.pl +144 -0
  495. tddlog-0.1.0/tests/regress/noisyor20_30.pl +194 -0
  496. tddlog-0.1.0/tests/regress/pdb40.pl +169 -0
  497. tddlog-0.1.0/tests/regress/potts.pl +71 -0
  498. tddlog-0.1.0/tests/regress/potts.uai +28 -0
  499. tddlog-0.1.0/tests/regress/potts.uai.evid +1 -0
  500. tddlog-0.1.0/tests/regress/schedule_join_first.pl +26 -0
  501. tddlog-0.1.0/tests/regress/step_chain_carried.pl +26 -0
  502. tddlog-0.1.0/tests/regress/terms_findall_sum.pl +46 -0
  503. tddlog-0.1.0/tests/regress/terms_hmm_list.pl +22 -0
  504. tddlog-0.1.0/tests/regress/terms_hmm_list_evidence.pl +24 -0
  505. tddlog-0.1.0/tests/regress/terms_lists_prob.pl +45 -0
  506. tddlog-0.1.0/tests/regress/terms_pcfg_list.pl +34 -0
  507. tddlog-0.1.0/tests/regress/terms_pcfg_list_evidence.pl +29 -0
  508. tddlog-0.1.0/tests/regress/terms_side_channel.pl +39 -0
  509. tddlog-0.1.0/tests/regress/test_at_call.pl +21 -0
  510. tddlog-0.1.0/tests/regress/topdown_cycle_completion.pl +34 -0
  511. tddlog-0.1.0/tests/regress/topdown_grammar.pl +30 -0
  512. tddlog-0.1.0/tests/regress/topdown_hmm.pl +32 -0
  513. tddlog-0.1.0/tests/regress/univ.pl +22 -0
  514. tddlog-0.1.0/tests/regress/unread_argument.pl +16 -0
  515. tddlog-0.1.0/tests/roulette/caesar-1.pl +284 -0
  516. tddlog-0.1.0/tests/roulette/caesar-2.pl +413 -0
  517. tddlog-0.1.0/tests/roulette/diamond-3.pl +16 -0
  518. tddlog-0.1.0/tests/roulette/hardware-5.pl +140 -0
  519. tddlog-0.1.0/tests/roulette/hardware-bitwidth-5.pl +50 -0
  520. tddlog-0.1.0/tests/roulette/hmm-filtering-joint-3.pl +35 -0
  521. tddlog-0.1.0/tests/roulette/hmm-filtering-marginal-3.pl +33 -0
  522. tddlog-0.1.0/tests/roulette/hmm-marginal-likelihood-3.pl +32 -0
  523. tddlog-0.1.0/tests/roulette/hmm-smoothing-joint-4.pl +43 -0
  524. tddlog-0.1.0/tests/roulette/hmm-smoothing-marginal-4.pl +42 -0
  525. tddlog-0.1.0/tests/roulette/ladder-3.pl +24 -0
  526. tddlog-0.1.0/tests/roulette/lib/diagnosis.pl +33 -0
  527. tddlog-0.1.0/tests/roulette/lib/diagnosis.rkt +30 -0
  528. tddlog-0.1.0/tests/roulette/lib/disrupt.pl +28 -0
  529. tddlog-0.1.0/tests/roulette/lib/disrupt.rkt +26 -0
  530. tddlog-0.1.0/tests/roulette/lib/tiny.pl +35 -0
  531. tddlog-0.1.0/tests/roulette/lib/tiny.rkt +31 -0
  532. tddlog-0.1.0/tests/roulette/motivating-3.pl +16 -0
  533. tddlog-0.1.0/tests/roulette/network-2.pl +65 -0
  534. tddlog-0.1.0/tests/roulette/tiny_path.pl +17 -0
  535. tddlog-0.1.0/tests/roulette/tiny_path.rkt +14 -0
  536. tddlog-0.1.0/tests/roulette/tiny_pr.pl +50 -0
  537. tddlog-0.1.0/tests/roulette/tiny_pr.rkt +20 -0
  538. tddlog-0.1.0/tests/test_release.py +55 -0
@@ -0,0 +1,80 @@
1
+ # Contributing
2
+
3
+ ## Checks
4
+
5
+ ```sh
6
+ cargo fmt --check
7
+ cargo test --profile quick
8
+ cargo clippy --all-targets -- -D warnings
9
+ RUSTDOCFLAGS="-D warnings" cargo doc --no-deps
10
+ python3 -m unittest discover -s tests -p 'test_*.py'
11
+ python3 .github/scripts/check_release.py
12
+ ```
13
+
14
+ `cargo test` runs `tests/it/`, the differential tests against ProbLog's
15
+ answers and exact sums, and the crate's doctests. `--profile quick`
16
+ builds without link-time optimization and gives release's answers, as CI
17
+ runs it; a plain `cargo test` builds without optimization and takes about
18
+ an hour. CI also checks that Rust 1.88 builds the crate. The
19
+ Python tests check the scripts and need numpy; `check_release.py` checks
20
+ that the crate and the bindings declare one version.
21
+
22
+ ## Every answer is checkable
23
+
24
+ Every probability tddlog prints must be checkable against ProbLog. A change
25
+ that adds a construct, a rewrite or a vtree strategy lands with a test in
26
+ `tests/it/` against ProbLog's answer (ProbLog 2.3.0, `-k sdd`, one query at
27
+ a time) or against a sum worked out by hand. `tests/compare.py` runs a
28
+ program through tddlog and ProbLog and diffs the probabilities, and
29
+ `tests/fuzz_problog.py` does it for random programs in the supported
30
+ fragment; both need ProbLog (`pip install problog`).
31
+
32
+ An option that does not apply to a program, or a combination that asks for
33
+ nothing, is an error: tddlog never ignores an option silently. The library
34
+ is single-threaded; the caller decides on parallelism.
35
+
36
+ ## Examples and the guide
37
+
38
+ `examples/*.pl` are small programs with known answers, and
39
+ `tests/it/examples.rs` checks each under several strategies. The programs
40
+ the playground offers are listed in `bindings/wasm/examples.js` with
41
+ ProbLog's answers to 12 significant digits and P(e), which
42
+ `bindings/wasm/tests/examples.cjs` checks the built module against. The
43
+ guide (`bindings/wasm/guide/index.html`) quotes the programs and outputs of
44
+ the examples it walks through; a change to one of them changes the guide
45
+ too.
46
+
47
+ ## Bindings and the site
48
+
49
+ - Python: `bindings/python/README.md` builds the extension with maturin;
50
+ `pytest bindings/python/tests` tests it.
51
+ - C: `python bindings/c/check.py` checks the committed header against
52
+ cbindgen's, builds and tests the library with CMake, and builds the
53
+ example against the installed package; after a change to
54
+ `bindings/c/src/lib.rs`, `python bindings/c/check.py --write-header`
55
+ regenerates the header.
56
+ - WebAssembly and the site: `bindings/wasm/README.md` builds the module and
57
+ the site and runs its tests, the last in a headless Chromium.
58
+
59
+ Each binding is a crate of its own, which CI formats with `cargo fmt
60
+ --check` and lints with `cargo clippy -- -D warnings`.
61
+
62
+ ## Documentation
63
+
64
+ `docs/design.md` describes the code as it is, and changes with it. The
65
+ README's results, `docs/benchmarks.md` (on the baselines branch) and the results page's data
66
+ (`bindings/wasm/results/*.json`) are generated from the records of a
67
+ release run, and are not edited by hand. Documentation and commit messages
68
+ are plain prose: technical facts, without flourish.
69
+
70
+ ## Releasing
71
+
72
+ A release sets one version in `Cargo.toml`, the three bindings'
73
+ `Cargo.toml` and `CITATION.cff`, and
74
+ `python3 .github/scripts/check_release.py --release-tag v<version>`
75
+ checks them before the tag is made. Publishing a GitHub release of that
76
+ tag builds and tests the wheels and uploads them to PyPI through trusted
77
+ publishing (`wheels.yml`), and attaches the C archives and their
78
+ checksums to the release (`c-bindings.yml`). Neither replaces what it
79
+ published: a PyPI version can be yanked but not uploaded again, and an
80
+ attached archive stays as it is.
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env python3
2
+ """Check that the crate, its bindings and the release metadata declare one
3
+ version, and that a release tag, where given, names it.
4
+
5
+ python3 .github/scripts/check_release.py [--release-tag vX.Y.Z]
6
+
7
+ A tag whose version had not been bumped would build wheels labelled with
8
+ the previous release and publish them to PyPI, where a version can be
9
+ yanked but never replaced.
10
+ """
11
+
12
+ import argparse
13
+ from pathlib import Path
14
+ import re
15
+
16
+ # The crate and its three bindings, each a package of its own.
17
+ MANIFESTS = ("Cargo.toml", "bindings/python/Cargo.toml", "bindings/c/Cargo.toml",
18
+ "bindings/wasm/Cargo.toml")
19
+
20
+
21
+ def one(text, pattern, source):
22
+ matches = re.findall(pattern, text, re.M)
23
+ if len(matches) != 1:
24
+ raise ValueError(f"{source}: expected one version declaration, found {len(matches)}")
25
+ return matches[0]
26
+
27
+
28
+ def check(root, tag=""):
29
+ """The version every file declares; ValueError where one differs."""
30
+ read = lambda relative: (root / relative).read_text(encoding="utf-8")
31
+ version = one(read("Cargo.toml"), r'^version = "([^"]+)"$', "Cargo.toml")
32
+ if tag and tag != f"v{version}":
33
+ raise ValueError(f"release tag {tag} differs from v{version}")
34
+ for relative in MANIFESTS[1:]:
35
+ found = one(read(relative), r'^version = "([^"]+)"$', relative)
36
+ if found != version:
37
+ raise ValueError(f"{relative}: version {found}, expected {version}")
38
+ locked = [one(package, r'^version = "([^"]+)"$', "Cargo.lock")
39
+ for package in read("Cargo.lock").split("[[package]]")[1:]
40
+ if re.search(r'^name = "tddlog"$', package, re.M)]
41
+ if locked != [version]:
42
+ raise ValueError(f"Cargo.lock: tddlog is {', '.join(locked) or 'missing'}, expected {version}")
43
+ citation = one(read("CITATION.cff"), r'^version:\s*["\']?([^"\'\s]+)["\']?\s*$', "CITATION.cff")
44
+ if citation != version:
45
+ raise ValueError(f"CITATION.cff: version {citation}, expected {version}")
46
+ # The README's BibTeX entry, where it names a version.
47
+ for found in re.findall(r'\bversion (\d+\.\d+\.\d+[^\s}]*)\}', read("README.md")):
48
+ if found != version:
49
+ raise ValueError(f"README.md: citation names version {found}, expected {version}")
50
+ # maturin and CMake take the version from the bindings' Cargo manifests.
51
+ pyproject = read("bindings/python/pyproject.toml")
52
+ if not re.search(r'^dynamic = \["version"\]$', pyproject, re.M) or re.search(r'^version\s*=', pyproject, re.M):
53
+ raise ValueError("bindings/python/pyproject.toml: the version must come from bindings/python/Cargo.toml")
54
+ cmake = one(read("bindings/c/CMakeLists.txt"), r'^project\(tddlog_c VERSION (\S+)', "bindings/c/CMakeLists.txt")
55
+ if cmake != "${TDDLOG_VERSION}":
56
+ raise ValueError("bindings/c/CMakeLists.txt: the version must come from bindings/c/Cargo.toml")
57
+ return version
58
+
59
+
60
+ if __name__ == "__main__":
61
+ parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
62
+ parser.add_argument("--release-tag", default="", help="the tag about to be released, such as v0.1.0")
63
+ args = parser.parse_args()
64
+ try:
65
+ print(f"release metadata agrees: {check(Path(__file__).resolve().parents[2], args.release_tag)}")
66
+ except ValueError as error:
67
+ parser.exit(1, f"{error}\n")
@@ -0,0 +1,260 @@
1
+ name: Binaries
2
+
3
+ # Builds the `tddlog` command line for Linux (x86-64, ARM64), macOS (ARM64,
4
+ # x86-64) and Windows x86-64, packs each with the license, the notices and
5
+ # the example programs, and checks every archive on a runner other than the
6
+ # one that built it, as a user would: the checksum, `--help`, `--version` and
7
+ # the README's first example. When a GitHub release is published it attaches
8
+ # the archives to it. A run by hand builds and checks them, and with a tag
9
+ # builds that tag and attaches what its release lacks.
10
+
11
+ on:
12
+ release:
13
+ types: [published]
14
+ pull_request:
15
+ paths:
16
+ - ".github/workflows/binaries.yml"
17
+ workflow_dispatch:
18
+ inputs:
19
+ tag:
20
+ description: Existing release tag to build the binaries for and attach them to
21
+ required: false
22
+ type: string
23
+
24
+ env:
25
+ CARGO_TERM_COLOR: always
26
+
27
+ jobs:
28
+ # As in the C bindings: the archive tag, and one version across the crate
29
+ # and the bindings, which a release tag must name. "dev" stands in for
30
+ # anything that is not a release tag. The dispatch input reaches the script
31
+ # through the environment rather than `${{ }}`, which would paste it into
32
+ # the shell.
33
+ versions:
34
+ runs-on: ubuntu-latest
35
+ outputs:
36
+ tag: ${{ steps.tag.outputs.tag }}
37
+ is-release: ${{ steps.tag.outputs.is-release }}
38
+ steps:
39
+ - uses: actions/checkout@v5
40
+ with:
41
+ ref: ${{ inputs.tag || '' }}
42
+ - name: Determine the archive tag
43
+ id: tag
44
+ env:
45
+ INPUT_TAG: ${{ inputs.tag }}
46
+ run: |
47
+ if [ -n "$INPUT_TAG" ]; then
48
+ tag="$INPUT_TAG"; is_release=true
49
+ elif [[ "$GITHUB_REF" == refs/tags/* ]]; then
50
+ tag="$GITHUB_REF_NAME"; is_release=true
51
+ else
52
+ tag=dev; is_release=false
53
+ fi
54
+ echo "tag=$tag" >> "$GITHUB_OUTPUT"
55
+ echo "is-release=$is_release" >> "$GITHUB_OUTPUT"
56
+ - name: Check the release metadata
57
+ env:
58
+ TAG: ${{ steps.tag.outputs.is-release == 'true' && steps.tag.outputs.tag || '' }}
59
+ run: python3 .github/scripts/check_release.py --release-tag "$TAG"
60
+
61
+ build:
62
+ needs: versions
63
+ strategy:
64
+ fail-fast: false
65
+ matrix:
66
+ include:
67
+ # The manylinux image, as for the wheels, fixes the oldest glibc
68
+ # the binary needs (2.28: RHEL 8, Debian 10, Ubuntu 18.10 and
69
+ # later) and carries a C++20 gcc for goatd's vendored solvers.
70
+ - os: ubuntu-latest
71
+ target: x86_64-unknown-linux-gnu
72
+ container: quay.io/pypa/manylinux_2_28_x86_64
73
+ # jemalloc is built for the largest page it may meet, 64 KiB:
74
+ # built for the runner's 4 KiB pages it aborts at start on the
75
+ # 16 KiB and 64 KiB kernels of some ARM64 machines.
76
+ - os: ubuntu-24.04-arm
77
+ target: aarch64-unknown-linux-gnu
78
+ container: quay.io/pypa/manylinux_2_28_aarch64
79
+ lg-page: "16"
80
+ - os: macos-latest
81
+ target: aarch64-apple-darwin
82
+ - os: macos-15-intel
83
+ target: x86_64-apple-darwin
84
+ - os: windows-latest
85
+ target: x86_64-pc-windows-msvc
86
+ runs-on: ${{ matrix.os }}
87
+ container: ${{ matrix.container }}
88
+ env:
89
+ NAME: tddlog-${{ needs.versions.outputs.tag }}-${{ matrix.target }}
90
+ defaults:
91
+ run:
92
+ shell: bash
93
+ steps:
94
+ - uses: actions/checkout@v5
95
+ with:
96
+ ref: ${{ inputs.tag || '' }}
97
+
98
+ - name: Install Rust in the container
99
+ if: matrix.container != ''
100
+ run: |
101
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
102
+ | sh -s -- -y --profile minimal --default-toolchain stable
103
+ echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
104
+
105
+ - uses: dtolnay/rust-toolchain@stable
106
+ if: matrix.container == ''
107
+
108
+ # The release profile, without the line tables it keeps for profiling,
109
+ # which would make the binary several times larger and not faster. On
110
+ # Windows the C runtime is linked in, Rust's and the vendored C++'s, so
111
+ # the binary runs without the Visual C++ redistributable.
112
+ - name: Build
113
+ env:
114
+ CARGO_PROFILE_RELEASE_DEBUG: "0"
115
+ LG_PAGE: ${{ matrix.lg-page }}
116
+ run: |
117
+ set -eux
118
+ if [ -n "$LG_PAGE" ]; then export JEMALLOC_SYS_WITH_LG_PAGE="$LG_PAGE"; fi
119
+ if [ "$RUNNER_OS" = Windows ]; then export RUSTFLAGS="-C target-feature=+crt-static"; fi
120
+ cargo build --release --locked --bin tddlog
121
+
122
+ # The newest glibc and libstdc++ symbol versions the binary asks for,
123
+ # which no newer system lacks.
124
+ - name: Check the libraries the binary needs (Linux)
125
+ if: runner.os == 'Linux'
126
+ run: |
127
+ set -eux
128
+ objdump -p target/release/tddlog | grep NEEDED
129
+ glibc=$(objdump -T target/release/tddlog | grep -o 'GLIBC_[0-9.]*' | sort -uV | tail -n 1)
130
+ glibcxx=$(objdump -T target/release/tddlog | grep -o 'GLIBCXX_[0-9.]*' | sort -uV | tail -n 1)
131
+ echo "needs $glibc and $glibcxx"
132
+ test "$(printf '%s\n' "$glibc" GLIBC_2.28 | sort -V | tail -n 1)" = GLIBC_2.28
133
+
134
+ # The x86-64 binary, built for macOS 10.12, names it in the older load
135
+ # command.
136
+ - name: Show the oldest macOS the binary runs on
137
+ if: runner.os == 'macOS'
138
+ run: otool -l target/release/tddlog | grep -A 4 -E "LC_BUILD_VERSION|LC_VERSION_MIN_MACOSX"
139
+
140
+ # The binary beside LICENSE, NOTICE and THIRD-PARTY.md (goatd's vendored
141
+ # solvers are BSD-2-Clause and MIT, and their notices travel with the
142
+ # binary they are compiled into), and examples/, so that the README's
143
+ # commands run in the unpacked directory. A zip on Windows, which opens
144
+ # it without extra tools.
145
+ - name: Package the archive
146
+ run: |
147
+ set -eux
148
+ mkdir "$NAME"
149
+ cp LICENSE NOTICE THIRD-PARTY.md "$NAME"
150
+ cp -R examples "$NAME"
151
+ if [ "$RUNNER_OS" = Windows ]; then
152
+ cp target/release/tddlog.exe "$NAME"
153
+ 7z a "$NAME.zip" "$NAME"
154
+ sha256sum "$NAME.zip" > "$NAME.zip.sha256"
155
+ else
156
+ cp target/release/tddlog "$NAME"
157
+ tar czf "$NAME.tar.gz" "$NAME"
158
+ if command -v sha256sum; then
159
+ sha256sum "$NAME.tar.gz" > "$NAME.tar.gz.sha256"
160
+ else
161
+ shasum -a 256 "$NAME.tar.gz" > "$NAME.tar.gz.sha256"
162
+ fi
163
+ fi
164
+ ls -l "$NAME".*
165
+
166
+ - uses: actions/upload-artifact@v4
167
+ with:
168
+ name: tddlog-${{ matrix.target }}
169
+ path: |
170
+ tddlog-*.tar.gz*
171
+ tddlog-*.zip*
172
+
173
+ # Each archive on a runner without the build's toolchain or container, the
174
+ # Linux ones on the oldest Ubuntu image and the ARM64 macOS one on the
175
+ # oldest macOS image there are, then attached to the release.
176
+ check:
177
+ needs: [versions, build]
178
+ permissions:
179
+ contents: write
180
+ strategy:
181
+ fail-fast: false
182
+ matrix:
183
+ include:
184
+ - os: ubuntu-22.04
185
+ target: x86_64-unknown-linux-gnu
186
+ - os: ubuntu-22.04-arm
187
+ target: aarch64-unknown-linux-gnu
188
+ - os: macos-15
189
+ target: aarch64-apple-darwin
190
+ - os: macos-15-intel
191
+ target: x86_64-apple-darwin
192
+ - os: windows-2022
193
+ target: x86_64-pc-windows-msvc
194
+ runs-on: ${{ matrix.os }}
195
+ env:
196
+ TAG: ${{ needs.versions.outputs.tag }}
197
+ IS_RELEASE: ${{ needs.versions.outputs.is-release }}
198
+ NAME: tddlog-${{ needs.versions.outputs.tag }}-${{ matrix.target }}
199
+ ARCHIVE: tddlog-${{ needs.versions.outputs.tag }}-${{ matrix.target }}.${{ matrix.target == 'x86_64-pc-windows-msvc' && 'zip' || 'tar.gz' }}
200
+ defaults:
201
+ run:
202
+ shell: bash
203
+ steps:
204
+ - uses: actions/download-artifact@v4
205
+ with:
206
+ name: tddlog-${{ matrix.target }}
207
+
208
+ # The README's first example, whose answers it prints, read from the
209
+ # unpacked directory; nothing on standard error. Each answer is
210
+ # `atom:<tab>probability`, as ProbLog prints it; carriage returns are
211
+ # dropped before the comparison.
212
+ - name: Verify, unpack and run
213
+ run: |
214
+ set -eux
215
+ if command -v sha256sum; then
216
+ sha256sum -c "$ARCHIVE.sha256"
217
+ else
218
+ shasum -a 256 -c "$ARCHIVE.sha256"
219
+ fi
220
+ mkdir unpacked
221
+ if [ "$RUNNER_OS" = Windows ]; then
222
+ 7z x -ounpacked "$ARCHIVE"
223
+ else
224
+ tar xzf "$ARCHIVE" -C unpacked
225
+ fi
226
+ cd "unpacked/$NAME"
227
+ ls -l
228
+ ./tddlog --help > help.txt
229
+ head -n 3 help.txt
230
+ ./tddlog --version | tee version.txt
231
+ if [ "$IS_RELEASE" = true ]; then
232
+ test "$(tr -d '\r' < version.txt)" = "tddlog ${TAG#v}"
233
+ fi
234
+ ./tddlog examples/alarm.pl > answers.txt 2> errors.txt
235
+ cat answers.txt errors.txt
236
+ printf 'burglary:\t0.357143\nearthquake:\t0.714286\ncalls(mary):\t0.400000\n' > expected.txt
237
+ tr -d '\r' < answers.txt | diff expected.txt -
238
+ test ! -s errors.txt
239
+
240
+ # An archive attached to a published release, and the checksum people
241
+ # verify it against, are never replaced: a pair already there is kept,
242
+ # and one half of a pair is an error. To rebuild an archive, delete
243
+ # both from the release and run this workflow with the tag.
244
+ - name: Attach to the release
245
+ if: env.IS_RELEASE == 'true'
246
+ env:
247
+ GH_TOKEN: ${{ github.token }}
248
+ GH_REPO: ${{ github.repository }}
249
+ run: |
250
+ set -eu
251
+ assets=$(gh release view "$TAG" --json assets --jq '.assets[].name')
252
+ have() { grep -qxF "$1" <<< "$assets"; }
253
+ if have "$ARCHIVE" && have "$ARCHIVE.sha256"; then
254
+ echo "$ARCHIVE and its checksum are already attached; kept"
255
+ elif have "$ARCHIVE" || have "$ARCHIVE.sha256"; then
256
+ echo "only one of $ARCHIVE and $ARCHIVE.sha256 is attached: delete it and run again"
257
+ exit 1
258
+ else
259
+ gh release upload "$TAG" "$ARCHIVE" "$ARCHIVE.sha256"
260
+ fi
@@ -0,0 +1,251 @@
1
+ name: C bindings
2
+
3
+ # Builds the C library in bindings/c on Linux (x86-64, ARM64), macOS (ARM64,
4
+ # x86-64) and Windows x86-64, checks the committed header, runs the C tests,
5
+ # builds and runs the example against the installed CMake and pkg-config
6
+ # package and against the static library, and packages the header, both
7
+ # libraries and the notices into an archive. On Windows the CMake package and
8
+ # the pkg-config file are not built or tested (see the step that skips them),
9
+ # and the example and the tests are compiled with cl.exe directly.
10
+ # When a GitHub release is published it attaches the archives to it. The
11
+ # packaging runs on every trigger, so it is proven working before a release
12
+ # needs it.
13
+
14
+ on:
15
+ push:
16
+ branches: [main]
17
+ pull_request:
18
+ release:
19
+ types: [published]
20
+ workflow_dispatch:
21
+ inputs:
22
+ tag:
23
+ description: Existing release tag to build the archives for and attach them to
24
+ required: false
25
+ type: string
26
+
27
+ env:
28
+ CARGO_TERM_COLOR: always
29
+
30
+ jobs:
31
+ # Before anything is built: the archive tag, and one version across the
32
+ # crate and the bindings, which a release tag must name. A pull request's
33
+ # ref name has a slash in it, which breaks a directory name below, so
34
+ # "dev" stands in for anything that is not a release tag. The dispatch
35
+ # input reaches the script through the environment rather than `${{ }}`,
36
+ # which would paste it into the shell.
37
+ versions:
38
+ runs-on: ubuntu-latest
39
+ outputs:
40
+ tag: ${{ steps.tag.outputs.tag }}
41
+ is-release: ${{ steps.tag.outputs.is-release }}
42
+ steps:
43
+ - uses: actions/checkout@v5
44
+ with:
45
+ ref: ${{ inputs.tag || '' }}
46
+ - name: Determine the archive tag
47
+ id: tag
48
+ env:
49
+ INPUT_TAG: ${{ inputs.tag }}
50
+ run: |
51
+ if [ -n "$INPUT_TAG" ]; then
52
+ tag="$INPUT_TAG"; is_release=true
53
+ elif [[ "$GITHUB_REF" == refs/tags/* ]]; then
54
+ tag="$GITHUB_REF_NAME"; is_release=true
55
+ else
56
+ tag=dev; is_release=false
57
+ fi
58
+ echo "tag=$tag" >> "$GITHUB_OUTPUT"
59
+ echo "is-release=$is_release" >> "$GITHUB_OUTPUT"
60
+ - name: Check the release metadata
61
+ env:
62
+ TAG: ${{ steps.tag.outputs.is-release == 'true' && steps.tag.outputs.tag || '' }}
63
+ run: python3 .github/scripts/check_release.py --release-tag "$TAG"
64
+
65
+ c-bindings:
66
+ needs: versions
67
+ permissions:
68
+ contents: write
69
+ strategy:
70
+ fail-fast: false
71
+ matrix:
72
+ # `target` is not passed to cargo, since the runner's default
73
+ # toolchain already builds for it; it only names the archive.
74
+ include:
75
+ - os: ubuntu-latest
76
+ target: x86_64-unknown-linux-gnu
77
+ - os: ubuntu-24.04-arm
78
+ target: aarch64-unknown-linux-gnu
79
+ - os: macos-latest
80
+ target: aarch64-apple-darwin
81
+ - os: macos-15-intel
82
+ target: x86_64-apple-darwin
83
+ - os: windows-latest
84
+ target: x86_64-pc-windows-msvc
85
+ runs-on: ${{ matrix.os }}
86
+ env:
87
+ TAG: ${{ needs.versions.outputs.tag }}
88
+ IS_RELEASE: ${{ needs.versions.outputs.is-release }}
89
+ defaults:
90
+ run:
91
+ shell: bash
92
+ steps:
93
+ # A tag input checks out that tag, so a run by hand builds and attaches
94
+ # the archives a published release lacks.
95
+ - uses: actions/checkout@v5
96
+ with:
97
+ ref: ${{ inputs.tag || '' }}
98
+
99
+ - uses: dtolnay/rust-toolchain@stable
100
+ with:
101
+ components: rustfmt, clippy
102
+
103
+ # check.py needs CMake and pkg-config, which the ARM64 image may lack.
104
+ - name: Install CMake and pkg-config
105
+ if: runner.os == 'Linux'
106
+ run: |
107
+ if ! command -v cmake || ! command -v pkg-config; then
108
+ sudo apt-get update && sudo apt-get install -y cmake pkg-config
109
+ fi
110
+
111
+ # The header against cbindgen's, the CMake build and its tests (the
112
+ # answers of a dozen ProbLog system tests, and the example), the
113
+ # installation, and the example built against the installed package
114
+ # through CMake and pkg-config.
115
+ #
116
+ # Not on Windows: the CMake package links `m`, names no import library
117
+ # for the DLL and installs the DLL beside the others in lib, and
118
+ # pkg-config is not installed there. The steps below build, run and
119
+ # package the Windows library without CMake.
120
+ - name: Build, test and install
121
+ if: runner.os != 'Windows'
122
+ run: python3 bindings/c/check.py
123
+
124
+ # Builds the static library as well, and prints the system libraries a
125
+ # static link has to name, the C++ runtime of goatd's vendored solvers
126
+ # among them. The example's static link uses that list rather than a
127
+ # guess per platform.
128
+ - name: Build the libraries
129
+ working-directory: bindings/c
130
+ env:
131
+ # The note below is read by sed, and colour escapes would hide it.
132
+ CARGO_TERM_COLOR: never
133
+ run: |
134
+ set -o pipefail
135
+ cargo rustc --release -- --print native-static-libs 2>&1 \
136
+ | tee "$RUNNER_TEMP/build.log"
137
+ libs=$(sed -n 's/^note: native-static-libs: //p' "$RUNNER_TEMP/build.log" | head -n 1)
138
+ test -n "$libs" || { echo "rustc printed no native-static-libs note"; exit 1; }
139
+ echo "NATIVE_STATIC_LIBS=$libs" >> "$GITHUB_ENV"
140
+
141
+ - name: Build and run the example against the static library
142
+ if: runner.os != 'Windows'
143
+ run: |
144
+ set -eux
145
+ # The list of libraries is split into words on purpose.
146
+ # shellcheck disable=SC2086
147
+ cc -std=c11 -Wall -Wextra -Werror -Ibindings/c/include \
148
+ bindings/c/examples/alarm.c bindings/c/target/release/libtddlog_c.a \
149
+ $NATIVE_STATIC_LIBS -lm -o alarm-static
150
+ ./alarm-static
151
+
152
+ # cl.exe is not on PATH until vcvars has run, and vswhere finds the
153
+ # installation without naming the Visual Studio edition. /MD is the
154
+ # dynamic C runtime that Rust and the vendored C++ are built against.
155
+ # The tests take the same programs as the CMake test `answers`
156
+ # (bindings/c/CMakeLists.txt). `-D_CRT_SECURE_NO_WARNINGS` silences
157
+ # MSVC's notes on fopen, which the tests use.
158
+ - name: Build and run the example and the tests (Windows)
159
+ if: runner.os == 'Windows'
160
+ shell: cmd
161
+ run: |
162
+ for /f "usebackq tokens=*" %%i in (`"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -property installationPath`) do set "VSPATH=%%i"
163
+ call "%VSPATH%\VC\Auxiliary\Build\vcvars64.bat" || exit /b 1
164
+ set OUT=bindings\c\target\release
165
+ copy %OUT%\tddlog_c.dll . || exit /b 1
166
+
167
+ cl /nologo /std:c11 /MD /W3 /D_CRT_SECURE_NO_WARNINGS /Ibindings\c\include ^
168
+ bindings\c\examples\alarm.c /Fe:alarm-shared.exe /link %OUT%\tddlog_c.dll.lib || exit /b 1
169
+ alarm-shared.exe || exit /b 1
170
+
171
+ cl /nologo /std:c11 /MD /W3 /D_CRT_SECURE_NO_WARNINGS /Ibindings\c\include ^
172
+ bindings\c\examples\alarm.c /Fe:alarm-static.exe /link %OUT%\tddlog_c.lib %NATIVE_STATIC_LIBS% || exit /b 1
173
+ alarm-static.exe || exit /b 1
174
+
175
+ cl /nologo /std:c11 /MD /W3 /D_CRT_SECURE_NO_WARNINGS /Ibindings\c\include ^
176
+ bindings\c\tests\answers.c /Fe:answers.exe /link %OUT%\tddlog_c.dll.lib || exit /b 1
177
+ set P=tests/problog
178
+ answers.exe %P%/00_trivial_and.pl %P%/00_trivial_not.pl %P%/00_trivial_or.pl %P%/10_cards.pl ^
179
+ %P%/11_ads_numerical.pl %P%/3_tossing_coin.pl %P%/4_bayesian_net.pl ^
180
+ %P%/7_probabilistic_graph.pl %P%/8_smokers_network.pl %P%/add.pl %P%/negation.pl ^
181
+ %P%/negative_query.pl %P%/smokers_or.pl %P%/tc_3.pl || exit /b 1
182
+
183
+ - name: Check formatting
184
+ if: ${{ !cancelled() && runner.os == 'Linux' }}
185
+ working-directory: bindings/c
186
+ run: cargo fmt --check
187
+
188
+ - name: Lint
189
+ if: ${{ !cancelled() && runner.os == 'Linux' }}
190
+ working-directory: bindings/c
191
+ run: cargo clippy --release -- -D warnings
192
+
193
+ # The archive is the installation check.py tested from another prefix:
194
+ # the header in include/, the shared library, the CMake package and the
195
+ # pkg-config file in lib/, and LICENSE, NOTICE and THIRD-PARTY.md in
196
+ # share/licenses/tddlog (goatd's vendored solvers are BSD-2-Clause and
197
+ # MIT, and their notices have to accompany the libraries they are
198
+ # compiled into). The static library goes beside the shared one, and
199
+ # NATIVE-STATIC-LIBS.txt records the system libraries it needs at link
200
+ # time, which differ per platform.
201
+ - name: Package the archive (Linux, macOS)
202
+ if: runner.os != 'Windows'
203
+ run: |
204
+ set -eux
205
+ name="tddlog-c-$TAG-${{ matrix.target }}"
206
+ cp -R bindings/c/build/package "$name"
207
+ cp bindings/c/target/release/libtddlog_c.a "$name/lib/"
208
+ {
209
+ echo "System libraries needed when linking libtddlog_c.a statically,"
210
+ echo "from 'cargo rustc --release -- --print native-static-libs':"
211
+ echo "$NATIVE_STATIC_LIBS"
212
+ } > "$name/NATIVE-STATIC-LIBS.txt"
213
+ tar czf "$name.tar.gz" "$name"
214
+ shasum -a 256 "$name.tar.gz" > "$name.tar.gz.sha256"
215
+ tar tzf "$name.tar.gz"
216
+
217
+ # MSVC names the DLL's import library tddlog_c.dll.lib, and the static
218
+ # archive tddlog_c.lib. A zip, which Windows opens without extra tools.
219
+ - name: Package the archive (Windows)
220
+ if: runner.os == 'Windows'
221
+ run: |
222
+ set -eux
223
+ out=bindings/c/target/release
224
+ name="tddlog-c-$TAG-${{ matrix.target }}"
225
+ mkdir "$name"
226
+ cp bindings/c/include/tddlog.h LICENSE NOTICE THIRD-PARTY.md "$name"
227
+ cp "$out/tddlog_c.dll" "$out/tddlog_c.dll.lib" "$out/tddlog_c.lib" "$name"
228
+ {
229
+ echo "System libraries needed when linking tddlog_c.lib statically,"
230
+ echo "from 'cargo rustc --release -- --print native-static-libs':"
231
+ echo "$NATIVE_STATIC_LIBS"
232
+ } > "$name/NATIVE-STATIC-LIBS.txt"
233
+ 7z a "$name.zip" "$name"
234
+ sha256sum "$name.zip" > "$name.zip.sha256"
235
+ 7z l "$name.zip"
236
+
237
+ - uses: actions/upload-artifact@v4
238
+ with:
239
+ name: tddlog-c-${{ matrix.target }}
240
+ path: |
241
+ tddlog-c-*.tar.gz*
242
+ tddlog-c-*.zip*
243
+
244
+ # No --clobber: an archive attached to a published release, and the
245
+ # checksum people verify it against, are never replaced. To rebuild one,
246
+ # delete it from the release and run this workflow with the tag.
247
+ - name: Attach to the release
248
+ if: env.IS_RELEASE == 'true'
249
+ env:
250
+ GH_TOKEN: ${{ github.token }}
251
+ run: gh release upload "$TAG" tddlog-c-"$TAG"-${{ matrix.target }}.*