diff --git a/examples/example-simple-chat/package.json b/examples/example-simple-chat/package.json index 8cdd79c..6ab153e 100644 --- a/examples/example-simple-chat/package.json +++ b/examples/example-simple-chat/package.json @@ -16,13 +16,13 @@ "author": "Tony Garnock-Jones ", "license": "GPL-3.0+", "dependencies": { - "@preserves/core": "0.992.4", + "@preserves/core": "0.995.200", "@syndicate-lang/core": "*", "@syndicate-lang/html": "*", "@syndicate-lang/ws-relay": "*" }, "devDependencies": { - "@preserves/schema-cli": "0.992.5", + "@preserves/schema-cli": "0.995.201", "@syndicate-lang/ts-plugin": "*", "@syndicate-lang/tsc": "*", "rollup": "^2.60", diff --git a/examples/example-simple-chat/server-config/standard-dataspace.pr b/examples/example-simple-chat/server-config/standard-dataspace.pr index f1d7bcf..1839c74 100644 --- a/examples/example-simple-chat/server-config/standard-dataspace.pr +++ b/examples/example-simple-chat/server-config/standard-dataspace.pr @@ -1,6 +1,6 @@ let ?ds = dataspace -# Connect using ] > +# Connect using ] $ds #f> # Connect using ] > diff --git a/examples/example-simple-chat/src/index.ts b/examples/example-simple-chat/src/index.ts index 5540e9d..314803a 100644 --- a/examples/example-simple-chat/src/index.ts +++ b/examples/example-simple-chat/src/index.ts @@ -1,7 +1,7 @@ /// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-FileCopyrightText: Copyright © 2016-2021 Tony Garnock-Jones -import { fromJS, Bytes, Dataspace, Ref, Sturdy, AnyValue, Reader, Schemas, Embedded, stringify } from "@syndicate-lang/core"; +import { fromJS, Bytes, Dataspace, Ref, Sturdy, AnyValue, Reader, Schemas, stringify } from "@syndicate-lang/core"; import { boot as bootHtml, Anchor, template as html, HtmlFragments, GlobalEvent, UIAttribute, UIChangeableProperty } from "@syndicate-lang/html"; import { boot as bootWakeDetector, WakeEvent } from "./wake-detector"; import { boot as bootWsRelay } from "@syndicate-lang/ws-relay"; @@ -46,12 +46,9 @@ function bootChat(ds: Ref) { during G.ResolvePath({ "route": route, "addr": $addr, - "control": $control_e: Embedded, - "resolved": G.Resolved.accepted($remoteDs_e: Embedded), + "control": $control: Ref, + "resolved": G.Resolved.accepted($remoteDs: Ref), }) => { - const remoteDs = remoteDs_e.embeddedValue; - const control = control_e.embeddedValue; - on message WakeEvent() => at control { send message G.ForceDisconnect(); } diff --git a/examples/example-simple-chat/yarn.lock b/examples/example-simple-chat/yarn.lock index 67fc7c5..7a56907 100644 --- a/examples/example-simple-chat/yarn.lock +++ b/examples/example-simple-chat/yarn.lock @@ -2,30 +2,30 @@ # yarn lockfile v1 -"@preserves/core@0.992", "@preserves/core@^0.992.2": - version "0.992.2" - resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.992.2.tgz#b3acc7badd25ccccbf8e034bb641c6cfad987c41" - integrity sha512-aibJ8c9mLcCf3MhXeLWv0hevfkHgu3pJmBDzhN9AGXMIw0/fO3uEEnLM1oPaFIPWnQG4WybiXTUh2wD1CoxABg== +"@preserves/core@0.995.200", "@preserves/core@^0.995.200": + version "0.995.200" + resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.200.tgz#65575cf8f9320e73b5d37fa9ac9d6881a33fd3a6" + integrity sha512-htZ2x+hltUpKoPsviWSuelzZW96po9zVSsN0RZEih60FahNX0R2LCqFJ6v5lyATuQ9oHALVi0w8w4rtf8oiAJw== -"@preserves/schema-cli@0.992": - version "0.992.2" - resolved "https://registry.yarnpkg.com/@preserves/schema-cli/-/schema-cli-0.992.2.tgz#53defa05b0bd34cf5032255d761076797254ce8f" - integrity sha512-ICJ0fqj3haJZosU7h8APm3GkoUaZs+BHKfj80BD8wuBf4iSLa4GAYASYThLZT/tlxU2iK1j4NghrG6/tCIj99w== +"@preserves/schema-cli@0.995.201": + version "0.995.201" + resolved "https://registry.yarnpkg.com/@preserves/schema-cli/-/schema-cli-0.995.201.tgz#e87cb7ba51b225ff6ea96f177c5388907adf6717" + integrity sha512-n/lpVgWBY1UTRySPXIwWG4Yu87OrQ9b7Xo8zPPQzD/DJDTEDT3y3SUujY7UTF1pQn09xRGnfPnDu1RoRCv2J3w== dependencies: - "@preserves/core" "^0.992.2" - "@preserves/schema" "^0.992.2" + "@preserves/core" "^0.995.200" + "@preserves/schema" "^0.995.201" chalk "^4.1" chokidar "^3.5" commander "^7.2" glob "^7.1" minimatch "^3.0" -"@preserves/schema@0.992", "@preserves/schema@^0.992.2": - version "0.992.2" - resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.992.2.tgz#975598b166500adc79f0d4e0cf2ae6dea3c2c111" - integrity sha512-I1zM9EWY0URw2zuRHLyROqVA9uqGhzQjuCpnTC8MeJToPt+xwVCXGl/NJYKhgofB14ZAgKT98h6YrLDR3yR6ug== +"@preserves/schema@^0.995.201": + version "0.995.201" + resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.995.201.tgz#827ad539afb0fdf68ba885ee3ff43db0fd473aa5" + integrity sha512-0SuhwOEAfxtrAeOTZ8V1yNEcHHHEbfUmoFawrF+vzTQFNZRz/X3LF1FM6wOiJlHtb7tBr4B+rHXX8jfNrqrdkA== dependencies: - "@preserves/core" "^0.992.2" + "@preserves/core" "^0.995.200" "@rollup/pluginutils@^3.0.9": version "3.1.0" @@ -36,52 +36,49 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@syndicate-lang/compiler@^0.13.2": - version "0.13.2" - resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.13.2.tgz#e66de9f5828efb88ebe62266d014e13620961996" - integrity sha512-GQa7GVkerWxoVqY3NtRZXS8aLqIsVfdA8KvgNSDb8fTNV8TKGLDxQRurtcCiuEKG9mtfnDTpk8i28HbijKw6fA== +"@syndicate-lang/compiler@^0.21.1": + version "0.21.1" + resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.21.1.tgz#b6316bac14d053c313b3442be68f532a60c47cb3" + integrity sha512-daaYh1i0XmoHt6eTtO4gWblfVKMjp9trwxqR62wUSONY3gtJ5Bn4hG3dMgfoMz2NvOWbJHaGz/95J0jRubITxA== -"@syndicate-lang/core@*", "@syndicate-lang/core@^0.19.1": - version "0.19.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.19.1.tgz#506e4e6e9f6a0b7bd0b5f6a61ad6e98c3a9ccae6" - integrity sha512-2CMtEhyb8cg/pcJWgEdsaPtb6TJS0EbgeHcvCRyEFm3gdENxrNHVpxTVznSNAJnZosMu1KbK735kkviH9etkjw== +"@syndicate-lang/core@*", "@syndicate-lang/core@^0.32.0": + version "0.32.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.32.0.tgz#0efbbff176cac2969c2b6ba70a19965add3a2c61" + integrity sha512-ERVXk0W1xLaKvUa79Ek74YvqfBU543cUTb2GJvp76TP5k1jA97q9GzhddicS/s8lqu8SUC1+IXmKiJk0NX2TWQ== dependencies: - "@preserves/core" "0.992" - "@preserves/schema" "0.992" salty-crypto "0.3.1" "@syndicate-lang/html@*": - version "0.19.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/html/-/html-0.19.1.tgz#21611a6c5718f01c00ac3b18e191548a6dd16538" - integrity sha512-qr4T065GIuMAI3VKAsYmUWcDyqTq/yGQndrG/Ub+L1P2ivU3AbU/0cuFUQVgFIZmoW/iqG9BQzjIUV8xiOsArw== + version "0.33.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/html/-/html-0.33.0.tgz#c53e6bf8a52b17c3747f4270713a8c9234f984af" + integrity sha512-xhN6NZOgLxlAQOyWG0JAgtyF1e1yQvrpNh5RBAPnucFYC024yo1ggZ08+KiaulhsoIKvRbBE6FU6p9dDm4/tpQ== dependencies: - "@syndicate-lang/core" "^0.19.1" + "@syndicate-lang/core" "^0.32.0" "@syndicate-lang/ts-plugin@*": - version "0.19.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/ts-plugin/-/ts-plugin-0.19.1.tgz#c7ecf4e836314e16d0849a539ab4b22f7d4c10aa" - integrity sha512-o7niu1QnhAONisil83jVnWK3ipwz8obB0iruJ1++W3nXEM2nW7yGPuJNyLwkk1cFuPzfknm/DFdf6WKz9CsJGw== + version "0.34.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/ts-plugin/-/ts-plugin-0.34.0.tgz#df92f9044eeba528c80c41c5c9df49ee28902411" + integrity sha512-OCO6Hm0euz2hZk6tYTrJQNEM8iDBeQ/dgpW2a/UP52XSP6fYj0OvUVfn+35ZkIL64S+zDsJjL/6XFN05UZyRGA== dependencies: - "@syndicate-lang/compiler" "^0.13.2" - "@syndicate-lang/core" "^0.19.1" + "@syndicate-lang/compiler" "^0.21.1" + "@syndicate-lang/core" "^0.32.0" "@syndicate-lang/tsc@*": - version "0.19.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.19.1.tgz#25d48aa1a29e51c983d1ab6d8ab184eed26b465a" - integrity sha512-Uul57ynMS3L6CRIponNyUQ4vmblA4iCXyIsjtsi3QktvFJ9DTV4MRJAXjq72662jjLneY/LKWuCPXFKG62PyQA== + version "0.34.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.34.0.tgz#1056fba7f639bbf436d0c2ecd2717edc4c1e612a" + integrity sha512-Ufj3xsdXMbMCavWsEkX/pFyXRpNIWRW+LFew1icD14DoSLqyBcoUEvskolOSgkSzC53tDjbd4/LXDVofIjIyUA== dependencies: - "@syndicate-lang/compiler" "^0.13.2" - "@syndicate-lang/core" "^0.19.1" + "@syndicate-lang/compiler" "^0.21.1" + "@syndicate-lang/core" "^0.32.0" glob "^7.1.6" yargs "^16.2.0" "@syndicate-lang/ws-relay@*": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/ws-relay/-/ws-relay-0.20.1.tgz#4d4fbc401e5eb8a474aedf5112f9e1de3391bff8" - integrity sha512-sv3r/eyQicBQFVJ8MrS2/OUOPtbr54fkgC6dGN0IdRIeMUFdsxn7HlF3Tumo9I9oOTMNL3Ye+Xkc0sKSLqm8ng== + version "0.34.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/ws-relay/-/ws-relay-0.34.0.tgz#8b450ef18b22ca8e0c159c7925a1068796ad2c71" + integrity sha512-PT24Pp+ol/wWMSp/6H8i5zu7CgXm5nh0UsfpxJ3ZpvWFs/rIsoMflL/g+C1Q4DW9oFTn6/WFs07VdSLmE2/Uog== dependencies: - "@preserves/core" "0.992" - "@syndicate-lang/core" "^0.19.1" + "@syndicate-lang/core" "^0.32.0" salty-crypto "0.3" "@types/estree@0.0.39": @@ -120,9 +117,9 @@ balanced-match@^1.0.0: integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== brace-expansion@^1.1.7: version "1.1.11" @@ -148,9 +145,9 @@ chalk@^4.1: supports-color "^7.1.0" chokidar@^3.5: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== dependencies: anymatch "~3.1.2" braces "~3.0.2" @@ -204,9 +201,9 @@ emoji-regex@^8.0.0: integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== estree-walker@^1.0.1: version "1.0.1" diff --git a/examples/how-to-use-syndicate-ts-plugin/package.json b/examples/how-to-use-syndicate-ts-plugin/package.json index 37b0752..76df755 100644 --- a/examples/how-to-use-syndicate-ts-plugin/package.json +++ b/examples/how-to-use-syndicate-ts-plugin/package.json @@ -12,6 +12,8 @@ "author": "Tony Garnock-Jones ", "license": "GPL-3.0+", "dependencies": { + "@preserves/core": "0.995.200", + "@preserves/schema": "0.995.201", "@syndicate-lang/core": "*" }, "devDependencies": { diff --git a/examples/how-to-use-syndicate-ts-plugin/yarn.lock b/examples/how-to-use-syndicate-ts-plugin/yarn.lock index 4b9098f..0a56ee6 100644 --- a/examples/how-to-use-syndicate-ts-plugin/yarn.lock +++ b/examples/how-to-use-syndicate-ts-plugin/yarn.lock @@ -2,17 +2,17 @@ # yarn lockfile v1 -"@preserves/core@0.990", "@preserves/core@^0.990.0": - version "0.990.0" - resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.990.0.tgz#c57c1c3d5159fc17477a4205d5a94a78fbf5b1aa" - integrity sha512-Mx013USv9JU1SrtMxaJISETBy2LZ402xH8ZnQI4JzG6W27ZwGV36DQrXAfF0x6cOmZMGKwJNqQrvmFhh7mEn6w== +"@preserves/core@0.995.200", "@preserves/core@^0.995.200": + version "0.995.200" + resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.200.tgz#65575cf8f9320e73b5d37fa9ac9d6881a33fd3a6" + integrity sha512-htZ2x+hltUpKoPsviWSuelzZW96po9zVSsN0RZEih60FahNX0R2LCqFJ6v5lyATuQ9oHALVi0w8w4rtf8oiAJw== -"@preserves/schema@0.990.1": - version "0.990.1" - resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.990.1.tgz#233e25855194ce0f6ffaa9968d59e50b7dc8635a" - integrity sha512-FdvH0peM7U+Yag8FUZ2CYqDTEWjX88+HWwAfVfndtGAwEOTyjqvAQib0aI9lRPPXHodtaNR9/mLFmZBqve80Ew== +"@preserves/schema@0.995.201": + version "0.995.201" + resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.995.201.tgz#827ad539afb0fdf68ba885ee3ff43db0fd473aa5" + integrity sha512-0SuhwOEAfxtrAeOTZ8V1yNEcHHHEbfUmoFawrF+vzTQFNZRz/X3LF1FM6wOiJlHtb7tBr4B+rHXX8jfNrqrdkA== dependencies: - "@preserves/core" "^0.990.0" + "@preserves/core" "^0.995.200" "@rollup/pluginutils@^3.0.9": version "3.1.0" @@ -23,45 +23,43 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@syndicate-lang/compiler@^0.13.2": - version "0.13.2" - resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.13.2.tgz#e66de9f5828efb88ebe62266d014e13620961996" - integrity sha512-GQa7GVkerWxoVqY3NtRZXS8aLqIsVfdA8KvgNSDb8fTNV8TKGLDxQRurtcCiuEKG9mtfnDTpk8i28HbijKw6fA== +"@syndicate-lang/compiler@^0.21.1": + version "0.21.1" + resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.21.1.tgz#b6316bac14d053c313b3442be68f532a60c47cb3" + integrity sha512-daaYh1i0XmoHt6eTtO4gWblfVKMjp9trwxqR62wUSONY3gtJ5Bn4hG3dMgfoMz2NvOWbJHaGz/95J0jRubITxA== -"@syndicate-lang/core@*", "@syndicate-lang/core@^0.18.1": - version "0.18.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.18.1.tgz#5cd2931acdab76150c0406428521e4746e62f18b" - integrity sha512-90d0YJCZJVrkxLe+fs5Z+vgigU3wux8VOnPje2E8Q/MXXecjHcBCQWQfcdwUxBdfPSFq9KdQS7g7VFqhu3X7mA== +"@syndicate-lang/core@*", "@syndicate-lang/core@^0.32.0": + version "0.32.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.32.0.tgz#0efbbff176cac2969c2b6ba70a19965add3a2c61" + integrity sha512-ERVXk0W1xLaKvUa79Ek74YvqfBU543cUTb2GJvp76TP5k1jA97q9GzhddicS/s8lqu8SUC1+IXmKiJk0NX2TWQ== dependencies: - "@preserves/core" "0.990" - "@preserves/schema" "0.990.1" salty-crypto "0.3.1" "@syndicate-lang/syndicatec@*": - version "0.18.2" - resolved "https://registry.yarnpkg.com/@syndicate-lang/syndicatec/-/syndicatec-0.18.2.tgz#e594f270705c3203a7e26420bc5df2b568977244" - integrity sha512-iUVKqxmiXMC8uYM5bXdyssY6mtVGI5RQRAtmtikji81XJoYb5pfqGlSkMB6n6x7Cde4OsrzeMJYTJ9q7LvEcsQ== + version "0.34.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/syndicatec/-/syndicatec-0.34.0.tgz#f3b88507b633552fe1f41f24def5121c0cafeaeb" + integrity sha512-h3MPifJdXZTS3JVcvRG8GXMJMPBH4RYmJ3B7c2sjM826Pf6O8zT47Vuv1y2WyD9PS8BiSCI01uOR0W5AVJJT5w== dependencies: - "@syndicate-lang/compiler" "^0.13.2" - "@syndicate-lang/core" "^0.18.1" + "@syndicate-lang/compiler" "^0.21.1" + "@syndicate-lang/core" "^0.32.0" glob "^7.1.6" yargs "^16.2.0" "@syndicate-lang/ts-plugin@*": - version "0.18.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/ts-plugin/-/ts-plugin-0.18.1.tgz#0567774f0d7cef6b498cf39bda6717bc334f7213" - integrity sha512-wQJhQxGLjf3cW2w9RUGToZofsd3iG6GQPTHtRYnAYjyiCdxSb7fhZf7TNRkRv3m20Q1XIUSTiLg3ChU+1I9eEA== + version "0.34.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/ts-plugin/-/ts-plugin-0.34.0.tgz#df92f9044eeba528c80c41c5c9df49ee28902411" + integrity sha512-OCO6Hm0euz2hZk6tYTrJQNEM8iDBeQ/dgpW2a/UP52XSP6fYj0OvUVfn+35ZkIL64S+zDsJjL/6XFN05UZyRGA== dependencies: - "@syndicate-lang/compiler" "^0.13.2" - "@syndicate-lang/core" "^0.18.1" + "@syndicate-lang/compiler" "^0.21.1" + "@syndicate-lang/core" "^0.32.0" "@syndicate-lang/tsc@*": - version "0.18.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.18.1.tgz#e56522052f792b8dad0bd21c6181b7c801ea893b" - integrity sha512-arNOK+0NnjCdg6lisOOBD4piMBAxV3OR5frDAQ+DI+44gruvY20Tzen2SFMre7vvr+xVkyQwiHH9VVrgtIQRkw== + version "0.34.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.34.0.tgz#1056fba7f639bbf436d0c2ecd2717edc4c1e612a" + integrity sha512-Ufj3xsdXMbMCavWsEkX/pFyXRpNIWRW+LFew1icD14DoSLqyBcoUEvskolOSgkSzC53tDjbd4/LXDVofIjIyUA== dependencies: - "@syndicate-lang/compiler" "^0.13.2" - "@syndicate-lang/core" "^0.18.1" + "@syndicate-lang/compiler" "^0.21.1" + "@syndicate-lang/core" "^0.32.0" glob "^7.1.6" yargs "^16.2.0" @@ -137,9 +135,9 @@ emoji-regex@^8.0.0: integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== estree-walker@^1.0.1: version "1.0.1" diff --git a/examples/how-to-use-syndicate-tsc/package.json b/examples/how-to-use-syndicate-tsc/package.json index c000ead..30c2ad0 100644 --- a/examples/how-to-use-syndicate-tsc/package.json +++ b/examples/how-to-use-syndicate-tsc/package.json @@ -12,6 +12,8 @@ "author": "Tony Garnock-Jones ", "license": "GPL-3.0+", "dependencies": { + "@preserves/core": "0.995.200", + "@preserves/schema": "0.995.201", "@syndicate-lang/core": "*" }, "devDependencies": { diff --git a/examples/how-to-use-syndicate-tsc/yarn.lock b/examples/how-to-use-syndicate-tsc/yarn.lock index 8c77d70..1c1abe2 100644 --- a/examples/how-to-use-syndicate-tsc/yarn.lock +++ b/examples/how-to-use-syndicate-tsc/yarn.lock @@ -2,17 +2,17 @@ # yarn lockfile v1 -"@preserves/core@0.990", "@preserves/core@^0.990.0": - version "0.990.0" - resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.990.0.tgz#c57c1c3d5159fc17477a4205d5a94a78fbf5b1aa" - integrity sha512-Mx013USv9JU1SrtMxaJISETBy2LZ402xH8ZnQI4JzG6W27ZwGV36DQrXAfF0x6cOmZMGKwJNqQrvmFhh7mEn6w== +"@preserves/core@0.995.200", "@preserves/core@^0.995.200": + version "0.995.200" + resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.200.tgz#65575cf8f9320e73b5d37fa9ac9d6881a33fd3a6" + integrity sha512-htZ2x+hltUpKoPsviWSuelzZW96po9zVSsN0RZEih60FahNX0R2LCqFJ6v5lyATuQ9oHALVi0w8w4rtf8oiAJw== -"@preserves/schema@0.990.1": - version "0.990.1" - resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.990.1.tgz#233e25855194ce0f6ffaa9968d59e50b7dc8635a" - integrity sha512-FdvH0peM7U+Yag8FUZ2CYqDTEWjX88+HWwAfVfndtGAwEOTyjqvAQib0aI9lRPPXHodtaNR9/mLFmZBqve80Ew== +"@preserves/schema@0.995.201": + version "0.995.201" + resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.995.201.tgz#827ad539afb0fdf68ba885ee3ff43db0fd473aa5" + integrity sha512-0SuhwOEAfxtrAeOTZ8V1yNEcHHHEbfUmoFawrF+vzTQFNZRz/X3LF1FM6wOiJlHtb7tBr4B+rHXX8jfNrqrdkA== dependencies: - "@preserves/core" "^0.990.0" + "@preserves/core" "^0.995.200" "@rollup/pluginutils@^3.0.9": version "3.1.0" @@ -23,27 +23,25 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@syndicate-lang/compiler@^0.13.2": - version "0.13.2" - resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.13.2.tgz#e66de9f5828efb88ebe62266d014e13620961996" - integrity sha512-GQa7GVkerWxoVqY3NtRZXS8aLqIsVfdA8KvgNSDb8fTNV8TKGLDxQRurtcCiuEKG9mtfnDTpk8i28HbijKw6fA== +"@syndicate-lang/compiler@^0.21.1": + version "0.21.1" + resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.21.1.tgz#b6316bac14d053c313b3442be68f532a60c47cb3" + integrity sha512-daaYh1i0XmoHt6eTtO4gWblfVKMjp9trwxqR62wUSONY3gtJ5Bn4hG3dMgfoMz2NvOWbJHaGz/95J0jRubITxA== -"@syndicate-lang/core@*", "@syndicate-lang/core@^0.18.1": - version "0.18.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.18.1.tgz#5cd2931acdab76150c0406428521e4746e62f18b" - integrity sha512-90d0YJCZJVrkxLe+fs5Z+vgigU3wux8VOnPje2E8Q/MXXecjHcBCQWQfcdwUxBdfPSFq9KdQS7g7VFqhu3X7mA== +"@syndicate-lang/core@*", "@syndicate-lang/core@^0.32.0": + version "0.32.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.32.0.tgz#0efbbff176cac2969c2b6ba70a19965add3a2c61" + integrity sha512-ERVXk0W1xLaKvUa79Ek74YvqfBU543cUTb2GJvp76TP5k1jA97q9GzhddicS/s8lqu8SUC1+IXmKiJk0NX2TWQ== dependencies: - "@preserves/core" "0.990" - "@preserves/schema" "0.990.1" salty-crypto "0.3.1" "@syndicate-lang/tsc@*": - version "0.18.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.18.1.tgz#e56522052f792b8dad0bd21c6181b7c801ea893b" - integrity sha512-arNOK+0NnjCdg6lisOOBD4piMBAxV3OR5frDAQ+DI+44gruvY20Tzen2SFMre7vvr+xVkyQwiHH9VVrgtIQRkw== + version "0.34.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.34.0.tgz#1056fba7f639bbf436d0c2ecd2717edc4c1e612a" + integrity sha512-Ufj3xsdXMbMCavWsEkX/pFyXRpNIWRW+LFew1icD14DoSLqyBcoUEvskolOSgkSzC53tDjbd4/LXDVofIjIyUA== dependencies: - "@syndicate-lang/compiler" "^0.13.2" - "@syndicate-lang/core" "^0.18.1" + "@syndicate-lang/compiler" "^0.21.1" + "@syndicate-lang/core" "^0.32.0" glob "^7.1.6" yargs "^16.2.0" @@ -119,9 +117,9 @@ emoji-regex@^8.0.0: integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== estree-walker@^1.0.1: version "1.0.1" diff --git a/examples/how-to-use-syndicatec-javascript/package.json b/examples/how-to-use-syndicatec-javascript/package.json index 7c793fe..4703593 100644 --- a/examples/how-to-use-syndicatec-javascript/package.json +++ b/examples/how-to-use-syndicatec-javascript/package.json @@ -12,6 +12,7 @@ "author": "Tony Garnock-Jones ", "license": "GPL-3.0+", "dependencies": { + "@preserves/core": "0.995.200", "@syndicate-lang/core": "*" }, "devDependencies": { diff --git a/examples/how-to-use-syndicatec-javascript/yarn.lock b/examples/how-to-use-syndicatec-javascript/yarn.lock index 1385bc0..76734c9 100644 --- a/examples/how-to-use-syndicatec-javascript/yarn.lock +++ b/examples/how-to-use-syndicatec-javascript/yarn.lock @@ -2,17 +2,10 @@ # yarn lockfile v1 -"@preserves/core@0.990", "@preserves/core@^0.990.0": - version "0.990.0" - resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.990.0.tgz#c57c1c3d5159fc17477a4205d5a94a78fbf5b1aa" - integrity sha512-Mx013USv9JU1SrtMxaJISETBy2LZ402xH8ZnQI4JzG6W27ZwGV36DQrXAfF0x6cOmZMGKwJNqQrvmFhh7mEn6w== - -"@preserves/schema@0.990.1": - version "0.990.1" - resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.990.1.tgz#233e25855194ce0f6ffaa9968d59e50b7dc8635a" - integrity sha512-FdvH0peM7U+Yag8FUZ2CYqDTEWjX88+HWwAfVfndtGAwEOTyjqvAQib0aI9lRPPXHodtaNR9/mLFmZBqve80Ew== - dependencies: - "@preserves/core" "^0.990.0" +"@preserves/core@0.995.200": + version "0.995.200" + resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.200.tgz#65575cf8f9320e73b5d37fa9ac9d6881a33fd3a6" + integrity sha512-htZ2x+hltUpKoPsviWSuelzZW96po9zVSsN0RZEih60FahNX0R2LCqFJ6v5lyATuQ9oHALVi0w8w4rtf8oiAJw== "@rollup/pluginutils@^3.0.9": version "3.1.0" @@ -23,27 +16,25 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@syndicate-lang/compiler@^0.13.2": - version "0.13.2" - resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.13.2.tgz#e66de9f5828efb88ebe62266d014e13620961996" - integrity sha512-GQa7GVkerWxoVqY3NtRZXS8aLqIsVfdA8KvgNSDb8fTNV8TKGLDxQRurtcCiuEKG9mtfnDTpk8i28HbijKw6fA== +"@syndicate-lang/compiler@^0.21.1": + version "0.21.1" + resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.21.1.tgz#b6316bac14d053c313b3442be68f532a60c47cb3" + integrity sha512-daaYh1i0XmoHt6eTtO4gWblfVKMjp9trwxqR62wUSONY3gtJ5Bn4hG3dMgfoMz2NvOWbJHaGz/95J0jRubITxA== -"@syndicate-lang/core@*", "@syndicate-lang/core@^0.18.1": - version "0.18.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.18.1.tgz#5cd2931acdab76150c0406428521e4746e62f18b" - integrity sha512-90d0YJCZJVrkxLe+fs5Z+vgigU3wux8VOnPje2E8Q/MXXecjHcBCQWQfcdwUxBdfPSFq9KdQS7g7VFqhu3X7mA== +"@syndicate-lang/core@*", "@syndicate-lang/core@^0.32.0": + version "0.32.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.32.0.tgz#0efbbff176cac2969c2b6ba70a19965add3a2c61" + integrity sha512-ERVXk0W1xLaKvUa79Ek74YvqfBU543cUTb2GJvp76TP5k1jA97q9GzhddicS/s8lqu8SUC1+IXmKiJk0NX2TWQ== dependencies: - "@preserves/core" "0.990" - "@preserves/schema" "0.990.1" salty-crypto "0.3.1" "@syndicate-lang/syndicatec@*": - version "0.18.2" - resolved "https://registry.yarnpkg.com/@syndicate-lang/syndicatec/-/syndicatec-0.18.2.tgz#e594f270705c3203a7e26420bc5df2b568977244" - integrity sha512-iUVKqxmiXMC8uYM5bXdyssY6mtVGI5RQRAtmtikji81XJoYb5pfqGlSkMB6n6x7Cde4OsrzeMJYTJ9q7LvEcsQ== + version "0.34.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/syndicatec/-/syndicatec-0.34.0.tgz#f3b88507b633552fe1f41f24def5121c0cafeaeb" + integrity sha512-h3MPifJdXZTS3JVcvRG8GXMJMPBH4RYmJ3B7c2sjM826Pf6O8zT47Vuv1y2WyD9PS8BiSCI01uOR0W5AVJJT5w== dependencies: - "@syndicate-lang/compiler" "^0.13.2" - "@syndicate-lang/core" "^0.18.1" + "@syndicate-lang/compiler" "^0.21.1" + "@syndicate-lang/core" "^0.32.0" glob "^7.1.6" yargs "^16.2.0" @@ -119,9 +110,9 @@ emoji-regex@^8.0.0: integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== estree-walker@^1.0.1: version "1.0.1" diff --git a/examples/how-to-use-syndicatec-typescript/package.json b/examples/how-to-use-syndicatec-typescript/package.json index f1b7ef8..329bb8d 100644 --- a/examples/how-to-use-syndicatec-typescript/package.json +++ b/examples/how-to-use-syndicatec-typescript/package.json @@ -12,6 +12,8 @@ "author": "Tony Garnock-Jones ", "license": "GPL-3.0+", "dependencies": { + "@preserves/core": "0.995.200", + "@preserves/schema": "0.995.201", "@syndicate-lang/core": "*" }, "devDependencies": { diff --git a/examples/how-to-use-syndicatec-typescript/yarn.lock b/examples/how-to-use-syndicatec-typescript/yarn.lock index 141f476..1ebd643 100644 --- a/examples/how-to-use-syndicatec-typescript/yarn.lock +++ b/examples/how-to-use-syndicatec-typescript/yarn.lock @@ -2,17 +2,17 @@ # yarn lockfile v1 -"@preserves/core@0.990", "@preserves/core@^0.990.0": - version "0.990.0" - resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.990.0.tgz#c57c1c3d5159fc17477a4205d5a94a78fbf5b1aa" - integrity sha512-Mx013USv9JU1SrtMxaJISETBy2LZ402xH8ZnQI4JzG6W27ZwGV36DQrXAfF0x6cOmZMGKwJNqQrvmFhh7mEn6w== +"@preserves/core@0.995.200", "@preserves/core@^0.995.200": + version "0.995.200" + resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.200.tgz#65575cf8f9320e73b5d37fa9ac9d6881a33fd3a6" + integrity sha512-htZ2x+hltUpKoPsviWSuelzZW96po9zVSsN0RZEih60FahNX0R2LCqFJ6v5lyATuQ9oHALVi0w8w4rtf8oiAJw== -"@preserves/schema@0.990.1": - version "0.990.1" - resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.990.1.tgz#233e25855194ce0f6ffaa9968d59e50b7dc8635a" - integrity sha512-FdvH0peM7U+Yag8FUZ2CYqDTEWjX88+HWwAfVfndtGAwEOTyjqvAQib0aI9lRPPXHodtaNR9/mLFmZBqve80Ew== +"@preserves/schema@0.995.201": + version "0.995.201" + resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.995.201.tgz#827ad539afb0fdf68ba885ee3ff43db0fd473aa5" + integrity sha512-0SuhwOEAfxtrAeOTZ8V1yNEcHHHEbfUmoFawrF+vzTQFNZRz/X3LF1FM6wOiJlHtb7tBr4B+rHXX8jfNrqrdkA== dependencies: - "@preserves/core" "^0.990.0" + "@preserves/core" "^0.995.200" "@rollup/pluginutils@^3.0.9": version "3.1.0" @@ -23,27 +23,25 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@syndicate-lang/compiler@^0.13.2": - version "0.13.2" - resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.13.2.tgz#e66de9f5828efb88ebe62266d014e13620961996" - integrity sha512-GQa7GVkerWxoVqY3NtRZXS8aLqIsVfdA8KvgNSDb8fTNV8TKGLDxQRurtcCiuEKG9mtfnDTpk8i28HbijKw6fA== +"@syndicate-lang/compiler@^0.21.1": + version "0.21.1" + resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.21.1.tgz#b6316bac14d053c313b3442be68f532a60c47cb3" + integrity sha512-daaYh1i0XmoHt6eTtO4gWblfVKMjp9trwxqR62wUSONY3gtJ5Bn4hG3dMgfoMz2NvOWbJHaGz/95J0jRubITxA== -"@syndicate-lang/core@*", "@syndicate-lang/core@^0.18.1": - version "0.18.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.18.1.tgz#5cd2931acdab76150c0406428521e4746e62f18b" - integrity sha512-90d0YJCZJVrkxLe+fs5Z+vgigU3wux8VOnPje2E8Q/MXXecjHcBCQWQfcdwUxBdfPSFq9KdQS7g7VFqhu3X7mA== +"@syndicate-lang/core@*", "@syndicate-lang/core@^0.32.0": + version "0.32.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.32.0.tgz#0efbbff176cac2969c2b6ba70a19965add3a2c61" + integrity sha512-ERVXk0W1xLaKvUa79Ek74YvqfBU543cUTb2GJvp76TP5k1jA97q9GzhddicS/s8lqu8SUC1+IXmKiJk0NX2TWQ== dependencies: - "@preserves/core" "0.990" - "@preserves/schema" "0.990.1" salty-crypto "0.3.1" "@syndicate-lang/syndicatec@*": - version "0.18.2" - resolved "https://registry.yarnpkg.com/@syndicate-lang/syndicatec/-/syndicatec-0.18.2.tgz#e594f270705c3203a7e26420bc5df2b568977244" - integrity sha512-iUVKqxmiXMC8uYM5bXdyssY6mtVGI5RQRAtmtikji81XJoYb5pfqGlSkMB6n6x7Cde4OsrzeMJYTJ9q7LvEcsQ== + version "0.34.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/syndicatec/-/syndicatec-0.34.0.tgz#f3b88507b633552fe1f41f24def5121c0cafeaeb" + integrity sha512-h3MPifJdXZTS3JVcvRG8GXMJMPBH4RYmJ3B7c2sjM826Pf6O8zT47Vuv1y2WyD9PS8BiSCI01uOR0W5AVJJT5w== dependencies: - "@syndicate-lang/compiler" "^0.13.2" - "@syndicate-lang/core" "^0.18.1" + "@syndicate-lang/compiler" "^0.21.1" + "@syndicate-lang/core" "^0.32.0" glob "^7.1.6" yargs "^16.2.0" @@ -119,9 +117,9 @@ emoji-regex@^8.0.0: integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== estree-walker@^1.0.1: version "1.0.1" diff --git a/examples/syndicate-html-example-flappy-bird/index.html b/examples/syndicate-html-example-flappy-bird/index.html index fa16fc7..12c86b1 100644 --- a/examples/syndicate-html-example-flappy-bird/index.html +++ b/examples/syndicate-html-example-flappy-bird/index.html @@ -3,6 +3,7 @@ + diff --git a/examples/syndicate-html-example-flappy-bird/package.json b/examples/syndicate-html-example-flappy-bird/package.json index 481b797..4fc659f 100644 --- a/examples/syndicate-html-example-flappy-bird/package.json +++ b/examples/syndicate-html-example-flappy-bird/package.json @@ -12,6 +12,8 @@ "author": "Tony Garnock-Jones ", "license": "GPL-3.0+", "dependencies": { + "@preserves/core": "0.995.200", + "@preserves/schema": "0.995.201", "@syndicate-lang/core": "*", "@syndicate-lang/html": "*", "@syndicate-lang/timer": "*" diff --git a/examples/syndicate-html-example-flappy-bird/src/index.ts b/examples/syndicate-html-example-flappy-bird/src/index.ts index 5fc778d..a5b58dd 100644 --- a/examples/syndicate-html-example-flappy-bird/src/index.ts +++ b/examples/syndicate-html-example-flappy-bird/src/index.ts @@ -1,7 +1,7 @@ /// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-FileCopyrightText: Copyright © 2016-2021 Tony Garnock-Jones -import { Record, Dataspace, Double, floatValue, Ref, stringify } from '@syndicate-lang/core'; +import { Turn, Dataspace, Double, floatValue, Ref, Facet } from '@syndicate-lang/core'; import { boot as bootHtml, WindowEvent, template, Anchor } from '@syndicate-lang/html'; import { boot as bootTimer, PeriodicTick } from '@syndicate-lang/timer'; @@ -86,9 +86,7 @@ function spawnGame(mainDs: Ref) { on (ypos.value > BOARD_HEIGHT - FLAPPY_HEIGHT) { ypos.value = BOARD_HEIGHT - FLAPPY_HEIGHT; - react { - assert GameOver(); - } + assert GameOver(); } } @@ -141,14 +139,14 @@ function spawnGame(mainDs: Ref) { react { const pipeNumber = nextPipe.value++; spawn linked named ['pipe', pipeNumber] { - runPipe(pipeNumber); + runPipe(pipeNumber, Turn.activeFacet); } } } } } - function runPipe(i: number) { + function runPipe(i: number, mainPipeFacet: Facet) { const xlocation = (i + 1) * 324; let ui = new Anchor(); @@ -159,21 +157,17 @@ function spawnGame(mainDs: Ref) { + PILLAR_HEAD_HEIGHT * 3; const lowerHeight = FIELD_HEIGHT - upperHeight - PILLAR_GAP; - stop on (xpos.value < -(PILLAR_WIDTH + FLAPPY_XPOS)); + stop mainPipeFacet on (xpos.value < -(PILLAR_WIDTH + FLAPPY_XPOS)); at gameDs { - react { - stop on (xpos.value <= 0) send message IncreaseScore(); - } + once (xpos.value <= 0) send message IncreaseScore(); on asserted Position($flappyXpos, _) => xpos.value = xlocation - floatValue(flappyXpos); on asserted Position($xpos, $ypos) => { if (touchingPillar(floatValue(xpos), floatValue(ypos))) { - react { - assert GameOver(); - } + assert GameOver(); } } } diff --git a/examples/syndicate-html-example-flappy-bird/yarn.lock b/examples/syndicate-html-example-flappy-bird/yarn.lock index 471ca78..01da2d9 100644 --- a/examples/syndicate-html-example-flappy-bird/yarn.lock +++ b/examples/syndicate-html-example-flappy-bird/yarn.lock @@ -2,17 +2,17 @@ # yarn lockfile v1 -"@preserves/core@0.990", "@preserves/core@^0.990.0": - version "0.990.0" - resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.990.0.tgz#c57c1c3d5159fc17477a4205d5a94a78fbf5b1aa" - integrity sha512-Mx013USv9JU1SrtMxaJISETBy2LZ402xH8ZnQI4JzG6W27ZwGV36DQrXAfF0x6cOmZMGKwJNqQrvmFhh7mEn6w== +"@preserves/core@0.995.200", "@preserves/core@^0.995.200": + version "0.995.200" + resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.200.tgz#65575cf8f9320e73b5d37fa9ac9d6881a33fd3a6" + integrity sha512-htZ2x+hltUpKoPsviWSuelzZW96po9zVSsN0RZEih60FahNX0R2LCqFJ6v5lyATuQ9oHALVi0w8w4rtf8oiAJw== -"@preserves/schema@0.990.1": - version "0.990.1" - resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.990.1.tgz#233e25855194ce0f6ffaa9968d59e50b7dc8635a" - integrity sha512-FdvH0peM7U+Yag8FUZ2CYqDTEWjX88+HWwAfVfndtGAwEOTyjqvAQib0aI9lRPPXHodtaNR9/mLFmZBqve80Ew== +"@preserves/schema@0.995.201": + version "0.995.201" + resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.995.201.tgz#827ad539afb0fdf68ba885ee3ff43db0fd473aa5" + integrity sha512-0SuhwOEAfxtrAeOTZ8V1yNEcHHHEbfUmoFawrF+vzTQFNZRz/X3LF1FM6wOiJlHtb7tBr4B+rHXX8jfNrqrdkA== dependencies: - "@preserves/core" "^0.990.0" + "@preserves/core" "^0.995.200" "@rollup/pluginutils@^3.0.9": version "3.1.0" @@ -23,49 +23,47 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@syndicate-lang/compiler@^0.13.2": - version "0.13.2" - resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.13.2.tgz#e66de9f5828efb88ebe62266d014e13620961996" - integrity sha512-GQa7GVkerWxoVqY3NtRZXS8aLqIsVfdA8KvgNSDb8fTNV8TKGLDxQRurtcCiuEKG9mtfnDTpk8i28HbijKw6fA== +"@syndicate-lang/compiler@^0.21.1": + version "0.21.1" + resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.21.1.tgz#b6316bac14d053c313b3442be68f532a60c47cb3" + integrity sha512-daaYh1i0XmoHt6eTtO4gWblfVKMjp9trwxqR62wUSONY3gtJ5Bn4hG3dMgfoMz2NvOWbJHaGz/95J0jRubITxA== -"@syndicate-lang/core@*", "@syndicate-lang/core@^0.18.1": - version "0.18.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.18.1.tgz#5cd2931acdab76150c0406428521e4746e62f18b" - integrity sha512-90d0YJCZJVrkxLe+fs5Z+vgigU3wux8VOnPje2E8Q/MXXecjHcBCQWQfcdwUxBdfPSFq9KdQS7g7VFqhu3X7mA== +"@syndicate-lang/core@*", "@syndicate-lang/core@^0.32.0": + version "0.32.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.32.0.tgz#0efbbff176cac2969c2b6ba70a19965add3a2c61" + integrity sha512-ERVXk0W1xLaKvUa79Ek74YvqfBU543cUTb2GJvp76TP5k1jA97q9GzhddicS/s8lqu8SUC1+IXmKiJk0NX2TWQ== dependencies: - "@preserves/core" "0.990" - "@preserves/schema" "0.990.1" salty-crypto "0.3.1" "@syndicate-lang/html@*": - version "0.18.2" - resolved "https://registry.yarnpkg.com/@syndicate-lang/html/-/html-0.18.2.tgz#276f70a209d90cf938eb27ebdddadfb1c299f234" - integrity sha512-VTMqrXLFvUQH/TWxTG+YZjUqymoNprde1bhJ2JQ1xyqlHAB82tYXZRJA+/qn93mFs6jCEN9vzvXyNbmJuyYH7Q== + version "0.33.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/html/-/html-0.33.0.tgz#c53e6bf8a52b17c3747f4270713a8c9234f984af" + integrity sha512-xhN6NZOgLxlAQOyWG0JAgtyF1e1yQvrpNh5RBAPnucFYC024yo1ggZ08+KiaulhsoIKvRbBE6FU6p9dDm4/tpQ== dependencies: - "@syndicate-lang/core" "^0.18.1" + "@syndicate-lang/core" "^0.32.0" "@syndicate-lang/timer@*": - version "0.18.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/timer/-/timer-0.18.1.tgz#64f1364eaea77b9ec5b77d41a464baeadf32031b" - integrity sha512-49acCxOpOR4LgW9ENQ32+A/wF+fQgvAwhsBS4phzk3DB/Yj9opFZW5MOlMP4R9+iyoN1Nocwq0OO89QGnqg9Wg== + version "0.33.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/timer/-/timer-0.33.0.tgz#cdb38ebe777332ec58a5b0b9483db809275a61de" + integrity sha512-cBon+nk8zvNeU4zC6tg7nhgJnmrRoXHYE140UK3gscNFcg1LZ1d7q9WxfVTzFtRocRBslv6pworSwCDn3Go7TQ== dependencies: - "@syndicate-lang/core" "^0.18.1" + "@syndicate-lang/core" "^0.32.0" "@syndicate-lang/ts-plugin@*": - version "0.18.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/ts-plugin/-/ts-plugin-0.18.1.tgz#0567774f0d7cef6b498cf39bda6717bc334f7213" - integrity sha512-wQJhQxGLjf3cW2w9RUGToZofsd3iG6GQPTHtRYnAYjyiCdxSb7fhZf7TNRkRv3m20Q1XIUSTiLg3ChU+1I9eEA== + version "0.34.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/ts-plugin/-/ts-plugin-0.34.0.tgz#df92f9044eeba528c80c41c5c9df49ee28902411" + integrity sha512-OCO6Hm0euz2hZk6tYTrJQNEM8iDBeQ/dgpW2a/UP52XSP6fYj0OvUVfn+35ZkIL64S+zDsJjL/6XFN05UZyRGA== dependencies: - "@syndicate-lang/compiler" "^0.13.2" - "@syndicate-lang/core" "^0.18.1" + "@syndicate-lang/compiler" "^0.21.1" + "@syndicate-lang/core" "^0.32.0" "@syndicate-lang/tsc@*": - version "0.18.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.18.1.tgz#e56522052f792b8dad0bd21c6181b7c801ea893b" - integrity sha512-arNOK+0NnjCdg6lisOOBD4piMBAxV3OR5frDAQ+DI+44gruvY20Tzen2SFMre7vvr+xVkyQwiHH9VVrgtIQRkw== + version "0.34.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.34.0.tgz#1056fba7f639bbf436d0c2ecd2717edc4c1e612a" + integrity sha512-Ufj3xsdXMbMCavWsEkX/pFyXRpNIWRW+LFew1icD14DoSLqyBcoUEvskolOSgkSzC53tDjbd4/LXDVofIjIyUA== dependencies: - "@syndicate-lang/compiler" "^0.13.2" - "@syndicate-lang/core" "^0.18.1" + "@syndicate-lang/compiler" "^0.21.1" + "@syndicate-lang/core" "^0.32.0" glob "^7.1.6" yargs "^16.2.0" @@ -141,9 +139,9 @@ emoji-regex@^8.0.0: integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== estree-walker@^1.0.1: version "1.0.1" diff --git a/examples/syndicate-html-example-table/index.html b/examples/syndicate-html-example-table/index.html index 413b66a..b040f31 100644 --- a/examples/syndicate-html-example-table/index.html +++ b/examples/syndicate-html-example-table/index.html @@ -3,6 +3,7 @@ Syndicate: Table Example + diff --git a/examples/syndicate-html-example-table/package.json b/examples/syndicate-html-example-table/package.json index 6f19e73..57fafc6 100644 --- a/examples/syndicate-html-example-table/package.json +++ b/examples/syndicate-html-example-table/package.json @@ -14,6 +14,8 @@ "author": "Tony Garnock-Jones ", "license": "GPL-3.0+", "dependencies": { + "@preserves/core": "0.995.200", + "@preserves/schema": "0.995.201", "@syndicate-lang/core": "*", "@syndicate-lang/html": "*" }, diff --git a/examples/syndicate-html-example-table/src/index.ts b/examples/syndicate-html-example-table/src/index.ts index 94b9063..25c96a7 100644 --- a/examples/syndicate-html-example-table/src/index.ts +++ b/examples/syndicate-html-example-table/src/index.ts @@ -1,7 +1,7 @@ /// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-FileCopyrightText: Copyright © 2016-2021 Tony Garnock-Jones -import { Dataspace, Embedded, Value, Ref } from '@syndicate-lang/core'; +import { Dataspace, Value, Ref } from '@syndicate-lang/core'; import { boot as bootHtml, UIEvent, GlobalEvent, HtmlFragments, template, Anchor } from '@syndicate-lang/html'; assertion type Person(id, firstName, lastName, address, age); @@ -42,7 +42,7 @@ Dataspace.boot(ds => { spawn named 'controller' { on message GlobalEvent('table#the-table th', 'click', $e) => { - const event = (e as Embedded).embeddedValue.target.data as Event; + const event = (e as Ref).target.data as Event; send message SetSortColumn(JSON.parse((event.target as HTMLElement).dataset.column!)); } } diff --git a/examples/syndicate-html-example-table/yarn.lock b/examples/syndicate-html-example-table/yarn.lock index e49b1ad..bfaece8 100644 --- a/examples/syndicate-html-example-table/yarn.lock +++ b/examples/syndicate-html-example-table/yarn.lock @@ -2,17 +2,17 @@ # yarn lockfile v1 -"@preserves/core@0.990", "@preserves/core@^0.990.0": - version "0.990.0" - resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.990.0.tgz#c57c1c3d5159fc17477a4205d5a94a78fbf5b1aa" - integrity sha512-Mx013USv9JU1SrtMxaJISETBy2LZ402xH8ZnQI4JzG6W27ZwGV36DQrXAfF0x6cOmZMGKwJNqQrvmFhh7mEn6w== +"@preserves/core@0.995.200", "@preserves/core@^0.995.200": + version "0.995.200" + resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.200.tgz#65575cf8f9320e73b5d37fa9ac9d6881a33fd3a6" + integrity sha512-htZ2x+hltUpKoPsviWSuelzZW96po9zVSsN0RZEih60FahNX0R2LCqFJ6v5lyATuQ9oHALVi0w8w4rtf8oiAJw== -"@preserves/schema@0.990.1": - version "0.990.1" - resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.990.1.tgz#233e25855194ce0f6ffaa9968d59e50b7dc8635a" - integrity sha512-FdvH0peM7U+Yag8FUZ2CYqDTEWjX88+HWwAfVfndtGAwEOTyjqvAQib0aI9lRPPXHodtaNR9/mLFmZBqve80Ew== +"@preserves/schema@0.995.201": + version "0.995.201" + resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.995.201.tgz#827ad539afb0fdf68ba885ee3ff43db0fd473aa5" + integrity sha512-0SuhwOEAfxtrAeOTZ8V1yNEcHHHEbfUmoFawrF+vzTQFNZRz/X3LF1FM6wOiJlHtb7tBr4B+rHXX8jfNrqrdkA== dependencies: - "@preserves/core" "^0.990.0" + "@preserves/core" "^0.995.200" "@rollup/pluginutils@^3.0.9": version "3.1.0" @@ -23,42 +23,40 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@syndicate-lang/compiler@^0.13.2": - version "0.13.2" - resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.13.2.tgz#e66de9f5828efb88ebe62266d014e13620961996" - integrity sha512-GQa7GVkerWxoVqY3NtRZXS8aLqIsVfdA8KvgNSDb8fTNV8TKGLDxQRurtcCiuEKG9mtfnDTpk8i28HbijKw6fA== +"@syndicate-lang/compiler@^0.21.1": + version "0.21.1" + resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.21.1.tgz#b6316bac14d053c313b3442be68f532a60c47cb3" + integrity sha512-daaYh1i0XmoHt6eTtO4gWblfVKMjp9trwxqR62wUSONY3gtJ5Bn4hG3dMgfoMz2NvOWbJHaGz/95J0jRubITxA== -"@syndicate-lang/core@*", "@syndicate-lang/core@^0.18.1": - version "0.18.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.18.1.tgz#5cd2931acdab76150c0406428521e4746e62f18b" - integrity sha512-90d0YJCZJVrkxLe+fs5Z+vgigU3wux8VOnPje2E8Q/MXXecjHcBCQWQfcdwUxBdfPSFq9KdQS7g7VFqhu3X7mA== +"@syndicate-lang/core@*", "@syndicate-lang/core@^0.32.0": + version "0.32.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.32.0.tgz#0efbbff176cac2969c2b6ba70a19965add3a2c61" + integrity sha512-ERVXk0W1xLaKvUa79Ek74YvqfBU543cUTb2GJvp76TP5k1jA97q9GzhddicS/s8lqu8SUC1+IXmKiJk0NX2TWQ== dependencies: - "@preserves/core" "0.990" - "@preserves/schema" "0.990.1" salty-crypto "0.3.1" "@syndicate-lang/html@*": - version "0.18.2" - resolved "https://registry.yarnpkg.com/@syndicate-lang/html/-/html-0.18.2.tgz#276f70a209d90cf938eb27ebdddadfb1c299f234" - integrity sha512-VTMqrXLFvUQH/TWxTG+YZjUqymoNprde1bhJ2JQ1xyqlHAB82tYXZRJA+/qn93mFs6jCEN9vzvXyNbmJuyYH7Q== + version "0.33.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/html/-/html-0.33.0.tgz#c53e6bf8a52b17c3747f4270713a8c9234f984af" + integrity sha512-xhN6NZOgLxlAQOyWG0JAgtyF1e1yQvrpNh5RBAPnucFYC024yo1ggZ08+KiaulhsoIKvRbBE6FU6p9dDm4/tpQ== dependencies: - "@syndicate-lang/core" "^0.18.1" + "@syndicate-lang/core" "^0.32.0" "@syndicate-lang/ts-plugin@*": - version "0.18.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/ts-plugin/-/ts-plugin-0.18.1.tgz#0567774f0d7cef6b498cf39bda6717bc334f7213" - integrity sha512-wQJhQxGLjf3cW2w9RUGToZofsd3iG6GQPTHtRYnAYjyiCdxSb7fhZf7TNRkRv3m20Q1XIUSTiLg3ChU+1I9eEA== + version "0.34.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/ts-plugin/-/ts-plugin-0.34.0.tgz#df92f9044eeba528c80c41c5c9df49ee28902411" + integrity sha512-OCO6Hm0euz2hZk6tYTrJQNEM8iDBeQ/dgpW2a/UP52XSP6fYj0OvUVfn+35ZkIL64S+zDsJjL/6XFN05UZyRGA== dependencies: - "@syndicate-lang/compiler" "^0.13.2" - "@syndicate-lang/core" "^0.18.1" + "@syndicate-lang/compiler" "^0.21.1" + "@syndicate-lang/core" "^0.32.0" "@syndicate-lang/tsc@*": - version "0.18.1" - resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.18.1.tgz#e56522052f792b8dad0bd21c6181b7c801ea893b" - integrity sha512-arNOK+0NnjCdg6lisOOBD4piMBAxV3OR5frDAQ+DI+44gruvY20Tzen2SFMre7vvr+xVkyQwiHH9VVrgtIQRkw== + version "0.34.0" + resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.34.0.tgz#1056fba7f639bbf436d0c2ecd2717edc4c1e612a" + integrity sha512-Ufj3xsdXMbMCavWsEkX/pFyXRpNIWRW+LFew1icD14DoSLqyBcoUEvskolOSgkSzC53tDjbd4/LXDVofIjIyUA== dependencies: - "@syndicate-lang/compiler" "^0.13.2" - "@syndicate-lang/core" "^0.18.1" + "@syndicate-lang/compiler" "^0.21.1" + "@syndicate-lang/core" "^0.32.0" glob "^7.1.6" yargs "^16.2.0" @@ -134,9 +132,9 @@ emoji-regex@^8.0.0: integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== estree-walker@^1.0.1: version "1.0.1" diff --git a/package.json b/package.json index 77011cd..b096538 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "packages/*/examples/*/" ], "devDependencies": { - "@preserves/core": "0.992.4", + "@preserves/core": "0.995.200", "@rollup/plugin-node-resolve": "^13.0", "@types/jest": "^27.0", "@types/node": "^14", diff --git a/packages/browser-stdenv/boot.js b/packages/browser-stdenv/boot.js index 5dce07a..2339d84 100644 --- a/packages/browser-stdenv/boot.js +++ b/packages/browser-stdenv/boot.js @@ -1,5 +1,5 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2023-2024 Tony Garnock-Jones const SyndicateBrowserStdenv = { autoboot: true, diff --git a/packages/browser-stdenv/package.json b/packages/browser-stdenv/package.json index 2efe231..2886ac6 100644 --- a/packages/browser-stdenv/package.json +++ b/packages/browser-stdenv/package.json @@ -1,6 +1,6 @@ { "name": "@syndicate-lang/browser-stdenv", - "version": "0.23.3", + "version": "0.33.0", "description": "Aggregated Syndicate and Preserves scripts for in-browser use", "homepage": "https://github.com/syndicate-lang/syndicate-js/tree/main/packages/browser-stdenv", "license": "GPL-3.0+", @@ -15,15 +15,15 @@ "author": "Tony Garnock-Jones ", "scripts": { "prepare": "./build-aggregate.sh", - "clean": "rm -rf index.js index.min.js", + "clean": "rm -rf index.js index.min.js *.js.map", "veryclean": "yarn run clean && rm -rf node_modules" }, "dependencies": { - "@preserves/core": "0.992.4", - "@preserves/schema": "0.992.5", - "@syndicate-lang/compiler": "^0.18.0", - "@syndicate-lang/core": "^0.23.0", - "@syndicate-lang/html2": "^0.24.2", - "@syndicate-lang/ws-relay": "^0.25.0" + "@preserves/core": "0.995.200", + "@preserves/schema": "0.995.201", + "@syndicate-lang/compiler": "^0.21.1", + "@syndicate-lang/core": "^0.32.0", + "@syndicate-lang/html2": "^0.33.0", + "@syndicate-lang/ws-relay": "^0.34.0" } } diff --git a/packages/compiler/jest.config.ts b/packages/compiler/jest.config.ts new file mode 100644 index 0000000..4a09b3e --- /dev/null +++ b/packages/compiler/jest.config.ts @@ -0,0 +1,7 @@ +/// SPDX-License-Identifier: GPL-3.0-or-later +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones + +export default { + preset: 'ts-jest', + testEnvironment: 'node', +}; diff --git a/packages/compiler/package.json b/packages/compiler/package.json index b6ff493..473accc 100644 --- a/packages/compiler/package.json +++ b/packages/compiler/package.json @@ -1,6 +1,6 @@ { "name": "@syndicate-lang/compiler", - "version": "0.18.0", + "version": "0.21.1", "description": "Syndicate/JS compiler library", "homepage": "https://github.com/syndicate-lang/syndicate-js/tree/main/packages/compiler", "license": "GPL-3.0+", @@ -18,7 +18,13 @@ "rollup": "../../node_modules/.bin/rollup -c", "rollup:watch": "../../node_modules/.bin/rollup -c -w", "clean": "rm -rf lib dist", - "veryclean": "yarn run clean && rm -rf node_modules" + "veryclean": "yarn run clean && rm -rf node_modules", + "test": "../../node_modules/.bin/jest", + "test:watch": "yarn test --watch" + }, + "devDependencies": { + "@types/js-beautify": "1.14", + "js-beautify": "1.15" }, "main": "dist/syndicate-compiler.js", "module": "lib/index.js", diff --git a/packages/compiler/rollup.config.js b/packages/compiler/rollup.config.js index 7860637..b26470d 100644 --- a/packages/compiler/rollup.config.js +++ b/packages/compiler/rollup.config.js @@ -1,5 +1,5 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones import { SyndicateRollup } from '../../rollup.js'; const r = new SyndicateRollup('syndicate-compiler', { globalName: 'SyndicateCompiler' }); diff --git a/packages/compiler/src/compiler/codegen.ts b/packages/compiler/src/compiler/codegen.ts index e4684e8..116de21 100644 --- a/packages/compiler/src/compiler/codegen.ts +++ b/packages/compiler/src/compiler/codegen.ts @@ -1,5 +1,5 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones import { isToken, isTokenType, replace, commaJoin, startPos, fixPos, joinItems, @@ -7,7 +7,7 @@ import { Items, Pattern, Templates, Substitution, TokenType, SourceMap, CodeWriter, TemplateFunction, Token, SpanIndex, match, TokenBase, getRange, Pos, -} from '../syntax/index.js'; +} from '../syntax/index'; import { SyndicateParser, SyndicateTypedParser, Identifier, @@ -17,7 +17,8 @@ import { compilePattern, SpawnStatement, -} from './grammar.js'; + FacetToStop, +} from './grammar'; export function stripShebang(items: Items): Items { if ((items.length > 0) && @@ -116,20 +117,43 @@ function binderTypeGuard(t: TemplateFunction): (binder: Binder, index: number) = export function expand(tree: Items, ctx: ExpansionContext): Items { const macro = new Templates(undefined, { extraDelimiters: ':' }); - function terminalWrap(t: TemplateFunction, isTerminal: boolean, body: Statement): Statement { - if (isTerminal) { - return t`__SYNDICATE__.Turn.active._stop(__SYNDICATE__.Turn.activeFacet, () => {${body}})` + function terminalWrap( + t: TemplateFunction, + facetToStop: FacetToStop | 'none' | 'once-wrapper', + body: Statement, + ): Statement { + if (facetToStop === 'none') { + return walk(body); } else { - return body; + const toStop = + facetToStop === 'default' ? 'currentSyndicateFacet' : + facetToStop === 'once-wrapper' ? '__once_facet' : + walk(facetToStop); + const resetCurrentSyndicateFacet = + facetToStop === 'once-wrapper' ? [] : + t`const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet;`; + return t`__SYNDICATE__.Turn.active._stop(${toStop}, () => {${resetCurrentSyndicateFacet}${walk(body)}})`; } } - function facetWrap(t: TemplateFunction, items: Items): Items { - return t`__SYNDICATE__.Turn.active.facet(() => {${items}})`; + function facetWrap( + t: TemplateFunction, + facetName: Identifier | 'default' | 'once-wrapper', + items: Items, + ): Items { + if (facetName === 'once-wrapper') { + return t`__SYNDICATE__.Turn.active.facet(() => {const __once_facet = __SYNDICATE__.Turn.activeFacet; ${items}});`; + } else { + const defaultLabel = t`const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; `; + const customLabel = facetName === 'default' + ? [] + : t`const ${facetName.text} = currentSyndicateFacet; `; + return t`__SYNDICATE__.Turn.active.facet(() => {${defaultLabel}${customLabel}${items}});`; + } } function x(p: Pattern, f: (v: T, t: TemplateFunction) => Items) { - tree = replace(tree, p, (v, start) => f(v, macro.template(fixPos(start)))); + tree = replace(tree, null, p, (v, start) => f(v, macro.template(fixPos(start)))); } function xf(p: Pattern, f: (v: T, t: TemplateFunction) => Items) { @@ -144,7 +168,7 @@ export function expand(tree: Items, ctx: ExpansionContext): Items { // following transformations matters. xf(ctx.parser.duringStatement, (s, t) => { - let spawn = match(ctx.parser.spawn, s.body, null); + let spawn = match(ctx.parser.spawn, s.body, null, null); if (spawn !== null) { if (spawn.linkedToken !== null) { ctx.emitError(`during ... spawn doesn't need "linked", it's always linked`, @@ -155,7 +179,7 @@ export function expand(tree: Items, ctx: ExpansionContext): Items { let body = (spawn === null) ? walk(s.body) - : expandSpawn(spawn, t, t`__SYNDICATE__.Turn.activeFacet.preventInertCheck();`); + : expandSpawn(spawn, t, t` __SYNDICATE__.Turn.activeFacet.preventInertCheck();`); const sa = compilePattern(s.pattern); const assertion = t`__SYNDICATE__.Observe({ @@ -185,8 +209,9 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')} ? t`, new __SYNDICATE__.Set([${commaJoin(s.initialAssertions.map(walk))}])` : ``; */ - const n = spawn.name === void 0 ? '' : t` __SYNDICATE__.Turn.activeFacet.actor.name = ${walk(spawn.name)};`; - return t`__SYNDICATE__.Dataspace._spawn${spawn.linkedToken ? 'Link': ''}(() => {${n} ${inject} ${walk(spawn.body)} });`; + const f = t` const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet;`; + const n = spawn.name === void 0 ? '' : t` currentSyndicateFacet.actor.name = ${walk(spawn.name)};`; + return t`__SYNDICATE__.Dataspace._spawn${spawn.linkedToken ? 'Link': ''}(() => {${f}${n}${inject}${walk(spawn.body)}});`; } x(ctx.parser.spawn, expandSpawn); @@ -226,10 +251,10 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')} t`_dataflow(() => {${walk(s.body)}});`); x(ctx.parser.eventHandlerEndpointStatement, (s, t) => { - const wrap = s.once ? (i: Items) => facetWrap(t, i) : (i: Items) => i; + const wrap = s.once ? (i: Items) => facetWrap(t, 'once-wrapper', i) : (i: Items) => i; if (s.triggerType === 'dataflow') { - return wrap(t`__SYNDICATE__.Turn.active._dataflow(() => { if (${walk(s.predicate)}) { ${terminalWrap(t, s.terminal, walk(s.body))} } });`); + return wrap(t`__SYNDICATE__.Turn.active._dataflow(() => { if (${walk(s.predicate)}) { ${terminalWrap(t, s.facetToStop, s.body)} } });`); } if (s.triggerType === 'stop') { @@ -247,19 +272,19 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')} case 'asserted': entity = t`{ assert: (${ctx.argDecl(t, '__vs', '__SYNDICATE__.AnyValue')}, ${ctx.argDecl(t, '__handle', '__SYNDICATE__.Handle')}) => { - ${guardBody(terminalWrap(t, s.terminal, walk(s.body)))} + ${guardBody(terminalWrap(t, s.facetToStop, s.body))} } }`; break; case 'retracted': entity = t`__SYNDICATE__.assertionObserver((${ctx.argDecl(t, '__vs', '__SYNDICATE__.AnyValue')}) => { - ${guardBody(t`return () => { ${terminalWrap(t, s.terminal, walk(s.body))} };`)} + ${guardBody(t`return () => { ${terminalWrap(t, s.facetToStop, s.body)} };`)} })`; break; case 'message': entity = t`{ message: (${ctx.argDecl(t, '__vs', '__SYNDICATE__.AnyValue')}) => { - ${guardBody(terminalWrap(t, s.terminal, walk(s.body)))} + ${guardBody(terminalWrap(t, s.facetToStop, s.body))} } }`; break; @@ -294,10 +319,9 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')} xf(ctx.parser.messageSendStatement, (s, t) => t`message(currentSyndicateTarget, ${walk(s.expr)});`); - x(ctx.parser.reactStatement, (s, t) => facetWrap(t, s.body)); + x(ctx.parser.reactStatement, (s, t) => facetWrap(t, s.label ?? 'default', s.body)); - x(ctx.parser.stopStatement, (s, t) => - t`__SYNDICATE__.Turn.active._stop(__SYNDICATE__.Turn.activeFacet, () => {${walk(s.body)}});`) + x(ctx.parser.stopStatement, (s, t) => t`${terminalWrap(t, s.facetToStop, s.body)};`); return tree; } diff --git a/packages/compiler/src/compiler/grammar.ts b/packages/compiler/src/compiler/grammar.ts index 127e8f4..3585e2b 100644 --- a/packages/compiler/src/compiler/grammar.ts +++ b/packages/compiler/src/compiler/grammar.ts @@ -1,16 +1,17 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones import { - Token, Items, TokenBase, TokenType, + Token, Items, TokenBase, TokenType, Pos, Pattern, foldItems, match, anonymousTemplate as template, commaJoin, + advancePos, - scope, bind, seq, alt, upTo, atom, atomString, group, + scope, bind, seq, seqTuple, alt, upTo, atom, atomString, group, repeat, option, withoutSpace, map, mapm, rest, discard, value, succeed, fail, separatedOrTerminatedBy, not, -} from '../syntax/index.js'; -import * as Matcher from '../syntax/matcher.js'; +} from '../syntax/index'; +import * as Matcher from '../syntax/matcher'; //--------------------------------------------------------------------------- // AST types @@ -50,8 +51,14 @@ export interface StatementTurnAction extends TurnAction { body: Statement; } +export type FacetToStop = 'default' | Expr; + +export interface StopStatement extends StatementTurnAction { + facetToStop: FacetToStop; +} + export interface GenericEventEndpointStatement extends StatementTurnAction { - terminal: boolean; + facetToStop: FacetToStop | 'none' | 'once-wrapper'; once: boolean; isDynamic: boolean; } @@ -90,6 +97,7 @@ export interface DuringStatement extends FacetSetupAction { } export interface ReactStatement extends FacetSetupAction { + label: Identifier | null; } export interface AtStatement { @@ -174,16 +182,29 @@ export class SyndicateParser { return group('{', map(rest, items => (acc?.push(... items), items))); } - readonly statementBoundary = alt(atom(';'), Matcher.newline); + readonly statementBoundary = alt( + atom(';'), + Matcher.newline, + seq(Matcher.end, i => { + if (i.context === null || i.context === '{') return discard(i); + // ^ toplevel, or inside braces, so presumably statement context + return fail(i); // otherwise, parens or brackets presumably, so not statement context + }), + ); readonly exprBoundary = alt(atom(';'), atom(','), group('{', discard), Matcher.end); readonly identifier: Pattern = atom(); - get binder(): Pattern { return scope(o => bind(o, 'id', this.identifier)); } + binder(... _extraStops: Pattern[]): Pattern { return scope(o => bind(o, 'id', this.identifier)); } + readonly defaultBinder = this.binder(); expr(... extraStops: Pattern[]): Pattern { return withoutSpace(upTo(alt(this.exprBoundary, ... extraStops))); } + expr1(... extraStops: Pattern[]): Pattern { + return mapm(this.expr(... extraStops), e => e.length ? succeed(e) : fail); + } + propertyNameExpr(): Pattern { const dq = template`"`; return alt( @@ -229,7 +250,7 @@ export class SyndicateParser { map(scope( (l: { b: Binder, init: Expr }) => seq(kw('let'), - bind(l, 'b', this.binder), + bind(l, 'b', this.defaultBinder), atom('='), bind(l, 'init', this.headerExpr))), l => { @@ -243,7 +264,7 @@ export class SyndicateParser { readonly fieldDeclarationStatement: Pattern = this.turnAction(o => { return seq(atom('field'), - bind(o, 'field', this.binder), + bind(o, 'field', this.defaultBinder), option(seq(atom('='), bind(o, 'init', this.expr()))), this.statementBoundary); }); @@ -271,22 +292,25 @@ export class SyndicateParser { mandatoryIfNotTerminal(o: GenericEventEndpointStatement, p: Pattern): Pattern { return i => { - return (o.terminal) ? option(p)(i) : p(i); + return (o.facetToStop !== 'none') ? option(p)(i) : p(i); }; } // Principal: Turn readonly eventHandlerEndpointStatement: Pattern = this.turnAction(o => { - o.terminal = false; + o.facetToStop = 'none'; o.once = false; o.isDynamic = true; o.body = []; - return seq(alt(seq(option(map(atom('stop'), _ => o.terminal = true)), + return seq(alt(seq(option(seq(atom('stop'), + map(option(this.expr1(atom('on'))), es => { + o.facetToStop = es.length ? es[0] : 'default'; + }))), atom('on')), map(atom('once'), _ => { - o.terminal = true; o.once = true; + o.facetToStop = 'once-wrapper'; })), alt(seq(map(group('(', bind(o as DataflowEndpointStatement, 'predicate', this.expr())), @@ -294,7 +318,7 @@ export class SyndicateParser { this.mandatoryIfNotTerminal(o, this.statement(o.body))), mapm(seq(bind(o, 'triggerType', atomString('stop')), option(this.statement(o.body))), - v => o.terminal ? fail : succeed(v)), + v => ((o.facetToStop !== 'none') || o.once) ? fail : succeed(v)), seq(bind(o, 'triggerType', alt(atomString('asserted'), atomString('retracted'), @@ -311,7 +335,7 @@ export class SyndicateParser { scope(o => seq(bind(o, 'expectedUse', alt(atomString('message'), atomString('assertion'))), atom('type'), bind(o, 'label', this.identifier), - group('(', bind(o, 'fields', repeat(this.binder, { separator: atom(',') }))), + group('(', bind(o, 'fields', repeat(this.defaultBinder, { separator: atom(',') }))), option(seq(atom('='), bind(o, 'wireName', withoutSpace(upTo(this.statementBoundary))))), this.statementBoundary)); @@ -338,12 +362,23 @@ export class SyndicateParser { // Principal: Turn readonly reactStatement: Pattern = this.turnAction(o => { + o.label = null; o.body = []; - return seq(atom('react'), this.block(o.body)); + return seq(option(map(seqTuple(this.identifier, atom(':')), + ([i, _colon]) => o.label = i)), + atom('react'), + this.block(o.body)); }); // Principal: Turn - readonly stopStatement = this.blockTurnAction(atom('stop')); + readonly stopStatement: Pattern = + this.turnAction(o => { + o.facetToStop = 'default'; + o.body = []; + return seq(atom('stop'), + option(map(this.expr1(), e => o.facetToStop = e)), + alt(this.block(o.body), this.statementBoundary)); + }); // Principal: none readonly atStatement: Pattern = @@ -374,12 +409,22 @@ export class SyndicateParser { // {expr: expr, ...} - constant // other - constant - readonly pCaptureBinder: Pattern = - mapm(this.binder, i => { - return i.id.text.startsWith('$') - ? succeed({ id: { ... i.id, text: i.id.text.slice(1) }, type: i.type }) - : fail; + pCaptureBinder = (b: Pattern): Pattern => + mapm(b, i => { + if (i.id.text.startsWith('$')) { + const adjustedStart: Pos = { ... i.id.start }; + advancePos(adjustedStart, ' '); + const adjustedId: Token = { + ... i.id, + start: adjustedStart, + text: i.id.text.slice(1), + }; + return succeed({ id: adjustedId, type: i.type }); + } else { + return fail; + } }); + readonly pCaptureDefaultBinder = this.pCaptureBinder(this.defaultBinder); readonly pDiscard: Pattern = mapm(this.identifier, i => i.text === '_' ? succeed(void 0) : fail); @@ -407,7 +452,7 @@ export class SyndicateParser { hasCapturesOrDiscards(e: Expr): boolean { return foldItems(e, - t => match(alt(this.pCaptureBinder, this.pDiscard), [t], null) !== null, + t => match(alt(this.pCaptureDefaultBinder, this.pDiscard), [t], null, '(') !== null, (_g, b, _k) => b, bs => bs.some(b => b)); } @@ -470,7 +515,7 @@ export class SyndicateParser { // }); // } else if (this.hasCapturesOrDiscards(o.ctor)) { - const r = match(this.pCaptureBinder, o.ctor, null); + const r = match(this.pCaptureDefaultBinder, o.ctor, null, '('); if (r !== null && o.arguments.length === 1) { return succeed({ type: 'PCapture', @@ -487,7 +532,7 @@ export class SyndicateParser { scope(o => { o.type = 'PCapture'; o.inner = { type: 'PDiscard' }; - return bind(o, 'binder', this.pCaptureBinder); + return bind(o, 'binder', this.pCaptureBinder(this.binder(... extraStops))); }), map(this.expr(... extraStops), e => ({ type: 'PConstant', value: e })) )); @@ -495,10 +540,10 @@ export class SyndicateParser { } export class SyndicateTypedParser extends SyndicateParser { - get binder(): Pattern { + binder(... extraStops: Pattern[]): Pattern { return scope(o => seq(bind(o, 'id', this.identifier), option(seq(atom(':'), - bind(o, 'type', this.type(atom('='))))))); + bind(o, 'type', this.type(atom('='), ... extraStops)))))); } } diff --git a/packages/compiler/src/compiler/index.ts b/packages/compiler/src/compiler/index.ts index bee8b4a..64281a2 100644 --- a/packages/compiler/src/compiler/index.ts +++ b/packages/compiler/src/compiler/index.ts @@ -1,6 +1,6 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones -export * as Grammar from './grammar.js'; -export * as Codegen from './codegen.js'; -export { compile, CompileOptions } from './codegen.js'; +export * as Grammar from './grammar'; +export * as Codegen from './codegen'; +export { compile, CompileOptions } from './codegen'; diff --git a/packages/compiler/src/index.ts b/packages/compiler/src/index.ts index 6705b7c..6172190 100644 --- a/packages/compiler/src/index.ts +++ b/packages/compiler/src/index.ts @@ -1,5 +1,5 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones -export * as Syntax from './syntax/index.js'; -export * from './compiler/index.js'; +export * as Syntax from './syntax/index'; +export * from './compiler/index'; diff --git a/packages/compiler/src/syntax/codewriter.ts b/packages/compiler/src/syntax/codewriter.ts index 7576744..d0657b1 100644 --- a/packages/compiler/src/syntax/codewriter.ts +++ b/packages/compiler/src/syntax/codewriter.ts @@ -1,10 +1,10 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones -import { Token, TokenType, Item, Items, isGroup } from './tokens.js'; -import { Pos, startPos, advancePos } from './position.js'; -import { vlqEncode } from './vlq.js'; -import { SpanInfo } from './span.js'; +import { Token, TokenType, Item, Items, isGroup } from './tokens'; +import { Pos, startPos, advancePos } from './position'; +import { vlqEncode } from './vlq'; +import { SpanInfo } from './span'; export interface SourceMap { version: 3; diff --git a/packages/compiler/src/syntax/index.ts b/packages/compiler/src/syntax/index.ts index 69dc5b0..2d1551e 100644 --- a/packages/compiler/src/syntax/index.ts +++ b/packages/compiler/src/syntax/index.ts @@ -1,13 +1,13 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones -export * from './codewriter.js'; -export * from './list.js'; -export * from './matcher.js'; -export * from './position.js'; -export * from './reader.js'; -export * from './scanner.js'; -export * from './span.js'; -export * from './template.js'; -export * from './tokens.js'; -export * from './vlq.js'; +export * from './codewriter'; +export * from './list'; +export * from './matcher'; +export * from './position'; +export * from './reader'; +export * from './scanner'; +export * from './span'; +export * from './template'; +export * from './tokens'; +export * from './vlq'; diff --git a/packages/compiler/src/syntax/list.ts b/packages/compiler/src/syntax/list.ts index f1223ac..411ebae 100644 --- a/packages/compiler/src/syntax/list.ts +++ b/packages/compiler/src/syntax/list.ts @@ -1,26 +1,27 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones -export interface List extends Iterable { +export interface List extends Iterable { item: T | null; - next: List | null; + next: List | null; + context: C; toArray(): Array; } -export function atEnd(xs: List): xs is (List & { item: null, next: null }) { +export function atEnd(xs: List): xs is (List & { item: null, next: null }) { return xs.item === null; } -export function notAtEnd(xs: List): xs is (List & { item: T, next: List }) { +export function notAtEnd(xs: List): xs is (List & { item: T, next: List }) { return xs.item !== null; } -export class ArrayList implements List { +export class ArrayList implements List { readonly items: Array; readonly index: number = 0; - constructor(items: Array, index = 0) { + constructor(items: Array, public context: C, index = 0) { this.items = items; this.index = index; } @@ -29,9 +30,9 @@ export class ArrayList implements List { return this.items[this.index] ?? null; } - get next(): List | null { + get next(): List | null { if (this.index >= this.items.length) return null; - return new ArrayList(this.items, this.index + 1); + return new ArrayList(this.items, this.context, this.index + 1); } toArray(): Array { @@ -39,7 +40,7 @@ export class ArrayList implements List { } [Symbol.iterator](): Iterator { - let i: List = this; + let i: List = this; return { next(): IteratorResult { if (notAtEnd(i)) { diff --git a/packages/compiler/src/syntax/matcher.ts b/packages/compiler/src/syntax/matcher.ts index 3d666c3..e8a5e6e 100644 --- a/packages/compiler/src/syntax/matcher.ts +++ b/packages/compiler/src/syntax/matcher.ts @@ -1,34 +1,38 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones import { Token, TokenType, Items, Item, isGroup, isToken, isSpace, isTokenType, -} from './tokens.js'; -import { Pos, startPos } from './position.js'; -import { List, ArrayList, atEnd, notAtEnd } from './list.js'; +} from './tokens'; +import { Pos, startPos } from './position'; +import { List, ArrayList, atEnd, notAtEnd } from './list'; //--------------------------------------------------------------------------- // Patterns over Item -export type PatternResult = [T, List] | null; -export type Pattern = (i: List) => PatternResult; +export type ItemContext = string /* the opener of the containing group, if any */ | null; +export type ItemList = List; +export type PatternResult = [T, ItemList] | null; +export type Pattern = (i: ItemList) => PatternResult; -export function match(p: Pattern, items: Items, failure: F): T | F { - const r = p(new ArrayList(items)); +export type PatternTypeArg

= P extends Pattern ? T : never; + +export function match(p: Pattern, items: Items, failure: F, context: ItemContext): T | F { + const r = p(new ArrayList(items, context)); if (r === null) return failure; if (notAtEnd(skipSpace(r[1]))) return failure; return r[0]; } -export const noItems = new ArrayList([]); +export const noItems = (c: ItemContext) => new ArrayList([], c); export const fail: Pattern = _i => null; export function succeed(t: T): Pattern { return i => [t, i]; } -export const discard: Pattern = _i => [void 0, noItems]; -export const rest: Pattern = i => [i.toArray(), noItems]; -export const end: Pattern = i => atEnd(skipSpace(i)) ? [void 0, noItems] : null; +export const discard: Pattern = i => [void 0, noItems(i.context)]; +export const rest: Pattern = i => [i.toArray(), noItems(i.context)]; +export const end: Pattern = i => atEnd(skipSpace(i)) ? [void 0, noItems(i.context)] : null; export const pos: Pattern = i => notAtEnd(i) ? [i.item.start, i] : null; export const newline: Pattern = i => { @@ -37,12 +41,12 @@ export const newline: Pattern = i => { return [i.item, i.next]; }; -export function skipSpace(i: List): List { +export function skipSpace(i: ItemList): ItemList { while (notAtEnd(i) && isSpace(i.item)) i = i.next; return i; } -export function collectSpace(i: List, acc: Array): List { +export function collectSpace(i: ItemList, acc: Array): ItemList { while (notAtEnd(i) && isSpace(i.item)) { acc.push(i.item); i = i.next; @@ -78,6 +82,22 @@ export function seq(... patterns: Pattern[]): Pattern { }; } +export function seqTuple[]]>( + ... patterns: Patterns +): Pattern<{ [I in keyof Patterns]: PatternTypeArg } & { length: Patterns['length'] }> +{ + return i => { + const rs = []; + for (const p of patterns) { + const r = p(i); + if (r === null) return null; + rs.push(r[0]); + i = r[1]; + } + return [rs as unknown as PatternTypeArg>>, i]; + }; +} + export function alt(... alts: Pattern[]): Pattern { return i => { for (const a of alts) { @@ -115,7 +135,7 @@ export function bind(target: T, key: K, pattern: Pattern) => void): Pattern { +export function exec(thunk: (i: ItemList) => void): Pattern { return i => { thunk(i); return [void 0, i]; @@ -156,7 +176,7 @@ export function group(opener: string, items: Pattern, options: GroupOption if (!notAtEnd(i)) return null; if (!isGroup(i.item)) return null; if (i.item.open.text !== opener) return null; - const r = items(new ArrayList(i.item.items)); + const r = items(new ArrayList(i.item.items, opener)); if (r === null) return null; if (!atEnd(r[1])) return null; return [r[0], (options.advance ?? true) ? i.next : i]; @@ -203,7 +223,7 @@ export function upTo(p: Pattern): Pattern { export function separatedBy(itemPattern: Pattern, separator: Pattern): Pattern { return i => { const acc: T[] = []; - if (end(i) !== null) return [acc, noItems]; + if (end(i) !== null) return [acc, noItems(i.context)]; while (true) { { const r = itemPattern(i); @@ -214,7 +234,7 @@ export function separatedBy(itemPattern: Pattern, separator: Pattern) { const r = separator(i); if (r === null) { - if (end(i) !== null) return [acc, noItems]; + if (end(i) !== null) return [acc, noItems(i.context)]; return null; } i = r[1]; @@ -229,7 +249,7 @@ export function separatedOrTerminatedBy( ): Pattern { return i => { const acc: T[] = []; - if (end(i) !== null) return [acc, noItems]; + if (end(i) !== null) return [acc, noItems(i.context)]; while (true) { { const r = itemPattern(i); @@ -240,11 +260,11 @@ export function separatedOrTerminatedBy( { const r = separator(i); if (r === null) { - if (end(i) !== null) return [acc, noItems]; + if (end(i) !== null) return [acc, noItems(i.context)]; return null; } else { i = r[1]; - if (end(i) !== null) return [acc, noItems]; + if (end(i) !== null) return [acc, noItems(i.context)]; } } } @@ -290,12 +310,13 @@ export function option(p: Pattern): Pattern { export function replace( items: Items, + outerContext: ItemContext, p: Pattern, f: (t: T, start: Pos, end: Pos) => Items, - end: Pos = items.length > 0 ? items[items.length - 1].end : startPos(null)) : Items -{ - const walkItems = (items: Items, end: Pos): Items => { - let i: List = new ArrayList(items); + end: Pos = items.length > 0 ? items[items.length - 1].end : startPos(null), +) : Items { + const walkItems = (items: Items, end: Pos, context: ItemContext): Items => { + let i: ItemList = new ArrayList(items, context); const acc: Items = []; while (notAtEnd(i = collectSpace(i, acc))) { const r = p(i); @@ -309,11 +330,14 @@ export function replace( acc.push(i.item); i = i.next; } else { - acc.push({ ... i.item, items: walkItems(i.item.items, i.item.end) }); + acc.push({ + ... i.item, + items: walkItems(i.item.items, i.item.end, i.item.open.text), + }); i = i.next; } } return acc; }; - return walkItems(items, end); + return walkItems(items, end, outerContext); } diff --git a/packages/compiler/src/syntax/position.ts b/packages/compiler/src/syntax/position.ts index ae095e7..546b6ea 100644 --- a/packages/compiler/src/syntax/position.ts +++ b/packages/compiler/src/syntax/position.ts @@ -1,5 +1,5 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones export interface Pos { line: number; diff --git a/packages/compiler/src/syntax/reader.ts b/packages/compiler/src/syntax/reader.ts index e1b6274..9cfbdfb 100644 --- a/packages/compiler/src/syntax/reader.ts +++ b/packages/compiler/src/syntax/reader.ts @@ -1,9 +1,9 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones -import { TokenType, Token, Group, GroupInProgress, Item, Items, finishGroup } from './tokens.js'; -import { Pos, startPos } from './position.js'; -import { Scanner, StringScanner } from './scanner.js'; +import { TokenType, Token, Group, GroupInProgress, Item, Items, finishGroup } from './tokens'; +import { Pos, startPos } from './position'; +import { Scanner, StringScanner } from './scanner'; function matchingParen(c: string): string | null { switch (c) { @@ -134,23 +134,10 @@ export class LaxReader implements IterableIterator { case TokenType.SPACE: case TokenType.NEWLINE: case TokenType.ATOM: + this.drop(); if (g === null) { - this.drop(); return t; } - if (t.text === ';') { - while ('(['.indexOf(g.open.text) >= 0) { - this.stack.pop(); - const outer = this.stackTop(); - if (outer === null) { - // do not drop the semicolon here - return finishGroup(g, t.start); - } - outer.items.push(finishGroup(g, t.start)); - g = outer; - } - } - this.drop(); g.items.push(t); break; diff --git a/packages/compiler/src/syntax/scanner.ts b/packages/compiler/src/syntax/scanner.ts index 57b7955..d990e55 100644 --- a/packages/compiler/src/syntax/scanner.ts +++ b/packages/compiler/src/syntax/scanner.ts @@ -1,8 +1,8 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones -import { TokenType, Token, Item, GroupInProgress } from './tokens.js'; -import { Pos, advancePos } from './position.js'; +import { TokenType, Token, Item, GroupInProgress } from './tokens'; +import { Pos, advancePos } from './position'; export abstract class Scanner implements IterableIterator { readonly pos: Pos; diff --git a/packages/compiler/src/syntax/span.ts b/packages/compiler/src/syntax/span.ts index 9cb8802..d7a15b4 100644 --- a/packages/compiler/src/syntax/span.ts +++ b/packages/compiler/src/syntax/span.ts @@ -1,5 +1,5 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones export class SpanResult { readonly searchTarget: number; diff --git a/packages/compiler/src/syntax/template.ts b/packages/compiler/src/syntax/template.ts index b52b4b5..dabd3fc 100644 --- a/packages/compiler/src/syntax/template.ts +++ b/packages/compiler/src/syntax/template.ts @@ -1,10 +1,10 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones -import { Items } from './tokens.js'; -import { Pos, startPos } from './position.js'; -import { laxRead, LaxReadOptions } from './reader.js'; -import * as M from './matcher.js'; +import { Items } from './tokens'; +import { Pos, startPos } from './position'; +import { laxRead, LaxReadOptions } from './reader'; +import * as M from './matcher'; const substPat = M.scope((o: { pos: Pos }) => M.seq(M.atom('$'), @@ -29,7 +29,7 @@ export class Templates { this.readOptions = readOptions; } - template(start0: Pos | string = this.defaultPos): TemplateFunction { + template(start0: Pos | string = this.defaultPos, context: M.ItemContext = null): TemplateFunction { const start = (typeof start0 === 'string') ? startPos(start0) : start0; return (consts, ... vars) => { const sourcePieces = [consts[0]]; @@ -53,6 +53,7 @@ export class Templates { (this.readOptions.extraDelimiters ?? '') + '$', synthetic: true, }), + context, substPat, sub => toItems(this.readOptions, vars[i++], sub.pos)); }; diff --git a/packages/compiler/src/syntax/tokens.ts b/packages/compiler/src/syntax/tokens.ts index 95ed828..69d70a6 100644 --- a/packages/compiler/src/syntax/tokens.ts +++ b/packages/compiler/src/syntax/tokens.ts @@ -1,7 +1,7 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones -import { Pos } from './position.js'; +import { Pos } from './position'; export enum TokenType { SPACE, diff --git a/packages/compiler/src/syntax/vlq.ts b/packages/compiler/src/syntax/vlq.ts index 119455d..f0285db 100644 --- a/packages/compiler/src/syntax/vlq.ts +++ b/packages/compiler/src/syntax/vlq.ts @@ -1,5 +1,5 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; const inverse_alphabet = diff --git a/packages/compiler/syndicate-browser-compiler.js b/packages/compiler/syndicate-browser-compiler.js index 4320771..8e4e7d5 100644 --- a/packages/compiler/syndicate-browser-compiler.js +++ b/packages/compiler/syndicate-browser-compiler.js @@ -1,5 +1,5 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2023-2024 Tony Garnock-Jones const __SYNDICATE__ = Syndicate; const currentSyndicateTarget = Syndicate.Dataspace.global; @@ -20,7 +20,7 @@ const currentSyndicateTarget = Syndicate.Dataspace.global; const sourceCode = sourceUrl ? await (await fetch(sourceUrl)).text() : script.innerHTML; const compilationResult = SyndicateCompiler.compile({ - name: sourceUrl || 'anonymous-script-tag', + name: sourceUrl || script.id || 'anonymous-script-tag', source: sourceCode, module: isModule ? 'es6' : 'none', runtime: isModule ? void 0 : 'Syndicate', diff --git a/packages/compiler/test/compiler.test.ts b/packages/compiler/test/compiler.test.ts new file mode 100644 index 0000000..c924f0a --- /dev/null +++ b/packages/compiler/test/compiler.test.ts @@ -0,0 +1,213 @@ +/// SPDX-License-Identifier: GPL-3.0-or-later +/// SPDX-FileCopyrightText: Copyright © 2024 Tony Garnock-Jones + +import { compile, CompileOptions, Syntax } from '../src/index'; +import Pos = Syntax.Pos; +import './test-utils'; +import { js as format } from 'js-beautify'; + +type Error = { message: string, start: Pos | undefined, end: Pos | undefined }; + +function translate(source: string, options: Partial = {}): { code: string, errors: Error[] } { + const errors: Error[] = []; + const result = compile({ + ... options, + module: 'none', + source, + emitError: (message, start, end) => errors.push({ message, start, end }), + }); + return { code: result.text, errors }; +} + +function translateNoErrors(source: string, options?: Partial): string { + const o = translate(source, options); + expect(o.errors.length).toBe(0); + return o.code; +} + +function expectCodeEqual(input: string, output: string, options?: Partial) { + expect(format(translateNoErrors(input, options))).toBe(format(output)); +} + +describe('react', () => { + + it('without label', () => expectCodeEqual(`react { a; b; c; }`, ` +__SYNDICATE__.Turn.active.facet(() => { + const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; + a; b; c; +});`)); + + it('with label', () => expectCodeEqual(`someLabel: react { a; b; c; }`, ` +__SYNDICATE__.Turn.active.facet(() => { + const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; + const someLabel = currentSyndicateFacet; + a; b; c; +});`)); + +}); + +describe('spawn', () => { + + it('without name', () => expectCodeEqual(`spawn { a; b; c; }`, ` +__SYNDICATE__.Dataspace._spawn(() => { + const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; + a; b; c; +});`)); + + it('with name', () => expectCodeEqual(`spawn named 'foo' { a; b; c; }`, ` +__SYNDICATE__.Dataspace._spawn(() => { + const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; + currentSyndicateFacet.actor.name = 'foo'; + a; b; c; +});`)); + + // At present, the expr() parser accepts *empty input*. TODO: something better. + it('with missing name (known incorrect parsing and codegen)', () => + expectCodeEqual(`spawn named { a; b; c; }`, ` +__SYNDICATE__.Dataspace._spawn(() => { + const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; + currentSyndicateFacet.actor.name = ; + a; b; c; +});`)); + +}); + +describe('stop', () => { + + it('non-statement', () => expectCodeEqual(`(stop)`, `(stop)`)); + it('toplevel end-delimited statement', () => expectCodeEqual(`stop`, ` +__SYNDICATE__.Turn.active._stop(currentSyndicateFacet, () => { + const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; +});`)); + it('nested end-delimited statement', () => expectCodeEqual(`{ stop }`, ` +{ + __SYNDICATE__.Turn.active._stop(currentSyndicateFacet, () => { + const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; + }); +}`)); + + it('without facet, without body', () => expectCodeEqual(`stop;`, ` +__SYNDICATE__.Turn.active._stop(currentSyndicateFacet, () => { + const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; +});`)); + + it('without facet, empty body', () => expectCodeEqual(`stop {}`, ` +__SYNDICATE__.Turn.active._stop(currentSyndicateFacet, () => { + const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; +});`)); + + it('without facet, non-empty body', () => expectCodeEqual(`stop { a; b; }`, ` +__SYNDICATE__.Turn.active._stop(currentSyndicateFacet, () => { + const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; + a; b; +});`)); + + it('with facet, without body', () => expectCodeEqual(`stop x.y;`, ` +__SYNDICATE__.Turn.active._stop(x.y, () => { + const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; +});`)); + + it('with facet, empty body', () => expectCodeEqual(`stop x.y {}`, ` +__SYNDICATE__.Turn.active._stop(x.y, () => { + const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; +});`)); + + it('with facet, non-empty body', () => expectCodeEqual(`stop x.y { a; b; }`, ` +__SYNDICATE__.Turn.active._stop(x.y, () => { + const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; + a; b; +});`)); + + it('nested stop, no labels', () => expectCodeEqual(`stop { stop; }`, ` +__SYNDICATE__.Turn.active._stop(currentSyndicateFacet, () => { + const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; + __SYNDICATE__.Turn.active._stop(currentSyndicateFacet, () => { + const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; + }); +});`)); + +}); + +describe('during', () => { + + it('stop in body', () => expectCodeEqual(`during P => { a; stop; b; }`, ` +__SYNDICATE__.Turn.active.assertDataflow(() => ({ + target: currentSyndicateTarget, + assertion: __SYNDICATE__.Observe({ + pattern: __SYNDICATE__.QuasiValue.finish((__SYNDICATE__.QuasiValue.lit(__SYNDICATE__.fromJS(P)))), + observer: __SYNDICATE__.Turn.ref(__SYNDICATE__.assertionFacetObserver( + (__vs) => { + if (Array.isArray(__vs)) { + + a; + __SYNDICATE__.Turn.active._stop(currentSyndicateFacet, () => { + const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet; + }); + b; + } + } + )) + }) +}));`)); + + it('capture with type at top', () => expectCodeEqual(`during $v: T => { ok() }`, ` +__SYNDICATE__.Turn.active.assertDataflow(() => ({ + target: currentSyndicateTarget, + assertion: __SYNDICATE__.Observe({ + pattern: __SYNDICATE__.QuasiValue.finish((__SYNDICATE__.QuasiValue.bind((__SYNDICATE__.QuasiValue._)))), + observer: __SYNDICATE__.Turn.ref(__SYNDICATE__.assertionFacetObserver( + (__vs: __SYNDICATE__.AnyValue) => { + if (Array.isArray(__vs)) { + const __v_0 = T.__from_preserve__(__vs[0]); + if (__v_0 === void 0) return; + const v = __v_0; + ok() + } + } + )) + }) +})); +`, { typescript: true })); + +}); + +describe('once', () => { + it('basics with block', () => expectCodeEqual(`once asserted P => { a; b; }`, ` +__SYNDICATE__.Turn.active.facet(() => { + const __once_facet = __SYNDICATE__.Turn.activeFacet; + __SYNDICATE__.Turn.active.assertDataflow(() => ({ + target: currentSyndicateTarget, + assertion: __SYNDICATE__.Observe({ + pattern: __SYNDICATE__.QuasiValue.finish((__SYNDICATE__.QuasiValue.lit(__SYNDICATE__.fromJS(P)))), + observer: __SYNDICATE__.Turn.ref({ + assert: (__vs, __handle) => { + if (Array.isArray(__vs)) { + + __SYNDICATE__.Turn.active._stop(__once_facet, () => { a; b; }) + } + } + }), + }), + })); +});`)); + + it('basics with statement', () => expectCodeEqual(`once asserted P => x;`, ` +__SYNDICATE__.Turn.active.facet(() => { + const __once_facet = __SYNDICATE__.Turn.activeFacet; + __SYNDICATE__.Turn.active.assertDataflow(() => ({ + target: currentSyndicateTarget, + assertion: __SYNDICATE__.Observe({ + pattern: __SYNDICATE__.QuasiValue.finish((__SYNDICATE__.QuasiValue.lit(__SYNDICATE__.fromJS(P)))), + observer: __SYNDICATE__.Turn.ref({ + assert: (__vs, __handle) => { + if (Array.isArray(__vs)) { + + __SYNDICATE__.Turn.active._stop(__once_facet, () => {x;}) + } + } + }), + }), + })); +});`)); + +}); diff --git a/packages/compiler/test/grammar.test.ts b/packages/compiler/test/grammar.test.ts new file mode 100644 index 0000000..6ff8fda --- /dev/null +++ b/packages/compiler/test/grammar.test.ts @@ -0,0 +1,30 @@ +/// SPDX-License-Identifier: GPL-3.0-or-later +/// SPDX-FileCopyrightText: Copyright © 2024 Tony Garnock-Jones + +import { Grammar, Syntax } from '../src/index'; +import './test-utils'; + +describe('statement boundary', () => { + function stmt(input: string): [string, string] | null { + const parser = new Grammar.SyndicateParser(); + const tree = Syntax.laxRead(input); + const items: Syntax.Items = []; + const r = parser.statement(items)(new Syntax.ArrayList(tree, '{')); + if (r === null) return null; + return [Syntax.itemText(items), Syntax.itemText(r[1].toArray())]; + } + + it('should include semicolon', () => { + expect(stmt('i am a statement ; ')).toEqual(['i am a statement;', ' ']); + }); + + it('should include newline', () => { + expect(stmt('i am a statement \n ')).toEqual(['i am a statement\n', ' ']); + }); + + it('should include closing brace on the same line', () => { + // Note that `" remainder is in outer group"` is discarded by `laxRead`. + expect(stmt('i am a statement } remainder is in outer group')) + .toEqual(['i am a statement', '']); + }); +}); diff --git a/packages/compiler/test/test-utils.ts b/packages/compiler/test/test-utils.ts new file mode 100644 index 0000000..ef7c81e --- /dev/null +++ b/packages/compiler/test/test-utils.ts @@ -0,0 +1,38 @@ +/// SPDX-License-Identifier: GPL-3.0-or-later +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones + +import { is, preserves } from '@preserves/core'; + +declare global { + namespace jest { + interface Matchers { + is(expected: any): R; + toThrowFilter(f: (e: Error) => boolean): R; + } + } +} + +expect.extend({ + is(actual, expected) { + return is(actual, expected) + ? { message: () => preserves`expected ${actual} not to be Preserves.is to ${expected}`, + pass: true } + : { message: () => preserves`expected ${actual} to be Preserves.is to ${expected}`, + pass: false }; + }, + + toThrowFilter(thunk, f) { + try { + thunk(); + return { message: () => preserves`expected an exception`, pass: false }; + } catch (e) { + if (f(e)) { + return { message: () => preserves`expected an exception not matching the filter`, + pass: true }; + } else { + return { message: () => preserves`expected an exception matching the filter: ${(e as any)?.constructor?.name}`, + pass: false }; + } + } + } +}); diff --git a/packages/core/examples/box-and-client.js b/packages/core/examples/box-and-client.js index 611da71..28d475e 100644 --- a/packages/core/examples/box-and-client.js +++ b/packages/core/examples/box-and-client.js @@ -1,6 +1,6 @@ #!/usr/bin/env node /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones import { Pattern as P, diff --git a/packages/core/examples/box-and-client.ts b/packages/core/examples/box-and-client.ts index c400517..7233a7a 100644 --- a/packages/core/examples/box-and-client.ts +++ b/packages/core/examples/box-and-client.ts @@ -1,6 +1,6 @@ #!/usr/bin/env -S npx ts-node -O '{"module": "commonjs"}' /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones import { Pattern as P, diff --git a/packages/core/jest.config.ts b/packages/core/jest.config.ts index ac0047a..4a09b3e 100644 --- a/packages/core/jest.config.ts +++ b/packages/core/jest.config.ts @@ -1,5 +1,5 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones export default { preset: 'ts-jest', diff --git a/packages/core/local-protocols/schemas/queuedTasks.prs b/packages/core/local-protocols/schemas/queuedTasks.prs index a0d079c..9276711 100644 --- a/packages/core/local-protocols/schemas/queuedTasks.prs +++ b/packages/core/local-protocols/schemas/queuedTasks.prs @@ -5,10 +5,10 @@ ActionDescription = / @spawnActor / @stopActor / @inertCheck -/ -/ -/ -/ +/ +/ +/ +/ . OptionalAny = / . diff --git a/packages/core/package.json b/packages/core/package.json index b48fe34..fb6cb51 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@syndicate-lang/core", - "version": "0.23.0", + "version": "0.32.0", "description": "Syndicate/JS for browser and node.js", "homepage": "https://github.com/syndicate-lang/syndicate-js/tree/main/packages/core", "license": "GPL-3.0+", @@ -21,7 +21,7 @@ "rollup:watch": "../../node_modules/.bin/rollup -c -w", "test": "../../node_modules/.bin/jest", "cover": "../../node_modules/.bin/nyc --reporter=html ../../node_modules/.bin/jest", - "clean": "rm -rf lib dist", + "clean": "rm -rf lib dist ./src/gen", "veryclean": "yarn run clean && rm -rf node_modules" }, "main": "dist/syndicate.js", @@ -29,11 +29,11 @@ "types": "lib/index.d.ts", "author": "Tony Garnock-Jones ", "devDependencies": { - "@preserves/core": "0.992.4", - "@preserves/schema-cli": "0.992.5" + "@preserves/core": "0.995.200", + "@preserves/schema-cli": "0.995.201" }, "peerDependencies": { - "@preserves/core": "0.992.4" + "@preserves/core": "0.995.200" }, "dependencies": { "salty-crypto": "0.3.1" diff --git a/packages/core/protocols/schema-bundle.bin b/packages/core/protocols/schema-bundle.bin index fc747ff..80b410e 100644 --- a/packages/core/protocols/schema-bundle.bin +++ b/packages/core/protocols/schema-bundle.bin @@ -2,15 +2,15 @@ tcp-remotetuplenamedhostatomStringnamedportatom SignedInteger TcpPeerInforeclittcp-peertuplenamedhandleembeddedanynamedlocalrefTcpLocalnamedremoteref TcpRemote embeddedTyperef EntityRefCaphttpschemaversion definitionsChunkorstringatomStringbytesatom ByteStringHeadersdictofatomSymbolatomStringMimeTypeatomSymbol QueryValueorstringatomStringfilereclitfiletuplenamedfilenameatomStringnamedheadersrefHeadersnamedbodyatom -ByteString HostPatternorhostatomStringanylit HttpBindingreclit http-bindtuplenamedhostref HostPatternnamedportatom SignedIntegernamedmethodref MethodPatternnamedpathref PathPatternnamedhandlerembeddedref HttpRequest HttpContextreclitrequesttuplenamedreqref HttpRequestnamedresembeddedref HttpResponse HttpRequestreclit http-requesttuplenamedsequenceNumberatom SignedIntegernamedhostatomStringnamedportatom SignedIntegernamedmethodatomSymbolnamedpathseqofatomStringnamedheadersrefHeadersnamedquerydictofatomSymbolseqofref +ByteString HostPatternorhostatomStringanylit HttpBindingreclit http-bindtuplenamedhostref HostPatternnamedportatom SignedIntegernamedmethodref MethodPatternnamedpathref PathPatternnamedhandlerembeddedref HttpRequest HttpContextreclitrequesttuplenamedreqref HttpRequestnamedresembeddedref HttpResponse HttpRequestreclit http-requesttuplenamedsequenceNumberatom SignedIntegernamedhostref RequestHostnamedportatom SignedIntegernamedmethodatomSymbolnamedpathseqofatomStringnamedheadersrefHeadersnamedquerydictofatomSymbolseqofref QueryValuenamedbodyref RequestBody HttpServicereclit http-servicetuplenamedhostref HostPatternnamedportatom SignedIntegernamedmethodref MethodPatternnamedpathref PathPattern PathPatternseqofrefPathPatternElement RequestBodyorpresentatom -ByteStringabsentlit HttpListenerreclit http-listenertuplenamedportatom SignedInteger HttpResponseorstatusreclitstatustuplenamedcodeatom SignedIntegernamedmessageatomStringheaderreclitheadertuplenamednameatomSymbolnamedvalueatomStringchunkreclitchunktuplenamedchunkrefChunkdonereclitdonetuplenamedchunkrefChunk MethodPatternoranylitspecificatomSymbolPathPatternElementorlabelatomStringwildcardlit_restlit... embeddedTypenoiseschemaversion definitionsPacketorcompleteatom +ByteStringabsentlit RequestHostorpresentatomStringabsentlit HttpListenerreclit http-listenertuplenamedportatom SignedInteger HttpResponseorstatusreclitstatustuplenamedcodeatom SignedIntegernamedmessageatomStringheaderreclitheadertuplenamednameatomSymbolnamedvalueatomStringchunkreclitchunktuplenamedchunkrefChunkdonereclitdonetuplenamedchunkrefChunk MethodPatternoranylitspecificatomSymbolPathPatternElementorlabelatomStringwildcardlit_restlit... embeddedTypenoiseschemaversion definitionsPacketorcompleteatom ByteString fragmentedseqofatom -ByteString NoiseSpecanddictkeynamedkeyatom -ByteStringservicenamedservicerefServiceSelectornamedprotocolref NoiseProtocolnamed preSharedKeysrefNoisePreSharedKeys NoiseProtocolorpresentdictprotocolnamedprotocolatomStringinvaliddictprotocolnamedprotocolanyabsentdict NoiseStepTypelitnoiseSecretKeyFieldorpresentdict secretKeynamed secretKeyatom +ByteString Initiatorreclit initiatortuplenamedinitiatorSessionembeddedrefPacket NoiseSpecanddictkeynamedkeyatom +ByteStringservicenamedservicerefServiceSelectornamedprotocolref NoiseProtocolnamed preSharedKeysrefNoisePreSharedKeys SessionItemor Initiatorref InitiatorPacketrefPacket NoiseProtocolorpresentdictprotocolnamedprotocolatomStringinvaliddictprotocolnamedprotocolanyabsentdict NoiseStepTypelitnoiseSecretKeyFieldorpresentdict secretKeynamed secretKeyatom ByteStringinvaliddict secretKeynamed secretKeyanyabsentdictDefaultProtocollit!Noise_NK_25519_ChaChaPoly_BLAKE2sNoiseStepDetailrefServiceSelectorServiceSelectoranyNoiseServiceSpecandnamedbaseref NoiseSpecnamed secretKeyrefSecretKeyFieldNoisePreSharedKeysorpresentdict preSharedKeysnamed preSharedKeysseqofatom -ByteStringinvaliddict preSharedKeysnamed preSharedKeysanyabsentdictNoisePathStepDetailref NoiseSpecNoiseDescriptionDetailrefNoiseServiceSpec embeddedTypetimerschemaversion definitionsSetTimerreclit set-timertuplenamedlabelanynamedsecondsatomDoublenamedkindref TimerKind LaterThanreclit +ByteStringinvaliddict preSharedKeysnamed preSharedKeysanyabsentdictNoisePathStepDetailref NoiseSpecNoiseDescriptionDetailrefNoiseServiceSpec embeddedTyperef EntityRefCaptimerschemaversion definitionsSetTimerreclit set-timertuplenamedlabelanynamedsecondsatomDoublenamedkindref TimerKind LaterThanreclit later-thantuplenamedsecondsatomDouble TimerKindorrelativelitrelativeabsolutelitabsoluteclearlitclear TimerExpiredreclit timer-expiredtuplenamedlabelanynamedsecondsatomDouble embeddedTypetraceschemaversion definitionsOidanyNameor anonymousreclit anonymoustuplenamedreclitnamedtuplenamednameanyTargetreclitentitytuplenamedactorrefActorIdnamedfacetrefFacetIdnamedoidrefOidTaskIdanyTurnIdanyActorIdanyFacetIdany TurnCauseorturnreclit caused-bytuplenamedidrefTurnIdcleanupreclitcleanuptuplelinkedTaskReleasereclitlinked-task-releasetuplenamedidrefTaskIdnamedreasonrefLinkedTaskReleaseReasonperiodicActivationreclitperiodic-activationtuplenamedperiodatomDoubledelayreclitdelaytuplenamed causingTurnrefTurnIdnamedamountatomDoubleexternalreclitexternaltuplenamed descriptionany TurnEventorassertreclitasserttuplenamed assertionrefAssertionDescriptionnamedhandlerefprotocolHandleretractreclitretracttuplenamedhandlerefprotocolHandlemessagereclitmessagetuplenamedbodyrefAssertionDescriptionsyncreclitsynctuplenamedpeerrefTarget breakLinkreclit break-linktuplenamedsourcerefActorIdnamedhandlerefprotocolHandle ExitStatusoroklitokErrorrefprotocolError @@ -24,7 +24,7 @@ ByteString ByteStringnamedoidanynamedcaveatsseqofrefsturdyCaveatgeneralref gatekeeperRouteStandardTransportorwsUrlatomStringotherany embeddedTypestreamschemaversion definitionsModeorbyteslitbyteslinesrefLineModepacketreclitpackettuplenamedsizeatom SignedIntegerobjectreclitobjecttuplenamed descriptionanySinkorsourcereclitsourcetuplenamed controllerembeddedrefSource StreamErrorref StreamErrordatareclitdatatuplenamedpayloadanynamedmoderefModeeofrecliteoftupleSourceorsinkreclitsinktuplenamed -controllerembeddedrefSink StreamErrorref StreamErrorcreditreclitcredittuplenamedamountref CreditAmountnamedmoderefModeLineModeorlflitlfcrlflitcrlf StreamErrorrecliterrortuplenamedmessageatomString CreditAmountorcountatom SignedInteger unboundedlit unboundedStreamConnectionreclitstream-connectiontuplenamedsourceembeddedrefSourcenamedsinkembeddedrefSinknamedspecanyStreamListenerErrorreclitstream-listener-errortuplenamedspecanynamedmessageatomStringStreamListenerReadyreclitstream-listener-readytuplenamedspecany embeddedTyperef EntityRefCapsturdyschemaversion definitionsLitreclitlittuplenamedvalueanyOidatom SignedIntegerAltsreclitortuplenamed alternativesseqofrefRewritePAndreclitandtuplenamedpatternsseqofrefPatternPNotreclitnottuplenamedpatternrefPatternTRefreclitreftuplenamedbindingatom SignedIntegerPAtomorBooleanlitBooleanFloatlitFloatDoublelitDouble SignedIntegerlit SignedIntegerStringlitString +controllerembeddedrefSink StreamErrorref StreamErrorcreditreclitcredittuplenamedamountref CreditAmountnamedmoderefModeLineModeorlflitlfcrlflitcrlf StreamErrorrecliterrortuplenamedmessageatomString CreditAmountorcountatom SignedInteger unboundedlit unboundedStreamConnectionreclitstream-connectiontuplenamedsourceembeddedrefSourcenamedsinkembeddedrefSinknamedspecanyStreamListenerErrorreclitstream-listener-errortuplenamedspecanynamedmessageatomStringStreamListenerReadyreclitstream-listener-readytuplenamedspecany embeddedTyperef EntityRefCapsturdyschemaversion definitionsLitreclitlittuplenamedvalueanyOidatom SignedIntegerAltsreclitortuplenamed alternativesseqofrefRewritePAndreclitandtuplenamedpatternsseqofrefPatternPNotreclitnottuplenamedpatternrefPatternTRefreclitreftuplenamedbindingatom SignedIntegerPAtomorBooleanlitBooleanDoublelitDouble SignedIntegerlit SignedIntegerStringlitString ByteStringlit ByteStringSymbollitSymbolPBindreclitbindtuplenamedpatternrefPatternCaveatorRewriterefRewriteAltsrefAltsRejectrefRejectunknownanyRejectreclitrejecttuplenamedpatternrefPatternPatternorPDiscardrefPDiscardPAtomrefPAtom PEmbeddedref PEmbeddedPBindrefPBindPAndrefPAndPNotrefPNotLitrefLit PCompoundref PCompoundRewritereclitrewritetuplenamedpatternrefPatternnamedtemplaterefTemplateWireReforminetuplelitnamedoidrefOidyours tuplePrefixlitnamedoidrefOidnamed attenuationseqofrefCaveatPDiscardreclit_tupleTemplateor TAttenuateref @@ -40,5 +40,5 @@ ByteString RunServicereclit run-servicetuplenamed serviceNameany ServiceStatereclit service-statetuplenamed serviceNameanynamedstaterefState ServiceObjectreclitservice-objecttuplenamed serviceNameanynamedobjectanyRequireServicereclitrequire-servicetuplenamed serviceNameanyRestartServicereclitrestart-servicetuplenamed serviceNameanyServiceDependencyreclit depends-ontuplenameddependeranynameddependeeref ServiceState embeddedTyperef EntityRefCapprotocolschemaversion definitionsOidatom SignedIntegerSyncreclitStuplenamedpeerembeddedlitTurnseqofref TurnEventErrorrecliterrortuplenamedmessageatomStringnameddetailanyEventorAssertrefAssertRetractrefRetractMessagerefMessageSyncrefSyncAssertreclitAtuplenamed assertionref AssertionnamedhandlerefHandleHandleatom SignedIntegerPacketorTurnrefTurnErrorrefError Extensionref ExtensionMessagereclitMtuplenamedbodyref AssertionRetractreclitRtuplenamedhandlerefHandle Assertionany Extensionrecnamedlabelanynamedfieldsseqofany TurnEventtuplenamedoidrefOidnamedeventrefEvent embeddedType dataspaceschemaversion definitionsObservereclitObservetuplenamedpatternrefdataspacePatternsPatternnamedobserverembeddedany embeddedTyperef EntityRefCap gatekeeperschemaversion definitionsBindreclitbindtuplenamed descriptionref Descriptionnamedtargetembeddedanynamedobserverref BindObserverSteprecnamedstepTypeatomSymboltuplenameddetailanyBoundorboundreclitboundtuplenamedpathSteprefPathStepRejectedrefRejectedRoutereclitroute tuplePrefixnamed -transportsseqofanynamed pathStepsseqofrefPathStepResolvereclitresolvetuplenamedsteprefStepnamedobserverembeddedrefResolvedPathSteprecnamedstepTypeatomSymboltuplenameddetailanyRejectedreclitrejectedtuplenameddetailanyResolvedoracceptedreclitacceptedtuplenamedresponderSessionembeddedanyRejectedrefRejected DescriptionrecnamedstepTypeatomSymboltuplenameddetailany ResolvePathreclit resolve-pathtuplenamedrouterefRoutenamedaddranynamedcontrolembeddedrefTransportControlnamedresolvedrefResolved BindObserverorpresentembeddedrefBoundabsentlitForceDisconnectreclitforce-disconnecttupleResolvedPathStepreclit path-steptuplenamedoriginembeddedrefResolvenamedpathSteprefPathStepnamedresolvedrefResolvedTransportControlrefForceDisconnectTransportConnectionreclitconnect-transporttuplenamedaddranynamedcontrolembeddedrefTransportControlnamedresolvedrefResolved embeddedTyperef EntityRefCaptransportAddressschemaversion definitionsTcpreclittcptuplenamedhostatomStringnamedportatom SignedIntegerUnixreclitunixtuplenamedpathatomStringStdioreclitstdiotuple WebSocketreclitwstuplenamedurlatomString embeddedTypedataspacePatternsschemaversion definitionsDLitreclitlittuplenamedvaluerefAnyAtomDBindreclitbindtuplenamedpatternrefPatternAnyAtomorboolatomBooleanfloatatomFloatdoubleatomDoubleintatom SignedIntegerstringatomStringbytesatom -ByteStringsymbolatomSymbolembeddedembeddedanyPatternorDDiscardrefDDiscardDBindrefDBindDLitrefDLit DCompoundref DCompoundDDiscardreclit_tuple DCompoundorrecreclitrectuplenamedlabelanynamedfieldsseqofrefPatternarrreclitarrtuplenameditemsseqofrefPatterndictreclitdicttuplenamedentriesdictofanyrefPattern embeddedTyperef EntityRefCap \ No newline at end of file +transportsseqofanynamed pathStepsseqofrefPathStepResolvereclitresolvetuplenamedsteprefStepnamedobserverembeddedrefResolvedPathSteprecnamedstepTypeatomSymboltuplenameddetailanyRejectedreclitrejectedtuplenameddetailanyResolvedoracceptedreclitacceptedtuplenamedresponderSessionembeddedanyRejectedrefRejected DescriptionrecnamedstepTypeatomSymboltuplenameddetailany ResolvePathreclit resolve-pathtuplenamedrouterefRoutenamedaddranynamedcontrolembeddedrefTransportControlnamedresolvedrefResolved BindObserverorpresentembeddedrefBoundabsentlitForceDisconnectreclitforce-disconnecttupleResolvedPathStepreclit path-steptuplenamedoriginembeddedrefResolvenamedpathSteprefPathStepnamedresolvedrefResolvedTransportControlrefForceDisconnectTransportConnectionreclitconnect-transporttuplenamedaddranynamedcontrolembeddedrefTransportControlnamedresolvedrefResolved embeddedTyperef EntityRefCaptransportAddressschemaversion definitionsTcpreclittcptuplenamedhostatomStringnamedportatom SignedIntegerUnixreclitunixtuplenamedpathatomStringStdioreclitstdiotuple WebSocketreclitwstuplenamedurlatomString embeddedTypedataspacePatternsschemaversion definitionsAnyAtomorboolatomBooleandoubleatomDoubleintatom SignedIntegerstringatomStringbytesatom +ByteStringsymbolatomSymbolembeddedembeddedanyPatternordiscardreclit_tuplebindreclitbindtuplenamedpatternrefPatternlitreclitlittuplenamedvaluerefAnyAtomgroupreclitgrouptuplenamedtyperef GroupTypenamedentriesdictofanyrefPattern GroupTypeorrecreclitrectuplenamedlabelanyarrreclitarrtupledictreclitdicttuple embeddedTyperef EntityRefCap \ No newline at end of file diff --git a/packages/core/protocols/schemas/dataspace.prs b/packages/core/protocols/schemas/dataspace.prs index 25c6640..9ca3834 100644 --- a/packages/core/protocols/schemas/dataspace.prs +++ b/packages/core/protocols/schemas/dataspace.prs @@ -1,4 +1,4 @@ version 1 . embeddedType EntityRef.Cap . -Observe = . +Observe = . diff --git a/packages/core/protocols/schemas/dataspacePatterns.prs b/packages/core/protocols/schemas/dataspacePatterns.prs index 5c55d11..e0c7e02 100644 --- a/packages/core/protocols/schemas/dataspacePatterns.prs +++ b/packages/core/protocols/schemas/dataspacePatterns.prs @@ -1,23 +1,30 @@ version 1 . embeddedType EntityRef.Cap . -# Dataspace patterns: a sublanguage of attenuation patterns. -Pattern = DDiscard / DBind / DLit / DCompound . +# Dataspace patterns: *almost* a sublanguage of attenuation patterns. +# +# One key difference is that Dataspace patterns are extensible, in that +# they ignore fields not mentioned in group patterns. -DDiscard = <_>. -DBind = . -DLit = . -DCompound = - / - / . +Pattern = + / @discard <_> + / + / + / +. + +GroupType = + / + / + / +. AnyAtom = / @bool bool - / @float float / @double double / @int int / @string string / @bytes bytes / @symbol symbol - / @embedded #!any + / @embedded #:any . diff --git a/packages/core/protocols/schemas/gatekeeper.prs b/packages/core/protocols/schemas/gatekeeper.prs index 9b11db6..9ba662c 100644 --- a/packages/core/protocols/schemas/gatekeeper.prs +++ b/packages/core/protocols/schemas/gatekeeper.prs @@ -6,18 +6,47 @@ embeddedType EntityRef.Cap . # Assertion. Gatekeeper will attempt to resolve `step`, responding with a `Resolved` to # `observer`. -Resolve = . -Resolved = / Rejected . +Resolve = . +Resolved = / Rejected . Step = < @stepType symbol [@detail any]> . # --------------------------------------------------------------------------- # Protocol at dataspaces *associated* with gatekeeper entities -# Assertion. Gatekeeper will compute an appropriate PathStep from `description` pointing at -# `target`, and will respond with a `Bound` to `observer` (if supplied). -Bind = . +# ## Handling `Resolve` requests +# +# When the gatekeeper entity receives a `Resolve` assertion (call it R1), it +# +# 1. asserts a `Resolve` (call it R2) into its associated dataspace that +# is the same as R1 except it has a different `observer`; and +# +# 2. observes a `Bind` with `description` matching the `step` of R1/R2 +# according to `stepType` (e.g. treatment of SturdyStepType is not the +# same as treatment of NoiseStepType). +# +# Normally, an appropriate `Bind` is expected to exist. If the gatekeeper +# sees the `Bind` first, it takes the `target` from it and does whatever +# `stepType` mandates before replying to R1's observer. +# +# However, if a `Resolved` is asserted to R2's observer before a `Bind` +# appears, that resolution is relayed on to R1's observer directly, be it +# positive or negative, and the gatekeeper stops waiting for a `Bind`. +# +# This way, entities can keep an eye out for `Resolve` requests that will +# never complete, and answer `Rejected` to them even when no matching +# `Bind` exists. Entities could also use `Resolve` requests to synthesize a +# `Bind` in a "just-in-time" fashion. +# +# ## General treatment of `Bind` assertions +# +# When the gatekeeper sees a `Bind`, independently of any potential +# `Resolve` requests, it computes an appropriate PathStep from +# `description` pointing at `target`, and responds with a `Bound` to +# `observer` (if supplied). +# +Bind = . Description = < @stepType symbol [@detail any]> . -BindObserver = @present #!Bound / @absent #f . +BindObserver = @present #:Bound / @absent #f . Bound = / Rejected . # --------------------------------------------------------------------------- @@ -27,10 +56,10 @@ Bound = / Rejected . # and `resolved`, respondent will follow `route.pathSteps` starting from one of the # `route.transports`, asserting `ResolvePath` with the final `Resolved` as well as the selected # transport `addr` and a `control` for it. -ResolvePath = . +ResolvePath = . -TransportConnection = . -ResolvedPathStep = . +TransportConnection = . +ResolvedPathStep = . PathStep = < @stepType symbol [@detail any]> . # A `Route` describes a network path that can be followed to reach some target entity. diff --git a/packages/core/protocols/schemas/http.prs b/packages/core/protocols/schemas/http.prs index c64a738..236a477 100644 --- a/packages/core/protocols/schemas/http.prs +++ b/packages/core/protocols/schemas/http.prs @@ -2,7 +2,7 @@ version 1 . # Assertion in driver DS # Causes creation of server and route -HttpBinding = . +HttpBinding = . # Assertion in driver DS # Describes active server and route @@ -21,7 +21,7 @@ MethodPattern = @any #f / @specific @"Lowercase" symbol . # Assertion in driver DS HttpRequest = . RequestBody = @present bytes / @absent #f . +RequestHost = @present string / @absent #f . # Assertion to handler entity -HttpContext = . +HttpContext = . +# HttpResponse protocol. Delivered to the `res` ref in `HttpContext`. +# +# (status | header)* . chunk* . done +# +# Done triggers completion of the response and retraction of the frame by the peer. If the +# HttpBinding responsible for the request is withdrawn mid-way through a response (i.e. when +# chunked transfer is used and at least one chunk has been sent) the request is abruptly +# closed; if it is withdrawn at any other moment in the lifetime of the request, a 500 Internal +# Server Error is send to the client. +# @ -# Messages HttpResponse = +# Messages. / /

/ diff --git a/packages/core/protocols/schemas/noise.prs b/packages/core/protocols/schemas/noise.prs index 3558b36..8bdf6a4 100644 --- a/packages/core/protocols/schemas/noise.prs +++ b/packages/core/protocols/schemas/noise.prs @@ -1,4 +1,5 @@ version 1 . +embeddedType EntityRef.Cap . # https://noiseprotocol.org/ @@ -42,13 +43,30 @@ DefaultProtocol = "Noise_NK_25519_ChaChaPoly_BLAKE2s" . # sequence is exhausted or not supplied, an all-zeros key is used each time a PSK is needed. NoisePreSharedKeys = @present { preSharedKeys: [bytes ...] } / @invalid { preSharedKeys: any } / @absent {} . -# Sessions proceed by sending Packets to the initiatorSession and responderSession according to -# the Noise protocol definition. Each Packet represents a complete logical unit of +# --------------------------------------------------------------------------- +# Handshaking and running a session + +# 1. initiator asserts #:A> at Gatekeeper +# 2. gatekeeper asserts at #:A +# 3. initiator asserts at #:B and then sends `Packet`s to #:B +# 4. responder sends `Packet`s to #:C +# +# Sessions begin with introduction of initiator (#:C) and responder (#:B) to each other, and +# then proceed by sending `Packet`s (from #:C) to #:B and (from #:B) to #:C according to +# the Noise protocol definition. Each `Packet` represents a complete logical unit of # communication; for example, a complete Turn when layering the Syndicate protocol over Noise. # Note well the restriction on Noise messages: no individual complete packet or packet fragment -# may exceed 65535 bytes (N.B. not 65536!). When `fragmented`, each portion of a Packet is a +# may exceed 65535 bytes (N.B. not 65536!). When `fragmented`, each portion of a `Packet` is a # complete Noise "transport message"; when `complete`, the whole thing is likewise a complete # "transport message". +# +# Retraction of the `Initiator` ends the session from the initiator-side; retraction of the +# `` assertion ends the session from the responder-side. + +SessionItem = Initiator / Packet . +# Assertion +Initiator = . +# Message Packet = @complete bytes / @fragmented [bytes ...] . # When layering Syndicate protocol over noise, diff --git a/packages/core/protocols/schemas/protocol.prs b/packages/core/protocols/schemas/protocol.prs index 449d6aa..da66672 100644 --- a/packages/core/protocols/schemas/protocol.prs +++ b/packages/core/protocols/schemas/protocol.prs @@ -16,4 +16,4 @@ TurnEvent = [@oid Oid @event Event]. Assert = . Retract = . Message = . -Sync = . +Sync = . diff --git a/packages/core/protocols/schemas/stream.prs b/packages/core/protocols/schemas/stream.prs index 079825a..90279b3 100644 --- a/packages/core/protocols/schemas/stream.prs +++ b/packages/core/protocols/schemas/stream.prs @@ -2,7 +2,7 @@ version 1 . embeddedType EntityRef.Cap . # Assertion: -StreamConnection = . +StreamConnection = . # Assertions: StreamListenerReady = . @@ -13,7 +13,7 @@ StreamError = . Source = # Assertions: - / + / / StreamError # Messages: @@ -22,7 +22,7 @@ Source = Sink = # Assertions: - / + / / StreamError # Messages: diff --git a/packages/core/protocols/schemas/sturdy.prs b/packages/core/protocols/schemas/sturdy.prs index 20e8eb0..5e8b4eb 100644 --- a/packages/core/protocols/schemas/sturdy.prs +++ b/packages/core/protocols/schemas/sturdy.prs @@ -51,7 +51,7 @@ Lit = . Pattern = PDiscard / PAtom / PEmbedded / PBind / PAnd / PNot / Lit / PCompound . PDiscard = <_>. -PAtom = =Boolean / =Float / =Double / =SignedInteger / =String / =ByteString / =Symbol . +PAtom = =Boolean / =Double / =SignedInteger / =String / =ByteString / =Symbol . PEmbedded = =Embedded . PBind = . PAnd = . diff --git a/packages/core/protocols/schemas/tcp.prs b/packages/core/protocols/schemas/tcp.prs index cc34741..c9d8ef6 100644 --- a/packages/core/protocols/schemas/tcp.prs +++ b/packages/core/protocols/schemas/tcp.prs @@ -4,4 +4,4 @@ embeddedType EntityRef.Cap . TcpRemote = . TcpLocal = . -TcpPeerInfo = . +TcpPeerInfo = . diff --git a/packages/core/rollup.config.js b/packages/core/rollup.config.js index 628e2cb..f9bd2b0 100644 --- a/packages/core/rollup.config.js +++ b/packages/core/rollup.config.js @@ -1,5 +1,5 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones import { SyndicateRollup } from '../../rollup.js'; const r = new SyndicateRollup('syndicate', { globalName: 'Syndicate' }); diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 971d2e1..0640bb6 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,5 +1,5 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones export * from '@preserves/core'; @@ -10,6 +10,7 @@ export * as DataspacePatterns from './gen/dataspacePatterns.js'; export * from './runtime/actor.js'; export * from './runtime/bag.js'; export * as Dataflow from './runtime/dataflow.js'; +export { Field } from './runtime/dataflow.js'; export * from './runtime/dataspace.js'; export * from './runtime/mirror.js'; export * as Pattern from './runtime/pattern.js'; diff --git a/packages/core/src/runtime/actor.ts b/packages/core/src/runtime/actor.ts index 37a66e9..ae3e23b 100644 --- a/packages/core/src/runtime/actor.ts +++ b/packages/core/src/runtime/actor.ts @@ -1,13 +1,13 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones -import { IdentitySet, Value, embeddedId, is, fromJS, stringify, Dictionary, KeyedSet } from '@preserves/core'; -import { Cell, Field, Graph } from './dataflow'; -import { Caveat, runRewrites } from './rewrite'; -import { ActorSpace } from './space'; -import { ActionDescription, StructuredTask, TaskAction } from './task'; -import { randomId } from './randomid'; -import * as Q from '../gen/queuedTasks'; +import { IdentitySet, Value, embeddedId, is, fromJS, stringify, KeyedSet, Tuple, Embeddable, IsEmbedded } from '@preserves/core'; +import { Cell, Field, Graph } from './dataflow.js'; +import { Caveat, runRewrites } from './rewrite.js'; +import { ActorSpace } from './space.js'; +import { ActionDescription, StructuredTask, TaskAction } from './task.js'; +import { randomId } from './randomid.js'; +import * as Q from '../gen/queuedTasks.js'; import { Mirror, Reflectable, _asRef } from './mirror'; import * as Refl from '../gen/mirror'; @@ -26,7 +26,11 @@ export type ExitReason = null | { ok: true } | { ok: false, err: unknown }; export type LocalAction = () => void; export type DetailedAction = LocalAction & { detail: T }; -export type Assertable = Assertion | { __as_preserve__: () => Value } | { __as_preserve__: () => Assertion }; +export type Assertable = + | Assertion + | { __as_preserve__: () => Value } + | { __as_preserve__: () => Assertion } +; export interface Entity { assert(assertion: Assertion, handle: Handle): void; @@ -43,13 +47,9 @@ export interface Entity { export type Cap = Ref; -export interface Ref { - readonly relay: Facet; - readonly target: Partial; - readonly attenuation?: Caveat[]; -} +export class Ref implements Reflectable { + get [IsEmbedded](): true { return true; } -export class RefImpl implements Ref, Reflectable { readonly relay: Facet; readonly target: Partial; readonly attenuation?: Caveat[]; @@ -76,6 +76,10 @@ export class RefImpl implements Ref, Reflectable { if ('sync' in this.target) sig = sig + 'S'; return `⌜${this.relay.idChain()}<${sig}>${entityRepr}⌝`; } + + static __from_preserve__(v: AnyValue): undefined | Ref { + return typeof v === 'object' && IsEmbedded in v && 'relay' in v ? v : void 0; + } } //--------------------------------------------------------------------------- @@ -180,8 +184,12 @@ export class Actor implements Reflectable { return this._dataflowGraph; } - atExit(a: LocalAction): void { + atExit(a: LocalAction): () => void { this.exitHooks.push(a); + return () => { + const i = this.exitHooks.indexOf(a); + if (i !== -1) this.exitHooks.splice(i, 1); + }; } _terminateWith(reason: Exclude) { @@ -284,6 +292,10 @@ export class Facet implements Reflectable { this._reflection?.mirror.setProp(this._reflection.childHandles, '' + child.id, void 0); } + wrap>(f: (... args: T) => void): (... args: T) => void { + return (... args) => this.turn(() => f(... args)); + } + turn(a: LocalAction) { Turn.for(this, a); } @@ -323,12 +335,17 @@ export class Facet implements Reflectable { _halfLink(other: Facet): void { const h = nextHandle++; - const peer = { relay: other, target: new StopOnRetract() }; - this.outbound.set(h, { handle: h, peer, crossSpace: null, established: true }); + const e = { + handle: h, + peer: new Ref(other, new StopOnRetract()), + crossSpace: null, + established: true, + }; + this.outbound.set(h, e); this._reflection?.mirror.setProp( this._reflection.assertionHandles, '' + h, - Refl.FacetAssertion({ handle: h, target: peer })); + Refl.FacetAssertion({ handle: h, target: e.peer })); } _terminate(orderly: boolean): void { @@ -383,7 +400,7 @@ export const STOP_ON_RETRACT = Symbol('stop-on-retract'); // NB. NOT A GLOBAL SY export class StopOnRetract implements Partial { retract(_handle: Handle): void { - Turn.active.stop(); + Turn.active.stop(Turn.activeFacet); } actor = STOP_ON_RETRACT; } @@ -455,7 +472,7 @@ export class Turn { } ref>(e: T): Ref { - return new RefImpl(this.activeFacet, e); + return new Ref(this.activeFacet, e); } facet(bootProc: LocalAction): Facet { @@ -465,11 +482,14 @@ export class Turn { } // Alias for syndicatec code generator to use - _stop(facet: Facet = this.activeFacet, continuation?: LocalAction) { + _stop(facet: Facet, continuation?: LocalAction) { this.stop(facet, continuation); } - stop(facet: Facet = this.activeFacet, continuation?: LocalAction) { + stop(facet: Facet, continuation?: LocalAction) { + if (facet.actor !== Turn.activeFacet.actor) { + throw new Error("Attempt to terminate a facet in a different actor"); + } if (continuation) facet.onStop(continuation); facet._terminate(true); } @@ -507,7 +527,7 @@ export class Turn { }); }, () => { - const a = new KeyedSet(); + const a = new KeyedSet(); initialAssertions.forEach(h => a.add(h)); return Q.ActionDescription.spawnActor({ detail, initialAssertions: a }); }); @@ -536,10 +556,10 @@ export class Turn { crash(err: Error): void { this.enqueue(this.activeFacet.actor.root, () => this.activeFacet.actor._terminateWith({ ok: false, err }), - () => Q.ActionDescription.stopActor(Q.OptionalAny.some(Dictionary.fromJS({ + () => Q.ActionDescription.stopActor(Q.OptionalAny.some({ message: err.message, stack: err.stack ? err.stack : false, - })))); + }))); } field(initial: V, name?: string): Field { diff --git a/packages/core/src/runtime/bag.ts b/packages/core/src/runtime/bag.ts index ba45fc7..b3e016c 100644 --- a/packages/core/src/runtime/bag.ts +++ b/packages/core/src/runtime/bag.ts @@ -1,9 +1,9 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones // Bags and Deltas (which are Bags where item-counts can be negative). -import { Value, KeyedDictionary, KeyedSet } from '@preserves/core'; +import { Value, KeyedDictionary, KeyedSet, Embeddable } from '@preserves/core'; export enum ChangeDescription { PRESENT_TO_ABSENT = -1, @@ -12,10 +12,10 @@ export enum ChangeDescription { PRESENT_TO_PRESENT = 2, } -export class Bag = Value> { - _items: KeyedDictionary; +export class Bag = Value> { + _items: KeyedDictionary; - constructor(s?: KeyedSet) { + constructor(s?: KeyedSet) { this._items = new KeyedDictionary(); if (s) s.forEach((v) => this._items.set(v, 1)); } @@ -68,7 +68,7 @@ export class Bag = Value> { this._items.forEach((c, v) => f(c, v)); } - snapshot(): KeyedDictionary { + snapshot(): KeyedDictionary { return this._items.clone(); } diff --git a/packages/core/src/runtime/dataflow.ts b/packages/core/src/runtime/dataflow.ts index 141a2b2..f370eaf 100644 --- a/packages/core/src/runtime/dataflow.ts +++ b/packages/core/src/runtime/dataflow.ts @@ -1,5 +1,5 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones // Property-based "dataflow" diff --git a/packages/core/src/runtime/dataspace.ts b/packages/core/src/runtime/dataspace.ts index e164283..1c281b7 100644 --- a/packages/core/src/runtime/dataspace.ts +++ b/packages/core/src/runtime/dataspace.ts @@ -1,5 +1,5 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones import { Record, IdentityMap, KeyedDictionary, stringify } from '@preserves/core'; import { Index, IndexObserver } from './skeleton.js'; @@ -18,7 +18,7 @@ export type DataspaceOptions = { }; export class DataspaceObserver implements IndexObserver { - readonly captureMap = new KeyedDictionary, Handle, Ref>(); + readonly captureMap = new KeyedDictionary, Handle>(); constructor( public readonly target: Ref, diff --git a/packages/core/src/runtime/mapset.ts b/packages/core/src/runtime/mapset.ts index dccaecb..eb6f2bb 100644 --- a/packages/core/src/runtime/mapset.ts +++ b/packages/core/src/runtime/mapset.ts @@ -1,5 +1,5 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones // Utilities for Maps of Sets diff --git a/packages/core/src/runtime/pattern.ts b/packages/core/src/runtime/pattern.ts index c22aeb2..df64a9f 100644 --- a/packages/core/src/runtime/pattern.ts +++ b/packages/core/src/runtime/pattern.ts @@ -1,7 +1,7 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones -import { canonicalString, KeyedDictionary, Dictionary, is, Record, RecordConstructorInfo, Value, CompoundKey, _iterMap } from '@preserves/core'; +import { canonicalString, KeyedDictionary, is, Record, RecordConstructorInfo, Value, _iterMap, DictionaryMap, Dictionary, EncodableDictionary } from '@preserves/core'; import { AnyValue, Ref } from './actor.js'; import * as P from '../gen/dataspacePatterns.js'; @@ -13,20 +13,20 @@ export function classOfValue(v: any): Shape | null { if (Record.isRecord(v)) { return constructorInfoSignature(Record.constructorInfo(v)); } else if (Array.isArray(v)) { - return '' + v.length; - } else if (Map.isMap(v)) { + return '[]'; + } else if (Dictionary.isDictionary(v)) { return '{}'; } else { return null; } } -export function classOfCtor(v: P.DCompound): Shape { +export function classOfCtor(v: P.GroupType): Shape { switch (v._variant) { case 'rec': - return canonicalString(v.label) + '/' + v.fields.length; + return canonicalString(v.label); case 'arr': - return '' + v.items.length; + return '[]'; case 'dict': return '{}'; } @@ -34,55 +34,59 @@ export function classOfCtor(v: P.DCompound): Shape { // Called by generated code in addition to functions in this module export function constructorInfoSignature(ci: RecordConstructorInfo): string { - return canonicalString(ci.label) + '/' + ci.arity; + return canonicalString(ci.label); } export function step(v: AnyValue, index: AnyValue): AnyValue | undefined { - if (Map.isMap(v)) { - return v.get(index); + const vMap = Dictionary.asMap(v); + if (vMap) { + return vMap.get(index); } else { return (v as Array /* includes Record! */)[index as number]; } } +export type ConstantPositions = { + withValues: Array, + requiredToExist: Array, +} + export type PatternAnalysis = { - constPaths: Array, + constPositions: ConstantPositions, constValues: Array, capturePaths: Array, }; export function analysePattern(p: P.Pattern): PatternAnalysis { const result: PatternAnalysis = { - constPaths: [], + constPositions: { + withValues: [], + requiredToExist: [], + }, constValues: [], capturePaths: [], }; const path: Path = []; - function walkKey(p: P.Pattern, key: AnyValue) { - path.push(key); - walk(p); - path.pop(); - } - function walk(p: P.Pattern) { switch (p._variant) { - case 'DCompound': - switch (p.value._variant) { - case 'rec': p.value.fields.forEach(walkKey); break; - case 'arr': p.value.items.forEach(walkKey); break; - case 'dict': p.value.entries.forEach(walkKey); break; - } + case 'group': + p.entries.forEach((p, k) => { + path.push(k); + walk(p); + path.pop(); + }); break; - case 'DBind': + case 'bind': result.capturePaths.push(path.slice()); - walk(p.value.pattern); + walk(p.pattern); break; - case 'DDiscard': + case 'discard': + result.constPositions.requiredToExist.push(path.slice()); break; - case 'DLit': - result.constPaths.push(path.slice()); - result.constValues.push(P.fromAnyAtom(p.value.value)); + case 'lit': + result.constPositions.withValues.push(path.slice()); + result.constValues.push(P.fromAnyAtom(p.value)); break; } } @@ -96,32 +100,20 @@ export function match(p: P.Pattern, v: AnyValue): Array | false { function walk(p: P.Pattern, v: AnyValue): boolean { switch (p._variant) { - case 'DBind': { + case 'bind': { captures.push(v); - return walk(p.value.pattern, v); + return walk(p.pattern, v); } - case 'DDiscard': + case 'discard': return true; - case 'DLit': - return is(p.value.value, v); - case 'DCompound': { - const pcls = classOfCtor(p.value); + case 'lit': + return is(p.value, v); + case 'group': { + const pcls = classOfCtor(p.type); const vcls = classOfValue(v); if (pcls !== vcls) return false; - let items: Array; - switch (p.value._variant) { - case 'dict': - for (const [stepIndex, pp] of p.value.entries.entries()) { - const vv = step(v, stepIndex); - if (vv === void 0 || !walk(pp, vv)) return false; - } - return true; - case 'rec': items = p.value.fields; break; - case 'arr': items = p.value.items; break; - } - let index = 0; - for (const pp of items) { - const vv = step(v, index++); + for (const [stepIndex, pp] of p.entries.entries()) { + const vv = step(v, stepIndex); if (vv === void 0 || !walk(pp, vv)) return false; } return true; @@ -135,19 +127,14 @@ export function match(p: P.Pattern, v: AnyValue): Array | false { export function isCompletelyConcrete(p: P.Pattern): boolean { function walk(p: P.Pattern): boolean { switch (p._variant) { - case 'DBind': return false; - case 'DDiscard': return false; - case 'DLit': return true; - case 'DCompound': switch (p.value._variant) { - case 'rec': return p.value.fields.every(isCompletelyConcrete); - case 'arr': return p.value.items.every(isCompletelyConcrete); - case 'dict': { - for (const pp of p.value.entries.values()) { - if (!walk(pp)) return false; - } - return true; + case 'bind': return false; + case 'discard': return false; + case 'lit': return true; + case 'group': + for (const pp of p.entries.values()) { + if (!walk(pp)) return false; } - } + return true; } } return walk(p); @@ -156,26 +143,19 @@ export function isCompletelyConcrete(p: P.Pattern): boolean { export function withoutCaptures(p: P.Pattern): P.Pattern { function walk(p: P.Pattern): P.Pattern { switch (p._variant) { - case 'DBind': return walk(p.value.pattern); - case 'DDiscard': return p; - case 'DLit': return p; - case 'DCompound': - switch (p.value._variant) { - case 'rec': - return P.Pattern.DCompound(P.DCompound.rec({ - label: p.value.label, - fields: p.value.fields.map(walk), - })); - case 'arr': - return P.Pattern.DCompound(P.DCompound.arr(p.value.items.map(walk))); - case 'dict': { - const newDict = new KeyedDictionary, P.Pattern, Ref>(); - for (const [k, v] of p.value.entries) { - newDict.set(k, walk(v)); - } - return P.Pattern.DCompound(P.DCompound.dict(newDict)); - } + case 'bind': return walk(p.pattern); + case 'discard': return p; + case 'lit': return p; + case 'group': { + const newEntries = new KeyedDictionary, P.Pattern>(); + for (const [kk, pp] of p.entries) { + newEntries.set(kk, walk(pp)); } + return P.Pattern.group({ + type: p.type, + entries: newEntries, + }); + } } } return walk(p); @@ -185,57 +165,92 @@ export function withoutCaptures(p: P.Pattern): P.Pattern { // Constructor helpers export function bind(p?: P.Pattern): P.Pattern { - return P.Pattern.DBind(P.DBind(p ?? _)); + return P.Pattern.bind(p ?? _); } export function discard(): P.Pattern { - return P.Pattern.DDiscard(P.DDiscard()); + return P.Pattern.discard(); } export const _ = discard(); +function lit_seq_entries(vs: AnyValue[]): KeyedDictionary> { + const entries = new KeyedDictionary>(); + vs.forEach((v, i) => entries.set(i, lit(v))); + return entries; +} + export function lit(v: AnyValue): P.Pattern { if (Array.isArray(v)) { if ('label' in v) { - return P.Pattern.DCompound(P.DCompound.rec({ - label: v.label, - fields: v.map(lit), - })); + return P.Pattern.group({ + type: P.GroupType.rec(v.label), + entries: lit_seq_entries(v), + }); } else { - return P.Pattern.DCompound(P.DCompound.arr(v.map(lit))); + return P.Pattern.group({ + type: P.GroupType.arr(), + entries: lit_seq_entries(v), + }); } - } else if (Map.isMap(v)) { - return P.Pattern.DCompound(P.DCompound.dict(v.mapEntries( - e => [e[0], lit(e[1])]))); - } else if (Set.isSet(v)) { - throw new Error("Cannot express literal set in pattern"); - } else { - return P.Pattern.DLit(P.DLit(P.asAnyAtom(v))); } + + const vMap = Dictionary.asMap(v); + if (vMap) { + const r = new KeyedDictionary(); + vMap.forEach((val, key) => r.set(key, lit(val))); + return P.Pattern.group({ + type: P.GroupType.dict(), + entries: r, + }); + } + + if (Set.isSet(v)) { + throw new Error("Cannot express literal set in pattern"); + } + + return P.Pattern.lit(P.asAnyAtom(v)); } export function drop_lit(p: P.Pattern): AnyValue | null { const e = new Error(); + + function walkEntries(target: AnyValue[], entries: EncodableDictionary>): void { + let maxKey = -1; + for (const key of entries.keys()) { + if (typeof key !== 'number') throw e; + maxKey = Math.max(maxKey, key); + } + for (let i = 0; i < maxKey + 1; i++) { + const p = entries.get(i); + if (p === void 0) throw e; + target.push(walk(p)); + } + } + function walk(p: P.Pattern): AnyValue { switch (p._variant) { - case 'DCompound': - switch (p.value._variant) { + case 'group': + switch (p.type._variant) { case 'rec': { const v = [] as unknown as Record; - v.label = p.value.label; - p.value.fields.forEach(tt => v.push(walk(tt))); + v.label = p.type.label; + walkEntries(v, p.entries); return v; } - case 'arr': - return p.value.items.map(walk); - case 'dict': { - const v = new Dictionary(); - p.value.entries.forEach((pp, key) => v.set(key, walk(pp))); + case 'arr': { + const v = [] as AnyValue[]; + walkEntries(v, p.entries); return v; } + case 'dict': { + const v = new DictionaryMap(); + p.entries.forEach((pp, key) => v.set(key, walk(pp))); + return v.simplifiedValue(); + } } - case 'DLit': - return P.fromAnyAtom(p.value.value); + case 'lit': + return P.fromAnyAtom(p.value); default: throw e; } @@ -249,13 +264,22 @@ export function drop_lit(p: P.Pattern): AnyValue | null { } export function rec(label: AnyValue, ... fields: P.Pattern[]): P.Pattern { - return P.Pattern.DCompound(P.DCompound.rec({ label, fields })); + return P.Pattern.group({ + type: P.GroupType.rec(label), + entries: new KeyedDictionary(fields.map((p, i) => [i, p])), + }); } export function arr(... patterns: P.Pattern[]): P.Pattern { - return P.Pattern.DCompound(P.DCompound.arr(patterns)); + return P.Pattern.group({ + type: P.GroupType.arr(), + entries: new KeyedDictionary(patterns.map((p, i) => [i, p])), + }); } export function dict(... entries: [AnyValue, P.Pattern][]): P.Pattern { - return P.Pattern.DCompound(P.DCompound.dict(new Dictionary(entries))); + return P.Pattern.group({ + type: P.GroupType.dict(), + entries: new KeyedDictionary(entries), + }); } diff --git a/packages/core/src/runtime/quasivalue.ts b/packages/core/src/runtime/quasivalue.ts index 8b4c568..fecccac 100644 --- a/packages/core/src/runtime/quasivalue.ts +++ b/packages/core/src/runtime/quasivalue.ts @@ -1,10 +1,10 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2021-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2021-2024 Tony Garnock-Jones import { AnyValue, Ref } from './actor.js'; -import { Pattern, toPattern } from '../gen/dataspacePatterns.js'; +import { Pattern, toPattern, GroupType, fromGroupType } from '../gen/dataspacePatterns.js'; import * as P from './pattern.js'; -import { RecordConstructorInfo, is, Record } from '@preserves/core'; +import { RecordConstructorInfo, is, Record, JsDictionary } from '@preserves/core'; import { Meta, Type, GenType, SchemaDefinition } from '@preserves/schema'; export type QuasiValueConstructorInfo = @@ -17,9 +17,7 @@ export type QuasiValue = | { type: 'bind', inner: QuasiValue } | { type: 'discard' } | { type: 'lit', value: AnyValue } - | { type: 'rec', label: AnyValue, items: QuasiValue[] } - | { type: 'arr', items: QuasiValue[] } - | { type: 'dict', entries: [AnyValue, QuasiValue][] } + | { type: 'group', groupType: GroupType, entries: [AnyValue, QuasiValue][] } | { type: 'unquote', unquoted: QuasiValue } ; @@ -58,7 +56,8 @@ export function rec(label: AnyValue, ... items: QuasiValue[]): QuasiValue { if (literals.length === items.length) { return lit(Record(label, literals)); } else { - return { type: 'rec', label, items }; + const entries = items.map((v, i) => [i, v] as [number, QuasiValue]); + return { type: 'group', groupType: GroupType.rec(label), entries }; } } @@ -67,12 +66,13 @@ export function arr(... items: QuasiValue[]): QuasiValue { if (literals.length === items.length) { return lit(literals); } else { - return { type: 'arr', items }; + const entries = items.map((v, i) => [i, v] as [number, QuasiValue]); + return { type: 'group', groupType: GroupType.arr(), entries }; } } export function dict(... entries: [AnyValue, QuasiValue][]): QuasiValue { - return { type: 'dict', entries }; + return { type: 'group', groupType: GroupType.dict(), entries }; } export function quote(quoted: QuasiValue): QuasiValue { @@ -80,12 +80,9 @@ export function quote(quoted: QuasiValue): QuasiValue { case 'bind': return quote(bind.quasiValue(quoted.inner)); case 'discard': return quote(discard.quasiValue()); case 'lit': return rec(Symbol.for('lit'), lit(quoted.value)); - case 'arr': return rec(Symbol.for('arr'), arr( - ... quoted.items.map(quote))); - case 'rec': return rec(Symbol.for('rec'), lit(quoted.label), arr( - ... quoted.items.map(quote))); - case 'dict': return rec(Symbol.for('dict'), dict( - ... quoted.entries.map(([k, qq]) => [k, quote(qq)] as [AnyValue, QuasiValue]))); + case 'group': + return rec(Symbol.for('group'), lit(fromGroupType(quoted.groupType)), dict( + ... quoted.entries.map(([k, qq]) => [k, quote(qq)] as [AnyValue, QuasiValue]))); case 'unquote': return quoted.unquoted; } } @@ -94,13 +91,27 @@ export function unquote(unquoted: QuasiValue): QuasiValue { return { type: 'unquote', unquoted }; } +function entriesSeq(entries: [AnyValue, V][], defaultValue: V): V[] { + let maxKey = -1; + const result: V[] = []; + for (const [k, q] of entries) { + if (typeof k !== 'number') throw new Error("Invalid sequence quasivalue entries key"); + result[k] = q; + maxKey = Math.max(maxKey, k); + } + for (let i = 0; i < maxKey + 1; i++) { + if (result[i] === void 0) result[i] = defaultValue; + } + return result; +} + export function ctor(info: QuasiValueConstructorInfo, ... items: QuasiValue[]): QuasiValue { if ('constructorInfo' in info) { return rec(info.constructorInfo.label, ... items); } else if ('schema' in info) { const definfo = info.schema(); const schema = Meta.asSchema(definfo.schema); - const def = schema.definitions.get(definfo.definitionName)!; + const def = JsDictionary.get(schema.definitions, definfo.definitionName)!; const defNameStr = definfo.definitionName.description!; const ctorArgs = items.slice(); @@ -158,7 +169,7 @@ export function ctor(info: QuasiValueConstructorInfo, ... items: QuasiValue[]): if (d.type === 'discard') { return d; } - if (d.type !== 'dict') { + if (d.type !== 'group' || d.groupType._variant !== 'dict') { throw new Error(`Dictionary argument needed to ${defNameStr}`); } for (const [k, p] of d.entries) { @@ -217,8 +228,8 @@ export function ctor(info: QuasiValueConstructorInfo, ... items: QuasiValue[]): } function qArr(q: QuasiValue): QuasiValue[] { - if (q.type === 'arr') { - return q.items; + if (q.type === 'group' && q.groupType._variant === 'arr') { + return entriesSeq(q.entries, discard()); } else if (q.type === 'lit' && Array.isArray(q.value)) { return q.value.map(lit); } else { @@ -284,10 +295,12 @@ function walk(q: QuasiValue): Pattern { case 'bind': return P.bind(walk(q.inner)); case 'discard': return P._; case 'lit': return P.lit(q.value); - case 'arr': return P.arr(... q.items.map(walk)); - case 'rec': return P.rec(q.label, ... q.items.map(walk)); - case 'dict': return P.dict(... q.entries.map( - ([k, qq]) => [k, walk(qq)] as [AnyValue, Pattern])); + case 'group': switch (q.groupType._variant) { + case 'arr': return P.arr(... entriesSeq(q.entries, discard()).map(walk)); + case 'rec': return P.rec(q.groupType.label, ... entriesSeq(q.entries, discard()).map(walk)); + case 'dict': return P.dict(... q.entries.map( + ([k, qq]) => [k, walk(qq)] as [AnyValue, Pattern])); + } case 'unquote': throw new Error('Unexpected unquote in QuasiValue'); } } diff --git a/packages/core/src/runtime/randomid.ts b/packages/core/src/runtime/randomid.ts index 0d6872e..ff38435 100644 --- a/packages/core/src/runtime/randomid.ts +++ b/packages/core/src/runtime/randomid.ts @@ -1,5 +1,5 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones import { Bytes } from '@preserves/core'; import * as node_crypto from 'crypto'; diff --git a/packages/core/src/runtime/rewrite.ts b/packages/core/src/runtime/rewrite.ts index 4c27c7b..90f2499 100644 --- a/packages/core/src/runtime/rewrite.ts +++ b/packages/core/src/runtime/rewrite.ts @@ -1,9 +1,9 @@ /// SPDX-License-Identifier: GPL-3.0-or-later -/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones +/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones -import { Turn } from "./actor.js"; -import { Bytes, Dictionary, DoubleFloat, embed, IdentityMap, is, isEmbedded, Record, SingleFloat, Tuple, stringify } from "@preserves/core"; -import type { Assertion, Handle, Ref } from "./actor.js"; +import { Turn, Ref } from "./actor.js"; +import { Bytes, Dictionary, DictionaryMap, DoubleFloat, IdentityMap, KeyedDictionary, is, isEmbedded, Record, Tuple, stringify } from "@preserves/core"; +import type { Assertion, Handle } from "./actor.js"; import type { SturdyValue } from "../transport/sturdy.js"; import { @@ -19,6 +19,8 @@ import { PEmbedded, Pattern, Rewrite, + TAttenuate, + TCompound, TRef, Template, _embedded, @@ -39,7 +41,6 @@ export function match(p: Pattern, v: Assertion): Bindings | null { case 'Boolean': return typeof v === 'boolean'; case 'ByteString': return Bytes.isBytes(v); case 'Double': return DoubleFloat.isDouble(v); - case 'Float': return SingleFloat.isSingle(v); case 'SignedInteger': return typeof v === 'number'; case 'String': return typeof v === 'string'; case 'Symbol': return typeof v === 'symbol'; @@ -88,9 +89,10 @@ export function match(p: Pattern, v: Assertion): Bindings | null { return true; } case 'dict':{ - if (!Dictionary.isDictionary(v)) return false; + const vMap = Dictionary.asMap(v); + if (!vMap) return false; for (const [key, pp] of p.value.entries.entries()) { - const vv = v.get(key); + const vv = vMap.get(key); if (vv === void 0) return false; if (!walk(pp, vv)) return false; } @@ -114,8 +116,7 @@ export function instantiate(t: Template, b: Bindings): Assertion { if (!isEmbedded(v)) { throw new Error(`Attempt to attenuate non-capability: ${stringify(v)}`); } - const r = v.embeddedValue; - return embed(attenuate(r, ... t.value.attenuation)); + return attenuate(v, ... t.value.attenuation); } case 'TRef': { const n = t.value.binding; @@ -136,9 +137,9 @@ export function instantiate(t: Template, b: Bindings): Assertion { case 'arr': return t.value.items.map(walk); case 'dict': { - const v = new Dictionary(); + const v = new DictionaryMap(); t.value.entries.forEach((tt, key) => v.set(key, walk(tt))); - return v; + return v.simplifiedValue(); } } } @@ -193,9 +194,14 @@ export function rfilter(... patterns: Pattern[]): Caveat { return ps.length === 1 ? Caveat.Rewrite(ps[0]) : Caveat.Alts(Alts(ps)); } +export function rmap(... rewrites: [Pattern, Template][]): Caveat { + const rs = rewrites.map(([pattern, template]) => Rewrite({ pattern, template })); + return rs.length === 1 ? Caveat.Rewrite(rs[0]) : Caveat.Alts(Alts(rs)); +} + export function attenuate(ref: Ref, ... a: Caveat[]): Ref { if (a.length === 0) return ref; - return { ... ref, attenuation: [... (ref.attenuation ?? []), ... a] }; + return new Ref(ref.relay, ref.target, [... (ref.attenuation ?? []), ... a]); } export function forwarder(ref: Ref): { proxy: Ref, revoker: Ref } { @@ -238,7 +244,7 @@ export function pArr(... items: Array): Pattern { } export function pDict(... entries: [SturdyValue, Pattern][]): Pattern { - return Pattern.PCompound(PCompound.dict(new Dictionary<_embedded, Pattern>(entries))); + return Pattern.PCompound(PCompound.dict(new KeyedDictionary<_embedded, SturdyValue, Pattern>(entries))); } export function pLit(value: SturdyValue): Pattern { @@ -281,10 +287,6 @@ export function pDouble(): Pattern { return Pattern.PAtom(PAtom.Double()); } -export function pFloat(): Pattern { - return Pattern.PAtom(PAtom.Float()); -} - export function pBoolean(): Pattern { return Pattern.PAtom(PAtom.Boolean()); } @@ -292,3 +294,27 @@ export function pBoolean(): Pattern { export function pDiscard(): Pattern { return Pattern.PDiscard(PDiscard()); } + +export function tRec(label: SturdyValue, ... fields: Array