@almadar/std 17.0.2 → 17.1.0

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 (317) hide show
  1. package/behaviors/lolo/auth/atoms/std-dev-personas.lolo +27 -2
  2. package/behaviors/lolo/cli/atoms/std-orb-goldens.lolo +6 -3
  3. package/behaviors/lolo/cli/atoms/std-orb-lint-mem-handles.lolo +54 -34
  4. package/behaviors/lolo/cli/atoms/std-orb-lint-os-grants.lolo +4 -4
  5. package/behaviors/lolo/cli/atoms/std-orb-mcp.lolo +16 -21
  6. package/behaviors/lolo/cli/atoms/std-orb-packages.lolo +26 -16
  7. package/behaviors/lolo/cli/atoms/std-orb-serve.lolo +24 -4
  8. package/behaviors/lolo/codec/atoms/std-lolo-kotlin.lolo +26 -3
  9. package/behaviors/lolo/codec/atoms/std-lolo-python.lolo +15 -2
  10. package/behaviors/lolo/codec/atoms/std-lolo-rust.lolo +27 -2
  11. package/behaviors/lolo/codec/atoms/std-lolo-source.lolo +251 -60
  12. package/behaviors/lolo/codec/atoms/std-lolo-swift.lolo +24 -1
  13. package/behaviors/lolo/codec/atoms/std-lolo-typescript.lolo +24 -3
  14. package/behaviors/lolo/connect/atoms/std-meta-ads.lolo +4 -4
  15. package/behaviors/lolo/connect/atoms/std-stdio-lines.lolo +7 -4
  16. package/behaviors/lolo/connect/atoms/std-youtube.lolo +9 -9
  17. package/behaviors/lolo/dev/atoms/std-guest-session.lolo +122 -10
  18. package/behaviors/lolo/dev/atoms/std-mock-seed-marks.lolo +66 -0
  19. package/behaviors/lolo/dev/organisms/std-behavior-playground.lolo +5 -2
  20. package/behaviors/lolo/dev/organisms/std-launchpad.lolo +4 -3
  21. package/behaviors/lolo/gpu/atoms/std-gpu-compute.lolo +329 -0
  22. package/behaviors/lolo/net/atoms/std-http-client.lolo +4 -4
  23. package/behaviors/lolo/net/atoms/std-http-fetch.lolo +6 -6
  24. package/behaviors/lolo/net/atoms/std-npm-lookup.lolo +1 -1
  25. package/behaviors/lolo/net/atoms/std-npm-registry.lolo +2 -2
  26. package/behaviors/lolo/spec/auth/dev-personas.replay.goldens.json +263 -2
  27. package/behaviors/lolo/spec/cli/lint-all.lolo +1 -0
  28. package/behaviors/lolo/spec/cli/lint-item-action-event.replay.goldens.json +9 -9
  29. package/behaviors/lolo/spec/cli/lint-mem-handles.replay.goldens.json +3021 -1
  30. package/behaviors/lolo/spec/cli/lint-os-grants.replay.goldens.json +284 -12
  31. package/behaviors/lolo/spec/cli/mcp-server.replay.goldens.json +51 -55
  32. package/behaviors/lolo/spec/cli/orb-compile.replay.goldens.json +10 -4
  33. package/behaviors/lolo/spec/cli/orb-packages.lolo +1 -1
  34. package/behaviors/lolo/spec/codec/lolo-kotlin.replay.goldens.json +7496 -7497
  35. package/behaviors/lolo/spec/codec/lolo-python.replay.goldens.json +341 -3
  36. package/behaviors/lolo/spec/codec/lolo-rust.replay.goldens.json +18931 -6142
  37. package/behaviors/lolo/spec/codec/lolo-source.fixtures/compose-pair.lolo +44 -0
  38. package/behaviors/lolo/spec/codec/lolo-source.fixtures/config-read.lolo +2 -1
  39. package/behaviors/lolo/spec/codec/lolo-source.fixtures/divide-default.lolo +2 -1
  40. package/behaviors/lolo/spec/codec/lolo-source.fixtures/divide-plain.lolo +2 -1
  41. package/behaviors/lolo/spec/codec/lolo-source.fixtures/get-past-end.lolo +2 -1
  42. package/behaviors/lolo/spec/codec/lolo-source.fixtures/list-call.lolo +2 -1
  43. package/behaviors/lolo/spec/codec/lolo-source.fixtures/list-plain.lolo +2 -1
  44. package/behaviors/lolo/spec/codec/lolo-source.fixtures/minus-binary.lolo +2 -1
  45. package/behaviors/lolo/spec/codec/lolo-source.fixtures/minus-unary.lolo +2 -1
  46. package/behaviors/lolo/spec/codec/lolo-source.fixtures/nested-let.lolo +2 -1
  47. package/behaviors/lolo/spec/codec/lolo-source.fixtures/no-machine.lolo +2 -1
  48. package/behaviors/lolo/spec/codec/lolo-source.fixtures/no-template.lolo +2 -1
  49. package/behaviors/lolo/spec/codec/lolo-source.fixtures/nth-past-end.lolo +2 -1
  50. package/behaviors/lolo/spec/codec/lolo-source.fixtures/nth-raw.lolo +2 -1
  51. package/behaviors/lolo/spec/codec/lolo-source.fixtures/ports-call.lolo +2 -1
  52. package/behaviors/lolo/spec/codec/lolo-source.fixtures/range-one.lolo +2 -1
  53. package/behaviors/lolo/spec/codec/lolo-source.fixtures/range-two.lolo +2 -1
  54. package/behaviors/lolo/spec/codec/lolo-source.fixtures/router-trio.lolo +88 -0
  55. package/behaviors/lolo/spec/codec/lolo-source.fixtures/store-pair.lolo +62 -0
  56. package/behaviors/lolo/spec/codec/lolo-source.fixtures/string-literal.lolo +2 -1
  57. package/behaviors/lolo/spec/codec/lolo-source.gen/knobs.py +27 -1
  58. package/behaviors/lolo/spec/codec/lolo-source.gen/src_assemble.in +54 -2
  59. package/behaviors/lolo/spec/codec/lolo-source.gen/src_finish.in +1 -1
  60. package/behaviors/lolo/spec/codec/lolo-source.gen/src_fold.in +24 -4
  61. package/behaviors/lolo/spec/codec/lolo-source.gen/src_head.in +8 -3
  62. package/behaviors/lolo/spec/codec/lolo-source.gen/src_prepare.in +6 -2
  63. package/behaviors/lolo/spec/codec/lolo-source.gen/src_trait.in +12 -2
  64. package/behaviors/lolo/spec/codec/lolo-source.parity/agent-step.lolo +2 -1
  65. package/behaviors/lolo/spec/codec/lolo-source.parity/agent-step.server.lolo +1 -0
  66. package/behaviors/lolo/spec/codec/lolo-source.parity/chunk.lolo +2 -1
  67. package/behaviors/lolo/spec/codec/lolo-source.parity/chunk.server.lolo +1 -0
  68. package/behaviors/lolo/spec/codec/lolo-source.parity/compose-pair.events.json +36 -0
  69. package/behaviors/lolo/spec/codec/lolo-source.parity/compose-pair.replay.goldens.json +91 -0
  70. package/behaviors/lolo/spec/codec/lolo-source.parity/cosine.lolo +2 -1
  71. package/behaviors/lolo/spec/codec/lolo-source.parity/cosine.server.lolo +1 -0
  72. package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/kotlin/compose-pair.kt +31 -0
  73. package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/kotlin/router-trio.kt +31 -0
  74. package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/kotlin/store-pair.kt +31 -0
  75. package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/python/compose-pair.py +18 -0
  76. package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/python/router-trio.py +18 -0
  77. package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/python/store-pair.py +17 -0
  78. package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/rust/compose-pair.rs +37 -0
  79. package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/rust/router-trio.rs +37 -0
  80. package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/rust/store-pair.rs +36 -0
  81. package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/swift/compose-pair.swift +24 -0
  82. package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/swift/router-trio.swift +24 -0
  83. package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/swift/store-pair.swift +23 -0
  84. package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/typescript/compose-pair.mts +24 -0
  85. package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/typescript/router-trio.mts +24 -0
  86. package/behaviors/lolo/spec/codec/lolo-source.parity/drivers/typescript/store-pair.mts +22 -0
  87. package/behaviors/lolo/spec/codec/lolo-source.parity/recall-at-k.lolo +2 -1
  88. package/behaviors/lolo/spec/codec/lolo-source.parity/recall-at-k.server.lolo +1 -0
  89. package/behaviors/lolo/spec/codec/lolo-source.parity/router-trio.events.json +18 -0
  90. package/behaviors/lolo/spec/codec/lolo-source.parity/router-trio.replay.goldens.json +87 -0
  91. package/behaviors/lolo/spec/codec/lolo-source.parity/store-pair.events.json +58 -0
  92. package/behaviors/lolo/spec/codec/lolo-source.parity/store-pair.replay.goldens.json +238 -0
  93. package/behaviors/lolo/spec/codec/lolo-swift.replay.goldens.json +15599 -2204
  94. package/behaviors/lolo/spec/codec/lolo-typescript.replay.goldens.json +28930 -28929
  95. package/behaviors/lolo/spec/connect/bearer-api.replay.goldens.json +1 -1
  96. package/behaviors/lolo/spec/connect/esign.replay.goldens.json +3 -3
  97. package/behaviors/lolo/spec/connect/github.replay.goldens.json +13 -13
  98. package/behaviors/lolo/spec/connect/google-calendar.replay.goldens.json +2 -2
  99. package/behaviors/lolo/spec/connect/image.replay.goldens.json +1 -1
  100. package/behaviors/lolo/spec/connect/meta-ads.replay.goldens.json +2 -2
  101. package/behaviors/lolo/spec/connect/stdio-lines.replay.goldens.json +90 -0
  102. package/behaviors/lolo/spec/connect/twilio.replay.goldens.json +2 -2
  103. package/behaviors/lolo/spec/connect/youtube.replay.goldens.json +1 -1
  104. package/behaviors/lolo/spec/dev/guest-session.replay.goldens.json +824 -0
  105. package/behaviors/lolo/spec/dev/mock-seed-marks.replay.goldens.json +365 -0
  106. package/behaviors/lolo/spec/dev/verify-walk.replay.goldens.json +2 -1
  107. package/behaviors/lolo/spec/gpu/gpu-compute.replay.goldens.json +784 -0
  108. package/behaviors/lolo/spec/mem/mem-buffer.replay.goldens.json +97 -1
  109. package/behaviors/lolo/spec/ml/vector-write.goldens.json +1 -1
  110. package/behaviors/lolo/spec/ml/vector-write.replay.goldens.json +2 -2
  111. package/behaviors/lolo/spec/net/http-client-call-host.replay.goldens.json +3 -3
  112. package/behaviors/lolo/spec/net/http-client-env-host.replay.goldens.json +3 -3
  113. package/behaviors/lolo/spec/net/http-client.replay.goldens.json +56 -56
  114. package/behaviors/lolo/spec/net/http-fetch.replay.goldens.json +2 -2
  115. package/behaviors/lolo/spec/net/npm-lookup.replay.goldens.json +1 -1
  116. package/behaviors/lolo/spec/net/npm-registry.replay.goldens.json +2 -2
  117. package/behaviors/lolo/spec/net/server-declared-traits.replay.goldens.json +6 -3
  118. package/behaviors/lolo/spec/net/server-external-inputs.replay.goldens.json +16 -8
  119. package/behaviors/lolo/spec/net/server-retargeted-leg.replay.goldens.json +4 -2
  120. package/behaviors/lolo/spec/net/server-untargeted-discovery.replay.goldens.json +50 -45
  121. package/behaviors/lolo/spec/ops/llm-spend-board.replay.goldens.json +112 -16
  122. package/behaviors/lolo/spec/store/firestore-twin.replay.goldens.json +1 -1
  123. package/behaviors/lolo/spec/store/row-store-postgres.gen/record_real_sql.py +1 -1
  124. package/behaviors/lolo/spec/ui/game/fx-particles.replay.goldens.json +37 -0
  125. package/behaviors/lolo/ui/avl/atoms/std-avl-cosmic-zoom.lolo +2 -2
  126. package/behaviors/lolo/ui/game/atoms/std-fx-particles.lolo +10 -1
  127. package/behaviors/lolo/ui/game/atoms/ui-draw-fx-layer.lolo +4 -4
  128. package/behaviors/lolo/ui/game/organisms/std-arcade-board-3d.lolo +9 -9
  129. package/behaviors/lolo/ui/game/organisms/std-crew-board-2d.lolo +4 -4
  130. package/behaviors/lolo/ui/game/organisms/std-dungeon-board-2d.lolo +5 -5
  131. package/behaviors/lolo/ui/game/organisms/std-market-board-3d.lolo +9 -9
  132. package/behaviors/lolo/ui/game/organisms/std-objective-board-3d.lolo +9 -9
  133. package/behaviors/lolo/ui/game/organisms/std-platformer-board-2d.lolo +5 -5
  134. package/behaviors/lolo/ui/game/organisms/std-platformer-puzzle.lolo +4 -4
  135. package/behaviors/lolo/ui/game/organisms/std-survival-board-3d.lolo +9 -9
  136. package/behaviors/lolo/ui/game/organisms/std-tactics-board-2d.lolo +5 -5
  137. package/behaviors/lolo/ui/game/organisms/std-tactics-board-3d.lolo +9 -9
  138. package/behaviors/registry/auth/atoms/std-dev-personas.orb +1 -1
  139. package/behaviors/registry/cli/atoms/std-orb-goldens.orb +1 -1
  140. package/behaviors/registry/cli/atoms/std-orb-lint-mem-handles.orb +1 -1
  141. package/behaviors/registry/cli/atoms/std-orb-lint-os-grants.orb +1 -1
  142. package/behaviors/registry/cli/atoms/std-orb-mcp.orb +1 -1
  143. package/behaviors/registry/cli/atoms/std-orb-packages.orb +1 -1
  144. package/behaviors/registry/cli/atoms/std-orb-serve.orb +1 -1
  145. package/behaviors/registry/codec/atoms/std-lolo-kotlin.orb +1 -1
  146. package/behaviors/registry/codec/atoms/std-lolo-python.orb +1 -1
  147. package/behaviors/registry/codec/atoms/std-lolo-rust.orb +1 -1
  148. package/behaviors/registry/codec/atoms/std-lolo-source.orb +1 -1
  149. package/behaviors/registry/codec/atoms/std-lolo-swift.orb +1 -1
  150. package/behaviors/registry/codec/atoms/std-lolo-typescript.orb +1 -1
  151. package/behaviors/registry/connect/atoms/std-meta-ads.orb +1 -1
  152. package/behaviors/registry/connect/atoms/std-stdio-lines.orb +1 -1
  153. package/behaviors/registry/connect/atoms/std-youtube.orb +1 -1
  154. package/behaviors/registry/dev/atoms/std-guest-session.orb +1 -1
  155. package/behaviors/registry/dev/atoms/std-mock-seed-marks.orb +1 -0
  156. package/behaviors/registry/dev/organisms/std-behavior-playground.orb +37 -0
  157. package/behaviors/registry/dev/organisms/std-launchpad.orb +25 -0
  158. package/behaviors/registry/gpu/atoms/std-gpu-compute.orb +1 -0
  159. package/behaviors/registry/net/atoms/std-http-client.orb +1 -1
  160. package/behaviors/registry/net/atoms/std-http-fetch.orb +1 -1
  161. package/behaviors/registry/net/atoms/std-npm-lookup.orb +1 -1
  162. package/behaviors/registry/net/atoms/std-npm-registry.orb +1 -1
  163. package/behaviors/registry/spec/cli/lint-all.orb +1 -1
  164. package/behaviors/registry/spec/cli/orb-packages.orb +1 -1
  165. package/behaviors/registry/spec/codec/lolo-source.fixtures/compose-pair.orb +1 -0
  166. package/behaviors/registry/spec/codec/lolo-source.fixtures/config-read.orb +1 -1
  167. package/behaviors/registry/spec/codec/lolo-source.fixtures/divide-default.orb +1 -1
  168. package/behaviors/registry/spec/codec/lolo-source.fixtures/divide-plain.orb +1 -1
  169. package/behaviors/registry/spec/codec/lolo-source.fixtures/get-past-end.orb +1 -1
  170. package/behaviors/registry/spec/codec/lolo-source.fixtures/list-call.orb +1 -1
  171. package/behaviors/registry/spec/codec/lolo-source.fixtures/list-plain.orb +1 -1
  172. package/behaviors/registry/spec/codec/lolo-source.fixtures/minus-binary.orb +1 -1
  173. package/behaviors/registry/spec/codec/lolo-source.fixtures/minus-unary.orb +1 -1
  174. package/behaviors/registry/spec/codec/lolo-source.fixtures/nested-let.orb +1 -1
  175. package/behaviors/registry/spec/codec/lolo-source.fixtures/no-machine.orb +1 -1
  176. package/behaviors/registry/spec/codec/lolo-source.fixtures/no-template.orb +1 -1
  177. package/behaviors/registry/spec/codec/lolo-source.fixtures/nth-past-end.orb +1 -1
  178. package/behaviors/registry/spec/codec/lolo-source.fixtures/nth-raw.orb +1 -1
  179. package/behaviors/registry/spec/codec/lolo-source.fixtures/ports-call.orb +1 -1
  180. package/behaviors/registry/spec/codec/lolo-source.fixtures/range-one.orb +1 -1
  181. package/behaviors/registry/spec/codec/lolo-source.fixtures/range-two.orb +1 -1
  182. package/behaviors/registry/spec/codec/lolo-source.fixtures/router-trio.orb +1 -0
  183. package/behaviors/registry/spec/codec/lolo-source.fixtures/store-pair.orb +1 -0
  184. package/behaviors/registry/spec/codec/lolo-source.fixtures/string-literal.orb +1 -1
  185. package/behaviors/registry/spec/codec/lolo-source.parity/agent-step.orb +1 -1
  186. package/behaviors/registry/spec/codec/lolo-source.parity/agent-step.server.orb +1 -1
  187. package/behaviors/registry/spec/codec/lolo-source.parity/chunk.orb +1 -1
  188. package/behaviors/registry/spec/codec/lolo-source.parity/chunk.server.orb +1 -1
  189. package/behaviors/registry/spec/codec/lolo-source.parity/cosine.orb +1 -1
  190. package/behaviors/registry/spec/codec/lolo-source.parity/cosine.server.orb +1 -1
  191. package/behaviors/registry/spec/codec/lolo-source.parity/recall-at-k.orb +1 -1
  192. package/behaviors/registry/spec/codec/lolo-source.parity/recall-at-k.server.orb +1 -1
  193. package/behaviors/registry/ui/avl/atoms/std-avl-cosmic-zoom.orb +1 -1
  194. package/behaviors/registry/ui/game/atoms/std-fx-particles.orb +1 -1
  195. package/behaviors/registry/ui/game/atoms/ui-draw-fx-layer.orb +1 -1
  196. package/behaviors/registry/ui/game/organisms/std-arcade-board-3d.orb +20 -13
  197. package/behaviors/registry/ui/game/organisms/std-crew-board-2d.orb +9 -5
  198. package/behaviors/registry/ui/game/organisms/std-dungeon-board-2d.orb +17 -7
  199. package/behaviors/registry/ui/game/organisms/std-market-board-3d.orb +19 -15
  200. package/behaviors/registry/ui/game/organisms/std-objective-board-3d.orb +15 -12
  201. package/behaviors/registry/ui/game/organisms/std-platformer-board-2d.orb +17 -7
  202. package/behaviors/registry/ui/game/organisms/std-platformer-puzzle.orb +4 -0
  203. package/behaviors/registry/ui/game/organisms/std-survival-board-3d.orb +15 -12
  204. package/behaviors/registry/ui/game/organisms/std-tactics-board-2d.orb +13 -6
  205. package/behaviors/registry/ui/game/organisms/std-tactics-board-3d.orb +14 -12
  206. package/canonical-operators.json +1426 -103
  207. package/dist/{chunk-EK22WRB6.js → chunk-2UGHBVU2.js} +2 -2
  208. package/dist/{chunk-GDMH5T4J.js → chunk-3DK7GI2C.js} +2 -2
  209. package/dist/chunk-3MDASC5C.js +26 -0
  210. package/dist/{chunk-K5ZI27PB.js → chunk-3PHO4RRF.js} +1 -1
  211. package/dist/{chunk-7IEMMYM6.js → chunk-4MJCLAZW.js} +1 -1
  212. package/dist/{chunk-W4IEV4BY.js → chunk-55JPIL7A.js} +2 -2
  213. package/dist/{chunk-RUGBZTV3.js → chunk-66BLZLFI.js} +1 -1
  214. package/dist/{chunk-YWFISV7L.js → chunk-66RAJFOD.js} +1 -1
  215. package/dist/{chunk-JWOWWGNZ.js → chunk-6ED4SUC6.js} +1 -1
  216. package/dist/{chunk-LL7P6EII.js → chunk-6KFCHNE2.js} +2 -2
  217. package/dist/{chunk-GFBL2TW6.js → chunk-A4QB3Y6L.js} +1 -1
  218. package/dist/chunk-BVWMLS32.js +123 -0
  219. package/dist/{chunk-5KQCGSNC.js → chunk-CRKVDCY7.js} +1 -1
  220. package/dist/{chunk-WHQDLLC3.js → chunk-EKWEY4OJ.js} +1 -1
  221. package/dist/{chunk-Y3BRVNYK.js → chunk-EU22GCGV.js} +2 -2
  222. package/dist/{chunk-XQPYTDZ4.js → chunk-FB6PKNRS.js} +1 -1
  223. package/dist/{chunk-UX3MDFX6.js → chunk-FSVOJQLP.js} +1 -1
  224. package/dist/{chunk-LDBD2FBQ.js → chunk-GAKLBWBR.js} +1 -1
  225. package/dist/{chunk-C3IEMPRZ.js → chunk-GO3FKBV2.js} +2 -2
  226. package/dist/{chunk-LZSPEHSM.js → chunk-GPDTJHYY.js} +1 -1
  227. package/dist/{chunk-W5ABMOXU.js → chunk-JQBWLH5V.js} +1 -1
  228. package/dist/{chunk-63X6RNY6.js → chunk-KKW3JHTC.js} +1 -1
  229. package/dist/{chunk-5PLJE42Q.js → chunk-LF2EZVAM.js} +1 -1
  230. package/dist/{chunk-RXWBYWQB.js → chunk-LGCKOZP3.js} +2 -2
  231. package/dist/{chunk-JJEADYP7.js → chunk-LMZ6XJFB.js} +2 -2
  232. package/dist/{chunk-CWYSQZJU.js → chunk-M2YQNSAZ.js} +2 -2
  233. package/dist/{chunk-GNCKJV3P.js → chunk-MKWHYBIS.js} +1 -1
  234. package/dist/{chunk-ZB2CLGEG.js → chunk-MXBGYTYF.js} +1 -1
  235. package/dist/{chunk-UN76TRSK.js → chunk-NH6MXHZR.js} +41 -41
  236. package/dist/{chunk-II2VW7T6.js → chunk-ODBIX4DB.js} +1 -1
  237. package/dist/{chunk-3F3CNWOG.js → chunk-OYDQR6DT.js} +2 -2
  238. package/dist/{chunk-FVL6BT6L.js → chunk-PD6POR44.js} +1 -1
  239. package/dist/{chunk-U6USXZ5M.js → chunk-PHFT3QNS.js} +2 -2
  240. package/dist/{chunk-RJYKIZMS.js → chunk-PQZ6PVKG.js} +2 -2
  241. package/dist/{chunk-TQPQXCSZ.js → chunk-Q6NHXIOZ.js} +2 -2
  242. package/dist/{chunk-KYGWVCTM.js → chunk-QMDVYTB7.js} +1 -1
  243. package/dist/{chunk-XKTATY45.js → chunk-RW2KMSG5.js} +4 -4
  244. package/dist/{chunk-UHNSPTFT.js → chunk-SA2ZS24W.js} +1 -1
  245. package/dist/{chunk-6YPUQK36.js → chunk-SFWP4UMK.js} +2 -2
  246. package/dist/{chunk-ZZYLFHBU.js → chunk-TLNEQA4D.js} +1 -1
  247. package/dist/{chunk-RGTBRWWA.js → chunk-TOODE5AD.js} +2 -2
  248. package/dist/{chunk-QGWAHOFR.js → chunk-U57GY7SM.js} +2 -2
  249. package/dist/{chunk-FDJZKB7J.js → chunk-UIDQQJSX.js} +1 -1
  250. package/dist/{chunk-LLH3WXM3.js → chunk-UVFP2B7I.js} +1 -1
  251. package/dist/{chunk-4OF7727E.js → chunk-VEGZPCTZ.js} +2 -2
  252. package/dist/{chunk-73YUPNIT.js → chunk-VXN4V7LC.js} +1 -1
  253. package/dist/{chunk-4D3W6AAE.js → chunk-YHQVZWPG.js} +1 -1
  254. package/dist/{chunk-XXYBHYLM.js → chunk-YQO3TO66.js} +2 -2
  255. package/dist/{chunk-YZAYFR5A.js → chunk-ZSJ3GEOJ.js} +1 -1
  256. package/dist/index.d.ts +3 -3
  257. package/dist/index.js +50 -50
  258. package/dist/modules/anim.js +2 -2
  259. package/dist/modules/array.js +2 -2
  260. package/dist/modules/auth.js +3 -3
  261. package/dist/modules/behavior.js +2 -2
  262. package/dist/modules/bit.js +2 -2
  263. package/dist/modules/browser.js +2 -2
  264. package/dist/modules/bytes.js +2 -2
  265. package/dist/modules/codec.js +3 -3
  266. package/dist/modules/composition.js +2 -2
  267. package/dist/modules/core.js +2 -2
  268. package/dist/modules/csv.js +2 -2
  269. package/dist/modules/ffi.js +3 -3
  270. package/dist/modules/format.js +2 -2
  271. package/dist/modules/geo.js +2 -2
  272. package/dist/modules/gpu.d.ts +12 -0
  273. package/dist/modules/gpu.js +3 -0
  274. package/dist/modules/grid.js +2 -2
  275. package/dist/modules/i18n.js +2 -2
  276. package/dist/modules/index.d.ts +1 -2
  277. package/dist/modules/index.js +45 -46
  278. package/dist/modules/json.js +2 -2
  279. package/dist/modules/kernel.js +3 -3
  280. package/dist/modules/kv.js +3 -3
  281. package/dist/modules/llm.js +2 -2
  282. package/dist/modules/math.js +2 -2
  283. package/dist/modules/mem.js +3 -3
  284. package/dist/modules/object.js +2 -2
  285. package/dist/modules/os-common.d.ts +1 -1
  286. package/dist/modules/os-common.js +2 -2
  287. package/dist/modules/os-desktop.js +3 -3
  288. package/dist/modules/os-dev.js +3 -3
  289. package/dist/modules/os-dir.js +3 -3
  290. package/dist/modules/os-env-stdio.js +3 -3
  291. package/dist/modules/os-fs.js +3 -3
  292. package/dist/modules/os-net.js +3 -3
  293. package/dist/modules/os-path.js +3 -3
  294. package/dist/modules/os-process.js +3 -3
  295. package/dist/modules/os-sys.js +3 -3
  296. package/dist/modules/os-time-users.js +3 -3
  297. package/dist/modules/os.js +13 -13
  298. package/dist/modules/path.js +2 -2
  299. package/dist/modules/prob.js +2 -2
  300. package/dist/modules/program.js +2 -2
  301. package/dist/modules/session.js +2 -2
  302. package/dist/modules/str.js +2 -2
  303. package/dist/modules/time.js +2 -2
  304. package/dist/modules/validate.js +2 -2
  305. package/dist/modules/vector.js +2 -2
  306. package/dist/modules/workspace.js +2 -2
  307. package/dist/modules/xml.js +2 -2
  308. package/dist/modules/yaml.js +2 -2
  309. package/dist/registry.d.ts +2 -2
  310. package/dist/registry.js +49 -49
  311. package/dist/{types-BA4LkhNJ.d.ts → types-CgiGhK6t.d.ts} +17 -3
  312. package/package.json +5 -5
  313. package/dist/chunk-F5TP25JA.js +0 -26
  314. package/dist/chunk-NE4WSTN7.js +0 -26
  315. package/dist/modules/trace.d.ts +0 -15
  316. package/dist/modules/trace.js +0 -2
  317. /package/dist/{chunk-SHSBTDDX.js → chunk-QUQ33UXH.js} +0 -0
@@ -6,7 +6,7 @@ app std-orb-packages [
6
6
  sys: [identity],
7
7
  fs: { cwd: "**": [read, write, create, remove], "/**": [read], "~/.orb/**": [read, write, create, remove], "~/.orb": [create] },
8
8
  net: { "registry.npmjs.org:443": [tcp] },
9
- description: "std-orb-packages — the `orb list|add|update|remove [--global]` client of the npm registry (spec/cli/orb-packages.lolo; golden: orbital-cli packages.rs), bun-free. Packages live in <dir>/node_modules (dir = the working directory, or ~/.orb with --global) and the lockfile <dir>/<lockfile> holds { packages: [{ name, version, url, integrity }] }. Every command first reads the lockfile (absent = empty) and scans node_modules (scoped names included; the entry kind symlink is the workspace link), reading each package.json: a package is an orb package when it declares orbLanguage, orb, orbVocabulary or orbProgram.kind shell|desktop, and its kinds are those. list prints one row per orb package sorted by name (package 34, version 12, kinds 26, `ok`, ` (linked)`, ` [<prefix>/]`) or --json rows. remove refuses a behavior package whose prefix a .lolo or .orb file under the working directory still imports, deletes the package (a link is unlinked, never its target) and drops its lock entry. add parses name@exact-version (a range is refused ORB_PACKAGE_RANGE; a workspace-linked package is refused ORB_PACKAGE_LINKED) or a direct tarball URL (refused: it carries no integrity), and resolves name@version through GET <registry>/<name>/<version> (the npm version manifest: dist.tarball and dist.integrity). update reads the npm packument GET <registry>/<name> of every non-linked orb package and of every missing baseline package (an upgrade from nothing), and moves each to the newest stable, non-deprecated version above the installed one whose language is compatible: the running orb answers `orb --version` as `orb X.Y.Z (language R)` (any other form is refused) and keeps R; @almadar/core resolves first, and its candidate is compatible when its orbLanguage.version satisfies R; every other package is compatible when its language range (orb.language, orbLanguage.language, orbVocabulary.language or orbProgram.language, the first present) is satisfied by the target core language, the orbLanguage.version of the core version this update installs, else of the installed core; a version with no language is skipped ORB_PACKAGE_NO_LANGUAGE (compatibility is declared by the version itself, so one that declares nothing is never assumed compatible). The release version of orb is never compared with a package range. The tarball is downloaded from the registry knob (RegistryHttp) or the sourceOrigin knob (SourceHttp, one client per origin; any other host is refused ORB_PACKAGE_SOURCE), and its sha512 digest must equal the registry dist.integrity (sha512- plus base64, hash/sha): a different digest is refused `integrity-mismatch`, an unhashable one `integrity-unavailable`, and nothing is written or recorded. A verified tarball is gunzipped (maxUnpackedBytes) and read as a ustar archive (maxEntries) by the kernel; a codec refusal is ORB_PACKAGE_ARCHIVE (<code>), an entry outside package/ ORB_PACKAGE_LAYOUT. The files are written into node_modules/.orb-staging/<name>@<version> (mode 755 for executables, else 644), the old node_modules/<name> is renamed to node_modules/.orb-staging/<name>@<version>.old, the staging directory is renamed into place and only then is the backup removed (a failed rename into place renames the backup back and refuses the package ORB_PACKAGE_INSTALL, saying the previous version was restored; a failed restore names where the backup is kept; a leftover backup from an earlier crashed swap is never overwritten, it refuses the package); only then is the package's lock entry replaced and the lockfile written last. Every version may carry a top-level orbRelease block { severity security|critical|normal, advisory (one line), fixes (a semver range of the earlier versions it fixes) } in its registry manifest; no block is normal, and any other severity word is read as normal. update names, after the list rows, one `<severity> update: <name> <from> → <to>: <advisory>` line for each applied version whose own severity is security or critical. `orb update --urgent` (update only; with any other command it is refused with the usage line) installs only urgent updates: a package is urgent when some stable, non-deprecated version newer than the installed one is security or critical, declares a fixes range, the installed version satisfies that range (std-semver) and the version passes the language check above; the newest such version is installed through the same integrity check, staging swap and lockfile write, a baseline package that is not installed is never urgent, and stdout carries only the applied `<severity> update:` lines. An urgent version that fails the language check (ORB_PACKAGE_INCOMPATIBLE or ORB_PACKAGE_NO_LANGUAGE), whose fixes range std-semver refuses (ORB_PACKAGE_RELEASE), or that fails its download, integrity or install, is not applied: the installed version stays, the call answers 500, and stderr names the refusals and each confirmed-urgent advisory (a failed install leaves the old package in place, never half-installed). `orb update --global` also keeps this host's orb binary package (the orbPlatforms knob, matched on os/uname sysname and machine: @almadar/orb-darwin-arm64, -darwin-x64, -linux-x64, -linux-arm64, -windows-x64) installed like a baseline package, in the registry knob, with its own compatibility rule: it has no language range, so its newest stable, non-deprecated version is taken whose package.json declares orbReads, a range the target core language satisfies (a version without orbReads is skipped ORB_PACKAGE_NO_LANGUAGE; its orb and orbProgram blocks are not read); a package that declares orbReads is listed with kind `orb`; --urgent never installs it from nothing. A host that matches no entry, or whose os/uname fails (the Windows host does not implement it), prints one ORB_PACKAGE_PLATFORM line on stderr and no orb package is considered. Not yet ported: the kind-loads-for-this-orb problem column, the behaviors count, the update-check record and the engines subcommands; add does not remove a package that declares no orb kind."
9
+ description: "std-orb-packages — the `orb list|add|update|remove [--global]` client of the npm registry (spec/cli/orb-packages.lolo; golden: orbital-cli packages.rs), bun-free. Packages live in <dir>/node_modules (dir = the working directory, or ~/.orb with --global) and the lockfile <dir>/<lockfile> holds { packages: [{ name, version, url, integrity }] }. Every command first reads the lockfile (absent = empty) and scans node_modules (scoped names included; the entry kind symlink is the workspace link), reading each package.json: a package is an orb package when it declares orbLanguage, orb, orbVocabulary or orbProgram.kind shell|desktop, and its kinds are those. list prints one row per orb package sorted by name (package 34, version 12, kinds 26, `ok`, ` (linked)`, ` [<prefix>/]`) or --json rows. remove refuses a behavior package whose prefix a .lolo or .orb file under the working directory still imports, deletes the package (a link is unlinked, never its target) and drops its lock entry. add parses name@exact-version (a range is refused ORB_PACKAGE_RANGE; a workspace-linked package is refused ORB_PACKAGE_LINKED) or a direct tarball URL (refused: it carries no integrity), and resolves name@version through GET <registry>/<name>/<version> (the npm version manifest: dist.tarball and dist.integrity). update reads the npm packument GET <registry>/<name> of every non-linked orb package and of every missing baseline package (an upgrade from nothing), and moves each to the newest stable, non-deprecated version above the installed one whose language is compatible: the running orb answers `orb --version` as `orb X.Y.Z (language R)` (any other form is refused) and keeps R; @almadar/core resolves first, and its candidate is compatible when its orbLanguage.version satisfies R; every other package is compatible when its language range (orb.language, orbLanguage.language, orbVocabulary.language or orbProgram.language, the first present) is satisfied by the target core language, the orbLanguage.version of the core version this update installs, else of the installed core; a version with no language is skipped ORB_PACKAGE_NO_LANGUAGE (compatibility is declared by the version itself, so one that declares nothing is never assumed compatible). The release version of orb is never compared with a package range. The tarball is downloaded from the registry knob (RegistryHttp) or the sourceOrigin knob (SourceHttp, one client per origin; any other host is refused ORB_PACKAGE_SOURCE), and its sha512 digest must equal the registry dist.integrity (sha512- plus base64, hash/sha): a different digest is refused `integrity-mismatch`, an unhashable one `integrity-unavailable`, and nothing is written or recorded. A verified tarball is gunzipped (maxUnpackedBytes) and read as a ustar archive (maxEntries) by the kernel; a codec refusal is ORB_PACKAGE_ARCHIVE (<code>), an entry outside package/ ORB_PACKAGE_LAYOUT. The files are written into node_modules/.orb-staging/<name>@<version> (mode 755 for executables, else 644), the old node_modules/<name> is renamed to node_modules/.orb-staging/<name>@<version>.old, the staging directory is renamed into place and only then is the backup removed (a failed rename into place renames the backup back and refuses the package ORB_PACKAGE_INSTALL, saying the previous version was restored; a failed restore names where the backup is kept; a leftover backup from an earlier crashed swap is never overwritten, it refuses the package); only then is the package's lock entry replaced and the lockfile written last. Every version may carry a top-level orbRelease block { severity security|critical|normal, advisory (one line), fixes (a semver range of the earlier versions it fixes) } in its registry manifest; no block is normal, and any other severity word is read as normal. update names, after the list rows, one `<severity> update: <name> <from> → <to>: <advisory>` line for each applied version whose own severity is security or critical. `orb update --urgent` (update only; with any other command it is refused with the usage line) installs only urgent updates: a package is urgent when some stable, non-deprecated version newer than the installed one is security or critical, declares a fixes range, the installed version satisfies that range (std-semver) and the version passes the language check above; the newest such version is installed through the same integrity check, staging swap and lockfile write, a baseline package that is not installed is never urgent, and stdout carries only the applied `<severity> update:` lines. An urgent version that fails the language check (ORB_PACKAGE_INCOMPATIBLE or ORB_PACKAGE_NO_LANGUAGE), whose fixes range std-semver refuses (ORB_PACKAGE_RELEASE), or that fails its download, integrity or install, is not applied: the installed version stays, the call answers 500, and stderr names the refusals and each confirmed-urgent advisory (a failed install leaves the old package in place, never half-installed). `orb update --global` also keeps this host's orb binary package (the orbPlatforms knob, matched on os/uname sysname and machine: @almadar/orb-darwin-arm64, -darwin-x64, -linux-x64, -linux-arm64, -windows-x64) installed like a baseline package, in the registry knob, with its own compatibility rule: it has no language range, so its newest stable, non-deprecated version is taken whose package.json declares orbReads, a range the target core language satisfies (a version without orbReads is skipped ORB_PACKAGE_NO_LANGUAGE; its orb and orbProgram blocks are not read); a package that declares orbReads is listed with kind `orb`; --urgent never installs it from nothing. A host that matches no entry, or whose os/uname fails (the Windows host does not implement it), prints one ORB_PACKAGE_PLATFORM line on stderr and no orb package is considered. A package whose package.json declares orbProgram also installs each of its optionalDependencies at its exact version whose registry manifest os and cpu include this host's (the os and cpu of the orbPlatforms entry os/uname matched, the npm platform rule; every add and update asks os/uname); a host os/uname cannot place installs none of them. Every file the package.json bin map names is written executable. Not yet ported: the kind-loads-for-this-orb problem column, the behaviors count, the update-check record and the engines subcommands; add does not remove a package that declares no orb kind."
10
10
  ]
11
11
  uses Spec from "almadar-std/orb-packages"
12
12
  uses Http from "std/behaviors/std-http-client"
@@ -17,18 +17,18 @@ type PackageKind = "language" | "behaviors" | "language pack" | "shell" | "deskt
17
17
  type PackageRow = { package : string!, kinds : [PackageKind]!, version : string!, path : string!, link : boolean!, prefix : string?, behaviors : number?, problem : string? }
18
18
  type LockEntry = { name : string!, version : string!, url : string!, integrity : string! }
19
19
  type BaselineEntry = { name : string!, registry : string! }
20
- type OrbPlatform = { sysname : string!, machine : string!, package : string! }
20
+ type OrbPlatform = { sysname : string!, machine : string!, package : string!, os : string!, cpu : string! }
21
21
  type LockFile = { packages : [LockEntry]! }
22
- type PackageTarget = { name : string!, version : string!, url : string!, integrity : string!, severity : string?, advisory : string?, installedVersion : string? }
22
+ type PackageTarget = { name : string!, version : string!, url : string!, integrity : string!, severity : string?, advisory : string?, installedVersion : string?, platform : boolean? }
23
23
  type Marker = { x : string? }
24
24
  type LanguageBlock = { version : string? }
25
25
  type OrbPackagesBlock = { prefix : string? }
26
26
  type ProgramBlock = { kind : string?, name : string? }
27
- type OrbPackagesManifest = { name : string?, version : string?, orbLanguage : LanguageBlock?, orb : OrbPackagesBlock?, orbVocabulary : Marker?, orbProgram : ProgramBlock?, orbReads : string? }
27
+ type OrbPackagesManifest = { name : string?, version : string?, orbLanguage : LanguageBlock?, orb : OrbPackagesBlock?, orbVocabulary : Marker?, orbProgram : ProgramBlock?, orbReads : string?, optionalDependencies : Map string string?, bin : Map string string? }
28
28
  type NpmDist = { tarball : string!, integrity : string? }
29
29
  type NpmLanguage = { language : string?, version : string? }
30
30
  type NpmRelease = { severity : string?, advisory : string?, fixes : string? }
31
- type NpmManifest = { version : string!, deprecated : string?, dist : NpmDist?, orb : NpmLanguage?, orbLanguage : NpmLanguage?, orbVocabulary : NpmLanguage?, orbProgram : NpmLanguage?, orbRelease : NpmRelease?, orbReads : string? }
31
+ type NpmManifest = { version : string!, deprecated : string?, dist : NpmDist?, orb : NpmLanguage?, orbLanguage : NpmLanguage?, orbVocabulary : NpmLanguage?, orbProgram : NpmLanguage?, orbRelease : NpmRelease?, orbReads : string?, os : [string]?, cpu : [string]? }
32
32
  type Packument = { name : string!, versions : Map string NpmManifest! }
33
33
  type Candidate = { version : string!, key : number!, language : string!, provides : string!, url : string!, integrity : string!, severity : string?, advisory : string?, fixes : string? }
34
34
  type Subject = { package : string!, version : string!, missing : boolean! }
@@ -107,6 +107,8 @@ orbital OrbPackagesOrbital {
107
107
  orbPackage : string = ""
108
108
  unamed : boolean = false
109
109
  platformNote : string = ""
110
+ hostOs : string = ""
111
+ hostCpu : string = ""
110
112
  placeError : string = ""
111
113
  }
112
114
 
@@ -176,6 +178,8 @@ orbital OrbPackagesOrbital {
176
178
  (set @entity.orbPackage "")
177
179
  (set @entity.unamed false)
178
180
  (set @entity.platformNote "")
181
+ (set @entity.hostOs "")
182
+ (set @entity.hostCpu "")
179
183
  (set @entity.lock [])
180
184
  (set @entity.pkgs [])
181
185
  (set @entity.rows [])
@@ -281,14 +285,14 @@ orbital OrbPackagesOrbital {
281
285
  (emit PKG_RM_NEXT { })
282
286
  PKG_DISPATCH -> ready when (and (not @entity.installed) (= @entity.cmd "add") (= (array/len @entity.args) 0))
283
287
  (emit PACKAGES_ANSWERED { status: 400, body: "", stderr: "usage: orb add <package, an at sign and an exact version | tarball url> [--global]" })
284
- PKG_DISPATCH -> resolving when (and (not @entity.installed) (= @entity.cmd "add") (> (array/len @entity.args) 0))
288
+ PKG_DISPATCH -> resolving when (and (not @entity.installed) (= @entity.cmd "add") (> (array/len @entity.args) 0) @entity.unamed)
285
289
  (set @entity.targets [])
286
290
  (set @entity.cursor 0)
287
291
  (emit PKG_PLAN_ADD { })
288
- PKG_DISPATCH -> resolving when (and (not @entity.installed) (= @entity.cmd "update") (and @entity.global (not @entity.urgent) (not @entity.unamed)))
292
+ PKG_DISPATCH -> resolving when (and (not @entity.installed) (or (= @entity.cmd "update") (and (= @entity.cmd "add") (> (array/len @entity.args) 0))) (not @entity.unamed))
289
293
  (set @entity.targets [])
290
294
  (os/uname { key: "uname" emit: { success: PKG_UNAME, failure: PKG_UNAME_FAILED } })
291
- PKG_DISPATCH -> resolving when (and (not @entity.installed) (= @entity.cmd "update") (not (and @entity.global (not @entity.urgent) (not @entity.unamed))))
295
+ PKG_DISPATCH -> resolving when (and (not @entity.installed) (= @entity.cmd "update") @entity.unamed)
292
296
  (set @entity.targets [])
293
297
  (set @entity.subjects (let ((all (array/concat (array/map (array/filter @entity.rows (fn r (not (object/get @r "link")))) (fn r { package: (object/get @r "package"), version: (object/get @r "version"), missing: false })) (if @entity.urgent [] (array/map (array/filter (array/concat @config.baseline (if (!= @entity.orbPackage "") [{ name: @entity.orbPackage, registry: @config.registry }] [])) (fn b (and (= (array/len (array/filter @entity.rows (fn r (= (object/get @r "package") (object/get @b "name"))))) 0) (= (object/get @b "registry") @config.registry)))) (fn b { package: (object/get @b "name"), version: "0.0.0", missing: true })))))) (array/concat (array/filter @all (fn s (= (object/get @s "package") @config.corePackage))) (array/filter @all (fn s (!= (object/get @s "package") @config.corePackage))))))
294
298
  (set @entity.refused (if @entity.urgent [] (array/map (array/filter (array/concat @config.baseline (if (!= @entity.orbPackage "") [{ name: @entity.orbPackage, registry: @config.registry }] [])) (fn b (and (= (array/len (array/filter @entity.rows (fn r (= (object/get @r "package") (object/get @b "name"))))) 0) (!= (object/get @b "registry") @config.registry)))) (fn b (str/concat (object/get @b "name") ": ORB_PACKAGE_SOURCE (baseline registry " (object/get @b "registry") " is not the registry knob)")))))
@@ -486,13 +490,15 @@ orbital OrbPackagesOrbital {
486
490
  INIT -> resolving
487
491
  PKG_UNAME -> dispatching
488
492
  (set @entity.unamed true)
489
- (set @entity.orbPackage (object/get (default (array/find @config.orbPlatforms (fn x (and (= (object/get @x "sysname") @payload.sysname) (= (object/get @x "machine") @payload.machine)))) { sysname: "", machine: "", package: "" }) "package"))
490
- (set @entity.platformNote (if (= (object/get (default (array/find @config.orbPlatforms (fn x (and (= (object/get @x "sysname") @payload.sysname) (= (object/get @x "machine") @payload.machine)))) { sysname: "", machine: "", package: "" }) "package") "") (str/concat "orb: ORB_PACKAGE_PLATFORM (" @payload.sysname " " @payload.machine " has no orb platform package in the orbPlatforms knob; the orb binary was not considered)") ""))
493
+ (set @entity.hostOs (object/get (default (array/find @config.orbPlatforms (fn x (and (= (object/get @x "sysname") @payload.sysname) (= (object/get @x "machine") @payload.machine)))) { sysname: "", machine: "", package: "", os: "", cpu: "" }) "os"))
494
+ (set @entity.hostCpu (object/get (default (array/find @config.orbPlatforms (fn x (and (= (object/get @x "sysname") @payload.sysname) (= (object/get @x "machine") @payload.machine)))) { sysname: "", machine: "", package: "", os: "", cpu: "" }) "cpu"))
495
+ (set @entity.orbPackage (if (and @entity.global (= @entity.cmd "update") (not @entity.urgent)) (object/get (default (array/find @config.orbPlatforms (fn x (and (= (object/get @x "sysname") @payload.sysname) (= (object/get @x "machine") @payload.machine)))) { sysname: "", machine: "", package: "", os: "", cpu: "" }) "package") ""))
496
+ (set @entity.platformNote (if (or (not (and @entity.global (= @entity.cmd "update") (not @entity.urgent))) (!= (object/get (default (array/find @config.orbPlatforms (fn x (and (= (object/get @x "sysname") @payload.sysname) (= (object/get @x "machine") @payload.machine)))) { sysname: "", machine: "", package: "", os: "", cpu: "" }) "package") "")) "" (str/concat "orb: ORB_PACKAGE_PLATFORM (" @payload.sysname " " @payload.machine " has no orb platform package in the orbPlatforms knob; the orb binary was not considered)")))
491
497
  (emit PKG_DISPATCH { })
492
498
  PKG_UNAME_FAILED -> dispatching
493
499
  (set @entity.unamed true)
494
500
  (set @entity.orbPackage "")
495
- (set @entity.platformNote (str/concat "orb: ORB_PACKAGE_PLATFORM (the platform could not be determined: " (default @payload.error "") "; the orb binary was not considered)"))
501
+ (set @entity.platformNote (if (and @entity.global (= @entity.cmd "update") (not @entity.urgent)) (str/concat "orb: ORB_PACKAGE_PLATFORM (the platform could not be determined: " (default @payload.error "") "; the orb binary was not considered)") ""))
496
502
  (emit PKG_DISPATCH { })
497
503
  PKG_BACKUP_NEXT -> resolving when (and @entity.hadOld @entity.global)
498
504
  (os/rmdir (str/concat "~/.orb/node_modules/" (str/concat @entity.stage ".old")) true { key: "backupclear" emit: { success: PKG_BACKUP_GONE, failure: PKG_BACKUP_GONE } })
@@ -609,8 +615,11 @@ orbital OrbPackagesOrbital {
609
615
  (emit PKG_DOWNLOAD { url: (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "url") })
610
616
  PKG_TARGET_NEXT -> resolving when (and (< @entity.cursor (array/len @entity.targets)) (= (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "url") ""))
611
617
  (emit PK_GET { key: "resolve", method: "GET", target: (str/concat "/" (str/join (str/split (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "name") "/") "%2f") "/" (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "version")), headers: [{ name: "accept", value: "application/json" }], body: (bytes/from-string ""), stream: "none" })
612
- PKG_RESOLVED -> downloading when (and (!= @entity.mf null) (!= (object/get @entity.mf "dist") null))
613
- (set @entity.targets (array/map (array/range 0 (array/len @entity.targets)) (fn i (if (= @i @entity.cursor) { name: (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "name"), version: (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "version"), url: (default (object/get (default (object/get @entity.mf "dist") { tarball: "" }) "tarball") ""), integrity: (default (object/get (default (object/get @entity.mf "dist") { tarball: "" }) "integrity") "") } (default (array/nth @entity.targets @i) { name: "", version: "", url: "", integrity: "" })))))
618
+ PKG_RESOLVED -> resolving when (and (default (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "platform") false) (!= @entity.mf null) (not (and (array/includes (default (object/get @entity.mf "os") []) @entity.hostOs) (array/includes (default (object/get @entity.mf "cpu") []) @entity.hostCpu))))
619
+ (set @entity.cursor (+ @entity.cursor 1))
620
+ (emit PKG_TARGET_NEXT { })
621
+ PKG_RESOLVED -> downloading when (and (!= @entity.mf null) (!= (object/get @entity.mf "dist") null) (not (and (default (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "platform") false) (not (and (array/includes (default (object/get @entity.mf "os") []) @entity.hostOs) (array/includes (default (object/get @entity.mf "cpu") []) @entity.hostCpu))))))
622
+ (set @entity.targets (array/map (array/range 0 (array/len @entity.targets)) (fn i (if (= @i @entity.cursor) { name: (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "name"), version: (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "version"), url: (default (object/get (default (object/get @entity.mf "dist") { tarball: "" }) "tarball") ""), integrity: (default (object/get (default (object/get @entity.mf "dist") { tarball: "" }) "integrity") ""), platform: (default (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "platform") false) } (default (array/nth @entity.targets @i) { name: "", version: "", url: "", integrity: "" })))))
614
623
  (emit PKG_DOWNLOAD { url: (default (object/get (default (object/get @entity.mf "dist") { tarball: "" }) "tarball") "") })
615
624
  PKG_RESOLVED -> resolving when (or (= @entity.mf null) (= (object/get @entity.mf "dist") null))
616
625
  (set @entity.refused (array/append @entity.refused (str/concat (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "name") " version " (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "version") ": ORB_PACKAGE_NOT_FOUND (registry answered " @payload.status ")")))
@@ -684,7 +693,7 @@ orbital OrbPackagesOrbital {
684
693
  (set @entity.cursor (+ @entity.cursor 1))
685
694
  (emit PKG_TARGET_NEXT { })
686
695
  PKG_UNTARRED -> installing when (and (!= @entity.tar null) (default (object/get @entity.tar "ok") false))
687
- (set @entity.files (default (object/get @entity.tar "entries") []))
696
+ (set @entity.files (let ((es (default (object/get @entity.tar "entries") []))) (let ((pj (array/find @es (fn e (= (object/get @e "path") "package/package.json"))))) (let ((bins (if (= @pj null) [] (let ((m (json/parse (default (bytes/to-string (object/get @pj "data")) "") OrbPackagesManifest))) (if (= @m null) [] (array/map (object/entries (default (object/get @m "bin") {})) (fn b (str/concat "package/" (str/replace-pattern (default (array/nth @b 1) "") "^\\./" ""))))))))) (array/map @es (fn e { path: (object/get @e "path"), data: (object/get @e "data"), executable: (or (object/get @e "executable") (array/includes @bins (object/get @e "path"))) }))))))
688
697
  (set @entity.tar null)
689
698
  (emit PKG_LAYOUT { })
690
699
  PKG_LAYOUT -> resolving when (or (= (array/len @entity.files) 0) (> (array/len (array/filter @entity.files (fn e (not (str/startsWith (object/get @e "path") "package/"))))) 0))
@@ -761,7 +770,8 @@ orbital OrbPackagesOrbital {
761
770
  (set @entity.lock (array/append (array/filter @entity.lock (fn l (!= (object/get @l "name") (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "name")))) { name: (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "name"), version: (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "version"), url: (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "url"), integrity: (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "integrity") }))
762
771
  (set @entity.lockDirty true)
763
772
  (set @entity.applied (if (array/includes ["security", "critical"] (default (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "severity") "normal")) (array/append @entity.applied (str/concat (default (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "severity") "") " update: " (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "name") " " (default (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "installedVersion") "") " → " (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "version") ": " (default (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "advisory") ""))) @entity.applied))
764
- (set @entity.done (array/append @entity.done (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "name")))
773
+ (set @entity.done (if (default (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "platform") false) @entity.done (array/append @entity.done (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "name"))))
774
+ (set @entity.targets (let ((pj (array/find @entity.files (fn e (= (object/get @e "path") "package/package.json"))))) (let ((m (if (= @pj null) null (json/parse (default (bytes/to-string (object/get @pj "data")) "") OrbPackagesManifest)))) (if (or (= @m null) (= (object/get @m "orbProgram") null) (= @entity.hostOs "")) @entity.targets (array/concat @entity.targets (array/map (object/entries (default (object/get @m "optionalDependencies") {})) (fn d { name: (array/nth @d 0), version: (array/nth @d 1), url: "", integrity: "", platform: true })))))))
765
775
  (set @entity.files [])
766
776
  (set @entity.tarball (bytes/from-string ""))
767
777
  (emit PACKAGE_INSTALLED { name: (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "name"), version: (object/get (default (array/nth @entity.targets @entity.cursor) { name: "", version: "", url: "", integrity: "" }) "version"), kinds: [] })
@@ -1076,7 +1086,7 @@ orbital OrbPackagesOrbital {
1076
1086
  baseline : [BaselineEntry] = [{ name: (quote "@almadar/core"), registry: "https://registry.npmjs.org" }, { name: (quote "@almadar/std"), registry: "https://registry.npmjs.org" }, { name: (quote "@almadar/lolo-ar"), registry: "https://registry.npmjs.org" }, { name: (quote "@almadar/lolo-sl"), registry: "https://registry.npmjs.org" }, { name: (quote "@almadar/orb-shell-typescript"), registry: "https://registry.npmjs.org" }]
1077
1087
  @label "Baseline"
1078
1088
  @description "The packages `orb update` installs when missing, each resolved like an upgrade from nothing: the newest stable, non-deprecated version whose language is compatible (core: its orbLanguage.version is in the range this orb reads; any other package: its language range accepts the core language this update installs, else the installed one), read from its registry."
1079
- orbPlatforms : [OrbPlatform] = [{ sysname: "Darwin", machine: "arm64", package: (quote "@almadar/orb-darwin-arm64") }, { sysname: "Darwin", machine: "x86_64", package: (quote "@almadar/orb-darwin-x64") }, { sysname: "Linux", machine: "x86_64", package: (quote "@almadar/orb-linux-x64") }, { sysname: "Linux", machine: "aarch64", package: (quote "@almadar/orb-linux-arm64") }, { sysname: "Linux", machine: "arm64", package: (quote "@almadar/orb-linux-arm64") }, { sysname: "Windows_NT", machine: "AMD64", package: (quote "@almadar/orb-windows-x64") }]
1089
+ orbPlatforms : [OrbPlatform] = [{ sysname: "Darwin", machine: "arm64", package: (quote "@almadar/orb-darwin-arm64"), os: "darwin", cpu: "arm64" }, { sysname: "Darwin", machine: "x86_64", package: (quote "@almadar/orb-darwin-x64"), os: "darwin", cpu: "x64" }, { sysname: "Linux", machine: "x86_64", package: (quote "@almadar/orb-linux-x64"), os: "linux", cpu: "x64" }, { sysname: "Linux", machine: "aarch64", package: (quote "@almadar/orb-linux-arm64"), os: "linux", cpu: "arm64" }, { sysname: "Linux", machine: "arm64", package: (quote "@almadar/orb-linux-arm64"), os: "linux", cpu: "arm64" }, { sysname: "Windows_NT", machine: "AMD64", package: (quote "@almadar/orb-windows-x64"), os: "win32", cpu: "x64" }]
1080
1090
  @label "Orb platform packages"
1081
1091
  @description "The orb binary's own package per platform, keyed by the sysname and machine os/uname answers. `orb update --global` (not --urgent) asks os/uname and resolves the entry that matches this host like a baseline package, in the registry knob, but on its own compatibility rule: an orb platform package has no language range, so a version is compatible when its package.json declares orbReads, a range of core languages, and the target core language satisfies it (a version with no orbReads is skipped ORB_PACKAGE_NO_LANGUAGE). A host that matches no entry, or whose os/uname fails, gets one loud ORB_PACKAGE_PLATFORM line on stderr and no orb package is considered."
1082
1092
  maxUnpackedBytes : number = 536870912
@@ -3,10 +3,11 @@ app std-orb-serve [
3
3
  inbound: ["cli-serve"],
4
4
  env: ["HOME", "FIREBASE_AUTH_EMULATOR_HOST", "FIREBASE_PROJECT_ID"],
5
5
  fs: { "~/.almadar/serve": [create], "~/.almadar/serve/**": [write, create, read], cwd: ".orbital": [create], cwd: ".orbital/serve": [create], cwd: ".orbital/serve/**": [write, create] },
6
- description: "std-orb-serve — the `orb serve <file> [--port N] [--host H] [--no-mock] [--client-dir DIR] [--open] [--no-emulators]` command (spec/cli/orb-serve.lolo; port of orbital-cli program_command.rs serve_program and server_overrides). It resolves the app with program/read { resolve: true, path }. An app that declares its own http endpoint is composed alone, and --port, --host or --client-dir is refused (status 400): its server's options are set in the program. Without --client-dir the app gets a browser client prepared first: program/eval generate { mode: client, webClient: true } compiles it client-mode into <cwd>/.orbital/serve/<app> and lays the typescript shell's prebuilt web client, with the app's runtime files over it, out in .orbital/serve/<app>/web-client, which becomes the clientDir; when FIREBASE_AUTH_EMULATOR_HOST and FIREBASE_PROJECT_ID are both set, that folder's __/firebase/init.json names the Auth emulator for the page. Otherwise it writes ~/.almadar/serve/<app path with / as _>.server.lolo, which imports std-http-server's HttpServerOrbital with the serve options as its call-site config (host, port, portFromEnv false and, with --client-dir made absolute against the working directory and required to lie under it, clientDir relative to the working directory), resolves it with program/read so each knob reaches the trait bodies, and composes the app with std-http-server's resolved program (behavior/resolve, for its header grants) carrying that configured orbital, adding the listen grant for host:port and the anchored cwd read grant of the client dir. The compose, prepare-client and answer half is std-orb-serve-handoff's ServeHandoff, which std-orb-launchpad composes as well. The command never runs the program: it answers a hand-off the bootloader acts on, status 200 with headers orb-run: server, orb-app: the absolute app path, and the composed program's JSON as the body. --open and --no-emulators answer status 500 on stderr with the texts the Rust command bailed with; a port that is not an integer in 0..65535 answers status 400 on stderr; a client dir outside the working directory, an app that names no app or a program that does not resolve or compose answers status 500 on stderr `Error: <reason>`; a missing or second file or an unknown flag answers the usage (status 400, exit 2). Defaults: port 3030, host 127.0.0.1. The resolved app is written (with its catalogs and lazy behaviors) to ~/.almadar/serve/<app path with / as _>.orb, the directory read from the HOME env grant and written under the fs grant ~/.almadar/serve/**; orb-app names that file, so the bootloader finds the catalogs."
6
+ description: "std-orb-serve — the `orb serve <file> [--port N] [--host H] [--no-mock] [--client-dir DIR] [--open] [--no-emulators]` command (spec/cli/orb-serve.lolo; port of orbital-cli program_command.rs serve_program and server_overrides). It resolves the app with program/read { resolve: true, path }. An app that declares its own http endpoint is composed alone, and --port, --host or --client-dir is refused (status 400): its server's options are set in the program. Without --client-dir the app gets a browser client prepared first: program/eval generate { mode: client, webClient: true } compiles it client-mode into <cwd>/.orbital/serve/<app> and lays the typescript shell's prebuilt web client, with the app's runtime files over it, out in .orbital/serve/<app>/web-client, which becomes the clientDir; when FIREBASE_AUTH_EMULATOR_HOST and FIREBASE_PROJECT_ID are both set, that folder's __/firebase/init.json names the Auth emulator for the page. Otherwise it writes ~/.almadar/serve/<app path with / as _>.server.lolo, which imports std-http-server's HttpServerOrbital with the serve options as its call-site config (host, port, portFromEnv false and, with --client-dir made absolute against the working directory and required to lie under it, clientDir relative to the working directory), resolves it with program/read so each knob reaches the trait bodies, and composes the app with std-http-server's resolved program (behavior/resolve, for its header grants) carrying that configured orbital, adding the listen grant for host:port and the anchored cwd read grant of the client dir. The compose, prepare-client and answer half is std-orb-serve-handoff's ServeHandoff, which std-orb-launchpad composes as well. The command never runs the program: it answers a hand-off the bootloader acts on, status 200 with headers orb-run: server, orb-app: the absolute app path, and the composed program's JSON as the body. --open and --no-emulators answer status 500 on stderr with the texts the Rust command bailed with; a port that is not an integer in 0..65535 answers status 400 on stderr; a client dir outside the working directory, an app that names no app or a program that does not resolve or compose answers status 500 on stderr `Error: <reason>`; a missing or second file or an unknown flag answers the usage (status 400, exit 2). Defaults: port 3030, host 127.0.0.1. The resolved app is written (with its catalogs and lazy behaviors) to ~/.almadar/serve/<app path with / as _>.orb, the directory read from the HOME env grant and written under the fs grant ~/.almadar/serve/**; orb-app names that file, so the bootloader finds the catalogs. Unless --no-mock, and when the app does not already seed itself, the server program also composes std-mock-page-seed, and, when the app declares an [identity] entity no trait of it signs in, std-dev-personas over that entity (std-mock-seed-marks answers both texts), so the seeder can sign each owner in and the session starts as the first declared role."
7
7
  ]
8
8
  uses Spec from "almadar-std/orb-serve"
9
9
  uses Args from "std/behaviors/std-args"
10
+ uses Marks from "std/behaviors/std-mock-seed-marks"
10
11
  uses Handoff from "std/behaviors/std-orb-serve-handoff"
11
12
  type OrbCommandArgs = { argv : [string]!, cwd : string! }
12
13
  type ArgFlag = { name : string!, aliases : [string]!, takesValue : boolean!, repeatable : boolean! }
@@ -47,6 +48,12 @@ orbital OrbServeOrbital {
47
48
  }
48
49
  }
49
50
 
51
+ trait MarksCli = Marks.traits.MarksCheck {
52
+ listens {
53
+ ServeEngine.SERVE_SEED_ASK -> MARKS_CHECK
54
+ }
55
+ }
56
+
50
57
  trait OrbServe -> ServeRun [optimistic] {
51
58
  initial: ready
52
59
 
@@ -222,8 +229,12 @@ orbital OrbServeOrbital {
222
229
 
223
230
  state writing {
224
231
  INIT -> writing
225
- SERVE_WRITE_SERVER -> writing
226
- (emit SERVE_SEED_DECIDED { seed: (if (and @entity.mock (not (array/some (object/get @entity.app "orbitals" []) (fn o (array/some (object/get @o "auxiliaryEntities" []) (fn e (= (object/get @e "collection" "") "mock_seed_marks"))))))) "uses Seed from \"std/behaviors/std-mock-page-seed\"\norbital MockData = Seed.orbitals.MockData {}\n" "") })
232
+ SERVE_WRITE_SERVER -> writing when (not @entity.mock)
233
+ (emit SERVE_SEED_DECIDED { seed: "" })
234
+ SERVE_WRITE_SERVER -> writing when @entity.mock
235
+ (emit SERVE_SEED_ASK { program: @entity.app })
236
+ SERVE_SEED_MARKED -> writing
237
+ (emit SERVE_SEED_DECIDED { seed: (if @payload.marked "" (str/concat "uses Seed from \"std/behaviors/std-mock-page-seed\"\norbital MockData = Seed.orbitals.MockData {}\n" @payload.personas)) })
227
238
  SERVE_SEED_DECIDED -> resolving
228
239
  (os/write-file (str/concat "~/.almadar/serve/" @entity.serverName) (bytes/from-string (str/concat
229
240
  "app orb-served-server [version: \"1.0.0\"]\n"
@@ -286,6 +297,11 @@ orbital OrbServeOrbital {
286
297
  SERVE_WRITE_SERVER { }
287
298
  @description "Write the server program, std-http-server imported with the serve options as its call-site config."
288
299
  @tier "internal"
300
+ SERVE_SEED_ASK {
301
+ program : ServeProgram!
302
+ }
303
+ @description "Ask std-mock-seed-marks whether the resolved app already declares the MockSeedMark store."
304
+ @tier "internal"
289
305
  SERVE_SEED_DECIDED {
290
306
  seed : string!
291
307
  }
@@ -350,6 +366,10 @@ orbital OrbServeOrbital {
350
366
  }
351
367
  @description "Compose the app with std-http-server."
352
368
  OrbServe.SERVE_START -> SERVE_START
369
+ MarksCli.MARKS_CHECKED -> SERVE_SEED_MARKED
370
+ SERVE_SEED_MARKED { marked : boolean! personas : string! }
371
+ @description "std-mock-seed-marks's MARKS_CHECKED: whether the app already declares the marks store, and the personas text that composes std-dev-personas onto the app's identity entity (empty when there is none)."
372
+ @tier "internal"
353
373
  SERVE_SEED_DECIDED { seed : string! }
354
374
  @description "The seed decision, which the server program write reads."
355
375
  @tier "internal"
@@ -363,5 +383,5 @@ orbital OrbServeOrbital {
363
383
  }
364
384
  }
365
385
 
366
- page boot as OrbServePage -> OrbServe, ArgsCli, ServeEngine, ServeHandoff
386
+ page boot as OrbServePage -> OrbServe, ArgsCli, MarksCli, ServeEngine, ServeHandoff
367
387
  }
@@ -19,7 +19,7 @@ orbital LoloKotlinOrbital {
19
19
  config {
20
20
  language: "Kotlin"
21
21
  requiresTypes: false
22
- operators: { "/": "_div({{0}}, {{1}})", "%": "_mod({{0}}, {{1}})", "math/mod": "_mod({{0}}, {{1}})", "=": "_eq({{0}}, {{1}})", "==": "_eq({{0}}, {{1}})", "!=": "(!_eq({{0}}, {{1}}))", "default": "_default({{0}}, {{1}})", "as": "{{0}}", "list": "listOf({{*}})", "str/len": "_strLen({{0}}).toDouble()", "str/upper": "{{0}}.uppercase()", "str/lower": "{{0}}.lowercase()", "str/trim": "{{0}}.trim()", "str/trimStart": "{{0}}.trimStart()", "str/trimEnd": "{{0}}.trimEnd()", "str/capitalize": "_capitalize({{0}})", "str/split": "_split({{0}}, {{1}})", "str/join": "_join({{0}}, {{1}})", "str/concat": "_concat({{*}})", "str/includes": "{{0}}.contains({{1}})", "str/startsWith": "{{0}}.startsWith({{1}})", "str/endsWith": "{{0}}.endsWith({{1}})", "str/replace": "{{0}}.replaceFirst({{1}}, {{2}})", "str/replaceAll": "{{0}}.replace({{1}}, {{2}})", "str/repeat": "{{0}}.repeat(_count({{1}}))", "str/reverse": "StringBuilder({{0}}).reverse().toString()", "str/slice#2": "_strSlice({{0}}, {{1}})", "str/slice#3": "_strSlice({{0}}, {{1}}, {{2}})", "str/padStart#2": "_padStart({{0}}, {{1}})", "str/padStart#3": "_padStart({{0}}, {{1}}, {{2}})", "str/padEnd#2": "_padEnd({{0}}, {{1}})", "str/padEnd#3": "_padEnd({{0}}, {{1}}, {{2}})", "str/truncate#2": "_truncate({{0}}, {{1}})", "str/truncate#3": "_truncate({{0}}, {{1}}, {{2}})", "str/to-int": "_toInt({{0}})", "array/len": "{{0}}.size.toDouble()", "array/avg#1": "_avg({{0}})", "array/max#1": "_amax({{0}})", "array/min#1": "_amin({{0}})", "array/first": "_first({{0}})", "array/last": "_last({{0}})", "array/nth": "_nth({{0}}, {{1}})", "array/range#2": "_range({{0}}, {{1}})", "array/range#3": "_range({{0}}, {{1}}, {{2}})", "array/slice#2": "_slice({{0}}, {{1}})", "array/slice#3": "_slice({{0}}, {{1}}, {{2}})", "array/take": "{{0}}.take(_count({{1}}))", "array/drop": "{{0}}.drop(_count({{1}}))", "array/takeLast": "{{0}}.takeLast(_count({{1}}))", "array/dropLast": "{{0}}.dropLast(_count({{1}}))", "array/append": "_append({{0}}, {{1}})", "array/prepend": "_prepend({{0}}, {{1}})", "array/includes": "{{0}}.contains({{1}})", "array/indexOf": "_indexOf({{0}}, {{1}})", "array/reverse": "{{0}}.reversed()", "array/unique": "{{0}}.distinct()", "array/flatten": "{{0}}.flatten()", "array/zip": "{{0}}.zip({{1}}).map { listOf(it.first, it.second) }", "array/sort#1": "_sort({{0}})", "array/reduce": "{{0}}.fold({{1}}, {{2}})", "array/filter": "{{0}}.filter({{1}})", "array/reject": "{{0}}.filterNot({{1}})", "array/find": "{{0}}.firstOrNull({{1}})", "array/findIndex": "{{0}}.indexOfFirst({{1}}).toDouble()", "math/abs": "Math.abs(({{0}}).toDouble())", "math/max": "maxOf({{*}})", "math/min": "minOf({{*}})", "math/round#1": "_round({{0}})", "math/round#2": "_round({{0}}, {{1}})", "math/sqrt": "_sqrt({{0}})", "math/ln": "_ln({{0}})", "math/log10": "_log10({{0}})", "math/pow": "_pow({{0}}, {{1}})", "math/sign": "Math.signum(({{0}}).toDouble())", "math/clamp": "Math.min(Math.max(({{0}}).toDouble(), ({{1}}).toDouble()), ({{2}}).toDouble())", "math/ceil": "Math.ceil(({{0}}).toDouble())", "math/floor": "Math.floor(({{0}}).toDouble())", "math/sin": "Math.sin(({{0}}).toDouble())", "math/cos": "Math.cos(({{0}}).toDouble())", "math/tan": "Math.tan(({{0}}).toDouble())", "math/atan": "Math.atan(({{0}}).toDouble())", "math/atan2": "Math.atan2(({{0}}).toDouble(), ({{1}}).toDouble())", "math/hypot": "Math.hypot(({{0}}).toDouble(), ({{1}}).toDouble())", "validate/required": "_required({{0}})", "validate/length": "(_strLen({{0}}).toDouble() == ({{1}}).toDouble())", "validate/minLength": "(_strLen({{0}}).toDouble() >= ({{1}}).toDouble())", "validate/maxLength": "(_strLen({{0}}).toDouble() <= ({{1}}).toDouble())", "validate/min": "(({{0}}).toDouble() >= ({{1}}).toDouble())", "validate/max": "(({{0}}).toDouble() <= ({{1}}).toDouble())", "validate/range": "(({{0}}).toDouble() in ({{1}}).toDouble()..({{2}}).toDouble())", "validate/oneOf": "{{1}}.contains({{0}})", "validate/equals": "_eq({{0}}, {{1}})" }
22
+ operators: { "object/get#2": "_get({{0}}, {{1}})", "/": "_div({{0}}, {{1}})", "%": "_mod({{0}}, {{1}})", "math/mod": "_mod({{0}}, {{1}})", "=": "_eq({{0}}, {{1}})", "==": "_eq({{0}}, {{1}})", "!=": "(!_eq({{0}}, {{1}}))", "default": "_default({{0}}, {{1}})", "as": "{{0}}", "list": "listOf({{*}})", "str/len": "_strLen({{0}}).toDouble()", "str/upper": "{{0}}.uppercase()", "str/lower": "{{0}}.lowercase()", "str/trim": "{{0}}.trim()", "str/trimStart": "{{0}}.trimStart()", "str/trimEnd": "{{0}}.trimEnd()", "str/capitalize": "_capitalize({{0}})", "str/split": "_split({{0}}, {{1}})", "str/join": "_join({{0}}, {{1}})", "str/concat": "_concat({{*}})", "str/includes": "{{0}}.contains({{1}})", "str/startsWith": "{{0}}.startsWith({{1}})", "str/endsWith": "{{0}}.endsWith({{1}})", "str/replace": "{{0}}.replaceFirst({{1}}, {{2}})", "str/replaceAll": "{{0}}.replace({{1}}, {{2}})", "str/repeat": "{{0}}.repeat(_count({{1}}))", "str/reverse": "StringBuilder({{0}}).reverse().toString()", "str/slice#2": "_strSlice({{0}}, {{1}})", "str/slice#3": "_strSlice({{0}}, {{1}}, {{2}})", "str/padStart#2": "_padStart({{0}}, {{1}})", "str/padStart#3": "_padStart({{0}}, {{1}}, {{2}})", "str/padEnd#2": "_padEnd({{0}}, {{1}})", "str/padEnd#3": "_padEnd({{0}}, {{1}}, {{2}})", "str/truncate#2": "_truncate({{0}}, {{1}})", "str/truncate#3": "_truncate({{0}}, {{1}}, {{2}})", "str/to-int": "_toInt({{0}})", "array/len": "{{0}}.size.toDouble()", "array/avg#1": "_avg({{0}})", "array/max#1": "_amax({{0}})", "array/min#1": "_amin({{0}})", "array/first": "_first({{0}})", "array/last": "_last({{0}})", "array/nth": "_nth({{0}}, {{1}})", "array/range#2": "_range({{0}}, {{1}})", "array/range#3": "_range({{0}}, {{1}}, {{2}})", "array/slice#2": "_slice({{0}}, {{1}})", "array/slice#3": "_slice({{0}}, {{1}}, {{2}})", "array/take": "{{0}}.take(_count({{1}}))", "array/drop": "{{0}}.drop(_count({{1}}))", "array/takeLast": "{{0}}.takeLast(_count({{1}}))", "array/dropLast": "{{0}}.dropLast(_count({{1}}))", "array/append": "_append({{0}}, {{1}})", "array/prepend": "_prepend({{0}}, {{1}})", "array/includes": "{{0}}.contains({{1}})", "array/indexOf": "_indexOf({{0}}, {{1}})", "array/reverse": "{{0}}.reversed()", "array/unique": "{{0}}.distinct()", "array/flatten": "{{0}}.flatten()", "array/zip": "{{0}}.zip({{1}}).map { listOf(it.first, it.second) }", "array/sort#1": "_sort({{0}})", "array/reduce": "{{0}}.fold({{1}}, {{2}})", "array/filter": "{{0}}.filter({{1}})", "array/reject": "{{0}}.filterNot({{1}})", "array/find": "{{0}}.firstOrNull({{1}})", "array/findIndex": "{{0}}.indexOfFirst({{1}}).toDouble()", "math/abs": "Math.abs(({{0}}).toDouble())", "math/max": "maxOf({{*}})", "math/min": "minOf({{*}})", "math/round#1": "_round({{0}})", "math/round#2": "_round({{0}}, {{1}})", "math/sqrt": "_sqrt({{0}})", "math/ln": "_ln({{0}})", "math/log10": "_log10({{0}})", "math/pow": "_pow({{0}}, {{1}})", "math/sign": "Math.signum(({{0}}).toDouble())", "math/clamp": "Math.min(Math.max(({{0}}).toDouble(), ({{1}}).toDouble()), ({{2}}).toDouble())", "math/ceil": "Math.ceil(({{0}}).toDouble())", "math/floor": "Math.floor(({{0}}).toDouble())", "math/sin": "Math.sin(({{0}}).toDouble())", "math/cos": "Math.cos(({{0}}).toDouble())", "math/tan": "Math.tan(({{0}}).toDouble())", "math/atan": "Math.atan(({{0}}).toDouble())", "math/atan2": "Math.atan2(({{0}}).toDouble(), ({{1}}).toDouble())", "math/hypot": "Math.hypot(({{0}}).toDouble(), ({{1}}).toDouble())", "validate/required": "_required({{0}})", "validate/length": "(_strLen({{0}}).toDouble() == ({{1}}).toDouble())", "validate/minLength": "(_strLen({{0}}).toDouble() >= ({{1}}).toDouble())", "validate/maxLength": "(_strLen({{0}}).toDouble() <= ({{1}}).toDouble())", "validate/min": "(({{0}}).toDouble() >= ({{1}}).toDouble())", "validate/max": "(({{0}}).toDouble() <= ({{1}}).toDouble())", "validate/range": "(({{0}}).toDouble() in ({{1}}).toDouble()..({{2}}).toDouble())", "validate/oneOf": "{{1}}.contains({{0}})", "validate/equals": "_eq({{0}}, {{1}})" }
23
23
  unary: { "-": "(-{{0}})", "not": "(!{{0}})", "array/range": "_range({{0}})", "array/sum": "_sum({{0}})", "array/count": "{{0}}.size.toDouble()", "array/sort": "_sort({{0}})", "math/round": "_round({{0}})", "array/concat": "{{0}}" }
24
24
  infix: { "+": "+", "-": "-", "*": "*", "<": "<", "<=": "<=", ">": ">", ">=": ">=", "and": "&&", "or": "||", "array/concat": "+" }
25
25
  infixForm: "({{*}})"
@@ -28,7 +28,7 @@ orbital LoloKotlinOrbital {
28
28
  indexedSource: "{{src}}.mapIndexed { i_, x_ -> Pair(i_.toDouble(), x_) }"
29
29
  indexedVars: "({{index}}, {{item}})"
30
30
  unsupportedForm: "_unsupported({{op}})"
31
- helpers: { "/": ["private fun _div(a: Number, b: Number): Double? = if (b.toDouble() == 0.0) null else a.toDouble() / b.toDouble()"], "%": ["private fun _mod(a: Number, b: Number): Double? = if (b.toDouble() == 0.0) null else a.toDouble() % b.toDouble()"], "math/mod": ["private fun _mod(a: Number, b: Number): Double? = if (b.toDouble() == 0.0) null else a.toDouble() % b.toDouble()"], "=": ["private fun _eq(a: Any?, b: Any?): Boolean = if (a is Number && b is Number) a.toDouble() == b.toDouble() else a == b"], "==": ["private fun _eq(a: Any?, b: Any?): Boolean = if (a is Number && b is Number) a.toDouble() == b.toDouble() else a == b"], "!=": ["private fun _eq(a: Any?, b: Any?): Boolean = if (a is Number && b is Number) a.toDouble() == b.toDouble() else a == b"], "default": ["private fun <T : Any> _default(v: T?, d: T): T = v ?: d"], "str/len": ["private fun _strLen(s: String): Int = s.codePointCount(0, s.length)"], "str/capitalize": ["private fun _capitalize(s: String): String {\n if (s.isEmpty()) return s\n val n = s.offsetByCodePoints(0, 1)\n return s.substring(0, n).uppercase() + s.substring(n).lowercase()\n}"], "str/split": ["private fun _split(s: String, d: String): List<String> =\n if (d == \"\") s.codePoints().toArray().map { String(Character.toChars(it)) } else s.split(d)"], "str/join": ["private fun _join(a: List<Any?>, d: String): String = a.joinToString(d) { _text(it) }", "private fun _text(v: Any?): String = when (v) {\n is String -> v\n is Boolean -> v.toString()\n is Long -> v.toString()\n is Int -> v.toString()\n is Double -> if (v.isFinite() && v == Math.floor(v)) java.math.BigDecimal(v).toBigInteger().toString() else v.toString()\n else -> throw IllegalArgumentException(\"expected string, number or boolean\")\n}"], "str/concat": ["private fun _concat(vararg v: Any?): String = v.joinToString(\"\") { _text(it) }", "private fun _text(v: Any?): String = when (v) {\n is String -> v\n is Boolean -> v.toString()\n is Long -> v.toString()\n is Int -> v.toString()\n is Double -> if (v.isFinite() && v == Math.floor(v)) java.math.BigDecimal(v).toBigInteger().toString() else v.toString()\n else -> throw IllegalArgumentException(\"expected string, number or boolean\")\n}"], "str/repeat": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _count(n: Number): Int {\n val k = _whole(n)\n if (k < 0) throw IllegalArgumentException(\"expected a whole number from 0, got \" + k)\n return k\n}"], "str/slice": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _strSlice(s: String, a: Number, b: Number? = null): String {\n val n = s.codePointCount(0, s.length)\n val x = _whole(a)\n val y = if (b == null) n else _whole(b)\n val from = if (x < 0) maxOf(n + x, 0) else minOf(x, n)\n val to = if (y < 0) maxOf(n + y, 0) else minOf(y, n)\n if (to <= from) return \"\"\n return s.substring(s.offsetByCodePoints(0, from), s.offsetByCodePoints(0, to))\n}"], "str/padStart": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _count(n: Number): Int {\n val k = _whole(n)\n if (k < 0) throw IllegalArgumentException(\"expected a whole number from 0, got \" + k)\n return k\n}", "private fun _strLen(s: String): Int = s.codePointCount(0, s.length)", "private fun _padUnit(p: String): String {\n if (p.codePointCount(0, p.length) != 1) throw IllegalArgumentException(\"expected a single padding character, got \" + p)\n return p\n}", "private fun _padStart(s: String, n: Number, p: String = \" \"): String {\n val k = _count(n) - _strLen(s)\n return if (k <= 0) s else _padUnit(p).repeat(k) + s\n}"], "str/padEnd": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _count(n: Number): Int {\n val k = _whole(n)\n if (k < 0) throw IllegalArgumentException(\"expected a whole number from 0, got \" + k)\n return k\n}", "private fun _strLen(s: String): Int = s.codePointCount(0, s.length)", "private fun _padUnit(p: String): String {\n if (p.codePointCount(0, p.length) != 1) throw IllegalArgumentException(\"expected a single padding character, got \" + p)\n return p\n}", "private fun _padEnd(s: String, n: Number, p: String = \" \"): String {\n val k = _count(n) - _strLen(s)\n return if (k <= 0) s else s + _padUnit(p).repeat(k)\n}"], "str/truncate": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _count(n: Number): Int {\n val k = _whole(n)\n if (k < 0) throw IllegalArgumentException(\"expected a whole number from 0, got \" + k)\n return k\n}", "private fun _strLen(s: String): Int = s.codePointCount(0, s.length)", "private fun _strSlice(s: String, a: Number, b: Number? = null): String {\n val n = s.codePointCount(0, s.length)\n val x = _whole(a)\n val y = if (b == null) n else _whole(b)\n val from = if (x < 0) maxOf(n + x, 0) else minOf(x, n)\n val to = if (y < 0) maxOf(n + y, 0) else minOf(y, n)\n if (to <= from) return \"\"\n return s.substring(s.offsetByCodePoints(0, from), s.offsetByCodePoints(0, to))\n}", "private fun _truncate(s: String, n: Number, suffix: String = \"...\"): String =\n if (_strLen(s) <= _count(n)) s else _strSlice(s, 0.0, n) + suffix"], "str/to-int": ["private fun _toInt(s: String): Double? =\n if (Regex(\"[+-]?[0-9]+\").matches(s)) s.toLongOrNull()?.toDouble() else null"], "array/avg": ["private fun _avg(a: List<Number>): Double? = if (a.isEmpty()) null else a.sumOf { it.toDouble() } / a.size"], "array/max": ["private fun _amax(a: List<Number>): Double? = a.maxOfOrNull { it.toDouble() }"], "array/min": ["private fun _amin(a: List<Number>): Double? = a.minOfOrNull { it.toDouble() }"], "array/first": ["private fun <T> _first(a: List<T>): T? = a.firstOrNull()"], "array/last": ["private fun <T> _last(a: List<T>): T? = a.lastOrNull()"], "array/nth": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun <T> _nth(a: List<T>, i: Number): T? {\n val k = _whole(i)\n if (k < 0) throw IllegalArgumentException(\"nth: index \" + k + \" is not a whole number from 0\")\n return a.getOrNull(k)\n}"], "array/range": ["private fun _range(a: Number, b: Number? = null, step: Number = 1.0): List<Double> {\n val from = if (b == null) 0.0 else a.toDouble()\n val to = if (b == null) a.toDouble() else b.toDouble()\n val st = step.toDouble()\n if (st == 0.0 || st.isNaN() || st.isInfinite()) throw IllegalArgumentException(\"range: step 0 must be a non-zero finite number\")\n val out = mutableListOf<Double>()\n var x = from\n while (if (st > 0) x < to else x > to) {\n out.add(x)\n x += st\n }\n return out\n}"], "array/slice": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun <T> _slice(a: List<T>, s: Number, e: Number? = null): List<T> {\n val from = _whole(s)\n val to = if (e == null) a.size else _whole(e)\n if (from < 0 || to < 0) throw IllegalArgumentException(\"slice: not a whole number from 0\")\n val end = minOf(to, a.size)\n return if (from >= end) listOf() else a.subList(from, end).toList()\n}"], "array/take": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _count(n: Number): Int {\n val k = _whole(n)\n if (k < 0) throw IllegalArgumentException(\"expected a whole number from 0, got \" + k)\n return k\n}"], "array/drop": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _count(n: Number): Int {\n val k = _whole(n)\n if (k < 0) throw IllegalArgumentException(\"expected a whole number from 0, got \" + k)\n return k\n}"], "array/takeLast": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _count(n: Number): Int {\n val k = _whole(n)\n if (k < 0) throw IllegalArgumentException(\"expected a whole number from 0, got \" + k)\n return k\n}"], "array/dropLast": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _count(n: Number): Int {\n val k = _whole(n)\n if (k < 0) throw IllegalArgumentException(\"expected a whole number from 0, got \" + k)\n return k\n}"], "array/append": ["private fun <T> _append(a: List<T>, x: T): List<T> = a + listOf(x)"], "array/prepend": ["private fun <T> _prepend(a: List<T>, x: T): List<T> = listOf(x) + a"], "array/indexOf": ["private fun <T> _indexOf(a: List<T>, x: T): Double = a.indexOf(x).toDouble()"], "array/sort": ["private fun <T : Comparable<T>> _sort(a: List<T>): List<T> = a.sorted()"], "math/round": ["private fun _round(x: Number, d: Number = 0.0): Double {\n val m = Math.pow(10.0, d.toDouble())\n return Math.copySign(Math.floor(Math.abs(x.toDouble()) * m + 0.5) / m, x.toDouble())\n}"], "math/sqrt": ["private fun _sqrt(x: Number): Double? = if (x.toDouble() < 0.0) null else Math.sqrt(x.toDouble())"], "math/ln": ["private fun _ln(x: Number): Double? = if (x.toDouble() <= 0.0) null else Math.log(x.toDouble())"], "math/log10": ["private fun _log10(x: Number): Double? = if (x.toDouble() <= 0.0) null else Math.log10(x.toDouble())"], "math/pow": ["private fun _pow(a: Number, b: Number): Double? {\n val r = Math.pow(a.toDouble(), b.toDouble())\n return if (r.isNaN() || r.isInfinite()) null else r\n}"], "validate/required": ["private fun _required(v: Any?): Boolean = v != null && v != \"\""], "validate/length": ["private fun _strLen(s: String): Int = s.codePointCount(0, s.length)"], "validate/minLength": ["private fun _strLen(s: String): Int = s.codePointCount(0, s.length)"], "validate/maxLength": ["private fun _strLen(s: String): Int = s.codePointCount(0, s.length)"], "validate/equals": ["private fun _eq(a: Any?, b: Any?): Boolean = if (a is Number && b is Number) a.toDouble() == b.toDouble() else a == b"], "array/sum": ["private fun _sum(a: List<Number>): Double = a.sumOf { it.toDouble() }"], "unsupported": ["private fun _unsupported(name: String): Nothing = throw UnsupportedOperationException(\"no native template for operator \" + name)"] }
31
+ helpers: { "object/get": ["private fun <V> _get(o: Map<String, V>, p: String): V? {\n if (p.contains(\".\")) error(\"object/get: a dotted path is not supported on a typed map\")\n return o[p]\n}"], "store": ["class Answer(val ok: Boolean, val payload: Map<String, Any?>)\n\ninterface Store {\n fun persist(op: String, entity: String, data: Any?): Answer\n fun fetch(entity: String, keep: ((Map<String, Any?>) -> Boolean)?): Answer\n}\n\nprivate fun _codePoints(a: String, b: String): Int {\n val x = a.codePoints().toArray()\n val y = b.codePoints().toArray()\n for (i in 0 until minOf(x.size, y.size)) if (x[i] != y[i]) return x[i].compareTo(y[i])\n return x.size.compareTo(y.size)\n}\n\nprivate fun _stampOrder(a: Map<String, Any?>, b: Map<String, Any?>): Int {\n val sa = a[\"createdAt\"]\n val sb = b[\"createdAt\"]\n if ((sa == null) != (sb == null)) return if (sa != null) -1 else 1\n if (sa is Number && sb is Number && sa.toDouble() != sb.toDouble()) return sa.toDouble().compareTo(sb.toDouble())\n if (sa is String && sb is String && sa != sb) return _codePoints(sa, sb)\n return _codePoints(a[\"id\"].toString(), b[\"id\"].toString())\n}\n\nclass MemoryStore : Store {\n private val tables = mutableMapOf<String, MutableList<Pair<String, MutableMap<String, Any?>>>>()\n private var minted = 0\n\n override fun persist(op: String, entity: String, data: Any?): Answer {\n val rows = tables.getOrPut(entity) { mutableListOf() }\n if (op == \"create\" && data is Map<*, *>) {\n val row = data.entries.associate { (k, v) -> k.toString() to v }.toMutableMap()\n val given = row[\"id\"]\n val id = if (given is String && given.isNotEmpty()) given else {\n minted += 1\n entity + \"-\" + minted\n }\n row[\"id\"] = id\n rows.add(id to row)\n return Answer(true, row.toMap())\n }\n val key = when (data) {\n is String -> data\n is Map<*, *> -> data[\"id\"]?.toString() ?: \"\"\n else -> \"\"\n }\n val pos = rows.indexOfFirst { it.first == key }\n if (pos < 0) return Answer(false, mapOf(\"error\" to entity + \" \" + key + \" not found\", \"code\" to \"not-found\"))\n if (op == \"delete\") {\n rows.removeAt(pos)\n return Answer(true, mapOf(\"id\" to key, \"deleted\" to true))\n }\n if (data is Map<*, *>) for ((k, v) in data) rows[pos].second[k.toString()] = v\n return Answer(true, rows[pos].second.toMap())\n }\n\n override fun fetch(entity: String, keep: ((Map<String, Any?>) -> Boolean)?): Answer {\n val rows = (tables[entity] ?: mutableListOf()).map { it.second.toMap() }.filter { keep?.invoke(it) ?: true }.sortedWith(::_stampOrder)\n return Answer(true, mapOf(\"data\" to rows, \"totalCount\" to rows.size))\n }\n}"], "router": ["private val _routerJson = kotlinx.serialization.json.Json { encodeDefaults = true; ignoreUnknownKeys = true }\n\nprivate fun _json(value: Any?): kotlinx.serialization.json.JsonElement = when (value) {\n null -> kotlinx.serialization.json.JsonNull\n Unit -> kotlinx.serialization.json.JsonObject(emptyMap())\n is kotlinx.serialization.json.JsonElement -> value\n is String -> kotlinx.serialization.json.JsonPrimitive(value)\n is Number -> kotlinx.serialization.json.JsonPrimitive(value)\n is Boolean -> kotlinx.serialization.json.JsonPrimitive(value)\n is Map<*, *> -> kotlinx.serialization.json.JsonObject(value.entries.associate { (k, v) -> k.toString() to _json(v) })\n is List<*> -> kotlinx.serialization.json.JsonArray(value.map { _json(it) })\n else -> _routerJson.encodeToJsonElement(kotlinx.serialization.serializer(value.javaClass), value)\n}\n\nprivate inline fun <reified T> _decode(value: kotlinx.serialization.json.JsonElement): T =\n _routerJson.decodeFromJsonElement(kotlinx.serialization.serializer<T>(), value)\n\nclass _RouterEntry(\n val key: String,\n val trait: Any,\n val state: () -> String,\n val entity: () -> kotlinx.serialization.json.JsonElement,\n val count: () -> Int,\n val from: (Int) -> List<Triple<String, kotlinx.serialization.json.JsonElement, Boolean>>,\n)\n\nclass _RouterItem(\n val target: String,\n val event: String,\n val payload: kotlinx.serialization.json.JsonElement,\n val source: kotlinx.serialization.json.JsonElement,\n val guard: ((kotlinx.serialization.json.JsonElement) -> Boolean)?,\n val fans: Boolean,\n val completion: Boolean,\n)\n\nclass _RouterRow(\n val source: String,\n val event: String,\n val target: String,\n val trigger: String,\n val guard: ((kotlinx.serialization.json.JsonElement) -> Boolean)?,\n val mapping: ((kotlinx.serialization.json.JsonElement) -> kotlinx.serialization.json.JsonElement)?,\n)\n\nopen class _Router {\n val entries = mutableListOf<_RouterEntry>()\n val handles = mutableMapOf<String, Map<String, List<String>>>()\n val rows = mutableListOf<_RouterRow>()\n val log = mutableListOf<Triple<String, String, kotlinx.serialization.json.JsonElement>>()\n\n fun add(\n key: String,\n trait: Any,\n state: () -> String,\n entity: () -> kotlinx.serialization.json.JsonElement,\n count: () -> Int,\n from: (Int) -> List<Triple<String, kotlinx.serialization.json.JsonElement, Boolean>>,\n ) {\n entries.add(_RouterEntry(key, trait, state, entity, count, from))\n }\n\n fun row(\n source: String,\n event: String,\n target: String,\n trigger: String,\n guard: ((kotlinx.serialization.json.JsonElement) -> Boolean)?,\n mapping: ((kotlinx.serialization.json.JsonElement) -> kotlinx.serialization.json.JsonElement)?,\n ) {\n rows.add(_RouterRow(source, event, target, trigger, guard, mapping))\n }\n\n fun entry(key: String): _RouterEntry? = entries.firstOrNull { it.key == key }\n\n fun trait(key: String): Any? = entry(key)?.trait\n\n open fun deliver(target: String, event: String, payload: kotlinx.serialization.json.JsonElement) {}\n\n private fun targets(source: String, event: String, payload: kotlinx.serialization.json.JsonElement, completion: Boolean): List<_RouterItem> =\n rows.filter { it.source == source && it.event == event }.map {\n _RouterItem(it.target, it.trigger, it.mapping?.invoke(payload) ?: payload, payload, it.guard, false, completion)\n }\n\n fun dispatch(trait: String, event: String, payload: kotlinx.serialization.json.JsonElement) {\n val queue = ArrayDeque(listOf(_RouterItem(trait, event, payload, payload, null, true, false)))\n val seen = mutableSetOf<String>()\n var steps = 0\n while (queue.isNotEmpty()) {\n val item = queue.removeFirst()\n val e = entry(item.target) ?: continue\n val key = listOf(item.target, item.event, e.state(), item.payload.toString(), e.entity().toString()).joinToString(\"\\u001f\")\n if (!item.completion && key in seen) continue\n val g = item.guard\n if (g != null && !g(item.source)) continue\n if (steps >= 2000) break\n steps += 1\n seen.add(key)\n val n = e.count()\n deliver(item.target, item.event, item.payload)\n val fanned = if (item.fans) targets(item.target, item.event, item.payload, false).toMutableList() else mutableListOf()\n val own = mutableListOf<_RouterItem>()\n val newState = e.state()\n for ((ev, out, completion) in e.from(n)) {\n log.add(Triple(item.target, ev, out))\n if (handles[item.target]?.get(newState)?.contains(ev) == true) {\n own.add(_RouterItem(item.target, ev, out, out, null, false, completion))\n }\n fanned.addAll(targets(item.target, ev, out, completion))\n }\n queue.addAll(0, own)\n queue.addAll(fanned)\n }\n }\n}"], "/": ["private fun _div(a: Number, b: Number): Double? = if (b.toDouble() == 0.0) null else a.toDouble() / b.toDouble()"], "%": ["private fun _mod(a: Number, b: Number): Double? = if (b.toDouble() == 0.0) null else a.toDouble() % b.toDouble()"], "math/mod": ["private fun _mod(a: Number, b: Number): Double? = if (b.toDouble() == 0.0) null else a.toDouble() % b.toDouble()"], "=": ["private fun _eq(a: Any?, b: Any?): Boolean = if (a is Number && b is Number) a.toDouble() == b.toDouble() else a == b"], "==": ["private fun _eq(a: Any?, b: Any?): Boolean = if (a is Number && b is Number) a.toDouble() == b.toDouble() else a == b"], "!=": ["private fun _eq(a: Any?, b: Any?): Boolean = if (a is Number && b is Number) a.toDouble() == b.toDouble() else a == b"], "default": ["private fun <T : Any> _default(v: T?, d: T): T = v ?: d"], "str/len": ["private fun _strLen(s: String): Int = s.codePointCount(0, s.length)"], "str/capitalize": ["private fun _capitalize(s: String): String {\n if (s.isEmpty()) return s\n val n = s.offsetByCodePoints(0, 1)\n return s.substring(0, n).uppercase() + s.substring(n).lowercase()\n}"], "str/split": ["private fun _split(s: String, d: String): List<String> =\n if (d == \"\") s.codePoints().toArray().map { String(Character.toChars(it)) } else s.split(d)"], "str/join": ["private fun _join(a: List<Any?>, d: String): String = a.joinToString(d) { _text(it) }", "private fun _text(v: Any?): String = when (v) {\n is String -> v\n is Boolean -> v.toString()\n is Long -> v.toString()\n is Int -> v.toString()\n is Double -> if (v.isFinite() && v == Math.floor(v)) java.math.BigDecimal(v).toBigInteger().toString() else v.toString()\n else -> throw IllegalArgumentException(\"expected string, number or boolean\")\n}"], "str/concat": ["private fun _concat(vararg v: Any?): String = v.joinToString(\"\") { _text(it) }", "private fun _text(v: Any?): String = when (v) {\n is String -> v\n is Boolean -> v.toString()\n is Long -> v.toString()\n is Int -> v.toString()\n is Double -> if (v.isFinite() && v == Math.floor(v)) java.math.BigDecimal(v).toBigInteger().toString() else v.toString()\n else -> throw IllegalArgumentException(\"expected string, number or boolean\")\n}"], "str/repeat": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _count(n: Number): Int {\n val k = _whole(n)\n if (k < 0) throw IllegalArgumentException(\"expected a whole number from 0, got \" + k)\n return k\n}"], "str/slice": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _strSlice(s: String, a: Number, b: Number? = null): String {\n val n = s.codePointCount(0, s.length)\n val x = _whole(a)\n val y = if (b == null) n else _whole(b)\n val from = if (x < 0) maxOf(n + x, 0) else minOf(x, n)\n val to = if (y < 0) maxOf(n + y, 0) else minOf(y, n)\n if (to <= from) return \"\"\n return s.substring(s.offsetByCodePoints(0, from), s.offsetByCodePoints(0, to))\n}"], "str/padStart": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _count(n: Number): Int {\n val k = _whole(n)\n if (k < 0) throw IllegalArgumentException(\"expected a whole number from 0, got \" + k)\n return k\n}", "private fun _strLen(s: String): Int = s.codePointCount(0, s.length)", "private fun _padUnit(p: String): String {\n if (p.codePointCount(0, p.length) != 1) throw IllegalArgumentException(\"expected a single padding character, got \" + p)\n return p\n}", "private fun _padStart(s: String, n: Number, p: String = \" \"): String {\n val k = _count(n) - _strLen(s)\n return if (k <= 0) s else _padUnit(p).repeat(k) + s\n}"], "str/padEnd": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _count(n: Number): Int {\n val k = _whole(n)\n if (k < 0) throw IllegalArgumentException(\"expected a whole number from 0, got \" + k)\n return k\n}", "private fun _strLen(s: String): Int = s.codePointCount(0, s.length)", "private fun _padUnit(p: String): String {\n if (p.codePointCount(0, p.length) != 1) throw IllegalArgumentException(\"expected a single padding character, got \" + p)\n return p\n}", "private fun _padEnd(s: String, n: Number, p: String = \" \"): String {\n val k = _count(n) - _strLen(s)\n return if (k <= 0) s else s + _padUnit(p).repeat(k)\n}"], "str/truncate": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _count(n: Number): Int {\n val k = _whole(n)\n if (k < 0) throw IllegalArgumentException(\"expected a whole number from 0, got \" + k)\n return k\n}", "private fun _strLen(s: String): Int = s.codePointCount(0, s.length)", "private fun _strSlice(s: String, a: Number, b: Number? = null): String {\n val n = s.codePointCount(0, s.length)\n val x = _whole(a)\n val y = if (b == null) n else _whole(b)\n val from = if (x < 0) maxOf(n + x, 0) else minOf(x, n)\n val to = if (y < 0) maxOf(n + y, 0) else minOf(y, n)\n if (to <= from) return \"\"\n return s.substring(s.offsetByCodePoints(0, from), s.offsetByCodePoints(0, to))\n}", "private fun _truncate(s: String, n: Number, suffix: String = \"...\"): String =\n if (_strLen(s) <= _count(n)) s else _strSlice(s, 0.0, n) + suffix"], "str/to-int": ["private fun _toInt(s: String): Double? =\n if (Regex(\"[+-]?[0-9]+\").matches(s)) s.toLongOrNull()?.toDouble() else null"], "array/avg": ["private fun _avg(a: List<Number>): Double? = if (a.isEmpty()) null else a.sumOf { it.toDouble() } / a.size"], "array/max": ["private fun _amax(a: List<Number>): Double? = a.maxOfOrNull { it.toDouble() }"], "array/min": ["private fun _amin(a: List<Number>): Double? = a.minOfOrNull { it.toDouble() }"], "array/first": ["private fun <T> _first(a: List<T>): T? = a.firstOrNull()"], "array/last": ["private fun <T> _last(a: List<T>): T? = a.lastOrNull()"], "array/nth": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun <T> _nth(a: List<T>, i: Number): T? {\n val k = _whole(i)\n if (k < 0) throw IllegalArgumentException(\"nth: index \" + k + \" is not a whole number from 0\")\n return a.getOrNull(k)\n}"], "array/range": ["private fun _range(a: Number, b: Number? = null, step: Number = 1.0): List<Double> {\n val from = if (b == null) 0.0 else a.toDouble()\n val to = if (b == null) a.toDouble() else b.toDouble()\n val st = step.toDouble()\n if (st == 0.0 || st.isNaN() || st.isInfinite()) throw IllegalArgumentException(\"range: step 0 must be a non-zero finite number\")\n val out = mutableListOf<Double>()\n var x = from\n while (if (st > 0) x < to else x > to) {\n out.add(x)\n x += st\n }\n return out\n}"], "array/slice": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun <T> _slice(a: List<T>, s: Number, e: Number? = null): List<T> {\n val from = _whole(s)\n val to = if (e == null) a.size else _whole(e)\n if (from < 0 || to < 0) throw IllegalArgumentException(\"slice: not a whole number from 0\")\n val end = minOf(to, a.size)\n return if (from >= end) listOf() else a.subList(from, end).toList()\n}"], "array/take": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _count(n: Number): Int {\n val k = _whole(n)\n if (k < 0) throw IllegalArgumentException(\"expected a whole number from 0, got \" + k)\n return k\n}"], "array/drop": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _count(n: Number): Int {\n val k = _whole(n)\n if (k < 0) throw IllegalArgumentException(\"expected a whole number from 0, got \" + k)\n return k\n}"], "array/takeLast": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _count(n: Number): Int {\n val k = _whole(n)\n if (k < 0) throw IllegalArgumentException(\"expected a whole number from 0, got \" + k)\n return k\n}"], "array/dropLast": ["private fun _whole(n: Number): Int {\n val d = n.toDouble()\n if (d != Math.floor(d) || d.isInfinite() || d < -2147483648.0 || d > 2147483647.0) throw IllegalArgumentException(\"expected a whole number, got \" + d)\n return d.toInt()\n}", "private fun _count(n: Number): Int {\n val k = _whole(n)\n if (k < 0) throw IllegalArgumentException(\"expected a whole number from 0, got \" + k)\n return k\n}"], "array/append": ["private fun <T> _append(a: List<T>, x: T): List<T> = a + listOf(x)"], "array/prepend": ["private fun <T> _prepend(a: List<T>, x: T): List<T> = listOf(x) + a"], "array/indexOf": ["private fun <T> _indexOf(a: List<T>, x: T): Double = a.indexOf(x).toDouble()"], "array/sort": ["private fun <T : Comparable<T>> _sort(a: List<T>): List<T> = a.sorted()"], "math/round": ["private fun _round(x: Number, d: Number = 0.0): Double {\n val m = Math.pow(10.0, d.toDouble())\n return Math.copySign(Math.floor(Math.abs(x.toDouble()) * m + 0.5) / m, x.toDouble())\n}"], "math/sqrt": ["private fun _sqrt(x: Number): Double? = if (x.toDouble() < 0.0) null else Math.sqrt(x.toDouble())"], "math/ln": ["private fun _ln(x: Number): Double? = if (x.toDouble() <= 0.0) null else Math.log(x.toDouble())"], "math/log10": ["private fun _log10(x: Number): Double? = if (x.toDouble() <= 0.0) null else Math.log10(x.toDouble())"], "math/pow": ["private fun _pow(a: Number, b: Number): Double? {\n val r = Math.pow(a.toDouble(), b.toDouble())\n return if (r.isNaN() || r.isInfinite()) null else r\n}"], "validate/required": ["private fun _required(v: Any?): Boolean = v != null && v != \"\""], "validate/length": ["private fun _strLen(s: String): Int = s.codePointCount(0, s.length)"], "validate/minLength": ["private fun _strLen(s: String): Int = s.codePointCount(0, s.length)"], "validate/maxLength": ["private fun _strLen(s: String): Int = s.codePointCount(0, s.length)"], "validate/equals": ["private fun _eq(a: Any?, b: Any?): Boolean = if (a is Number && b is Number) a.toDouble() == b.toDouble() else a == b"], "array/sum": ["private fun _sum(a: List<Number>): Double = a.sumOf { it.toDouble() }"], "unsupported": ["private fun _unsupported(name: String): Nothing = throw UnsupportedOperationException(\"no native template for operator \" + name)"] }
32
32
  helperGap: "\n\n"
33
33
  portEffects: ["persist", "fetch", "fetch-stream", "notify", "navigate", "navigate-back", "call-service", "cancel-call", "send-server", "spawn", "despawn", "log"]
34
34
  portCall: "ports?.invoke(\"{{name}}\", listOf({{*}}))"
@@ -51,6 +51,24 @@ orbital LoloKotlinOrbital {
51
51
  setStyle: "copy"
52
52
  fieldCase: "split-camel"
53
53
  voidPayload: "Unit"
54
+ programOpen: ["class Program({{entities}}{{store}}) : _Router() {", "{{i}}init {"]
55
+ programEntity: "e{{n}}: {{entity}}"
56
+ programEntitySep: ", "
57
+ programTrait: "{{i}}{{i}}val t{{n}} = {{class}}(e{{n}}); add({{key}}, t{{n}}, { t{{n}}.state }, { _json(t{{n}}.entity) }, { t{{n}}.emitted.size }, { n -> t{{n}}.emitted.drop(n).map { Triple(it.event, _json(it.payload), false) } })"
58
+ programHandles: "{{i}}{{i}}handles[{{key}}] = {{table}}"
59
+ programRow: "{{i}}{{i}}row({{source}}, {{event}}, {{target}}, {{trigger}}, {{guard}}, {{map}})"
60
+ deliverOpen: ["{{i}}}", "", "{{i}}override fun deliver(target: String, event: String, payload: kotlinx.serialization.json.JsonElement) {"]
61
+ deliverCase: "{{i}}{{i}}if (target == {{target}} && event == {{event}}) { (trait(target) as? {{class}})?.{{method}}({{arg}}); return }"
62
+ deliverCasePlain: "{{i}}{{i}}if (target == {{target}} && event == {{event}}) { (trait(target) as? {{class}})?.{{method}}(); return }"
63
+ deliverClose: ["{{i}}}"]
64
+ programClose: ["}"]
65
+ payloadDecode: "_decode<{{type}}>({{value}})"
66
+ guardForm: ["", "private fun {{name}}(payload_json: kotlinx.serialization.json.JsonElement): Boolean {", "{{i}}val payload = {{decode}}", "{{i}}return {{expr}}", "}"]
67
+ mapForm: ["", "private fun {{name}}(payload_json: kotlinx.serialization.json.JsonElement): kotlinx.serialization.json.JsonElement {", "{{i}}val payload = {{decode}}", "{{i}}return _json({{expr}})", "}"]
68
+ guardName: "_guard{{n}}"
69
+ mapName: "_map{{n}}"
70
+ guardRef: "::{{name}}"
71
+ mapRef: "::{{name}}"
54
72
  recordForm: "{{type}}({{fields}})"
55
73
  recordField: "{{name}} = {{value}}"
56
74
  unionArmForm: "{{union}}.{{union}}{{arm}}({{inner}})"
@@ -59,9 +77,14 @@ orbital LoloKotlinOrbital {
59
77
  methodCase: "pascal"
60
78
  classOpen: "class {{class}}("
61
79
  classEmpty: ""
62
- constructor: ["{{i}}var entity: {{entity}},", "{{i}}val ports: ((String, List<Any?>) -> Unit)? = null,", "{{i}}val config: {{configType}} = {{configType}}(),", ") {", "{{i}}var state: String = {{initial}}", "{{i}}val emitted = mutableListOf<Emitted>()", "", "{{i}}data class Emitted(val event: String, val payload: Any)"]
80
+ constructor: ["{{i}}var entity: {{entity}},", "{{i}}val ports: ((String, List<Any?>) -> Unit)? = null,", "{{i}}val config: {{configType}} = {{configType}}(),", ") {", "{{i}}var state: String = {{initial}}", "{{i}}val emitted = mutableListOf<Emitted>()", "{{withStore}}{{i}}var store: Store? = null", "{{withStore}}{{i}}val completed = mutableSetOf<Int>()", "", "{{i}}data class Emitted(val event: String, val payload: Any)"]
63
81
  configType: "{{trait}}Config"
64
82
  emitMethod: ["{{i}}fun emit(event: String, payload: Any) {", "{{i}}{{i}}emitted.add(Emitted(event, payload))", "{{i}}}"]
83
+ completeMethod: ["", "{{i}}fun complete(answer: Answer, success: String?, failure: String?) {", "{{i}}{{i}}val route = (if (answer.ok) success else failure) ?: return", "{{i}}{{i}}completed.add(emitted.size)", "{{i}}{{i}}emitted.add(Emitted(route, answer.payload))", "{{i}}}", "", "{{i}}fun useStore(): Store = store ?: error(\"no store\")"]
84
+ routedEffects: {"persist": "complete(useStore().persist({{0}}, {{1}}, {{2}}), {{success}}, {{failure}})", "fetch": "complete(useStore().fetch({{entity}}, {{filter}}), {{success}}, {{failure}})"}
85
+ fetchAll: "null"
86
+ programStoreParam: ", store: Store"
87
+ programTraitStore: "{{i}}{{i}}val t{{n}} = {{class}}(e{{n}}); t{{n}}.store = store; add({{key}}, t{{n}}, { t{{n}}.state }, { _json(t{{n}}.entity) }, { t{{n}}.emitted.size }, { n -> t{{n}}.emitted.drop(n).mapIndexed { j, it -> Triple(it.event, _json(it.payload), (n + j) in t{{n}}.completed) } })"
65
88
  entityNames: { "Any": "AnyEntity", "Array": "ArrayEntity", "Boolean": "BooleanEntity", "Box": "BoxEntity", "Button": "ButtonEntity", "Card": "CardEntity", "Char": "CharEntity", "Color": "ColorEntity", "Column": "ColumnEntity", "Double": "DoubleEntity", "Enum": "EnumEntity", "Exception": "ExceptionEntity", "Float": "FloatEntity", "Image": "ImageEntity", "Int": "IntEntity", "List": "ListEntity", "Long": "LongEntity", "Map": "MapEntity", "Modifier": "ModifierEntity", "Nothing": "NothingEntity", "Number": "NumberEntity", "Pair": "PairEntity", "Result": "ResultEntity", "Row": "RowEntity", "Set": "SetEntity", "Short": "ShortEntity", "State": "StateEntity", "String": "StringEntity", "Surface": "SurfaceEntity", "Text": "TextEntity", "Throwable": "ThrowableEntity", "Triple": "TripleEntity", "Unit": "UnitEntity" }
66
89
  typeMap: { }
67
90
  indent: " "
@@ -31,9 +31,9 @@ orbital LoloPythonOrbital {
31
31
  calleeForm: "{{callee}}({{*}})"
32
32
  unsupportedForm: "_unsupported({{op}})"
33
33
  unsupportedWarn: "no {{language}} template for operator {{op}}"
34
- helpers: { "/": ["def _div(a, b): return None if b == 0 else a / b"], "%": ["def _mod(a, b): return None if b == 0 else math.fmod(a, b)"], "math/mod": ["def _mod(a, b): return None if b == 0 else math.fmod(a, b)"], "default": ["def _default(v, d): return d if v is None else v"], "str/split": ["def _split(s, d): return list(s) if d == '' else s.split(d)"], "str/join": ["def _join(a, d): return d.join(_text(v) for v in a)", "def _text(v):\n if isinstance(v, bool): return 'true' if v else 'false'\n if isinstance(v, float) and v - v == 0 and v == int(v): return str(int(v))\n if isinstance(v, (int, float, str)): return str(v)\n raise TypeError('expected string, number or boolean')"], "str/concat": ["def _text(v):\n if isinstance(v, bool): return 'true' if v else 'false'\n if isinstance(v, float) and v - v == 0 and v == int(v): return str(int(v))\n if isinstance(v, (int, float, str)): return str(v)\n raise TypeError('expected string, number or boolean')"], "str/slice": ["def _str_slice(s, a, b=None):\n if a != int(a) or (b is not None and b != int(b)): raise ValueError('slice: not a whole number')\n return s[int(a):None if b is None else int(b)]"], "str/padStart": ["def _pad_start(s, n, p=' '):\n if len(p) != 1: raise ValueError('expected a single padding character')\n return s.rjust(int(n), p)"], "str/padEnd": ["def _pad_end(s, n, p=' '):\n if len(p) != 1: raise ValueError('expected a single padding character')\n return s.ljust(int(n), p)"], "str/truncate": ["def _truncate(s, n, suffix='...'): return s if len(s) <= n else s[:int(n)] + suffix"], "str/to-int": ["def _to_int(s):\n t = s[1:] if s[:1] in ('+', '-') else s\n return int(s) if t.isascii() and t.isdigit() and -2 ** 63 <= int(s) < 2 ** 63 else None"], "array/sum": ["def _sum(a, k=None): return sum(a) if k is None else sum(x[k] for x in a)"], "array/avg": ["def _avg(a, k=None):\n v = a if k is None else [x[k] for x in a]\n return sum(v) / len(v) if v else None"], "array/max": ["def _amax(a, k=None):\n v = a if k is None else [x[k] for x in a]\n return max(v) if v else None"], "array/min": ["def _amin(a, k=None):\n v = a if k is None else [x[k] for x in a]\n return min(v) if v else None"], "array/first": ["def _first(a): return a[0] if a else None"], "array/last": ["def _last(a): return a[-1] if a else None"], "array/nth": ["def _nth(a, i):\n if i != int(i) or i < 0: raise ValueError('nth: index is not a whole number from 0')\n return a[int(i)] if i < len(a) else None"], "array/range": ["def _range(a, b=None, step=1):\n start, end = (0, a) if b is None else (a, b)\n if step == 0: raise ValueError('range: step 0 must be a non-zero finite number')\n out = []\n x = start\n while (x < end) if step > 0 else (x > end):\n out.append(x)\n x += step\n return out"], "array/slice": ["def _slice(a, s, e=None):\n if s != int(s) or s < 0 or (e is not None and (e != int(e) or e < 0)): raise ValueError('slice: not a whole number from 0')\n return a[int(s):None if e is None else int(e)]"], "array/take": ["def _take(a, n):\n if n != int(n) or n < 0: raise ValueError('count is not a whole number from 0')\n return a[:int(n)]"], "array/drop": ["def _drop(a, n):\n if n != int(n) or n < 0: raise ValueError('count is not a whole number from 0')\n return a[int(n):]"], "array/takeLast": ["def _take_last(a, n):\n if n != int(n) or n < 0: raise ValueError('count is not a whole number from 0')\n return a[len(a) - int(n):] if n < len(a) else a[:]"], "array/dropLast": ["def _drop_last(a, n):\n if n != int(n) or n < 0: raise ValueError('count is not a whole number from 0')\n return a[:len(a) - int(n)] if n < len(a) else []"], "array/indexOf": ["def _index_of(a, x): return a.index(x) if x in a else -1"], "array/unique": ["def _unique(a):\n out = []\n for x in a:\n if x not in out: out.append(x)\n return out"], "array/sort": ["def _sort(a, k=None, o='asc'): return sorted(a, key=None if k is None else (lambda x: x[k]), reverse=(o == 'desc'))"], "object/get": ["def _get(o, p, d=None):\n for s in p.replace(chr(92) + '.', chr(0)).split('.'):\n s = s.replace(chr(0), '.')\n if isinstance(o, dict) and s in o: o = o[s]\n elif isinstance(o, list) and s.isdigit() and int(s) < len(o): o = o[int(s)]\n else: return d\n return o"], "object/has": ["def _has(o, p):\n for s in p.replace(chr(92) + '.', chr(0)).split('.'):\n s = s.replace(chr(0), '.')\n if isinstance(o, dict) and s in o: o = o[s]\n elif isinstance(o, list) and s.isdigit() and int(s) < len(o): o = o[int(s)]\n else: return False\n return True"], "object/set": ["def _set(o, p, v):\n out = dict(o)\n cur = out\n parts = [s.replace(chr(0), '.') for s in p.replace(chr(92) + '.', chr(0)).split('.')]\n for s in parts[:-1]:\n cur[s] = dict(cur[s]) if isinstance(cur.get(s), dict) else {}\n cur = cur[s]\n cur[parts[-1]] = v\n return out"], "object/pick": ["def _pick(o, ks): return {k: o[k] for k in ks if k in o}"], "object/omit": ["def _omit(o, ks): return {k: v for k, v in o.items() if k not in ks}"], "json/parse": ["def _json_parse(t):\n try: return json.loads(t)\n except ValueError: return None"], "json/stringify": ["def _json_dumps(v):\n def n(x):\n if isinstance(x, float) and x - x == 0 and x == int(x): return int(x)\n if isinstance(x, list): return [n(y) for y in x]\n if isinstance(x, dict): return {k: n(y) for k, y in x.items()}\n return x\n return json.dumps(n(v), separators=(',', ':'), ensure_ascii=False)"], "math/round": ["def _round(x, d=0):\n m = 10 ** d\n return math.copysign(math.floor(abs(x) * m + 0.5) / m, x)"], "math/sqrt": ["def _sqrt(x): return None if x < 0 else math.sqrt(x)"], "math/ln": ["def _ln(x): return None if x <= 0 else math.log(x)"], "math/log10": ["def _log10(x): return None if x <= 0 else math.log10(x)"], "math/pow": ["def _pow(a, b):\n try: return math.pow(a, b)\n except (ValueError, OverflowError, ZeroDivisionError): return None"], "math/sign": ["def _sign(x): return (x > 0) - (x < 0)"], "math/clamp": ["def _clamp(v, lo, hi): return min(max(v, lo), hi)"], "validate/required": ["def _required(v): return v is not None and v != ''"], "validate/number": ["def _is_number(v): return isinstance(v, (int, float)) and not isinstance(v, bool)"], "unsupported": ["def _unsupported(name): raise NotImplementedError('no native template for operator ' + name)"] }
34
+ helpers: { "store": ["class MemoryStore:\n def __init__(self):\n self.tables = {}\n self.minted = 0\n\n def persist(self, op, entity, data):\n rows = self.tables.setdefault(entity, {})\n if op == \"create\":\n row = dict(_plain(data))\n if not row.get(\"id\"):\n self.minted += 1\n row[\"id\"] = entity + \"-\" + str(self.minted)\n rows[row[\"id\"]] = row\n return True, dict(row)\n key = data if isinstance(data, str) else _plain(data).get(\"id\")\n if key not in rows:\n return False, {\"error\": entity + \" \" + str(key) + \" not found\", \"code\": \"not-found\"}\n if op == \"delete\":\n del rows[key]\n return True, {\"id\": key, \"deleted\": True}\n rows[key].update(_plain(data))\n return True, dict(rows[key])\n\n def fetch(self, entity, keep):\n rows = [dict(r) for r in self.tables.get(entity, {}).values() if keep is None or keep(dict(r))]\n rows.sort(key=lambda r: (0, r[\"createdAt\"], r[\"id\"]) if \"createdAt\" in r else (1, 0, r[\"id\"]))\n return True, {\"data\": rows, \"totalCount\": len(rows)}"], "router": ["def _plain(v):\n if dataclasses.is_dataclass(v):\n return dataclasses.asdict(v)\n return {} if v is None else v", "def _decode(cls, payload):\n names = {f.name for f in dataclasses.fields(cls)}\n return cls(**{k: v for k, v in (payload or {}).items() if k in names})", "class _Router:\n def __init__(self):\n self.traits = {}\n self.handles = {}\n self.rows = []\n self.log = []\n\n def add(self, key, trait):\n self.traits[key] = trait\n\n def row(self, source, event, target, trigger, guard, mapping):\n self.rows.append((source, event, target, trigger, guard, mapping))\n\n def targets(self, source, event, payload, completion):\n return [{\"trait\": target, \"event\": trigger, \"payload\": mapping(payload) if mapping else payload, \"source\": payload,\n \"guard\": guard, \"fans\": False, \"completion\": completion}\n for (s, e, target, trigger, guard, mapping) in self.rows if s == source and e == event]\n\n def dispatch(self, trait, event, payload):\n queue = deque([{\"trait\": trait, \"event\": event, \"payload\": payload, \"source\": payload, \"guard\": None, \"fans\": True, \"completion\": False}])\n seen = set()\n steps = 0\n while queue:\n item = queue.popleft()\n t = self.traits[item[\"trait\"]]\n key = json.dumps([item[\"trait\"], item[\"event\"], t.state, item[\"payload\"], _plain(t.entity)], sort_keys=True, default=str)\n if not item[\"completion\"] and key in seen:\n continue\n if item[\"guard\"] is not None and not item[\"guard\"](item[\"source\"]):\n continue\n if steps >= 2000:\n break\n steps += 1\n seen.add(key)\n n = len(t.emitted)\n self.deliver(item[\"trait\"], item[\"event\"], item[\"payload\"])\n own, fanned = [], []\n if item[\"fans\"]:\n fanned += self.targets(item[\"trait\"], item[\"event\"], item[\"payload\"], False)\n for emitted in t.emitted[n:]:\n ev, out = emitted[0], _plain(emitted[1])\n completion = len(emitted) > 2 and emitted[2]\n self.log.append((item[\"trait\"], ev, out))\n if ev in self.handles[item[\"trait\"]].get(t.state, ()):\n own.append({\"trait\": item[\"trait\"], \"event\": ev, \"payload\": out, \"source\": out, \"guard\": None, \"fans\": False, \"completion\": completion})\n fanned += self.targets(item[\"trait\"], ev, out, completion)\n queue.extendleft(reversed(own))\n queue.extend(fanned)"], "/": ["def _div(a, b): return None if b == 0 else a / b"], "%": ["def _mod(a, b): return None if b == 0 else math.fmod(a, b)"], "math/mod": ["def _mod(a, b): return None if b == 0 else math.fmod(a, b)"], "default": ["def _default(v, d): return d if v is None else v"], "str/split": ["def _split(s, d): return list(s) if d == '' else s.split(d)"], "str/join": ["def _join(a, d): return d.join(_text(v) for v in a)", "def _text(v):\n if isinstance(v, bool): return 'true' if v else 'false'\n if isinstance(v, float) and v - v == 0 and v == int(v): return str(int(v))\n if isinstance(v, (int, float, str)): return str(v)\n raise TypeError('expected string, number or boolean')"], "str/concat": ["def _text(v):\n if isinstance(v, bool): return 'true' if v else 'false'\n if isinstance(v, float) and v - v == 0 and v == int(v): return str(int(v))\n if isinstance(v, (int, float, str)): return str(v)\n raise TypeError('expected string, number or boolean')"], "str/slice": ["def _str_slice(s, a, b=None):\n if a != int(a) or (b is not None and b != int(b)): raise ValueError('slice: not a whole number')\n return s[int(a):None if b is None else int(b)]"], "str/padStart": ["def _pad_start(s, n, p=' '):\n if len(p) != 1: raise ValueError('expected a single padding character')\n return s.rjust(int(n), p)"], "str/padEnd": ["def _pad_end(s, n, p=' '):\n if len(p) != 1: raise ValueError('expected a single padding character')\n return s.ljust(int(n), p)"], "str/truncate": ["def _truncate(s, n, suffix='...'): return s if len(s) <= n else s[:int(n)] + suffix"], "str/to-int": ["def _to_int(s):\n t = s[1:] if s[:1] in ('+', '-') else s\n return int(s) if t.isascii() and t.isdigit() and -2 ** 63 <= int(s) < 2 ** 63 else None"], "array/sum": ["def _sum(a, k=None): return sum(a) if k is None else sum(x[k] for x in a)"], "array/avg": ["def _avg(a, k=None):\n v = a if k is None else [x[k] for x in a]\n return sum(v) / len(v) if v else None"], "array/max": ["def _amax(a, k=None):\n v = a if k is None else [x[k] for x in a]\n return max(v) if v else None"], "array/min": ["def _amin(a, k=None):\n v = a if k is None else [x[k] for x in a]\n return min(v) if v else None"], "array/first": ["def _first(a): return a[0] if a else None"], "array/last": ["def _last(a): return a[-1] if a else None"], "array/nth": ["def _nth(a, i):\n if i != int(i) or i < 0: raise ValueError('nth: index is not a whole number from 0')\n return a[int(i)] if i < len(a) else None"], "array/range": ["def _range(a, b=None, step=1):\n start, end = (0, a) if b is None else (a, b)\n if step == 0: raise ValueError('range: step 0 must be a non-zero finite number')\n out = []\n x = start\n while (x < end) if step > 0 else (x > end):\n out.append(x)\n x += step\n return out"], "array/slice": ["def _slice(a, s, e=None):\n if s != int(s) or s < 0 or (e is not None and (e != int(e) or e < 0)): raise ValueError('slice: not a whole number from 0')\n return a[int(s):None if e is None else int(e)]"], "array/take": ["def _take(a, n):\n if n != int(n) or n < 0: raise ValueError('count is not a whole number from 0')\n return a[:int(n)]"], "array/drop": ["def _drop(a, n):\n if n != int(n) or n < 0: raise ValueError('count is not a whole number from 0')\n return a[int(n):]"], "array/takeLast": ["def _take_last(a, n):\n if n != int(n) or n < 0: raise ValueError('count is not a whole number from 0')\n return a[len(a) - int(n):] if n < len(a) else a[:]"], "array/dropLast": ["def _drop_last(a, n):\n if n != int(n) or n < 0: raise ValueError('count is not a whole number from 0')\n return a[:len(a) - int(n)] if n < len(a) else []"], "array/indexOf": ["def _index_of(a, x): return a.index(x) if x in a else -1"], "array/unique": ["def _unique(a):\n out = []\n for x in a:\n if x not in out: out.append(x)\n return out"], "array/sort": ["def _sort(a, k=None, o='asc'): return sorted(a, key=None if k is None else (lambda x: x[k]), reverse=(o == 'desc'))"], "object/get": ["def _get(o, p, d=None):\n for s in p.replace(chr(92) + '.', chr(0)).split('.'):\n s = s.replace(chr(0), '.')\n if isinstance(o, dict) and s in o: o = o[s]\n elif isinstance(o, list) and s.isdigit() and int(s) < len(o): o = o[int(s)]\n else: return d\n return o"], "object/has": ["def _has(o, p):\n for s in p.replace(chr(92) + '.', chr(0)).split('.'):\n s = s.replace(chr(0), '.')\n if isinstance(o, dict) and s in o: o = o[s]\n elif isinstance(o, list) and s.isdigit() and int(s) < len(o): o = o[int(s)]\n else: return False\n return True"], "object/set": ["def _set(o, p, v):\n out = dict(o)\n cur = out\n parts = [s.replace(chr(0), '.') for s in p.replace(chr(92) + '.', chr(0)).split('.')]\n for s in parts[:-1]:\n cur[s] = dict(cur[s]) if isinstance(cur.get(s), dict) else {}\n cur = cur[s]\n cur[parts[-1]] = v\n return out"], "object/pick": ["def _pick(o, ks): return {k: o[k] for k in ks if k in o}"], "object/omit": ["def _omit(o, ks): return {k: v for k, v in o.items() if k not in ks}"], "json/parse": ["def _json_parse(t):\n try: return json.loads(t)\n except ValueError: return None"], "json/stringify": ["def _json_dumps(v):\n def n(x):\n if isinstance(x, float) and x - x == 0 and x == int(x): return int(x)\n if isinstance(x, list): return [n(y) for y in x]\n if isinstance(x, dict): return {k: n(y) for k, y in x.items()}\n return x\n return json.dumps(n(v), separators=(',', ':'), ensure_ascii=False)"], "math/round": ["def _round(x, d=0):\n m = 10 ** d\n return math.copysign(math.floor(abs(x) * m + 0.5) / m, x)"], "math/sqrt": ["def _sqrt(x): return None if x < 0 else math.sqrt(x)"], "math/ln": ["def _ln(x): return None if x <= 0 else math.log(x)"], "math/log10": ["def _log10(x): return None if x <= 0 else math.log10(x)"], "math/pow": ["def _pow(a, b):\n try: return math.pow(a, b)\n except (ValueError, OverflowError, ZeroDivisionError): return None"], "math/sign": ["def _sign(x): return (x > 0) - (x < 0)"], "math/clamp": ["def _clamp(v, lo, hi): return min(max(v, lo), hi)"], "validate/required": ["def _required(v): return v is not None and v != ''"], "validate/number": ["def _is_number(v): return isinstance(v, (int, float)) and not isinstance(v, bool)"], "unsupported": ["def _unsupported(name): raise NotImplementedError('no native template for operator ' + name)"] }
35
35
  helperGap: "\n"
36
- imports: { "Literal": "from typing import Literal", "Any": "from typing import Any", "field": "from dataclasses import field", "dataclass": "from dataclasses import dataclass", "%": "import math", "math/mod": "import math", "math/ceil": "import math", "math/floor": "import math", "math/sin": "import math", "math/cos": "import math", "math/tan": "import math", "math/atan": "import math", "math/atan2": "import math", "math/hypot": "import math", "math/round": "import math", "math/sqrt": "import math", "math/ln": "import math", "math/log10": "import math", "math/pow": "import math", "array/reduce": "import functools", "json/parse": "import json", "json/stringify": "import json" }
36
+ imports: { "router": "from collections import deque\nimport dataclasses\nimport json", "Literal": "from typing import Literal", "Any": "from typing import Any", "field": "from dataclasses import field", "dataclass": "from dataclasses import dataclass", "%": "import math", "math/mod": "import math", "math/ceil": "import math", "math/floor": "import math", "math/sin": "import math", "math/cos": "import math", "math/tan": "import math", "math/atan": "import math", "math/atan2": "import math", "math/hypot": "import math", "math/round": "import math", "math/sqrt": "import math", "math/ln": "import math", "math/log10": "import math", "math/pow": "import math", "array/reduce": "import functools", "json/parse": "import json", "json/stringify": "import json" }
37
37
  portEffects: ["persist", "fetch", "fetch-stream", "notify", "navigate", "navigate-back", "call-service", "cancel-call", "send-server", "spawn", "despawn", "log"]
38
38
  portCall: "self.ports.{{name}}({{*}})"
39
39
  portCase: "lower"
@@ -77,6 +77,16 @@ orbital LoloPythonOrbital {
77
77
  localCase: "keep"
78
78
  methodCase: "lower"
79
79
  methodName: "on_{{event}}"
80
+ programOpen: ["class Program(_Router):", "{{i}}def __init__(self, entities, ports=None):", "{{i}}{{i}}super().__init__()"]
81
+ programTrait: "{{i}}{{i}}self.add({{key}}, {{class}}(entities[{{key}}], ports))"
82
+ programHandles: "{{i}}{{i}}self.handles[{{key}}] = {{table}}"
83
+ programRow: "{{i}}{{i}}self.row({{source}}, {{event}}, {{target}}, {{trigger}}, {{guard}}, {{map}})"
84
+ deliverOpen: ["", "{{i}}def deliver(self, target, event, payload):"]
85
+ deliverCase: "{{i}}{{i}}if target == {{target}} and event == {{event}}:\n{{i}}{{i}}{{i}}return self.traits[target].{{method}}({{arg}})"
86
+ deliverCasePlain: "{{i}}{{i}}if target == {{target}} and event == {{event}}:\n{{i}}{{i}}{{i}}return self.traits[target].{{method}}()"
87
+ payloadDecode: "_decode({{type}}, {{value}})"
88
+ guardForm: ["", "", "def {{name}}(payload_json):", "{{i}}payload = {{decode}}", "{{i}}return {{expr}}"]
89
+ mapForm: ["", "", "def {{name}}(payload_json):", "{{i}}payload = {{decode}}", "{{i}}return {{expr}}"]
80
90
  modelImports: { "entity": "from orbital_app.generated.entities import {{names}}", "payload": "from orbital_app.generated.events import {{names}}" }
81
91
  modelImportEach: false
82
92
  modelImportSep: ", "
@@ -86,6 +96,9 @@ orbital LoloPythonOrbital {
86
96
  classEmpty: "{{i}}pass"
87
97
  constructor: ["{{i}}def __init__(self, entity: {{entity}}, ports=None, config: {{configType}} | None = None):", "{{noConfig}}{{i}}def __init__(self, entity: {{entity}}, ports=None):", "{{i}}{{i}}self.state = {{initial}}", "{{i}}{{i}}self.entity = entity", "{{i}}{{i}}self.ports = ports", "{{i}}{{i}}self.config = config if config is not None else {{configType}}()", "{{i}}{{i}}self.emitted: list[tuple[str, object]] = []"]
88
98
  emitMethod: ["{{i}}def emit(self, event, payload):", "{{i}}{{i}}self.emitted.append((event, payload))"]
99
+ completeMethod: ["", "{{i}}def complete(self, answer, success, failure):", "{{i}}{{i}}ok, payload = answer", "{{i}}{{i}}route = success if ok else failure", "{{i}}{{i}}if route is not None:", "{{i}}{{i}}{{i}}self.emitted.append((route, payload, True))"]
100
+ routedEffects: {"persist": "self.complete(self.ports.persist({{args}}), {{success}}, {{failure}})", "fetch": "self.complete(self.ports.fetch({{entity}}, {{filter}}), {{success}}, {{failure}})"}
101
+ fetchAll: "None"
89
102
  methodOpen: "{{i}}def {{method}}(self, payload: {{payloadType}}) -> None:"
90
103
  methodOpenPlain: "{{i}}def {{method}}(self, payload=None) -> None:"
91
104
  methodClose: ""