Merge branch 'main' into mirror

This commit is contained in:
Tony Garnock-Jones 2024-04-15 09:53:46 +02:00
commit 6d82440704
131 changed files with 2671 additions and 1750 deletions

View File

@ -16,13 +16,13 @@
"author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>", "author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>",
"license": "GPL-3.0+", "license": "GPL-3.0+",
"dependencies": { "dependencies": {
"@preserves/core": "0.992.4", "@preserves/core": "0.995.200",
"@syndicate-lang/core": "*", "@syndicate-lang/core": "*",
"@syndicate-lang/html": "*", "@syndicate-lang/html": "*",
"@syndicate-lang/ws-relay": "*" "@syndicate-lang/ws-relay": "*"
}, },
"devDependencies": { "devDependencies": {
"@preserves/schema-cli": "0.992.5", "@preserves/schema-cli": "0.995.201",
"@syndicate-lang/ts-plugin": "*", "@syndicate-lang/ts-plugin": "*",
"@syndicate-lang/tsc": "*", "@syndicate-lang/tsc": "*",
"rollup": "^2.60", "rollup": "^2.60",

View File

@ -1,6 +1,6 @@
let ?ds = dataspace let ?ds = dataspace
# Connect using <route [<ws "...">] <ref "syndicate" [] #[acowDB2/oI+6aSEC3YIxGg]>> # Connect using <route [<ws "...">] <ref {oid: "syndicate" sig: #[acowDB2/oI+6aSEC3YIxGg]}>
<bind <ref {oid: "syndicate" key: #x""}> $ds #f> <bind <ref {oid: "syndicate" key: #x""}> $ds #f>
# Connect using <route [<ws "...">] <noise { service: "syndicate", key: #x"21f6cd4e11e7e37711d6b3084ff18cded8fc8abf293aa47d43e8bb86dda65516" }>> # Connect using <route [<ws "...">] <noise { service: "syndicate", key: #x"21f6cd4e11e7e37711d6b3084ff18cded8fc8abf293aa47d43e8bb86dda65516" }>>

View File

@ -1,7 +1,7 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2021 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2021 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
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 bootHtml, Anchor, template as html, HtmlFragments, GlobalEvent, UIAttribute, UIChangeableProperty } from "@syndicate-lang/html";
import { boot as bootWakeDetector, WakeEvent } from "./wake-detector"; import { boot as bootWakeDetector, WakeEvent } from "./wake-detector";
import { boot as bootWsRelay } from "@syndicate-lang/ws-relay"; import { boot as bootWsRelay } from "@syndicate-lang/ws-relay";
@ -46,12 +46,9 @@ function bootChat(ds: Ref) {
during G.ResolvePath({ during G.ResolvePath({
"route": route, "route": route,
"addr": $addr, "addr": $addr,
"control": $control_e: Embedded, "control": $control: Ref,
"resolved": G.Resolved.accepted($remoteDs_e: Embedded), "resolved": G.Resolved.accepted($remoteDs: Ref),
}) => { }) => {
const remoteDs = remoteDs_e.embeddedValue;
const control = control_e.embeddedValue;
on message WakeEvent() => at control { on message WakeEvent() => at control {
send message G.ForceDisconnect(); send message G.ForceDisconnect();
} }

View File

@ -2,30 +2,30 @@
# yarn lockfile v1 # yarn lockfile v1
"@preserves/core@0.992", "@preserves/core@^0.992.2": "@preserves/core@0.995.200", "@preserves/core@^0.995.200":
version "0.992.2" version "0.995.200"
resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.992.2.tgz#b3acc7badd25ccccbf8e034bb641c6cfad987c41" resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.200.tgz#65575cf8f9320e73b5d37fa9ac9d6881a33fd3a6"
integrity sha512-aibJ8c9mLcCf3MhXeLWv0hevfkHgu3pJmBDzhN9AGXMIw0/fO3uEEnLM1oPaFIPWnQG4WybiXTUh2wD1CoxABg== integrity sha512-htZ2x+hltUpKoPsviWSuelzZW96po9zVSsN0RZEih60FahNX0R2LCqFJ6v5lyATuQ9oHALVi0w8w4rtf8oiAJw==
"@preserves/schema-cli@0.992": "@preserves/schema-cli@0.995.201":
version "0.992.2" version "0.995.201"
resolved "https://registry.yarnpkg.com/@preserves/schema-cli/-/schema-cli-0.992.2.tgz#53defa05b0bd34cf5032255d761076797254ce8f" resolved "https://registry.yarnpkg.com/@preserves/schema-cli/-/schema-cli-0.995.201.tgz#e87cb7ba51b225ff6ea96f177c5388907adf6717"
integrity sha512-ICJ0fqj3haJZosU7h8APm3GkoUaZs+BHKfj80BD8wuBf4iSLa4GAYASYThLZT/tlxU2iK1j4NghrG6/tCIj99w== integrity sha512-n/lpVgWBY1UTRySPXIwWG4Yu87OrQ9b7Xo8zPPQzD/DJDTEDT3y3SUujY7UTF1pQn09xRGnfPnDu1RoRCv2J3w==
dependencies: dependencies:
"@preserves/core" "^0.992.2" "@preserves/core" "^0.995.200"
"@preserves/schema" "^0.992.2" "@preserves/schema" "^0.995.201"
chalk "^4.1" chalk "^4.1"
chokidar "^3.5" chokidar "^3.5"
commander "^7.2" commander "^7.2"
glob "^7.1" glob "^7.1"
minimatch "^3.0" minimatch "^3.0"
"@preserves/schema@0.992", "@preserves/schema@^0.992.2": "@preserves/schema@^0.995.201":
version "0.992.2" version "0.995.201"
resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.992.2.tgz#975598b166500adc79f0d4e0cf2ae6dea3c2c111" resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.995.201.tgz#827ad539afb0fdf68ba885ee3ff43db0fd473aa5"
integrity sha512-I1zM9EWY0URw2zuRHLyROqVA9uqGhzQjuCpnTC8MeJToPt+xwVCXGl/NJYKhgofB14ZAgKT98h6YrLDR3yR6ug== integrity sha512-0SuhwOEAfxtrAeOTZ8V1yNEcHHHEbfUmoFawrF+vzTQFNZRz/X3LF1FM6wOiJlHtb7tBr4B+rHXX8jfNrqrdkA==
dependencies: dependencies:
"@preserves/core" "^0.992.2" "@preserves/core" "^0.995.200"
"@rollup/pluginutils@^3.0.9": "@rollup/pluginutils@^3.0.9":
version "3.1.0" version "3.1.0"
@ -36,52 +36,49 @@
estree-walker "^1.0.1" estree-walker "^1.0.1"
picomatch "^2.2.2" picomatch "^2.2.2"
"@syndicate-lang/compiler@^0.13.2": "@syndicate-lang/compiler@^0.21.1":
version "0.13.2" version "0.21.1"
resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.13.2.tgz#e66de9f5828efb88ebe62266d014e13620961996" resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.21.1.tgz#b6316bac14d053c313b3442be68f532a60c47cb3"
integrity sha512-GQa7GVkerWxoVqY3NtRZXS8aLqIsVfdA8KvgNSDb8fTNV8TKGLDxQRurtcCiuEKG9mtfnDTpk8i28HbijKw6fA== integrity sha512-daaYh1i0XmoHt6eTtO4gWblfVKMjp9trwxqR62wUSONY3gtJ5Bn4hG3dMgfoMz2NvOWbJHaGz/95J0jRubITxA==
"@syndicate-lang/core@*", "@syndicate-lang/core@^0.19.1": "@syndicate-lang/core@*", "@syndicate-lang/core@^0.32.0":
version "0.19.1" version "0.32.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.19.1.tgz#506e4e6e9f6a0b7bd0b5f6a61ad6e98c3a9ccae6" resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.32.0.tgz#0efbbff176cac2969c2b6ba70a19965add3a2c61"
integrity sha512-2CMtEhyb8cg/pcJWgEdsaPtb6TJS0EbgeHcvCRyEFm3gdENxrNHVpxTVznSNAJnZosMu1KbK735kkviH9etkjw== integrity sha512-ERVXk0W1xLaKvUa79Ek74YvqfBU543cUTb2GJvp76TP5k1jA97q9GzhddicS/s8lqu8SUC1+IXmKiJk0NX2TWQ==
dependencies: dependencies:
"@preserves/core" "0.992"
"@preserves/schema" "0.992"
salty-crypto "0.3.1" salty-crypto "0.3.1"
"@syndicate-lang/html@*": "@syndicate-lang/html@*":
version "0.19.1" version "0.33.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/html/-/html-0.19.1.tgz#21611a6c5718f01c00ac3b18e191548a6dd16538" resolved "https://registry.yarnpkg.com/@syndicate-lang/html/-/html-0.33.0.tgz#c53e6bf8a52b17c3747f4270713a8c9234f984af"
integrity sha512-qr4T065GIuMAI3VKAsYmUWcDyqTq/yGQndrG/Ub+L1P2ivU3AbU/0cuFUQVgFIZmoW/iqG9BQzjIUV8xiOsArw== integrity sha512-xhN6NZOgLxlAQOyWG0JAgtyF1e1yQvrpNh5RBAPnucFYC024yo1ggZ08+KiaulhsoIKvRbBE6FU6p9dDm4/tpQ==
dependencies: dependencies:
"@syndicate-lang/core" "^0.19.1" "@syndicate-lang/core" "^0.32.0"
"@syndicate-lang/ts-plugin@*": "@syndicate-lang/ts-plugin@*":
version "0.19.1" version "0.34.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/ts-plugin/-/ts-plugin-0.19.1.tgz#c7ecf4e836314e16d0849a539ab4b22f7d4c10aa" resolved "https://registry.yarnpkg.com/@syndicate-lang/ts-plugin/-/ts-plugin-0.34.0.tgz#df92f9044eeba528c80c41c5c9df49ee28902411"
integrity sha512-o7niu1QnhAONisil83jVnWK3ipwz8obB0iruJ1++W3nXEM2nW7yGPuJNyLwkk1cFuPzfknm/DFdf6WKz9CsJGw== integrity sha512-OCO6Hm0euz2hZk6tYTrJQNEM8iDBeQ/dgpW2a/UP52XSP6fYj0OvUVfn+35ZkIL64S+zDsJjL/6XFN05UZyRGA==
dependencies: dependencies:
"@syndicate-lang/compiler" "^0.13.2" "@syndicate-lang/compiler" "^0.21.1"
"@syndicate-lang/core" "^0.19.1" "@syndicate-lang/core" "^0.32.0"
"@syndicate-lang/tsc@*": "@syndicate-lang/tsc@*":
version "0.19.1" version "0.34.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.19.1.tgz#25d48aa1a29e51c983d1ab6d8ab184eed26b465a" resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.34.0.tgz#1056fba7f639bbf436d0c2ecd2717edc4c1e612a"
integrity sha512-Uul57ynMS3L6CRIponNyUQ4vmblA4iCXyIsjtsi3QktvFJ9DTV4MRJAXjq72662jjLneY/LKWuCPXFKG62PyQA== integrity sha512-Ufj3xsdXMbMCavWsEkX/pFyXRpNIWRW+LFew1icD14DoSLqyBcoUEvskolOSgkSzC53tDjbd4/LXDVofIjIyUA==
dependencies: dependencies:
"@syndicate-lang/compiler" "^0.13.2" "@syndicate-lang/compiler" "^0.21.1"
"@syndicate-lang/core" "^0.19.1" "@syndicate-lang/core" "^0.32.0"
glob "^7.1.6" glob "^7.1.6"
yargs "^16.2.0" yargs "^16.2.0"
"@syndicate-lang/ws-relay@*": "@syndicate-lang/ws-relay@*":
version "0.20.1" version "0.34.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/ws-relay/-/ws-relay-0.20.1.tgz#4d4fbc401e5eb8a474aedf5112f9e1de3391bff8" resolved "https://registry.yarnpkg.com/@syndicate-lang/ws-relay/-/ws-relay-0.34.0.tgz#8b450ef18b22ca8e0c159c7925a1068796ad2c71"
integrity sha512-sv3r/eyQicBQFVJ8MrS2/OUOPtbr54fkgC6dGN0IdRIeMUFdsxn7HlF3Tumo9I9oOTMNL3Ye+Xkc0sKSLqm8ng== integrity sha512-PT24Pp+ol/wWMSp/6H8i5zu7CgXm5nh0UsfpxJ3ZpvWFs/rIsoMflL/g+C1Q4DW9oFTn6/WFs07VdSLmE2/Uog==
dependencies: dependencies:
"@preserves/core" "0.992" "@syndicate-lang/core" "^0.32.0"
"@syndicate-lang/core" "^0.19.1"
salty-crypto "0.3" salty-crypto "0.3"
"@types/estree@0.0.39": "@types/estree@0.0.39":
@ -120,9 +117,9 @@ balanced-match@^1.0.0:
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
binary-extensions@^2.0.0: binary-extensions@^2.0.0:
version "2.2.0" version "2.3.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
brace-expansion@^1.1.7: brace-expansion@^1.1.7:
version "1.1.11" version "1.1.11"
@ -148,9 +145,9 @@ chalk@^4.1:
supports-color "^7.1.0" supports-color "^7.1.0"
chokidar@^3.5: chokidar@^3.5:
version "3.5.3" version "3.6.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
dependencies: dependencies:
anymatch "~3.1.2" anymatch "~3.1.2"
braces "~3.0.2" braces "~3.0.2"
@ -204,9 +201,9 @@ emoji-regex@^8.0.0:
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
escalade@^3.1.1: escalade@^3.1.1:
version "3.1.1" version "3.1.2"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==
estree-walker@^1.0.1: estree-walker@^1.0.1:
version "1.0.1" version "1.0.1"

View File

@ -12,6 +12,8 @@
"author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>", "author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>",
"license": "GPL-3.0+", "license": "GPL-3.0+",
"dependencies": { "dependencies": {
"@preserves/core": "0.995.200",
"@preserves/schema": "0.995.201",
"@syndicate-lang/core": "*" "@syndicate-lang/core": "*"
}, },
"devDependencies": { "devDependencies": {

View File

@ -2,17 +2,17 @@
# yarn lockfile v1 # yarn lockfile v1
"@preserves/core@0.990", "@preserves/core@^0.990.0": "@preserves/core@0.995.200", "@preserves/core@^0.995.200":
version "0.990.0" version "0.995.200"
resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.990.0.tgz#c57c1c3d5159fc17477a4205d5a94a78fbf5b1aa" resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.200.tgz#65575cf8f9320e73b5d37fa9ac9d6881a33fd3a6"
integrity sha512-Mx013USv9JU1SrtMxaJISETBy2LZ402xH8ZnQI4JzG6W27ZwGV36DQrXAfF0x6cOmZMGKwJNqQrvmFhh7mEn6w== integrity sha512-htZ2x+hltUpKoPsviWSuelzZW96po9zVSsN0RZEih60FahNX0R2LCqFJ6v5lyATuQ9oHALVi0w8w4rtf8oiAJw==
"@preserves/schema@0.990.1": "@preserves/schema@0.995.201":
version "0.990.1" version "0.995.201"
resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.990.1.tgz#233e25855194ce0f6ffaa9968d59e50b7dc8635a" resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.995.201.tgz#827ad539afb0fdf68ba885ee3ff43db0fd473aa5"
integrity sha512-FdvH0peM7U+Yag8FUZ2CYqDTEWjX88+HWwAfVfndtGAwEOTyjqvAQib0aI9lRPPXHodtaNR9/mLFmZBqve80Ew== integrity sha512-0SuhwOEAfxtrAeOTZ8V1yNEcHHHEbfUmoFawrF+vzTQFNZRz/X3LF1FM6wOiJlHtb7tBr4B+rHXX8jfNrqrdkA==
dependencies: dependencies:
"@preserves/core" "^0.990.0" "@preserves/core" "^0.995.200"
"@rollup/pluginutils@^3.0.9": "@rollup/pluginutils@^3.0.9":
version "3.1.0" version "3.1.0"
@ -23,45 +23,43 @@
estree-walker "^1.0.1" estree-walker "^1.0.1"
picomatch "^2.2.2" picomatch "^2.2.2"
"@syndicate-lang/compiler@^0.13.2": "@syndicate-lang/compiler@^0.21.1":
version "0.13.2" version "0.21.1"
resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.13.2.tgz#e66de9f5828efb88ebe62266d014e13620961996" resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.21.1.tgz#b6316bac14d053c313b3442be68f532a60c47cb3"
integrity sha512-GQa7GVkerWxoVqY3NtRZXS8aLqIsVfdA8KvgNSDb8fTNV8TKGLDxQRurtcCiuEKG9mtfnDTpk8i28HbijKw6fA== integrity sha512-daaYh1i0XmoHt6eTtO4gWblfVKMjp9trwxqR62wUSONY3gtJ5Bn4hG3dMgfoMz2NvOWbJHaGz/95J0jRubITxA==
"@syndicate-lang/core@*", "@syndicate-lang/core@^0.18.1": "@syndicate-lang/core@*", "@syndicate-lang/core@^0.32.0":
version "0.18.1" version "0.32.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.18.1.tgz#5cd2931acdab76150c0406428521e4746e62f18b" resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.32.0.tgz#0efbbff176cac2969c2b6ba70a19965add3a2c61"
integrity sha512-90d0YJCZJVrkxLe+fs5Z+vgigU3wux8VOnPje2E8Q/MXXecjHcBCQWQfcdwUxBdfPSFq9KdQS7g7VFqhu3X7mA== integrity sha512-ERVXk0W1xLaKvUa79Ek74YvqfBU543cUTb2GJvp76TP5k1jA97q9GzhddicS/s8lqu8SUC1+IXmKiJk0NX2TWQ==
dependencies: dependencies:
"@preserves/core" "0.990"
"@preserves/schema" "0.990.1"
salty-crypto "0.3.1" salty-crypto "0.3.1"
"@syndicate-lang/syndicatec@*": "@syndicate-lang/syndicatec@*":
version "0.18.2" version "0.34.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/syndicatec/-/syndicatec-0.18.2.tgz#e594f270705c3203a7e26420bc5df2b568977244" resolved "https://registry.yarnpkg.com/@syndicate-lang/syndicatec/-/syndicatec-0.34.0.tgz#f3b88507b633552fe1f41f24def5121c0cafeaeb"
integrity sha512-iUVKqxmiXMC8uYM5bXdyssY6mtVGI5RQRAtmtikji81XJoYb5pfqGlSkMB6n6x7Cde4OsrzeMJYTJ9q7LvEcsQ== integrity sha512-h3MPifJdXZTS3JVcvRG8GXMJMPBH4RYmJ3B7c2sjM826Pf6O8zT47Vuv1y2WyD9PS8BiSCI01uOR0W5AVJJT5w==
dependencies: dependencies:
"@syndicate-lang/compiler" "^0.13.2" "@syndicate-lang/compiler" "^0.21.1"
"@syndicate-lang/core" "^0.18.1" "@syndicate-lang/core" "^0.32.0"
glob "^7.1.6" glob "^7.1.6"
yargs "^16.2.0" yargs "^16.2.0"
"@syndicate-lang/ts-plugin@*": "@syndicate-lang/ts-plugin@*":
version "0.18.1" version "0.34.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/ts-plugin/-/ts-plugin-0.18.1.tgz#0567774f0d7cef6b498cf39bda6717bc334f7213" resolved "https://registry.yarnpkg.com/@syndicate-lang/ts-plugin/-/ts-plugin-0.34.0.tgz#df92f9044eeba528c80c41c5c9df49ee28902411"
integrity sha512-wQJhQxGLjf3cW2w9RUGToZofsd3iG6GQPTHtRYnAYjyiCdxSb7fhZf7TNRkRv3m20Q1XIUSTiLg3ChU+1I9eEA== integrity sha512-OCO6Hm0euz2hZk6tYTrJQNEM8iDBeQ/dgpW2a/UP52XSP6fYj0OvUVfn+35ZkIL64S+zDsJjL/6XFN05UZyRGA==
dependencies: dependencies:
"@syndicate-lang/compiler" "^0.13.2" "@syndicate-lang/compiler" "^0.21.1"
"@syndicate-lang/core" "^0.18.1" "@syndicate-lang/core" "^0.32.0"
"@syndicate-lang/tsc@*": "@syndicate-lang/tsc@*":
version "0.18.1" version "0.34.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.18.1.tgz#e56522052f792b8dad0bd21c6181b7c801ea893b" resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.34.0.tgz#1056fba7f639bbf436d0c2ecd2717edc4c1e612a"
integrity sha512-arNOK+0NnjCdg6lisOOBD4piMBAxV3OR5frDAQ+DI+44gruvY20Tzen2SFMre7vvr+xVkyQwiHH9VVrgtIQRkw== integrity sha512-Ufj3xsdXMbMCavWsEkX/pFyXRpNIWRW+LFew1icD14DoSLqyBcoUEvskolOSgkSzC53tDjbd4/LXDVofIjIyUA==
dependencies: dependencies:
"@syndicate-lang/compiler" "^0.13.2" "@syndicate-lang/compiler" "^0.21.1"
"@syndicate-lang/core" "^0.18.1" "@syndicate-lang/core" "^0.32.0"
glob "^7.1.6" glob "^7.1.6"
yargs "^16.2.0" yargs "^16.2.0"
@ -137,9 +135,9 @@ emoji-regex@^8.0.0:
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
escalade@^3.1.1: escalade@^3.1.1:
version "3.1.1" version "3.1.2"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==
estree-walker@^1.0.1: estree-walker@^1.0.1:
version "1.0.1" version "1.0.1"

View File

@ -12,6 +12,8 @@
"author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>", "author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>",
"license": "GPL-3.0+", "license": "GPL-3.0+",
"dependencies": { "dependencies": {
"@preserves/core": "0.995.200",
"@preserves/schema": "0.995.201",
"@syndicate-lang/core": "*" "@syndicate-lang/core": "*"
}, },
"devDependencies": { "devDependencies": {

View File

@ -2,17 +2,17 @@
# yarn lockfile v1 # yarn lockfile v1
"@preserves/core@0.990", "@preserves/core@^0.990.0": "@preserves/core@0.995.200", "@preserves/core@^0.995.200":
version "0.990.0" version "0.995.200"
resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.990.0.tgz#c57c1c3d5159fc17477a4205d5a94a78fbf5b1aa" resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.200.tgz#65575cf8f9320e73b5d37fa9ac9d6881a33fd3a6"
integrity sha512-Mx013USv9JU1SrtMxaJISETBy2LZ402xH8ZnQI4JzG6W27ZwGV36DQrXAfF0x6cOmZMGKwJNqQrvmFhh7mEn6w== integrity sha512-htZ2x+hltUpKoPsviWSuelzZW96po9zVSsN0RZEih60FahNX0R2LCqFJ6v5lyATuQ9oHALVi0w8w4rtf8oiAJw==
"@preserves/schema@0.990.1": "@preserves/schema@0.995.201":
version "0.990.1" version "0.995.201"
resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.990.1.tgz#233e25855194ce0f6ffaa9968d59e50b7dc8635a" resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.995.201.tgz#827ad539afb0fdf68ba885ee3ff43db0fd473aa5"
integrity sha512-FdvH0peM7U+Yag8FUZ2CYqDTEWjX88+HWwAfVfndtGAwEOTyjqvAQib0aI9lRPPXHodtaNR9/mLFmZBqve80Ew== integrity sha512-0SuhwOEAfxtrAeOTZ8V1yNEcHHHEbfUmoFawrF+vzTQFNZRz/X3LF1FM6wOiJlHtb7tBr4B+rHXX8jfNrqrdkA==
dependencies: dependencies:
"@preserves/core" "^0.990.0" "@preserves/core" "^0.995.200"
"@rollup/pluginutils@^3.0.9": "@rollup/pluginutils@^3.0.9":
version "3.1.0" version "3.1.0"
@ -23,27 +23,25 @@
estree-walker "^1.0.1" estree-walker "^1.0.1"
picomatch "^2.2.2" picomatch "^2.2.2"
"@syndicate-lang/compiler@^0.13.2": "@syndicate-lang/compiler@^0.21.1":
version "0.13.2" version "0.21.1"
resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.13.2.tgz#e66de9f5828efb88ebe62266d014e13620961996" resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.21.1.tgz#b6316bac14d053c313b3442be68f532a60c47cb3"
integrity sha512-GQa7GVkerWxoVqY3NtRZXS8aLqIsVfdA8KvgNSDb8fTNV8TKGLDxQRurtcCiuEKG9mtfnDTpk8i28HbijKw6fA== integrity sha512-daaYh1i0XmoHt6eTtO4gWblfVKMjp9trwxqR62wUSONY3gtJ5Bn4hG3dMgfoMz2NvOWbJHaGz/95J0jRubITxA==
"@syndicate-lang/core@*", "@syndicate-lang/core@^0.18.1": "@syndicate-lang/core@*", "@syndicate-lang/core@^0.32.0":
version "0.18.1" version "0.32.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.18.1.tgz#5cd2931acdab76150c0406428521e4746e62f18b" resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.32.0.tgz#0efbbff176cac2969c2b6ba70a19965add3a2c61"
integrity sha512-90d0YJCZJVrkxLe+fs5Z+vgigU3wux8VOnPje2E8Q/MXXecjHcBCQWQfcdwUxBdfPSFq9KdQS7g7VFqhu3X7mA== integrity sha512-ERVXk0W1xLaKvUa79Ek74YvqfBU543cUTb2GJvp76TP5k1jA97q9GzhddicS/s8lqu8SUC1+IXmKiJk0NX2TWQ==
dependencies: dependencies:
"@preserves/core" "0.990"
"@preserves/schema" "0.990.1"
salty-crypto "0.3.1" salty-crypto "0.3.1"
"@syndicate-lang/tsc@*": "@syndicate-lang/tsc@*":
version "0.18.1" version "0.34.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.18.1.tgz#e56522052f792b8dad0bd21c6181b7c801ea893b" resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.34.0.tgz#1056fba7f639bbf436d0c2ecd2717edc4c1e612a"
integrity sha512-arNOK+0NnjCdg6lisOOBD4piMBAxV3OR5frDAQ+DI+44gruvY20Tzen2SFMre7vvr+xVkyQwiHH9VVrgtIQRkw== integrity sha512-Ufj3xsdXMbMCavWsEkX/pFyXRpNIWRW+LFew1icD14DoSLqyBcoUEvskolOSgkSzC53tDjbd4/LXDVofIjIyUA==
dependencies: dependencies:
"@syndicate-lang/compiler" "^0.13.2" "@syndicate-lang/compiler" "^0.21.1"
"@syndicate-lang/core" "^0.18.1" "@syndicate-lang/core" "^0.32.0"
glob "^7.1.6" glob "^7.1.6"
yargs "^16.2.0" yargs "^16.2.0"
@ -119,9 +117,9 @@ emoji-regex@^8.0.0:
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
escalade@^3.1.1: escalade@^3.1.1:
version "3.1.1" version "3.1.2"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==
estree-walker@^1.0.1: estree-walker@^1.0.1:
version "1.0.1" version "1.0.1"

View File

@ -12,6 +12,7 @@
"author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>", "author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>",
"license": "GPL-3.0+", "license": "GPL-3.0+",
"dependencies": { "dependencies": {
"@preserves/core": "0.995.200",
"@syndicate-lang/core": "*" "@syndicate-lang/core": "*"
}, },
"devDependencies": { "devDependencies": {

View File

@ -2,17 +2,10 @@
# yarn lockfile v1 # yarn lockfile v1
"@preserves/core@0.990", "@preserves/core@^0.990.0": "@preserves/core@0.995.200":
version "0.990.0" version "0.995.200"
resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.990.0.tgz#c57c1c3d5159fc17477a4205d5a94a78fbf5b1aa" resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.200.tgz#65575cf8f9320e73b5d37fa9ac9d6881a33fd3a6"
integrity sha512-Mx013USv9JU1SrtMxaJISETBy2LZ402xH8ZnQI4JzG6W27ZwGV36DQrXAfF0x6cOmZMGKwJNqQrvmFhh7mEn6w== 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==
dependencies:
"@preserves/core" "^0.990.0"
"@rollup/pluginutils@^3.0.9": "@rollup/pluginutils@^3.0.9":
version "3.1.0" version "3.1.0"
@ -23,27 +16,25 @@
estree-walker "^1.0.1" estree-walker "^1.0.1"
picomatch "^2.2.2" picomatch "^2.2.2"
"@syndicate-lang/compiler@^0.13.2": "@syndicate-lang/compiler@^0.21.1":
version "0.13.2" version "0.21.1"
resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.13.2.tgz#e66de9f5828efb88ebe62266d014e13620961996" resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.21.1.tgz#b6316bac14d053c313b3442be68f532a60c47cb3"
integrity sha512-GQa7GVkerWxoVqY3NtRZXS8aLqIsVfdA8KvgNSDb8fTNV8TKGLDxQRurtcCiuEKG9mtfnDTpk8i28HbijKw6fA== integrity sha512-daaYh1i0XmoHt6eTtO4gWblfVKMjp9trwxqR62wUSONY3gtJ5Bn4hG3dMgfoMz2NvOWbJHaGz/95J0jRubITxA==
"@syndicate-lang/core@*", "@syndicate-lang/core@^0.18.1": "@syndicate-lang/core@*", "@syndicate-lang/core@^0.32.0":
version "0.18.1" version "0.32.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.18.1.tgz#5cd2931acdab76150c0406428521e4746e62f18b" resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.32.0.tgz#0efbbff176cac2969c2b6ba70a19965add3a2c61"
integrity sha512-90d0YJCZJVrkxLe+fs5Z+vgigU3wux8VOnPje2E8Q/MXXecjHcBCQWQfcdwUxBdfPSFq9KdQS7g7VFqhu3X7mA== integrity sha512-ERVXk0W1xLaKvUa79Ek74YvqfBU543cUTb2GJvp76TP5k1jA97q9GzhddicS/s8lqu8SUC1+IXmKiJk0NX2TWQ==
dependencies: dependencies:
"@preserves/core" "0.990"
"@preserves/schema" "0.990.1"
salty-crypto "0.3.1" salty-crypto "0.3.1"
"@syndicate-lang/syndicatec@*": "@syndicate-lang/syndicatec@*":
version "0.18.2" version "0.34.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/syndicatec/-/syndicatec-0.18.2.tgz#e594f270705c3203a7e26420bc5df2b568977244" resolved "https://registry.yarnpkg.com/@syndicate-lang/syndicatec/-/syndicatec-0.34.0.tgz#f3b88507b633552fe1f41f24def5121c0cafeaeb"
integrity sha512-iUVKqxmiXMC8uYM5bXdyssY6mtVGI5RQRAtmtikji81XJoYb5pfqGlSkMB6n6x7Cde4OsrzeMJYTJ9q7LvEcsQ== integrity sha512-h3MPifJdXZTS3JVcvRG8GXMJMPBH4RYmJ3B7c2sjM826Pf6O8zT47Vuv1y2WyD9PS8BiSCI01uOR0W5AVJJT5w==
dependencies: dependencies:
"@syndicate-lang/compiler" "^0.13.2" "@syndicate-lang/compiler" "^0.21.1"
"@syndicate-lang/core" "^0.18.1" "@syndicate-lang/core" "^0.32.0"
glob "^7.1.6" glob "^7.1.6"
yargs "^16.2.0" yargs "^16.2.0"
@ -119,9 +110,9 @@ emoji-regex@^8.0.0:
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
escalade@^3.1.1: escalade@^3.1.1:
version "3.1.1" version "3.1.2"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==
estree-walker@^1.0.1: estree-walker@^1.0.1:
version "1.0.1" version "1.0.1"

View File

@ -12,6 +12,8 @@
"author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>", "author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>",
"license": "GPL-3.0+", "license": "GPL-3.0+",
"dependencies": { "dependencies": {
"@preserves/core": "0.995.200",
"@preserves/schema": "0.995.201",
"@syndicate-lang/core": "*" "@syndicate-lang/core": "*"
}, },
"devDependencies": { "devDependencies": {

View File

@ -2,17 +2,17 @@
# yarn lockfile v1 # yarn lockfile v1
"@preserves/core@0.990", "@preserves/core@^0.990.0": "@preserves/core@0.995.200", "@preserves/core@^0.995.200":
version "0.990.0" version "0.995.200"
resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.990.0.tgz#c57c1c3d5159fc17477a4205d5a94a78fbf5b1aa" resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.200.tgz#65575cf8f9320e73b5d37fa9ac9d6881a33fd3a6"
integrity sha512-Mx013USv9JU1SrtMxaJISETBy2LZ402xH8ZnQI4JzG6W27ZwGV36DQrXAfF0x6cOmZMGKwJNqQrvmFhh7mEn6w== integrity sha512-htZ2x+hltUpKoPsviWSuelzZW96po9zVSsN0RZEih60FahNX0R2LCqFJ6v5lyATuQ9oHALVi0w8w4rtf8oiAJw==
"@preserves/schema@0.990.1": "@preserves/schema@0.995.201":
version "0.990.1" version "0.995.201"
resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.990.1.tgz#233e25855194ce0f6ffaa9968d59e50b7dc8635a" resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.995.201.tgz#827ad539afb0fdf68ba885ee3ff43db0fd473aa5"
integrity sha512-FdvH0peM7U+Yag8FUZ2CYqDTEWjX88+HWwAfVfndtGAwEOTyjqvAQib0aI9lRPPXHodtaNR9/mLFmZBqve80Ew== integrity sha512-0SuhwOEAfxtrAeOTZ8V1yNEcHHHEbfUmoFawrF+vzTQFNZRz/X3LF1FM6wOiJlHtb7tBr4B+rHXX8jfNrqrdkA==
dependencies: dependencies:
"@preserves/core" "^0.990.0" "@preserves/core" "^0.995.200"
"@rollup/pluginutils@^3.0.9": "@rollup/pluginutils@^3.0.9":
version "3.1.0" version "3.1.0"
@ -23,27 +23,25 @@
estree-walker "^1.0.1" estree-walker "^1.0.1"
picomatch "^2.2.2" picomatch "^2.2.2"
"@syndicate-lang/compiler@^0.13.2": "@syndicate-lang/compiler@^0.21.1":
version "0.13.2" version "0.21.1"
resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.13.2.tgz#e66de9f5828efb88ebe62266d014e13620961996" resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.21.1.tgz#b6316bac14d053c313b3442be68f532a60c47cb3"
integrity sha512-GQa7GVkerWxoVqY3NtRZXS8aLqIsVfdA8KvgNSDb8fTNV8TKGLDxQRurtcCiuEKG9mtfnDTpk8i28HbijKw6fA== integrity sha512-daaYh1i0XmoHt6eTtO4gWblfVKMjp9trwxqR62wUSONY3gtJ5Bn4hG3dMgfoMz2NvOWbJHaGz/95J0jRubITxA==
"@syndicate-lang/core@*", "@syndicate-lang/core@^0.18.1": "@syndicate-lang/core@*", "@syndicate-lang/core@^0.32.0":
version "0.18.1" version "0.32.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.18.1.tgz#5cd2931acdab76150c0406428521e4746e62f18b" resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.32.0.tgz#0efbbff176cac2969c2b6ba70a19965add3a2c61"
integrity sha512-90d0YJCZJVrkxLe+fs5Z+vgigU3wux8VOnPje2E8Q/MXXecjHcBCQWQfcdwUxBdfPSFq9KdQS7g7VFqhu3X7mA== integrity sha512-ERVXk0W1xLaKvUa79Ek74YvqfBU543cUTb2GJvp76TP5k1jA97q9GzhddicS/s8lqu8SUC1+IXmKiJk0NX2TWQ==
dependencies: dependencies:
"@preserves/core" "0.990"
"@preserves/schema" "0.990.1"
salty-crypto "0.3.1" salty-crypto "0.3.1"
"@syndicate-lang/syndicatec@*": "@syndicate-lang/syndicatec@*":
version "0.18.2" version "0.34.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/syndicatec/-/syndicatec-0.18.2.tgz#e594f270705c3203a7e26420bc5df2b568977244" resolved "https://registry.yarnpkg.com/@syndicate-lang/syndicatec/-/syndicatec-0.34.0.tgz#f3b88507b633552fe1f41f24def5121c0cafeaeb"
integrity sha512-iUVKqxmiXMC8uYM5bXdyssY6mtVGI5RQRAtmtikji81XJoYb5pfqGlSkMB6n6x7Cde4OsrzeMJYTJ9q7LvEcsQ== integrity sha512-h3MPifJdXZTS3JVcvRG8GXMJMPBH4RYmJ3B7c2sjM826Pf6O8zT47Vuv1y2WyD9PS8BiSCI01uOR0W5AVJJT5w==
dependencies: dependencies:
"@syndicate-lang/compiler" "^0.13.2" "@syndicate-lang/compiler" "^0.21.1"
"@syndicate-lang/core" "^0.18.1" "@syndicate-lang/core" "^0.32.0"
glob "^7.1.6" glob "^7.1.6"
yargs "^16.2.0" yargs "^16.2.0"
@ -119,9 +117,9 @@ emoji-regex@^8.0.0:
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
escalade@^3.1.1: escalade@^3.1.1:
version "3.1.1" version "3.1.2"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==
estree-walker@^1.0.1: estree-walker@^1.0.1:
version "1.0.1" version "1.0.1"

View File

@ -3,6 +3,7 @@
<meta charset=utf-8> <meta charset=utf-8>
<meta name="viewport" content="width=device-width, initial-scale=0.67, maximum-scale=0.67, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=0.67, maximum-scale=0.67, user-scalable=no">
<link href="css/style.css" rel="stylesheet" type="text/css"> <link href="css/style.css" rel="stylesheet" type="text/css">
<script src="node_modules/@preserves/core/dist/preserves.js"></script>
<script src="node_modules/@syndicate-lang/core/dist/syndicate.js"></script> <script src="node_modules/@syndicate-lang/core/dist/syndicate.js"></script>
<script src="node_modules/@syndicate-lang/html/dist/syndicate-html.js"></script> <script src="node_modules/@syndicate-lang/html/dist/syndicate-html.js"></script>
<script src="node_modules/@syndicate-lang/timer/dist/syndicate-timer.js"></script> <script src="node_modules/@syndicate-lang/timer/dist/syndicate-timer.js"></script>

View File

@ -12,6 +12,8 @@
"author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>", "author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>",
"license": "GPL-3.0+", "license": "GPL-3.0+",
"dependencies": { "dependencies": {
"@preserves/core": "0.995.200",
"@preserves/schema": "0.995.201",
"@syndicate-lang/core": "*", "@syndicate-lang/core": "*",
"@syndicate-lang/html": "*", "@syndicate-lang/html": "*",
"@syndicate-lang/timer": "*" "@syndicate-lang/timer": "*"

View File

@ -1,7 +1,7 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2021 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2021 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
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 bootHtml, WindowEvent, template, Anchor } from '@syndicate-lang/html';
import { boot as bootTimer, PeriodicTick } from '@syndicate-lang/timer'; import { boot as bootTimer, PeriodicTick } from '@syndicate-lang/timer';
@ -86,9 +86,7 @@ function spawnGame(mainDs: Ref) {
on (ypos.value > BOARD_HEIGHT - FLAPPY_HEIGHT) { on (ypos.value > BOARD_HEIGHT - FLAPPY_HEIGHT) {
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 { react {
const pipeNumber = nextPipe.value++; const pipeNumber = nextPipe.value++;
spawn linked named ['pipe', pipeNumber] { 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; const xlocation = (i + 1) * 324;
let ui = new Anchor(); let ui = new Anchor();
@ -159,21 +157,17 @@ function spawnGame(mainDs: Ref) {
+ PILLAR_HEAD_HEIGHT * 3; + PILLAR_HEAD_HEIGHT * 3;
const lowerHeight = FIELD_HEIGHT - upperHeight - PILLAR_GAP; 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 { at gameDs {
react { once (xpos.value <= 0) send message IncreaseScore();
stop on (xpos.value <= 0) send message IncreaseScore();
}
on asserted Position($flappyXpos, _) => on asserted Position($flappyXpos, _) =>
xpos.value = xlocation - floatValue(flappyXpos); xpos.value = xlocation - floatValue(flappyXpos);
on asserted Position($xpos, $ypos) => { on asserted Position($xpos, $ypos) => {
if (touchingPillar(floatValue(xpos), floatValue(ypos))) { if (touchingPillar(floatValue(xpos), floatValue(ypos))) {
react { assert GameOver();
assert GameOver();
}
} }
} }
} }

View File

@ -2,17 +2,17 @@
# yarn lockfile v1 # yarn lockfile v1
"@preserves/core@0.990", "@preserves/core@^0.990.0": "@preserves/core@0.995.200", "@preserves/core@^0.995.200":
version "0.990.0" version "0.995.200"
resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.990.0.tgz#c57c1c3d5159fc17477a4205d5a94a78fbf5b1aa" resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.200.tgz#65575cf8f9320e73b5d37fa9ac9d6881a33fd3a6"
integrity sha512-Mx013USv9JU1SrtMxaJISETBy2LZ402xH8ZnQI4JzG6W27ZwGV36DQrXAfF0x6cOmZMGKwJNqQrvmFhh7mEn6w== integrity sha512-htZ2x+hltUpKoPsviWSuelzZW96po9zVSsN0RZEih60FahNX0R2LCqFJ6v5lyATuQ9oHALVi0w8w4rtf8oiAJw==
"@preserves/schema@0.990.1": "@preserves/schema@0.995.201":
version "0.990.1" version "0.995.201"
resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.990.1.tgz#233e25855194ce0f6ffaa9968d59e50b7dc8635a" resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.995.201.tgz#827ad539afb0fdf68ba885ee3ff43db0fd473aa5"
integrity sha512-FdvH0peM7U+Yag8FUZ2CYqDTEWjX88+HWwAfVfndtGAwEOTyjqvAQib0aI9lRPPXHodtaNR9/mLFmZBqve80Ew== integrity sha512-0SuhwOEAfxtrAeOTZ8V1yNEcHHHEbfUmoFawrF+vzTQFNZRz/X3LF1FM6wOiJlHtb7tBr4B+rHXX8jfNrqrdkA==
dependencies: dependencies:
"@preserves/core" "^0.990.0" "@preserves/core" "^0.995.200"
"@rollup/pluginutils@^3.0.9": "@rollup/pluginutils@^3.0.9":
version "3.1.0" version "3.1.0"
@ -23,49 +23,47 @@
estree-walker "^1.0.1" estree-walker "^1.0.1"
picomatch "^2.2.2" picomatch "^2.2.2"
"@syndicate-lang/compiler@^0.13.2": "@syndicate-lang/compiler@^0.21.1":
version "0.13.2" version "0.21.1"
resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.13.2.tgz#e66de9f5828efb88ebe62266d014e13620961996" resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.21.1.tgz#b6316bac14d053c313b3442be68f532a60c47cb3"
integrity sha512-GQa7GVkerWxoVqY3NtRZXS8aLqIsVfdA8KvgNSDb8fTNV8TKGLDxQRurtcCiuEKG9mtfnDTpk8i28HbijKw6fA== integrity sha512-daaYh1i0XmoHt6eTtO4gWblfVKMjp9trwxqR62wUSONY3gtJ5Bn4hG3dMgfoMz2NvOWbJHaGz/95J0jRubITxA==
"@syndicate-lang/core@*", "@syndicate-lang/core@^0.18.1": "@syndicate-lang/core@*", "@syndicate-lang/core@^0.32.0":
version "0.18.1" version "0.32.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.18.1.tgz#5cd2931acdab76150c0406428521e4746e62f18b" resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.32.0.tgz#0efbbff176cac2969c2b6ba70a19965add3a2c61"
integrity sha512-90d0YJCZJVrkxLe+fs5Z+vgigU3wux8VOnPje2E8Q/MXXecjHcBCQWQfcdwUxBdfPSFq9KdQS7g7VFqhu3X7mA== integrity sha512-ERVXk0W1xLaKvUa79Ek74YvqfBU543cUTb2GJvp76TP5k1jA97q9GzhddicS/s8lqu8SUC1+IXmKiJk0NX2TWQ==
dependencies: dependencies:
"@preserves/core" "0.990"
"@preserves/schema" "0.990.1"
salty-crypto "0.3.1" salty-crypto "0.3.1"
"@syndicate-lang/html@*": "@syndicate-lang/html@*":
version "0.18.2" version "0.33.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/html/-/html-0.18.2.tgz#276f70a209d90cf938eb27ebdddadfb1c299f234" resolved "https://registry.yarnpkg.com/@syndicate-lang/html/-/html-0.33.0.tgz#c53e6bf8a52b17c3747f4270713a8c9234f984af"
integrity sha512-VTMqrXLFvUQH/TWxTG+YZjUqymoNprde1bhJ2JQ1xyqlHAB82tYXZRJA+/qn93mFs6jCEN9vzvXyNbmJuyYH7Q== integrity sha512-xhN6NZOgLxlAQOyWG0JAgtyF1e1yQvrpNh5RBAPnucFYC024yo1ggZ08+KiaulhsoIKvRbBE6FU6p9dDm4/tpQ==
dependencies: dependencies:
"@syndicate-lang/core" "^0.18.1" "@syndicate-lang/core" "^0.32.0"
"@syndicate-lang/timer@*": "@syndicate-lang/timer@*":
version "0.18.1" version "0.33.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/timer/-/timer-0.18.1.tgz#64f1364eaea77b9ec5b77d41a464baeadf32031b" resolved "https://registry.yarnpkg.com/@syndicate-lang/timer/-/timer-0.33.0.tgz#cdb38ebe777332ec58a5b0b9483db809275a61de"
integrity sha512-49acCxOpOR4LgW9ENQ32+A/wF+fQgvAwhsBS4phzk3DB/Yj9opFZW5MOlMP4R9+iyoN1Nocwq0OO89QGnqg9Wg== integrity sha512-cBon+nk8zvNeU4zC6tg7nhgJnmrRoXHYE140UK3gscNFcg1LZ1d7q9WxfVTzFtRocRBslv6pworSwCDn3Go7TQ==
dependencies: dependencies:
"@syndicate-lang/core" "^0.18.1" "@syndicate-lang/core" "^0.32.0"
"@syndicate-lang/ts-plugin@*": "@syndicate-lang/ts-plugin@*":
version "0.18.1" version "0.34.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/ts-plugin/-/ts-plugin-0.18.1.tgz#0567774f0d7cef6b498cf39bda6717bc334f7213" resolved "https://registry.yarnpkg.com/@syndicate-lang/ts-plugin/-/ts-plugin-0.34.0.tgz#df92f9044eeba528c80c41c5c9df49ee28902411"
integrity sha512-wQJhQxGLjf3cW2w9RUGToZofsd3iG6GQPTHtRYnAYjyiCdxSb7fhZf7TNRkRv3m20Q1XIUSTiLg3ChU+1I9eEA== integrity sha512-OCO6Hm0euz2hZk6tYTrJQNEM8iDBeQ/dgpW2a/UP52XSP6fYj0OvUVfn+35ZkIL64S+zDsJjL/6XFN05UZyRGA==
dependencies: dependencies:
"@syndicate-lang/compiler" "^0.13.2" "@syndicate-lang/compiler" "^0.21.1"
"@syndicate-lang/core" "^0.18.1" "@syndicate-lang/core" "^0.32.0"
"@syndicate-lang/tsc@*": "@syndicate-lang/tsc@*":
version "0.18.1" version "0.34.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.18.1.tgz#e56522052f792b8dad0bd21c6181b7c801ea893b" resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.34.0.tgz#1056fba7f639bbf436d0c2ecd2717edc4c1e612a"
integrity sha512-arNOK+0NnjCdg6lisOOBD4piMBAxV3OR5frDAQ+DI+44gruvY20Tzen2SFMre7vvr+xVkyQwiHH9VVrgtIQRkw== integrity sha512-Ufj3xsdXMbMCavWsEkX/pFyXRpNIWRW+LFew1icD14DoSLqyBcoUEvskolOSgkSzC53tDjbd4/LXDVofIjIyUA==
dependencies: dependencies:
"@syndicate-lang/compiler" "^0.13.2" "@syndicate-lang/compiler" "^0.21.1"
"@syndicate-lang/core" "^0.18.1" "@syndicate-lang/core" "^0.32.0"
glob "^7.1.6" glob "^7.1.6"
yargs "^16.2.0" yargs "^16.2.0"
@ -141,9 +139,9 @@ emoji-regex@^8.0.0:
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
escalade@^3.1.1: escalade@^3.1.1:
version "3.1.1" version "3.1.2"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==
estree-walker@^1.0.1: estree-walker@^1.0.1:
version "1.0.1" version "1.0.1"

View File

@ -3,6 +3,7 @@
<head> <head>
<title>Syndicate: Table Example</title> <title>Syndicate: Table Example</title>
<meta charset="utf-8"> <meta charset="utf-8">
<script src="node_modules/@preserves/core/dist/preserves.js"></script>
<script src="node_modules/@syndicate-lang/core/dist/syndicate.js"></script> <script src="node_modules/@syndicate-lang/core/dist/syndicate.js"></script>
<script src="node_modules/@syndicate-lang/html/dist/syndicate-html.js"></script> <script src="node_modules/@syndicate-lang/html/dist/syndicate-html.js"></script>
</head> </head>

View File

@ -14,6 +14,8 @@
"author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>", "author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>",
"license": "GPL-3.0+", "license": "GPL-3.0+",
"dependencies": { "dependencies": {
"@preserves/core": "0.995.200",
"@preserves/schema": "0.995.201",
"@syndicate-lang/core": "*", "@syndicate-lang/core": "*",
"@syndicate-lang/html": "*" "@syndicate-lang/html": "*"
}, },

View File

@ -1,7 +1,7 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2021 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2021 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
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'; import { boot as bootHtml, UIEvent, GlobalEvent, HtmlFragments, template, Anchor } from '@syndicate-lang/html';
assertion type Person(id, firstName, lastName, address, age); assertion type Person(id, firstName, lastName, address, age);
@ -42,7 +42,7 @@ Dataspace.boot(ds => {
spawn named 'controller' { spawn named 'controller' {
on message GlobalEvent('table#the-table th', 'click', $e) => { on message GlobalEvent('table#the-table th', 'click', $e) => {
const event = (e as Embedded<Ref>).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!)); send message SetSortColumn(JSON.parse((event.target as HTMLElement).dataset.column!));
} }
} }

View File

@ -2,17 +2,17 @@
# yarn lockfile v1 # yarn lockfile v1
"@preserves/core@0.990", "@preserves/core@^0.990.0": "@preserves/core@0.995.200", "@preserves/core@^0.995.200":
version "0.990.0" version "0.995.200"
resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.990.0.tgz#c57c1c3d5159fc17477a4205d5a94a78fbf5b1aa" resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.200.tgz#65575cf8f9320e73b5d37fa9ac9d6881a33fd3a6"
integrity sha512-Mx013USv9JU1SrtMxaJISETBy2LZ402xH8ZnQI4JzG6W27ZwGV36DQrXAfF0x6cOmZMGKwJNqQrvmFhh7mEn6w== integrity sha512-htZ2x+hltUpKoPsviWSuelzZW96po9zVSsN0RZEih60FahNX0R2LCqFJ6v5lyATuQ9oHALVi0w8w4rtf8oiAJw==
"@preserves/schema@0.990.1": "@preserves/schema@0.995.201":
version "0.990.1" version "0.995.201"
resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.990.1.tgz#233e25855194ce0f6ffaa9968d59e50b7dc8635a" resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.995.201.tgz#827ad539afb0fdf68ba885ee3ff43db0fd473aa5"
integrity sha512-FdvH0peM7U+Yag8FUZ2CYqDTEWjX88+HWwAfVfndtGAwEOTyjqvAQib0aI9lRPPXHodtaNR9/mLFmZBqve80Ew== integrity sha512-0SuhwOEAfxtrAeOTZ8V1yNEcHHHEbfUmoFawrF+vzTQFNZRz/X3LF1FM6wOiJlHtb7tBr4B+rHXX8jfNrqrdkA==
dependencies: dependencies:
"@preserves/core" "^0.990.0" "@preserves/core" "^0.995.200"
"@rollup/pluginutils@^3.0.9": "@rollup/pluginutils@^3.0.9":
version "3.1.0" version "3.1.0"
@ -23,42 +23,40 @@
estree-walker "^1.0.1" estree-walker "^1.0.1"
picomatch "^2.2.2" picomatch "^2.2.2"
"@syndicate-lang/compiler@^0.13.2": "@syndicate-lang/compiler@^0.21.1":
version "0.13.2" version "0.21.1"
resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.13.2.tgz#e66de9f5828efb88ebe62266d014e13620961996" resolved "https://registry.yarnpkg.com/@syndicate-lang/compiler/-/compiler-0.21.1.tgz#b6316bac14d053c313b3442be68f532a60c47cb3"
integrity sha512-GQa7GVkerWxoVqY3NtRZXS8aLqIsVfdA8KvgNSDb8fTNV8TKGLDxQRurtcCiuEKG9mtfnDTpk8i28HbijKw6fA== integrity sha512-daaYh1i0XmoHt6eTtO4gWblfVKMjp9trwxqR62wUSONY3gtJ5Bn4hG3dMgfoMz2NvOWbJHaGz/95J0jRubITxA==
"@syndicate-lang/core@*", "@syndicate-lang/core@^0.18.1": "@syndicate-lang/core@*", "@syndicate-lang/core@^0.32.0":
version "0.18.1" version "0.32.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.18.1.tgz#5cd2931acdab76150c0406428521e4746e62f18b" resolved "https://registry.yarnpkg.com/@syndicate-lang/core/-/core-0.32.0.tgz#0efbbff176cac2969c2b6ba70a19965add3a2c61"
integrity sha512-90d0YJCZJVrkxLe+fs5Z+vgigU3wux8VOnPje2E8Q/MXXecjHcBCQWQfcdwUxBdfPSFq9KdQS7g7VFqhu3X7mA== integrity sha512-ERVXk0W1xLaKvUa79Ek74YvqfBU543cUTb2GJvp76TP5k1jA97q9GzhddicS/s8lqu8SUC1+IXmKiJk0NX2TWQ==
dependencies: dependencies:
"@preserves/core" "0.990"
"@preserves/schema" "0.990.1"
salty-crypto "0.3.1" salty-crypto "0.3.1"
"@syndicate-lang/html@*": "@syndicate-lang/html@*":
version "0.18.2" version "0.33.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/html/-/html-0.18.2.tgz#276f70a209d90cf938eb27ebdddadfb1c299f234" resolved "https://registry.yarnpkg.com/@syndicate-lang/html/-/html-0.33.0.tgz#c53e6bf8a52b17c3747f4270713a8c9234f984af"
integrity sha512-VTMqrXLFvUQH/TWxTG+YZjUqymoNprde1bhJ2JQ1xyqlHAB82tYXZRJA+/qn93mFs6jCEN9vzvXyNbmJuyYH7Q== integrity sha512-xhN6NZOgLxlAQOyWG0JAgtyF1e1yQvrpNh5RBAPnucFYC024yo1ggZ08+KiaulhsoIKvRbBE6FU6p9dDm4/tpQ==
dependencies: dependencies:
"@syndicate-lang/core" "^0.18.1" "@syndicate-lang/core" "^0.32.0"
"@syndicate-lang/ts-plugin@*": "@syndicate-lang/ts-plugin@*":
version "0.18.1" version "0.34.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/ts-plugin/-/ts-plugin-0.18.1.tgz#0567774f0d7cef6b498cf39bda6717bc334f7213" resolved "https://registry.yarnpkg.com/@syndicate-lang/ts-plugin/-/ts-plugin-0.34.0.tgz#df92f9044eeba528c80c41c5c9df49ee28902411"
integrity sha512-wQJhQxGLjf3cW2w9RUGToZofsd3iG6GQPTHtRYnAYjyiCdxSb7fhZf7TNRkRv3m20Q1XIUSTiLg3ChU+1I9eEA== integrity sha512-OCO6Hm0euz2hZk6tYTrJQNEM8iDBeQ/dgpW2a/UP52XSP6fYj0OvUVfn+35ZkIL64S+zDsJjL/6XFN05UZyRGA==
dependencies: dependencies:
"@syndicate-lang/compiler" "^0.13.2" "@syndicate-lang/compiler" "^0.21.1"
"@syndicate-lang/core" "^0.18.1" "@syndicate-lang/core" "^0.32.0"
"@syndicate-lang/tsc@*": "@syndicate-lang/tsc@*":
version "0.18.1" version "0.34.0"
resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.18.1.tgz#e56522052f792b8dad0bd21c6181b7c801ea893b" resolved "https://registry.yarnpkg.com/@syndicate-lang/tsc/-/tsc-0.34.0.tgz#1056fba7f639bbf436d0c2ecd2717edc4c1e612a"
integrity sha512-arNOK+0NnjCdg6lisOOBD4piMBAxV3OR5frDAQ+DI+44gruvY20Tzen2SFMre7vvr+xVkyQwiHH9VVrgtIQRkw== integrity sha512-Ufj3xsdXMbMCavWsEkX/pFyXRpNIWRW+LFew1icD14DoSLqyBcoUEvskolOSgkSzC53tDjbd4/LXDVofIjIyUA==
dependencies: dependencies:
"@syndicate-lang/compiler" "^0.13.2" "@syndicate-lang/compiler" "^0.21.1"
"@syndicate-lang/core" "^0.18.1" "@syndicate-lang/core" "^0.32.0"
glob "^7.1.6" glob "^7.1.6"
yargs "^16.2.0" yargs "^16.2.0"
@ -134,9 +132,9 @@ emoji-regex@^8.0.0:
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
escalade@^3.1.1: escalade@^3.1.1:
version "3.1.1" version "3.1.2"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==
estree-walker@^1.0.1: estree-walker@^1.0.1:
version "1.0.1" version "1.0.1"

View File

@ -6,7 +6,7 @@
"packages/*/examples/*/" "packages/*/examples/*/"
], ],
"devDependencies": { "devDependencies": {
"@preserves/core": "0.992.4", "@preserves/core": "0.995.200",
"@rollup/plugin-node-resolve": "^13.0", "@rollup/plugin-node-resolve": "^13.0",
"@types/jest": "^27.0", "@types/jest": "^27.0",
"@types/node": "^14", "@types/node": "^14",

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2023-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
const SyndicateBrowserStdenv = { const SyndicateBrowserStdenv = {
autoboot: true, autoboot: true,

View File

@ -1,6 +1,6 @@
{ {
"name": "@syndicate-lang/browser-stdenv", "name": "@syndicate-lang/browser-stdenv",
"version": "0.23.3", "version": "0.33.0",
"description": "Aggregated Syndicate and Preserves scripts for in-browser use", "description": "Aggregated Syndicate and Preserves scripts for in-browser use",
"homepage": "https://github.com/syndicate-lang/syndicate-js/tree/main/packages/browser-stdenv", "homepage": "https://github.com/syndicate-lang/syndicate-js/tree/main/packages/browser-stdenv",
"license": "GPL-3.0+", "license": "GPL-3.0+",
@ -15,15 +15,15 @@
"author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>", "author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>",
"scripts": { "scripts": {
"prepare": "./build-aggregate.sh", "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" "veryclean": "yarn run clean && rm -rf node_modules"
}, },
"dependencies": { "dependencies": {
"@preserves/core": "0.992.4", "@preserves/core": "0.995.200",
"@preserves/schema": "0.992.5", "@preserves/schema": "0.995.201",
"@syndicate-lang/compiler": "^0.18.0", "@syndicate-lang/compiler": "^0.21.1",
"@syndicate-lang/core": "^0.23.0", "@syndicate-lang/core": "^0.32.0",
"@syndicate-lang/html2": "^0.24.2", "@syndicate-lang/html2": "^0.33.0",
"@syndicate-lang/ws-relay": "^0.25.0" "@syndicate-lang/ws-relay": "^0.34.0"
} }
} }

View File

@ -0,0 +1,7 @@
/// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
export default {
preset: 'ts-jest',
testEnvironment: 'node',
};

View File

@ -1,6 +1,6 @@
{ {
"name": "@syndicate-lang/compiler", "name": "@syndicate-lang/compiler",
"version": "0.18.0", "version": "0.21.1",
"description": "Syndicate/JS compiler library", "description": "Syndicate/JS compiler library",
"homepage": "https://github.com/syndicate-lang/syndicate-js/tree/main/packages/compiler", "homepage": "https://github.com/syndicate-lang/syndicate-js/tree/main/packages/compiler",
"license": "GPL-3.0+", "license": "GPL-3.0+",
@ -18,7 +18,13 @@
"rollup": "../../node_modules/.bin/rollup -c", "rollup": "../../node_modules/.bin/rollup -c",
"rollup:watch": "../../node_modules/.bin/rollup -c -w", "rollup:watch": "../../node_modules/.bin/rollup -c -w",
"clean": "rm -rf lib dist", "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", "main": "dist/syndicate-compiler.js",
"module": "lib/index.js", "module": "lib/index.js",

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { SyndicateRollup } from '../../rollup.js'; import { SyndicateRollup } from '../../rollup.js';
const r = new SyndicateRollup('syndicate-compiler', { globalName: 'SyndicateCompiler' }); const r = new SyndicateRollup('syndicate-compiler', { globalName: 'SyndicateCompiler' });

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { import {
isToken, isTokenType, replace, commaJoin, startPos, fixPos, joinItems, isToken, isTokenType, replace, commaJoin, startPos, fixPos, joinItems,
@ -7,7 +7,7 @@ import {
Items, Pattern, Templates, Substitution, TokenType, Items, Pattern, Templates, Substitution, TokenType,
SourceMap, CodeWriter, TemplateFunction, Token, SpanIndex, match, TokenBase, getRange, Pos, SourceMap, CodeWriter, TemplateFunction, Token, SpanIndex, match, TokenBase, getRange, Pos,
} from '../syntax/index.js'; } from '../syntax/index';
import { import {
SyndicateParser, SyndicateTypedParser, SyndicateParser, SyndicateTypedParser,
Identifier, Identifier,
@ -17,7 +17,8 @@ import {
compilePattern, compilePattern,
SpawnStatement, SpawnStatement,
} from './grammar.js'; FacetToStop,
} from './grammar';
export function stripShebang(items: Items): Items { export function stripShebang(items: Items): Items {
if ((items.length > 0) && if ((items.length > 0) &&
@ -116,20 +117,43 @@ function binderTypeGuard(t: TemplateFunction): (binder: Binder, index: number) =
export function expand(tree: Items, ctx: ExpansionContext): Items { export function expand(tree: Items, ctx: ExpansionContext): Items {
const macro = new Templates(undefined, { extraDelimiters: ':' }); const macro = new Templates(undefined, { extraDelimiters: ':' });
function terminalWrap(t: TemplateFunction, isTerminal: boolean, body: Statement): Statement { function terminalWrap(
if (isTerminal) { t: TemplateFunction,
return t`__SYNDICATE__.Turn.active._stop(__SYNDICATE__.Turn.activeFacet, () => {${body}})` facetToStop: FacetToStop | 'none' | 'once-wrapper',
body: Statement,
): Statement {
if (facetToStop === 'none') {
return walk(body);
} else { } 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 { function facetWrap(
return t`__SYNDICATE__.Turn.active.facet(() => {${items}})`; 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<T>(p: Pattern<T>, f: (v: T, t: TemplateFunction) => Items) { function x<T>(p: Pattern<T>, 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<T extends TurnAction>(p: Pattern<T>, f: (v: T, t: TemplateFunction) => Items) { function xf<T extends TurnAction>(p: Pattern<T>, f: (v: T, t: TemplateFunction) => Items) {
@ -144,7 +168,7 @@ export function expand(tree: Items, ctx: ExpansionContext): Items {
// following transformations matters. // following transformations matters.
xf(ctx.parser.duringStatement, (s, t) => { 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 !== null) {
if (spawn.linkedToken !== null) { if (spawn.linkedToken !== null) {
ctx.emitError(`during ... spawn doesn't need "linked", it's always linked`, 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) let body = (spawn === null)
? walk(s.body) ? 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 sa = compilePattern(s.pattern);
const assertion = t`__SYNDICATE__.Observe({ 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))}])` ? t`, new __SYNDICATE__.Set([${commaJoin(s.initialAssertions.map(walk))}])`
: ``; : ``;
*/ */
const n = spawn.name === void 0 ? '' : t` __SYNDICATE__.Turn.activeFacet.actor.name = ${walk(spawn.name)};`; const f = t` const currentSyndicateFacet = __SYNDICATE__.Turn.activeFacet;`;
return t`__SYNDICATE__.Dataspace._spawn${spawn.linkedToken ? 'Link': ''}(() => {${n} ${inject} ${walk(spawn.body)} });`; 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); x(ctx.parser.spawn, expandSpawn);
@ -226,10 +251,10 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')}
t`_dataflow(() => {${walk(s.body)}});`); t`_dataflow(() => {${walk(s.body)}});`);
x(ctx.parser.eventHandlerEndpointStatement, (s, t) => { 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') { 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') { if (s.triggerType === 'stop') {
@ -247,19 +272,19 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')}
case 'asserted': case 'asserted':
entity = t`{ entity = t`{
assert: (${ctx.argDecl(t, '__vs', '__SYNDICATE__.AnyValue')}, ${ctx.argDecl(t, '__handle', '__SYNDICATE__.Handle')}) => { 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; break;
case 'retracted': case 'retracted':
entity = t`__SYNDICATE__.assertionObserver((${ctx.argDecl(t, '__vs', '__SYNDICATE__.AnyValue')}) => { 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; break;
case 'message': case 'message':
entity = t`{ entity = t`{
message: (${ctx.argDecl(t, '__vs', '__SYNDICATE__.AnyValue')}) => { message: (${ctx.argDecl(t, '__vs', '__SYNDICATE__.AnyValue')}) => {
${guardBody(terminalWrap(t, s.terminal, walk(s.body)))} ${guardBody(terminalWrap(t, s.facetToStop, s.body))}
} }
}`; }`;
break; break;
@ -294,10 +319,9 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')}
xf(ctx.parser.messageSendStatement, (s, t) => t`message(currentSyndicateTarget, ${walk(s.expr)});`); 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) => x(ctx.parser.stopStatement, (s, t) => t`${terminalWrap(t, s.facetToStop, s.body)};`);
t`__SYNDICATE__.Turn.active._stop(__SYNDICATE__.Turn.activeFacet, () => {${walk(s.body)}});`)
return tree; return tree;
} }

View File

@ -1,16 +1,17 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { import {
Token, Items, TokenBase, TokenType, Token, Items, TokenBase, TokenType, Pos,
Pattern, Pattern,
foldItems, match, anonymousTemplate as template, commaJoin, 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, repeat, option, withoutSpace, map, mapm, rest, discard,
value, succeed, fail, separatedOrTerminatedBy, not, value, succeed, fail, separatedOrTerminatedBy, not,
} from '../syntax/index.js'; } from '../syntax/index';
import * as Matcher from '../syntax/matcher.js'; import * as Matcher from '../syntax/matcher';
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// AST types // AST types
@ -50,8 +51,14 @@ export interface StatementTurnAction extends TurnAction {
body: Statement; body: Statement;
} }
export type FacetToStop = 'default' | Expr;
export interface StopStatement extends StatementTurnAction {
facetToStop: FacetToStop;
}
export interface GenericEventEndpointStatement extends StatementTurnAction { export interface GenericEventEndpointStatement extends StatementTurnAction {
terminal: boolean; facetToStop: FacetToStop | 'none' | 'once-wrapper';
once: boolean; once: boolean;
isDynamic: boolean; isDynamic: boolean;
} }
@ -90,6 +97,7 @@ export interface DuringStatement extends FacetSetupAction {
} }
export interface ReactStatement extends FacetSetupAction { export interface ReactStatement extends FacetSetupAction {
label: Identifier | null;
} }
export interface AtStatement { export interface AtStatement {
@ -174,16 +182,29 @@ export class SyndicateParser {
return group('{', map(rest, items => (acc?.push(... items), items))); return group('{', map(rest, items => (acc?.push(... items), items)));
} }
readonly statementBoundary = alt<any>(atom(';'), Matcher.newline); readonly statementBoundary = alt<any>(
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<any>(atom(';'), atom(','), group('{', discard), Matcher.end); readonly exprBoundary = alt<any>(atom(';'), atom(','), group('{', discard), Matcher.end);
readonly identifier: Pattern<Identifier> = atom(); readonly identifier: Pattern<Identifier> = atom();
get binder(): Pattern<Binder> { return scope(o => bind(o, 'id', this.identifier)); } binder(... _extraStops: Pattern<any>[]): Pattern<Binder> { return scope(o => bind(o, 'id', this.identifier)); }
readonly defaultBinder = this.binder();
expr(... extraStops: Pattern<any>[]): Pattern<Expr> { expr(... extraStops: Pattern<any>[]): Pattern<Expr> {
return withoutSpace(upTo(alt(this.exprBoundary, ... extraStops))); return withoutSpace(upTo(alt(this.exprBoundary, ... extraStops)));
} }
expr1(... extraStops: Pattern<any>[]): Pattern<Expr> {
return mapm(this.expr(... extraStops), e => e.length ? succeed(e) : fail);
}
propertyNameExpr(): Pattern<Expr> { propertyNameExpr(): Pattern<Expr> {
const dq = template`"`; const dq = template`"`;
return alt<Expr>( return alt<Expr>(
@ -229,7 +250,7 @@ export class SyndicateParser {
map(scope( map(scope(
(l: { b: Binder, init: Expr }) => (l: { b: Binder, init: Expr }) =>
seq(kw('let'), seq(kw('let'),
bind(l, 'b', this.binder), bind(l, 'b', this.defaultBinder),
atom('='), atom('='),
bind(l, 'init', this.headerExpr))), bind(l, 'init', this.headerExpr))),
l => { l => {
@ -243,7 +264,7 @@ export class SyndicateParser {
readonly fieldDeclarationStatement: Pattern<FieldDeclarationStatement> = readonly fieldDeclarationStatement: Pattern<FieldDeclarationStatement> =
this.turnAction(o => { this.turnAction(o => {
return seq(atom('field'), return seq(atom('field'),
bind(o, 'field', this.binder), bind(o, 'field', this.defaultBinder),
option(seq(atom('='), bind(o, 'init', this.expr()))), option(seq(atom('='), bind(o, 'init', this.expr()))),
this.statementBoundary); this.statementBoundary);
}); });
@ -271,22 +292,25 @@ export class SyndicateParser {
mandatoryIfNotTerminal(o: GenericEventEndpointStatement, p: Pattern<any>): Pattern<any> { mandatoryIfNotTerminal(o: GenericEventEndpointStatement, p: Pattern<any>): Pattern<any> {
return i => { return i => {
return (o.terminal) ? option(p)(i) : p(i); return (o.facetToStop !== 'none') ? option(p)(i) : p(i);
}; };
} }
// Principal: Turn // Principal: Turn
readonly eventHandlerEndpointStatement: Pattern<EventHandlerEndpointStatement> = readonly eventHandlerEndpointStatement: Pattern<EventHandlerEndpointStatement> =
this.turnAction(o => { this.turnAction(o => {
o.terminal = false; o.facetToStop = 'none';
o.once = false; o.once = false;
o.isDynamic = true; o.isDynamic = true;
o.body = []; 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')), atom('on')),
map(atom('once'), _ => { map(atom('once'), _ => {
o.terminal = true;
o.once = true; o.once = true;
o.facetToStop = 'once-wrapper';
})), })),
alt<any>(seq(map(group('(', bind(o as DataflowEndpointStatement, 'predicate', alt<any>(seq(map(group('(', bind(o as DataflowEndpointStatement, 'predicate',
this.expr())), this.expr())),
@ -294,7 +318,7 @@ export class SyndicateParser {
this.mandatoryIfNotTerminal(o, this.statement(o.body))), this.mandatoryIfNotTerminal(o, this.statement(o.body))),
mapm(seq(bind(o, 'triggerType', atomString('stop')), mapm(seq(bind(o, 'triggerType', atomString('stop')),
option(this.statement(o.body))), option(this.statement(o.body))),
v => o.terminal ? fail : succeed(v)), v => ((o.facetToStop !== 'none') || o.once) ? fail : succeed(v)),
seq(bind(o, 'triggerType', seq(bind(o, 'triggerType',
alt(atomString('asserted'), alt(atomString('asserted'),
atomString('retracted'), atomString('retracted'),
@ -311,7 +335,7 @@ export class SyndicateParser {
scope(o => seq(bind(o, 'expectedUse', alt(atomString('message'), atomString('assertion'))), scope(o => seq(bind(o, 'expectedUse', alt(atomString('message'), atomString('assertion'))),
atom('type'), atom('type'),
bind(o, 'label', this.identifier), 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('='), option(seq(atom('='),
bind(o, 'wireName', withoutSpace(upTo(this.statementBoundary))))), bind(o, 'wireName', withoutSpace(upTo(this.statementBoundary))))),
this.statementBoundary)); this.statementBoundary));
@ -338,12 +362,23 @@ export class SyndicateParser {
// Principal: Turn // Principal: Turn
readonly reactStatement: Pattern<ReactStatement> = readonly reactStatement: Pattern<ReactStatement> =
this.turnAction(o => { this.turnAction(o => {
o.label = null;
o.body = []; 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 // Principal: Turn
readonly stopStatement = this.blockTurnAction(atom('stop')); readonly stopStatement: Pattern<StopStatement> =
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 // Principal: none
readonly atStatement: Pattern<AtStatement> = readonly atStatement: Pattern<AtStatement> =
@ -374,12 +409,22 @@ export class SyndicateParser {
// {expr: expr, ...} - constant // {expr: expr, ...} - constant
// other - constant // other - constant
readonly pCaptureBinder: Pattern<Binder> = pCaptureBinder = (b: Pattern<Binder>): Pattern<Binder> =>
mapm(this.binder, i => { mapm(b, i => {
return i.id.text.startsWith('$') if (i.id.text.startsWith('$')) {
? succeed({ id: { ... i.id, text: i.id.text.slice(1) }, type: i.type }) const adjustedStart: Pos = { ... i.id.start };
: fail; 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<void> = readonly pDiscard: Pattern<void> =
mapm(this.identifier, i => i.text === '_' ? succeed(void 0) : fail); mapm(this.identifier, i => i.text === '_' ? succeed(void 0) : fail);
@ -407,7 +452,7 @@ export class SyndicateParser {
hasCapturesOrDiscards(e: Expr): boolean { hasCapturesOrDiscards(e: Expr): boolean {
return foldItems(e, return foldItems(e,
t => match(alt<any>(this.pCaptureBinder, this.pDiscard), [t], null) !== null, t => match(alt<any>(this.pCaptureDefaultBinder, this.pDiscard), [t], null, '(') !== null,
(_g, b, _k) => b, (_g, b, _k) => b,
bs => bs.some(b => b)); bs => bs.some(b => b));
} }
@ -470,7 +515,7 @@ export class SyndicateParser {
// }); // });
// } else // } else
if (this.hasCapturesOrDiscards(o.ctor)) { 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) { if (r !== null && o.arguments.length === 1) {
return succeed({ return succeed({
type: 'PCapture', type: 'PCapture',
@ -487,7 +532,7 @@ export class SyndicateParser {
scope<PCapture>(o => { scope<PCapture>(o => {
o.type = 'PCapture'; o.type = 'PCapture';
o.inner = { type: 'PDiscard' }; 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 })) map(this.expr(... extraStops), e => ({ type: 'PConstant', value: e }))
)); ));
@ -495,10 +540,10 @@ export class SyndicateParser {
} }
export class SyndicateTypedParser extends SyndicateParser { export class SyndicateTypedParser extends SyndicateParser {
get binder(): Pattern<Binder> { binder(... extraStops: Pattern<any>[]): Pattern<Binder> {
return scope(o => seq(bind(o, 'id', this.identifier), return scope(o => seq(bind(o, 'id', this.identifier),
option(seq(atom(':'), option(seq(atom(':'),
bind(o, 'type', this.type(atom('='))))))); bind(o, 'type', this.type(atom('='), ... extraStops))))));
} }
} }

View File

@ -1,6 +1,6 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
export * as Grammar from './grammar.js'; export * as Grammar from './grammar';
export * as Codegen from './codegen.js'; export * as Codegen from './codegen';
export { compile, CompileOptions } from './codegen.js'; export { compile, CompileOptions } from './codegen';

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
export * as Syntax from './syntax/index.js'; export * as Syntax from './syntax/index';
export * from './compiler/index.js'; export * from './compiler/index';

View File

@ -1,10 +1,10 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Token, TokenType, Item, Items, isGroup } from './tokens.js'; import { Token, TokenType, Item, Items, isGroup } from './tokens';
import { Pos, startPos, advancePos } from './position.js'; import { Pos, startPos, advancePos } from './position';
import { vlqEncode } from './vlq.js'; import { vlqEncode } from './vlq';
import { SpanInfo } from './span.js'; import { SpanInfo } from './span';
export interface SourceMap { export interface SourceMap {
version: 3; version: 3;

View File

@ -1,13 +1,13 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
export * from './codewriter.js'; export * from './codewriter';
export * from './list.js'; export * from './list';
export * from './matcher.js'; export * from './matcher';
export * from './position.js'; export * from './position';
export * from './reader.js'; export * from './reader';
export * from './scanner.js'; export * from './scanner';
export * from './span.js'; export * from './span';
export * from './template.js'; export * from './template';
export * from './tokens.js'; export * from './tokens';
export * from './vlq.js'; export * from './vlq';

View File

@ -1,26 +1,27 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
export interface List<T> extends Iterable<T> { export interface List<T, C> extends Iterable<T> {
item: T | null; item: T | null;
next: List<T> | null; next: List<T, C> | null;
context: C;
toArray(): Array<T>; toArray(): Array<T>;
} }
export function atEnd<T>(xs: List<T>): xs is (List<T> & { item: null, next: null }) { export function atEnd<T, C>(xs: List<T, C>): xs is (List<T, C> & { item: null, next: null }) {
return xs.item === null; return xs.item === null;
} }
export function notAtEnd<T>(xs: List<T>): xs is (List<T> & { item: T, next: List<T> }) { export function notAtEnd<T, C>(xs: List<T, C>): xs is (List<T, C> & { item: T, next: List<T, C> }) {
return xs.item !== null; return xs.item !== null;
} }
export class ArrayList<T> implements List<T> { export class ArrayList<T, C> implements List<T, C> {
readonly items: Array<T>; readonly items: Array<T>;
readonly index: number = 0; readonly index: number = 0;
constructor(items: Array<T>, index = 0) { constructor(items: Array<T>, public context: C, index = 0) {
this.items = items; this.items = items;
this.index = index; this.index = index;
} }
@ -29,9 +30,9 @@ export class ArrayList<T> implements List<T> {
return this.items[this.index] ?? null; return this.items[this.index] ?? null;
} }
get next(): List<T> | null { get next(): List<T, C> | null {
if (this.index >= this.items.length) return 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<T> { toArray(): Array<T> {
@ -39,7 +40,7 @@ export class ArrayList<T> implements List<T> {
} }
[Symbol.iterator](): Iterator<T> { [Symbol.iterator](): Iterator<T> {
let i: List<T> = this; let i: List<T, C> = this;
return { return {
next(): IteratorResult<T> { next(): IteratorResult<T> {
if (notAtEnd(i)) { if (notAtEnd(i)) {

View File

@ -1,34 +1,38 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { import {
Token, TokenType, Items, Item, Token, TokenType, Items, Item,
isGroup, isToken, isSpace, isTokenType, isGroup, isToken, isSpace, isTokenType,
} from './tokens.js'; } from './tokens';
import { Pos, startPos } from './position.js'; import { Pos, startPos } from './position';
import { List, ArrayList, atEnd, notAtEnd } from './list.js'; import { List, ArrayList, atEnd, notAtEnd } from './list';
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Patterns over Item // Patterns over Item
export type PatternResult<T> = [T, List<Item>] | null; export type ItemContext = string /* the opener of the containing group, if any */ | null;
export type Pattern<T> = (i: List<Item>) => PatternResult<T>; export type ItemList = List<Item, ItemContext>;
export type PatternResult<T> = [T, ItemList] | null;
export type Pattern<T> = (i: ItemList) => PatternResult<T>;
export function match<T,F>(p: Pattern<T>, items: Items, failure: F): T | F { export type PatternTypeArg<P> = P extends Pattern<infer T> ? T : never;
const r = p(new ArrayList(items));
export function match<T,F>(p: Pattern<T>, items: Items, failure: F, context: ItemContext): T | F {
const r = p(new ArrayList(items, context));
if (r === null) return failure; if (r === null) return failure;
if (notAtEnd(skipSpace(r[1]))) return failure; if (notAtEnd(skipSpace(r[1]))) return failure;
return r[0]; return r[0];
} }
export const noItems = new ArrayList<Item>([]); export const noItems = (c: ItemContext) => new ArrayList([], c);
export const fail: Pattern<never> = _i => null; export const fail: Pattern<never> = _i => null;
export function succeed<T>(t: T): Pattern<T> { return i => [t, i]; } export function succeed<T>(t: T): Pattern<T> { return i => [t, i]; }
export const discard: Pattern<void> = _i => [void 0, noItems]; export const discard: Pattern<void> = i => [void 0, noItems(i.context)];
export const rest: Pattern<Items> = i => [i.toArray(), noItems]; export const rest: Pattern<Items> = i => [i.toArray(), noItems(i.context)];
export const end: Pattern<void> = i => atEnd(skipSpace(i)) ? [void 0, noItems] : null; export const end: Pattern<void> = i => atEnd(skipSpace(i)) ? [void 0, noItems(i.context)] : null;
export const pos: Pattern<Pos> = i => notAtEnd(i) ? [i.item.start, i] : null; export const pos: Pattern<Pos> = i => notAtEnd(i) ? [i.item.start, i] : null;
export const newline: Pattern<Item> = i => { export const newline: Pattern<Item> = i => {
@ -37,12 +41,12 @@ export const newline: Pattern<Item> = i => {
return [i.item, i.next]; return [i.item, i.next];
}; };
export function skipSpace(i: List<Item>): List<Item> { export function skipSpace(i: ItemList): ItemList {
while (notAtEnd(i) && isSpace(i.item)) i = i.next; while (notAtEnd(i) && isSpace(i.item)) i = i.next;
return i; return i;
} }
export function collectSpace(i: List<Item>, acc: Array<Item>): List<Item> { export function collectSpace(i: ItemList, acc: Array<Item>): ItemList {
while (notAtEnd(i) && isSpace(i.item)) { while (notAtEnd(i) && isSpace(i.item)) {
acc.push(i.item); acc.push(i.item);
i = i.next; i = i.next;
@ -78,6 +82,22 @@ export function seq(... patterns: Pattern<any>[]): Pattern<any> {
}; };
} }
export function seqTuple<Patterns extends [...Pattern<any>[]]>(
... patterns: Patterns
): Pattern<{ [I in keyof Patterns]: PatternTypeArg<Patterns[I]> } & { 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<ReturnType<typeof seqTuple<Patterns>>>, i];
};
}
export function alt<T>(... alts: Pattern<T>[]): Pattern<T> { export function alt<T>(... alts: Pattern<T>[]): Pattern<T> {
return i => { return i => {
for (const a of alts) { for (const a of alts) {
@ -115,7 +135,7 @@ export function bind<T, K extends keyof T>(target: T, key: K, pattern: Pattern<T
}; };
} }
export function exec(thunk: (i: List<Item>) => void): Pattern<void> { export function exec(thunk: (i: ItemList) => void): Pattern<void> {
return i => { return i => {
thunk(i); thunk(i);
return [void 0, i]; return [void 0, i];
@ -156,7 +176,7 @@ export function group<T>(opener: string, items: Pattern<T>, options: GroupOption
if (!notAtEnd(i)) return null; if (!notAtEnd(i)) return null;
if (!isGroup(i.item)) return null; if (!isGroup(i.item)) return null;
if (i.item.open.text !== opener) 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 (r === null) return null;
if (!atEnd(r[1])) return null; if (!atEnd(r[1])) return null;
return [r[0], (options.advance ?? true) ? i.next : i]; return [r[0], (options.advance ?? true) ? i.next : i];
@ -203,7 +223,7 @@ export function upTo(p: Pattern<any>): Pattern<Items> {
export function separatedBy<T>(itemPattern: Pattern<T>, separator: Pattern<any>): Pattern<T[]> { export function separatedBy<T>(itemPattern: Pattern<T>, separator: Pattern<any>): Pattern<T[]> {
return i => { return i => {
const acc: T[] = []; const acc: T[] = [];
if (end(i) !== null) return [acc, noItems]; if (end(i) !== null) return [acc, noItems(i.context)];
while (true) { while (true) {
{ {
const r = itemPattern(i); const r = itemPattern(i);
@ -214,7 +234,7 @@ export function separatedBy<T>(itemPattern: Pattern<T>, separator: Pattern<any>)
{ {
const r = separator(i); const r = separator(i);
if (r === null) { if (r === null) {
if (end(i) !== null) return [acc, noItems]; if (end(i) !== null) return [acc, noItems(i.context)];
return null; return null;
} }
i = r[1]; i = r[1];
@ -229,7 +249,7 @@ export function separatedOrTerminatedBy<T>(
): Pattern<T[]> { ): Pattern<T[]> {
return i => { return i => {
const acc: T[] = []; const acc: T[] = [];
if (end(i) !== null) return [acc, noItems]; if (end(i) !== null) return [acc, noItems(i.context)];
while (true) { while (true) {
{ {
const r = itemPattern(i); const r = itemPattern(i);
@ -240,11 +260,11 @@ export function separatedOrTerminatedBy<T>(
{ {
const r = separator(i); const r = separator(i);
if (r === null) { if (r === null) {
if (end(i) !== null) return [acc, noItems]; if (end(i) !== null) return [acc, noItems(i.context)];
return null; return null;
} else { } else {
i = r[1]; 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<T>(p: Pattern<T>): Pattern<T[]> {
export function replace<T>( export function replace<T>(
items: Items, items: Items,
outerContext: ItemContext,
p: Pattern<T>, p: Pattern<T>,
f: (t: T, start: Pos, end: Pos) => Items, f: (t: T, start: Pos, end: Pos) => Items,
end: Pos = items.length > 0 ? items[items.length - 1].end : startPos(null)) : Items end: Pos = items.length > 0 ? items[items.length - 1].end : startPos(null),
{ ) : Items {
const walkItems = (items: Items, end: Pos): Items => { const walkItems = (items: Items, end: Pos, context: ItemContext): Items => {
let i: List<Item> = new ArrayList(items); let i: ItemList = new ArrayList(items, context);
const acc: Items = []; const acc: Items = [];
while (notAtEnd(i = collectSpace(i, acc))) { while (notAtEnd(i = collectSpace(i, acc))) {
const r = p(i); const r = p(i);
@ -309,11 +330,14 @@ export function replace<T>(
acc.push(i.item); acc.push(i.item);
i = i.next; i = i.next;
} else { } 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; i = i.next;
} }
} }
return acc; return acc;
}; };
return walkItems(items, end); return walkItems(items, end, outerContext);
} }

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
export interface Pos { export interface Pos {
line: number; line: number;

View File

@ -1,9 +1,9 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { TokenType, Token, Group, GroupInProgress, Item, Items, finishGroup } from './tokens.js'; import { TokenType, Token, Group, GroupInProgress, Item, Items, finishGroup } from './tokens';
import { Pos, startPos } from './position.js'; import { Pos, startPos } from './position';
import { Scanner, StringScanner } from './scanner.js'; import { Scanner, StringScanner } from './scanner';
function matchingParen(c: string): string | null { function matchingParen(c: string): string | null {
switch (c) { switch (c) {
@ -134,23 +134,10 @@ export class LaxReader implements IterableIterator<Item> {
case TokenType.SPACE: case TokenType.SPACE:
case TokenType.NEWLINE: case TokenType.NEWLINE:
case TokenType.ATOM: case TokenType.ATOM:
this.drop();
if (g === null) { if (g === null) {
this.drop();
return t; 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); g.items.push(t);
break; break;

View File

@ -1,8 +1,8 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { TokenType, Token, Item, GroupInProgress } from './tokens.js'; import { TokenType, Token, Item, GroupInProgress } from './tokens';
import { Pos, advancePos } from './position.js'; import { Pos, advancePos } from './position';
export abstract class Scanner implements IterableIterator<Token> { export abstract class Scanner implements IterableIterator<Token> {
readonly pos: Pos; readonly pos: Pos;

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
export class SpanResult<T> { export class SpanResult<T> {
readonly searchTarget: number; readonly searchTarget: number;

View File

@ -1,10 +1,10 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Items } from './tokens.js'; import { Items } from './tokens';
import { Pos, startPos } from './position.js'; import { Pos, startPos } from './position';
import { laxRead, LaxReadOptions } from './reader.js'; import { laxRead, LaxReadOptions } from './reader';
import * as M from './matcher.js'; import * as M from './matcher';
const substPat = M.scope((o: { pos: Pos }) => const substPat = M.scope((o: { pos: Pos }) =>
M.seq(M.atom('$'), M.seq(M.atom('$'),
@ -29,7 +29,7 @@ export class Templates {
this.readOptions = readOptions; 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; const start = (typeof start0 === 'string') ? startPos(start0) : start0;
return (consts, ... vars) => { return (consts, ... vars) => {
const sourcePieces = [consts[0]]; const sourcePieces = [consts[0]];
@ -53,6 +53,7 @@ export class Templates {
(this.readOptions.extraDelimiters ?? '') + '$', (this.readOptions.extraDelimiters ?? '') + '$',
synthetic: true, synthetic: true,
}), }),
context,
substPat, substPat,
sub => toItems(this.readOptions, vars[i++], sub.pos)); sub => toItems(this.readOptions, vars[i++], sub.pos));
}; };

View File

@ -1,7 +1,7 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Pos } from './position.js'; import { Pos } from './position';
export enum TokenType { export enum TokenType {
SPACE, SPACE,

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const inverse_alphabet = const inverse_alphabet =

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2023-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
const __SYNDICATE__ = Syndicate; const __SYNDICATE__ = Syndicate;
const currentSyndicateTarget = Syndicate.Dataspace.global; 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 sourceCode = sourceUrl ? await (await fetch(sourceUrl)).text() : script.innerHTML;
const compilationResult = SyndicateCompiler.compile({ const compilationResult = SyndicateCompiler.compile({
name: sourceUrl || 'anonymous-script-tag', name: sourceUrl || script.id || 'anonymous-script-tag',
source: sourceCode, source: sourceCode,
module: isModule ? 'es6' : 'none', module: isModule ? 'es6' : 'none',
runtime: isModule ? void 0 : 'Syndicate', runtime: isModule ? void 0 : 'Syndicate',

View File

@ -0,0 +1,213 @@
/// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
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<CompileOptions> = {}): { 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<CompileOptions>): string {
const o = translate(source, options);
expect(o.errors.length).toBe(0);
return o.code;
}
function expectCodeEqual(input: string, output: string, options?: Partial<CompileOptions>) {
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;})
}
}
}),
}),
}));
});`));
});

View File

@ -0,0 +1,30 @@
/// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
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', '']);
});
});

View File

@ -0,0 +1,38 @@
/// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { is, preserves } from '@preserves/core';
declare global {
namespace jest {
interface Matchers<R> {
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 };
}
}
}
});

View File

@ -1,6 +1,6 @@
#!/usr/bin/env node #!/usr/bin/env node
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { import {
Pattern as P, Pattern as P,

View File

@ -1,6 +1,6 @@
#!/usr/bin/env -S npx ts-node -O '{"module": "commonjs"}' #!/usr/bin/env -S npx ts-node -O '{"module": "commonjs"}'
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { import {
Pattern as P, Pattern as P,

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
export default { export default {
preset: 'ts-jest', preset: 'ts-jest',

View File

@ -5,10 +5,10 @@ ActionDescription =
/ @spawnActor <spawn-actor @detail OptionalAny @initialAssertions #{protocol.Handle}> / @spawnActor <spawn-actor @detail OptionalAny @initialAssertions #{protocol.Handle}>
/ @stopActor <stop-actor @error OptionalAny> / @stopActor <stop-actor @error OptionalAny>
/ @inertCheck <inert-check> / @inertCheck <inert-check>
/ <assert @target #!any @crossSpace bool @handle protocol.Handle @assertion any> / <assert @target #:any @crossSpace bool @handle protocol.Handle @assertion any>
/ <retract @target #!any @crossSpace bool @handle protocol.Handle> / <retract @target #:any @crossSpace bool @handle protocol.Handle>
/ <message @target #!any @assertion any> / <message @target #:any @assertion any>
/ <sync @target #!any @callback #!any> / <sync @target #:any @callback #:any>
. .
OptionalAny = <none> / <some @value any> . OptionalAny = <none> / <some @value any> .

View File

@ -1,6 +1,6 @@
{ {
"name": "@syndicate-lang/core", "name": "@syndicate-lang/core",
"version": "0.23.0", "version": "0.32.0",
"description": "Syndicate/JS for browser and node.js", "description": "Syndicate/JS for browser and node.js",
"homepage": "https://github.com/syndicate-lang/syndicate-js/tree/main/packages/core", "homepage": "https://github.com/syndicate-lang/syndicate-js/tree/main/packages/core",
"license": "GPL-3.0+", "license": "GPL-3.0+",
@ -21,7 +21,7 @@
"rollup:watch": "../../node_modules/.bin/rollup -c -w", "rollup:watch": "../../node_modules/.bin/rollup -c -w",
"test": "../../node_modules/.bin/jest", "test": "../../node_modules/.bin/jest",
"cover": "../../node_modules/.bin/nyc --reporter=html ../../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" "veryclean": "yarn run clean && rm -rf node_modules"
}, },
"main": "dist/syndicate.js", "main": "dist/syndicate.js",
@ -29,11 +29,11 @@
"types": "lib/index.d.ts", "types": "lib/index.d.ts",
"author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>", "author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>",
"devDependencies": { "devDependencies": {
"@preserves/core": "0.992.4", "@preserves/core": "0.995.200",
"@preserves/schema-cli": "0.992.5" "@preserves/schema-cli": "0.995.201"
}, },
"peerDependencies": { "peerDependencies": {
"@preserves/core": "0.992.4" "@preserves/core": "0.995.200"
}, },
"dependencies": { "dependencies": {
"salty-crypto": "0.3.1" "salty-crypto": "0.3.1"

View File

@ -2,15 +2,15 @@
tcp-remote„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³ SignedInteger„„„„„³ TcpPeerInfo´³rec´³lit³tcp-peer„´³tupleµ´³named³handle´³embedded³any„„´³named³local´³refµ„³TcpLocal„„´³named³remote´³refµ„³ TcpRemote„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³http„´³schema·³version°³ definitions·³Chunk´³orµµ±string´³atom³String„„µ±bytes´³atom³ tcp-remote„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³ SignedInteger„„„„„³ TcpPeerInfo´³rec´³lit³tcp-peer„´³tupleµ´³named³handle´³embedded³any„„´³named³local´³refµ„³TcpLocal„„´³named³remote´³refµ„³ TcpRemote„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³http„´³schema·³version°³ definitions·³Chunk´³orµµ±string´³atom³String„„µ±bytes´³atom³
ByteString„„„„³Headers´³dictof´³atom³Symbol„´³atom³String„„³MimeType´³atom³Symbol„³ ByteString„„„„³Headers´³dictof´³atom³Symbol„´³atom³String„„³MimeType´³atom³Symbol„³
QueryValue´³orµµ±string´³atom³String„„µ±file´³rec´³lit³file„´³tupleµ´³named³filename´³atom³String„„´³named³headers´³refµ„³Headers„„´³named³body´³atom³ QueryValue´³orµµ±string´³atom³String„„µ±file´³rec´³lit³file„´³tupleµ´³named³filename´³atom³String„„´³named³headers´³refµ„³Headers„„´³named³body´³atom³
ByteString„„„„„„„„³ HostPattern´³orµµ±host´³atom³String„„µ±any´³lit€„„„„³ HttpBinding´³rec´³lit³ http-bind„´³tupleµ´³named³host´³refµ„³ HostPattern„„´³named³port´³atom³ SignedInteger„„´³named³method´³refµ„³ MethodPattern„„´³named³path´³refµ„³ PathPattern„„´³named³handler´³embedded´³refµ„³ HttpRequest„„„„„„³ HttpContext´³rec´³lit³request„´³tupleµ´³named³req´³refµ„³ HttpRequest„„´³named³res´³embedded´³refµ„³ HttpResponse„„„„„„³ HttpRequest´³rec´³lit³ http-request„´³tupleµ´³named³sequenceNumber´³atom³ SignedInteger„„´³named³host´³atom³String„„´³named³port´³atom³ SignedInteger„„´³named³method´³atom³Symbol„„´³named³path´³seqof´³atom³String„„„´³named³headers´³refµ„³Headers„„´³named³query´³dictof´³atom³Symbol„´³seqof´³refµ„³ ByteString„„„„„„„„³ HostPattern´³orµµ±host´³atom³String„„µ±any´³lit€„„„„³ HttpBinding´³rec´³lit³ http-bind„´³tupleµ´³named³host´³refµ„³ HostPattern„„´³named³port´³atom³ SignedInteger„„´³named³method´³refµ„³ MethodPattern„„´³named³path´³refµ„³ PathPattern„„´³named³handler´³embedded´³refµ„³ HttpRequest„„„„„„³ HttpContext´³rec´³lit³request„´³tupleµ´³named³req´³refµ„³ HttpRequest„„´³named³res´³embedded´³refµ„³ HttpResponse„„„„„„³ HttpRequest´³rec´³lit³ http-request„´³tupleµ´³named³sequenceNumber´³atom³ SignedInteger„„´³named³host´³refµ„³ RequestHost„„´³named³port´³atom³ SignedInteger„„´³named³method´³atom³Symbol„„´³named³path´³seqof´³atom³String„„„´³named³headers´³refµ„³Headers„„´³named³query´³dictof´³atom³Symbol„´³seqof´³refµ„³
QueryValue„„„„´³named³body´³refµ„³ RequestBody„„„„„³ HttpService´³rec´³lit³ http-service„´³tupleµ´³named³host´³refµ„³ HostPattern„„´³named³port´³atom³ SignedInteger„„´³named³method´³refµ„³ MethodPattern„„´³named³path´³refµ„³ PathPattern„„„„„³ PathPattern´³seqof´³refµ„³PathPatternElement„„³ RequestBody´³orµµ±present´³atom³ QueryValue„„„„´³named³body´³refµ„³ RequestBody„„„„„³ HttpService´³rec´³lit³ http-service„´³tupleµ´³named³host´³refµ„³ HostPattern„„´³named³port´³atom³ SignedInteger„„´³named³method´³refµ„³ MethodPattern„„´³named³path´³refµ„³ PathPattern„„„„„³ PathPattern´³seqof´³refµ„³PathPatternElement„„³ RequestBody´³orµµ±present´³atom³
ByteString„„µ±absent´³lit€„„„„³ HttpListener´³rec´³lit³ http-listener„´³tupleµ´³named³port´³atom³ SignedInteger„„„„„³ HttpResponse´³orµµ±status´³rec´³lit³status„´³tupleµ´³named³code´³atom³ SignedInteger„„´³named³message´³atom³String„„„„„„µ±header´³rec´³lit³header„´³tupleµ´³named³name´³atom³Symbol„„´³named³value´³atom³String„„„„„„µ±chunk´³rec´³lit³chunk„´³tupleµ´³named³chunk´³refµ„³Chunk„„„„„„µ±done´³rec´³lit³done„´³tupleµ´³named³chunk´³refµ„³Chunk„„„„„„„„³ MethodPattern´³orµµ±any´³lit€„„µ±specific´³atom³Symbol„„„„³PathPatternElement´³orµµ±label´³atom³String„„µ±wildcard´³lit³_„„µ±rest´³lit³...„„„„„³ embeddedType€„„µ³noise„´³schema·³version°³ definitions·³Packet´³orµµ±complete´³atom³ ByteString„„µ±absent´³lit€„„„„³ RequestHost´³orµµ±present´³atom³String„„µ±absent´³lit€„„„„³ HttpListener´³rec´³lit³ http-listener„´³tupleµ´³named³port´³atom³ SignedInteger„„„„„³ HttpResponse´³orµµ±status´³rec´³lit³status„´³tupleµ´³named³code´³atom³ SignedInteger„„´³named³message´³atom³String„„„„„„µ±header´³rec´³lit³header„´³tupleµ´³named³name´³atom³Symbol„„´³named³value´³atom³String„„„„„„µ±chunk´³rec´³lit³chunk„´³tupleµ´³named³chunk´³refµ„³Chunk„„„„„„µ±done´³rec´³lit³done„´³tupleµ´³named³chunk´³refµ„³Chunk„„„„„„„„³ MethodPattern´³orµµ±any´³lit€„„µ±specific´³atom³Symbol„„„„³PathPatternElement´³orµµ±label´³atom³String„„µ±wildcard´³lit³_„„µ±rest´³lit³...„„„„„³ embeddedType€„„µ³noise„´³schema·³version°³ definitions·³Packet´³orµµ±complete´³atom³
ByteString„„µ± ByteString„„µ±
fragmented´³seqof´³atom³ fragmented´³seqof´³atom³
ByteString„„„„„³ NoiseSpec´³andµ´³dict·³key´³named³key´³atom³ ByteString„„„„„³ Initiator´³rec´³lit³ initiator„´³tupleµ´³named³initiatorSession´³embedded´³refµ„³Packet„„„„„„³ NoiseSpec´³andµ´³dict·³key´³named³key´³atom³
ByteString„„³service´³named³service´³refµ„³ServiceSelector„„„„´³named³protocol´³refµ„³ NoiseProtocol„„´³named³ preSharedKeys´³refµ„³NoisePreSharedKeys„„„„³ NoiseProtocol´³orµµ±present´³dict·³protocol´³named³protocol´³atom³String„„„„„µ±invalid´³dict·³protocol´³named³protocol³any„„„„µ±absent´³dict·„„„„„³ NoiseStepType´³lit³noise„³SecretKeyField´³orµµ±present´³dict·³ secretKey´³named³ secretKey´³atom³ ByteString„„³service´³named³service´³refµ„³ServiceSelector„„„„´³named³protocol´³refµ„³ NoiseProtocol„„´³named³ preSharedKeys´³refµ„³NoisePreSharedKeys„„„„³ SessionItem´³orµµ± Initiator´³refµ„³ Initiator„„µ±Packet´³refµ„³Packet„„„„³ NoiseProtocol´³orµµ±present´³dict·³protocol´³named³protocol´³atom³String„„„„„µ±invalid´³dict·³protocol´³named³protocol³any„„„„µ±absent´³dict·„„„„„³ NoiseStepType´³lit³noise„³SecretKeyField´³orµµ±present´³dict·³ secretKey´³named³ secretKey´³atom³
ByteString„„„„„µ±invalid´³dict·³ secretKey´³named³ secretKey³any„„„„µ±absent´³dict·„„„„„³DefaultProtocol´³lit±!Noise_NK_25519_ChaChaPoly_BLAKE2s„³NoiseStepDetail´³refµ„³ServiceSelector„³ServiceSelector³any³NoiseServiceSpec´³andµ´³named³base´³refµ„³ NoiseSpec„„´³named³ secretKey´³refµ„³SecretKeyField„„„„³NoisePreSharedKeys´³orµµ±present´³dict·³ preSharedKeys´³named³ preSharedKeys´³seqof´³atom³ ByteString„„„„„µ±invalid´³dict·³ secretKey´³named³ secretKey³any„„„„µ±absent´³dict·„„„„„³DefaultProtocol´³lit±!Noise_NK_25519_ChaChaPoly_BLAKE2s„³NoiseStepDetail´³refµ„³ServiceSelector„³ServiceSelector³any³NoiseServiceSpec´³andµ´³named³base´³refµ„³ NoiseSpec„„´³named³ secretKey´³refµ„³SecretKeyField„„„„³NoisePreSharedKeys´³orµµ±present´³dict·³ preSharedKeys´³named³ preSharedKeys´³seqof´³atom³
ByteString„„„„„„µ±invalid´³dict·³ preSharedKeys´³named³ preSharedKeys³any„„„„µ±absent´³dict·„„„„„³NoisePathStepDetail´³refµ„³ NoiseSpec„³NoiseDescriptionDetail´³refµ„³NoiseServiceSpec„„³ embeddedType„„µ³timer„´³schema·³version°³ definitions·³SetTimer´³rec´³lit³ set-timer„´³tupleµ´³named³label³any„´³named³seconds´³atom³Double„„´³named³kind´³refµ„³ TimerKind„„„„„³ LaterThan´³rec´³lit³ ByteString„„„„„„µ±invalid´³dict·³ preSharedKeys´³named³ preSharedKeys³any„„„„µ±absent´³dict·„„„„„³NoisePathStepDetail´³refµ„³ NoiseSpec„³NoiseDescriptionDetail´³refµ„³NoiseServiceSpec„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³timer„´³schema·³version°³ definitions·³SetTimer´³rec´³lit³ set-timer„´³tupleµ´³named³label³any„´³named³seconds´³atom³Double„„´³named³kind´³refµ„³ TimerKind„„„„„³ LaterThan´³rec´³lit³
later-than„´³tupleµ´³named³seconds´³atom³Double„„„„„³ TimerKind´³orµµ±relative´³lit³relative„„µ±absolute´³lit³absolute„„µ±clear´³lit³clear„„„„³ TimerExpired´³rec´³lit³ timer-expired„´³tupleµ´³named³label³any„´³named³seconds´³atom³Double„„„„„„³ embeddedType€„„µ³trace„´³schema·³version°³ definitions·³Oid³any³Name´³orµµ± anonymous´³rec´³lit³ anonymous„´³tupleµ„„„„µ±named´³rec´³lit³named„´³tupleµ´³named³name³any„„„„„„„³Target´³rec´³lit³entity„´³tupleµ´³named³actor´³refµ„³ActorId„„´³named³facet´³refµ„³FacetId„„´³named³oid´³refµ„³Oid„„„„„³TaskId³any³TurnId³any³ActorId³any³FacetId³any³ TurnCause´³orµµ±turn´³rec´³lit³ caused-by„´³tupleµ´³named³id´³refµ„³TurnId„„„„„„µ±cleanup´³rec´³lit³cleanup„´³tupleµ„„„„µ±linkedTaskRelease´³rec´³lit³linked-task-release„´³tupleµ´³named³id´³refµ„³TaskId„„´³named³reason´³refµ„³LinkedTaskReleaseReason„„„„„„µ±periodicActivation´³rec´³lit³periodic-activation„´³tupleµ´³named³period´³atom³Double„„„„„„µ±delay´³rec´³lit³delay„´³tupleµ´³named³ causingTurn´³refµ„³TurnId„„´³named³amount´³atom³Double„„„„„„µ±external´³rec´³lit³external„´³tupleµ´³named³ description³any„„„„„„„³ TurnEvent´³orµµ±assert´³rec´³lit³assert„´³tupleµ´³named³ assertion´³refµ„³AssertionDescription„„´³named³handle´³refµ³protocol„³Handle„„„„„„µ±retract´³rec´³lit³retract„´³tupleµ´³named³handle´³refµ³protocol„³Handle„„„„„„µ±message´³rec´³lit³message„´³tupleµ´³named³body´³refµ„³AssertionDescription„„„„„„µ±sync´³rec´³lit³sync„´³tupleµ´³named³peer´³refµ„³Target„„„„„„µ± breakLink´³rec´³lit³ later-than„´³tupleµ´³named³seconds´³atom³Double„„„„„³ TimerKind´³orµµ±relative´³lit³relative„„µ±absolute´³lit³absolute„„µ±clear´³lit³clear„„„„³ TimerExpired´³rec´³lit³ timer-expired„´³tupleµ´³named³label³any„´³named³seconds´³atom³Double„„„„„„³ embeddedType€„„µ³trace„´³schema·³version°³ definitions·³Oid³any³Name´³orµµ± anonymous´³rec´³lit³ anonymous„´³tupleµ„„„„µ±named´³rec´³lit³named„´³tupleµ´³named³name³any„„„„„„„³Target´³rec´³lit³entity„´³tupleµ´³named³actor´³refµ„³ActorId„„´³named³facet´³refµ„³FacetId„„´³named³oid´³refµ„³Oid„„„„„³TaskId³any³TurnId³any³ActorId³any³FacetId³any³ TurnCause´³orµµ±turn´³rec´³lit³ caused-by„´³tupleµ´³named³id´³refµ„³TurnId„„„„„„µ±cleanup´³rec´³lit³cleanup„´³tupleµ„„„„µ±linkedTaskRelease´³rec´³lit³linked-task-release„´³tupleµ´³named³id´³refµ„³TaskId„„´³named³reason´³refµ„³LinkedTaskReleaseReason„„„„„„µ±periodicActivation´³rec´³lit³periodic-activation„´³tupleµ´³named³period´³atom³Double„„„„„„µ±delay´³rec´³lit³delay„´³tupleµ´³named³ causingTurn´³refµ„³TurnId„„´³named³amount´³atom³Double„„„„„„µ±external´³rec´³lit³external„´³tupleµ´³named³ description³any„„„„„„„³ TurnEvent´³orµµ±assert´³rec´³lit³assert„´³tupleµ´³named³ assertion´³refµ„³AssertionDescription„„´³named³handle´³refµ³protocol„³Handle„„„„„„µ±retract´³rec´³lit³retract„´³tupleµ´³named³handle´³refµ³protocol„³Handle„„„„„„µ±message´³rec´³lit³message„´³tupleµ´³named³body´³refµ„³AssertionDescription„„„„„„µ±sync´³rec´³lit³sync„´³tupleµ´³named³peer´³refµ„³Target„„„„„„µ± breakLink´³rec´³lit³
break-link„´³tupleµ´³named³source´³refµ„³ActorId„„´³named³handle´³refµ³protocol„³Handle„„„„„„„„³ break-link„´³tupleµ´³named³source´³refµ„³ActorId„„´³named³handle´³refµ³protocol„³Handle„„„„„„„„³
ExitStatus´³orµµ±ok´³lit³ok„„µ±Error´³refµ³protocol„³Error„„„„³ ExitStatus´³orµµ±ok´³lit³ok„„µ±Error´³refµ³protocol„³Error„„„„³
@ -24,7 +24,7 @@ ByteString
ByteString„„´³named³oid³any„„´³named³caveats´³seqof´³refµ³sturdy„³Caveat„„„„„µ±general´³refµ³ ByteString„„´³named³oid³any„„´³named³caveats´³seqof´³refµ³sturdy„³Caveat„„„„„µ±general´³refµ³
gatekeeper„³Route„„„„³StandardTransport´³orµµ±wsUrl´³atom³String„„µ±other³any„„„„³ embeddedType€„„µ³stream„´³schema·³version°³ definitions·³Mode´³orµµ±bytes´³lit³bytes„„µ±lines´³refµ„³LineMode„„µ±packet´³rec´³lit³packet„´³tupleµ´³named³size´³atom³ SignedInteger„„„„„„µ±object´³rec´³lit³object„´³tupleµ´³named³ description³any„„„„„„„³Sink´³orµµ±source´³rec´³lit³source„´³tupleµ´³named³ gatekeeper„³Route„„„„³StandardTransport´³orµµ±wsUrl´³atom³String„„µ±other³any„„„„³ embeddedType€„„µ³stream„´³schema·³version°³ definitions·³Mode´³orµµ±bytes´³lit³bytes„„µ±lines´³refµ„³LineMode„„µ±packet´³rec´³lit³packet„´³tupleµ´³named³size´³atom³ SignedInteger„„„„„„µ±object´³rec´³lit³object„´³tupleµ´³named³ description³any„„„„„„„³Sink´³orµµ±source´³rec´³lit³source„´³tupleµ´³named³
controller´³embedded´³refµ„³Source„„„„„„„µ± StreamError´³refµ„³ StreamError„„µ±data´³rec´³lit³data„´³tupleµ´³named³payload³any„´³named³mode´³refµ„³Mode„„„„„„µ±eof´³rec´³lit³eof„´³tupleµ„„„„„„³Source´³orµµ±sink´³rec´³lit³sink„´³tupleµ´³named³ controller´³embedded´³refµ„³Source„„„„„„„µ± StreamError´³refµ„³ StreamError„„µ±data´³rec´³lit³data„´³tupleµ´³named³payload³any„´³named³mode´³refµ„³Mode„„„„„„µ±eof´³rec´³lit³eof„´³tupleµ„„„„„„³Source´³orµµ±sink´³rec´³lit³sink„´³tupleµ´³named³
controller´³embedded´³refµ„³Sink„„„„„„„µ± StreamError´³refµ„³ StreamError„„µ±credit´³rec´³lit³credit„´³tupleµ´³named³amount´³refµ„³ CreditAmount„„´³named³mode´³refµ„³Mode„„„„„„„„³LineMode´³orµµ±lf´³lit³lf„„µ±crlf´³lit³crlf„„„„³ StreamError´³rec´³lit³error„´³tupleµ´³named³message´³atom³String„„„„„³ CreditAmount´³orµµ±count´³atom³ SignedInteger„„µ± unbounded´³lit³ unbounded„„„„³StreamConnection´³rec´³lit³stream-connection„´³tupleµ´³named³source´³embedded´³refµ„³Source„„„´³named³sink´³embedded´³refµ„³Sink„„„´³named³spec³any„„„„³StreamListenerError´³rec´³lit³stream-listener-error„´³tupleµ´³named³spec³any„´³named³message´³atom³String„„„„„³StreamListenerReady´³rec´³lit³stream-listener-ready„´³tupleµ´³named³spec³any„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³sturdy„´³schema·³version°³ definitions·³Lit´³rec´³lit³lit„´³tupleµ´³named³value³any„„„„³Oid´³atom³ SignedInteger„³Alts´³rec´³lit³or„´³tupleµ´³named³ alternatives´³seqof´³refµ„³Rewrite„„„„„„³PAnd´³rec´³lit³and„´³tupleµ´³named³patterns´³seqof´³refµ„³Pattern„„„„„„³PNot´³rec´³lit³not„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„³TRef´³rec´³lit³ref„´³tupleµ´³named³binding´³atom³ SignedInteger„„„„„³PAtom´³orµµ±Boolean´³lit³Boolean„„µ±Float´³lit³Float„„µ±Double´³lit³Double„„µ± SignedInteger´³lit³ SignedInteger„„µ±String´³lit³String„„µ± controller´³embedded´³refµ„³Sink„„„„„„„µ± StreamError´³refµ„³ StreamError„„µ±credit´³rec´³lit³credit„´³tupleµ´³named³amount´³refµ„³ CreditAmount„„´³named³mode´³refµ„³Mode„„„„„„„„³LineMode´³orµµ±lf´³lit³lf„„µ±crlf´³lit³crlf„„„„³ StreamError´³rec´³lit³error„´³tupleµ´³named³message´³atom³String„„„„„³ CreditAmount´³orµµ±count´³atom³ SignedInteger„„µ± unbounded´³lit³ unbounded„„„„³StreamConnection´³rec´³lit³stream-connection„´³tupleµ´³named³source´³embedded´³refµ„³Source„„„´³named³sink´³embedded´³refµ„³Sink„„„´³named³spec³any„„„„³StreamListenerError´³rec´³lit³stream-listener-error„´³tupleµ´³named³spec³any„´³named³message´³atom³String„„„„„³StreamListenerReady´³rec´³lit³stream-listener-ready„´³tupleµ´³named³spec³any„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³sturdy„´³schema·³version°³ definitions·³Lit´³rec´³lit³lit„´³tupleµ´³named³value³any„„„„³Oid´³atom³ SignedInteger„³Alts´³rec´³lit³or„´³tupleµ´³named³ alternatives´³seqof´³refµ„³Rewrite„„„„„„³PAnd´³rec´³lit³and„´³tupleµ´³named³patterns´³seqof´³refµ„³Pattern„„„„„„³PNot´³rec´³lit³not„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„³TRef´³rec´³lit³ref„´³tupleµ´³named³binding´³atom³ SignedInteger„„„„„³PAtom´³orµµ±Boolean´³lit³Boolean„„µ±Double´³lit³Double„„µ± SignedInteger´³lit³ SignedInteger„„µ±String´³lit³String„„µ±
ByteString´³lit³ ByteString´³lit³
ByteString„„µ±Symbol´³lit³Symbol„„„„³PBind´³rec´³lit³bind„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„³Caveat´³orµµ±Rewrite´³refµ„³Rewrite„„µ±Alts´³refµ„³Alts„„µ±Reject´³refµ„³Reject„„µ±unknown³any„„„³Reject´³rec´³lit³reject„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„³Pattern´³orµµ±PDiscard´³refµ„³PDiscard„„µ±PAtom´³refµ„³PAtom„„µ± PEmbedded´³refµ„³ PEmbedded„„µ±PBind´³refµ„³PBind„„µ±PAnd´³refµ„³PAnd„„µ±PNot´³refµ„³PNot„„µ±Lit´³refµ„³Lit„„µ± PCompound´³refµ„³ PCompound„„„„³Rewrite´³rec´³lit³rewrite„´³tupleµ´³named³pattern´³refµ„³Pattern„„´³named³template´³refµ„³Template„„„„„³WireRef´³orµµ±mine´³tupleµ´³lit°„´³named³oid´³refµ„³Oid„„„„„µ±yours´³ tuplePrefixµ´³lit°„´³named³oid´³refµ„³Oid„„„´³named³ attenuation´³seqof´³refµ„³Caveat„„„„„„„³PDiscard´³rec´³lit³_„´³tupleµ„„„³Template´³orµµ± ByteString„„µ±Symbol´³lit³Symbol„„„„³PBind´³rec´³lit³bind„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„³Caveat´³orµµ±Rewrite´³refµ„³Rewrite„„µ±Alts´³refµ„³Alts„„µ±Reject´³refµ„³Reject„„µ±unknown³any„„„³Reject´³rec´³lit³reject„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„³Pattern´³orµµ±PDiscard´³refµ„³PDiscard„„µ±PAtom´³refµ„³PAtom„„µ± PEmbedded´³refµ„³ PEmbedded„„µ±PBind´³refµ„³PBind„„µ±PAnd´³refµ„³PAnd„„µ±PNot´³refµ„³PNot„„µ±Lit´³refµ„³Lit„„µ± PCompound´³refµ„³ PCompound„„„„³Rewrite´³rec´³lit³rewrite„´³tupleµ´³named³pattern´³refµ„³Pattern„„´³named³template´³refµ„³Template„„„„„³WireRef´³orµµ±mine´³tupleµ´³lit°„´³named³oid´³refµ„³Oid„„„„„µ±yours´³ tuplePrefixµ´³lit°„´³named³oid´³refµ„³Oid„„„´³named³ attenuation´³seqof´³refµ„³Caveat„„„„„„„³PDiscard´³rec´³lit³_„´³tupleµ„„„³Template´³orµµ±
TAttenuate´³refµ„³ TAttenuate´³refµ„³
@ -40,5 +40,5 @@ ByteString
RunService´³rec´³lit³ run-service„´³tupleµ´³named³ serviceName³any„„„„³ ServiceState´³rec´³lit³ service-state„´³tupleµ´³named³ serviceName³any„´³named³state´³refµ„³State„„„„„³ ServiceObject´³rec´³lit³service-object„´³tupleµ´³named³ serviceName³any„´³named³object³any„„„„³RequireService´³rec´³lit³require-service„´³tupleµ´³named³ serviceName³any„„„„³RestartService´³rec´³lit³restart-service„´³tupleµ´³named³ serviceName³any„„„„³ServiceDependency´³rec´³lit³ RunService´³rec´³lit³ run-service„´³tupleµ´³named³ serviceName³any„„„„³ ServiceState´³rec´³lit³ service-state„´³tupleµ´³named³ serviceName³any„´³named³state´³refµ„³State„„„„„³ ServiceObject´³rec´³lit³service-object„´³tupleµ´³named³ serviceName³any„´³named³object³any„„„„³RequireService´³rec´³lit³require-service„´³tupleµ´³named³ serviceName³any„„„„³RestartService´³rec´³lit³restart-service„´³tupleµ´³named³ serviceName³any„„„„³ServiceDependency´³rec´³lit³
depends-on„´³tupleµ´³named³depender³any„´³named³dependee´³refµ„³ ServiceState„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³protocol„´³schema·³version°³ definitions·³Oid´³atom³ SignedInteger„³Sync´³rec´³lit³S„´³tupleµ´³named³peer´³embedded´³lit<69>„„„„„„³Turn´³seqof´³refµ„³ TurnEvent„„³Error´³rec´³lit³error„´³tupleµ´³named³message´³atom³String„„´³named³detail³any„„„„³Event´³orµµ±Assert´³refµ„³Assert„„µ±Retract´³refµ„³Retract„„µ±Message´³refµ„³Message„„µ±Sync´³refµ„³Sync„„„„³Assert´³rec´³lit³A„´³tupleµ´³named³ assertion´³refµ„³ Assertion„„´³named³handle´³refµ„³Handle„„„„„³Handle´³atom³ SignedInteger„³Packet´³orµµ±Turn´³refµ„³Turn„„µ±Error´³refµ„³Error„„µ± Extension´³refµ„³ Extension„„„„³Message´³rec´³lit³M„´³tupleµ´³named³body´³refµ„³ Assertion„„„„„³Retract´³rec´³lit³R„´³tupleµ´³named³handle´³refµ„³Handle„„„„„³ Assertion³any³ Extension´³rec´³named³label³any„´³named³fields´³seqof³any„„„³ TurnEvent´³tupleµ´³named³oid´³refµ„³Oid„„´³named³event´³refµ„³Event„„„„„³ embeddedType€„„µ³ dataspace„´³schema·³version°³ definitions·³Observe´³rec´³lit³Observe„´³tupleµ´³named³pattern´³refµ³dataspacePatterns„³Pattern„„´³named³observer´³embedded³any„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³ depends-on„´³tupleµ´³named³depender³any„´³named³dependee´³refµ„³ ServiceState„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³protocol„´³schema·³version°³ definitions·³Oid´³atom³ SignedInteger„³Sync´³rec´³lit³S„´³tupleµ´³named³peer´³embedded´³lit<69>„„„„„„³Turn´³seqof´³refµ„³ TurnEvent„„³Error´³rec´³lit³error„´³tupleµ´³named³message´³atom³String„„´³named³detail³any„„„„³Event´³orµµ±Assert´³refµ„³Assert„„µ±Retract´³refµ„³Retract„„µ±Message´³refµ„³Message„„µ±Sync´³refµ„³Sync„„„„³Assert´³rec´³lit³A„´³tupleµ´³named³ assertion´³refµ„³ Assertion„„´³named³handle´³refµ„³Handle„„„„„³Handle´³atom³ SignedInteger„³Packet´³orµµ±Turn´³refµ„³Turn„„µ±Error´³refµ„³Error„„µ± Extension´³refµ„³ Extension„„„„³Message´³rec´³lit³M„´³tupleµ´³named³body´³refµ„³ Assertion„„„„„³Retract´³rec´³lit³R„´³tupleµ´³named³handle´³refµ„³Handle„„„„„³ Assertion³any³ Extension´³rec´³named³label³any„´³named³fields´³seqof³any„„„³ TurnEvent´³tupleµ´³named³oid´³refµ„³Oid„„´³named³event´³refµ„³Event„„„„„³ embeddedType€„„µ³ dataspace„´³schema·³version°³ definitions·³Observe´³rec´³lit³Observe„´³tupleµ´³named³pattern´³refµ³dataspacePatterns„³Pattern„„´³named³observer´³embedded³any„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³
gatekeeper„´³schema·³version°³ definitions·³Bind´³rec´³lit³bind„´³tupleµ´³named³ description´³refµ„³ Description„„´³named³target´³embedded³any„„´³named³observer´³refµ„³ BindObserver„„„„„³Step´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Bound´³orµµ±bound´³rec´³lit³bound„´³tupleµ´³named³pathStep´³refµ„³PathStep„„„„„„µ±Rejected´³refµ„³Rejected„„„„³Route´³rec´³lit³route„´³ tuplePrefixµ´³named³ gatekeeper„´³schema·³version°³ definitions·³Bind´³rec´³lit³bind„´³tupleµ´³named³ description´³refµ„³ Description„„´³named³target´³embedded³any„„´³named³observer´³refµ„³ BindObserver„„„„„³Step´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Bound´³orµµ±bound´³rec´³lit³bound„´³tupleµ´³named³pathStep´³refµ„³PathStep„„„„„„µ±Rejected´³refµ„³Rejected„„„„³Route´³rec´³lit³route„´³ tuplePrefixµ´³named³
transports´³seqof³any„„„´³named³ pathSteps´³seqof´³refµ„³PathStep„„„„„³Resolve´³rec´³lit³resolve„´³tupleµ´³named³step´³refµ„³Step„„´³named³observer´³embedded´³refµ„³Resolved„„„„„„³PathStep´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Rejected´³rec´³lit³rejected„´³tupleµ´³named³detail³any„„„„³Resolved´³orµµ±accepted´³rec´³lit³accepted„´³tupleµ´³named³responderSession´³embedded³any„„„„„„µ±Rejected´³refµ„³Rejected„„„„³ Description´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³ ResolvePath´³rec´³lit³ resolve-path„´³tupleµ´³named³route´³refµ„³Route„„´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³resolved´³refµ„³Resolved„„„„„³ BindObserver´³orµµ±present´³embedded´³refµ„³Bound„„„µ±absent´³lit€„„„„³ForceDisconnect´³rec´³lit³force-disconnect„´³tupleµ„„„³ResolvedPathStep´³rec´³lit³ path-step„´³tupleµ´³named³origin´³embedded´³refµ„³Resolve„„„´³named³pathStep´³refµ„³PathStep„„´³named³resolved´³refµ„³Resolved„„„„„³TransportControl´³refµ„³ForceDisconnect„³TransportConnection´³rec´³lit³connect-transport„´³tupleµ´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³resolved´³refµ„³Resolved„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³transportAddress„´³schema·³version°³ definitions·³Tcp´³rec´³lit³tcp„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³ SignedInteger„„„„„³Unix´³rec´³lit³unix„´³tupleµ´³named³path´³atom³String„„„„„³Stdio´³rec´³lit³stdio„´³tupleµ„„„³ WebSocket´³rec´³lit³ws„´³tupleµ´³named³url´³atom³String„„„„„„³ embeddedType€„„µ³dataspacePatterns„´³schema·³version°³ definitions·³DLit´³rec´³lit³lit„´³tupleµ´³named³value´³refµ„³AnyAtom„„„„„³DBind´³rec´³lit³bind„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„³AnyAtom´³orµµ±bool´³atom³Boolean„„µ±float´³atom³Float„„µ±double´³atom³Double„„µ±int´³atom³ SignedInteger„„µ±string´³atom³String„„µ±bytes´³atom³ transports´³seqof³any„„„´³named³ pathSteps´³seqof´³refµ„³PathStep„„„„„³Resolve´³rec´³lit³resolve„´³tupleµ´³named³step´³refµ„³Step„„´³named³observer´³embedded´³refµ„³Resolved„„„„„„³PathStep´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Rejected´³rec´³lit³rejected„´³tupleµ´³named³detail³any„„„„³Resolved´³orµµ±accepted´³rec´³lit³accepted„´³tupleµ´³named³responderSession´³embedded³any„„„„„„µ±Rejected´³refµ„³Rejected„„„„³ Description´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³ ResolvePath´³rec´³lit³ resolve-path„´³tupleµ´³named³route´³refµ„³Route„„´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³resolved´³refµ„³Resolved„„„„„³ BindObserver´³orµµ±present´³embedded´³refµ„³Bound„„„µ±absent´³lit€„„„„³ForceDisconnect´³rec´³lit³force-disconnect„´³tupleµ„„„³ResolvedPathStep´³rec´³lit³ path-step„´³tupleµ´³named³origin´³embedded´³refµ„³Resolve„„„´³named³pathStep´³refµ„³PathStep„„´³named³resolved´³refµ„³Resolved„„„„„³TransportControl´³refµ„³ForceDisconnect„³TransportConnection´³rec´³lit³connect-transport„´³tupleµ´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³resolved´³refµ„³Resolved„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„µ³transportAddress„´³schema·³version°³ definitions·³Tcp´³rec´³lit³tcp„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³ SignedInteger„„„„„³Unix´³rec´³lit³unix„´³tupleµ´³named³path´³atom³String„„„„„³Stdio´³rec´³lit³stdio„´³tupleµ„„„³ WebSocket´³rec´³lit³ws„´³tupleµ´³named³url´³atom³String„„„„„„³ embeddedType€„„µ³dataspacePatterns„´³schema·³version°³ definitions·³AnyAtom´³orµµ±bool´³atom³Boolean„„µ±double´³atom³Double„„µ±int´³atom³ SignedInteger„„µ±string´³atom³String„„µ±bytes´³atom³
ByteString„„µ±symbol´³atom³Symbol„„µ±embedded´³embedded³any„„„„³Pattern´³orµµ±DDiscard´³refµ„³DDiscard„„µ±DBind´³refµ„³DBind„„µ±DLit´³refµ„³DLit„„µ± DCompound´³refµ„³ DCompound„„„„³DDiscard´³rec´³lit³_„´³tupleµ„„„³ DCompound´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label³any„´³named³fields´³seqof´³refµ„³Pattern„„„„„„„µ±arr´³rec´³lit³arr„´³tupleµ´³named³items´³seqof´³refµ„³Pattern„„„„„„„µ±dict´³rec´³lit³dict„´³tupleµ´³named³entries´³dictof³any´³refµ„³Pattern„„„„„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„„„ ByteString„„µ±symbol´³atom³Symbol„„µ±embedded´³embedded³any„„„„³Pattern´³orµµ±discard´³rec´³lit³_„´³tupleµ„„„„µ±bind´³rec´³lit³bind„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„„µ±lit´³rec´³lit³lit„´³tupleµ´³named³value´³refµ„³AnyAtom„„„„„„µ±group´³rec´³lit³group„´³tupleµ´³named³type´³refµ„³ GroupType„„´³named³entries´³dictof³any´³refµ„³Pattern„„„„„„„„„³ GroupType´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label³any„„„„„µ±arr´³rec´³lit³arr„´³tupleµ„„„„µ±dict´³rec´³lit³dict„´³tupleµ„„„„„„„³ embeddedType´³refµ³ EntityRef„³Cap„„„„„

View File

@ -1,4 +1,4 @@
version 1 . version 1 .
embeddedType EntityRef.Cap . embeddedType EntityRef.Cap .
Observe = <Observe @pattern dataspacePatterns.Pattern @observer #!any>. Observe = <Observe @pattern dataspacePatterns.Pattern @observer #:any>.

View File

@ -1,23 +1,30 @@
version 1 . version 1 .
embeddedType EntityRef.Cap . embeddedType EntityRef.Cap .
# Dataspace patterns: a sublanguage of attenuation patterns. # Dataspace patterns: *almost* a sublanguage of attenuation patterns.
Pattern = DDiscard / DBind / DLit / DCompound . #
# One key difference is that Dataspace patterns are extensible, in that
# they ignore fields not mentioned in group patterns.
DDiscard = <_>. Pattern =
DBind = <bind @pattern Pattern>. / @discard <_>
DLit = <lit @value AnyAtom>. / <bind @pattern Pattern>
DCompound = <rec @label any @fields [Pattern ...]> / <lit @value AnyAtom>
/ <arr @items [Pattern ...]> / <group @type GroupType @entries { any: Pattern ...:... }>
/ <dict @entries { any: Pattern ...:... }> . .
GroupType =
/ <rec @label any>
/ <arr>
/ <dict>
.
AnyAtom = AnyAtom =
/ @bool bool / @bool bool
/ @float float
/ @double double / @double double
/ @int int / @int int
/ @string string / @string string
/ @bytes bytes / @bytes bytes
/ @symbol symbol / @symbol symbol
/ @embedded #!any / @embedded #:any
. .

View File

@ -6,18 +6,47 @@ embeddedType EntityRef.Cap .
# Assertion. Gatekeeper will attempt to resolve `step`, responding with a `Resolved` to # Assertion. Gatekeeper will attempt to resolve `step`, responding with a `Resolved` to
# `observer`. # `observer`.
Resolve = <resolve @step Step @observer #!Resolved> . Resolve = <resolve @step Step @observer #:Resolved> .
Resolved = <accepted @responderSession #!any> / Rejected . Resolved = <accepted @responderSession #:any> / Rejected .
Step = <<rec> @stepType symbol [@detail any]> . Step = <<rec> @stepType symbol [@detail any]> .
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Protocol at dataspaces *associated* with gatekeeper entities # Protocol at dataspaces *associated* with gatekeeper entities
# Assertion. Gatekeeper will compute an appropriate PathStep from `description` pointing at # ## Handling `Resolve` requests
# `target`, and will respond with a `Bound` to `observer` (if supplied). #
Bind = <bind @description Description @target #!any @observer BindObserver> . # 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 = <bind @description Description @target #:any @observer BindObserver> .
Description = <<rec> @stepType symbol [@detail any]> . Description = <<rec> @stepType symbol [@detail any]> .
BindObserver = @present #!Bound / @absent #f . BindObserver = @present #:Bound / @absent #f .
Bound = <bound @pathStep PathStep> / Rejected . Bound = <bound @pathStep PathStep> / Rejected .
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@ -27,10 +56,10 @@ Bound = <bound @pathStep PathStep> / Rejected .
# and `resolved`, respondent will follow `route.pathSteps` starting from one of the # 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 # `route.transports`, asserting `ResolvePath` with the final `Resolved` as well as the selected
# transport `addr` and a `control` for it. # transport `addr` and a `control` for it.
ResolvePath = <resolve-path @route Route @addr any @control #!TransportControl @resolved Resolved> . ResolvePath = <resolve-path @route Route @addr any @control #:TransportControl @resolved Resolved> .
TransportConnection = <connect-transport @addr any @control #!TransportControl @resolved Resolved> . TransportConnection = <connect-transport @addr any @control #:TransportControl @resolved Resolved> .
ResolvedPathStep = <path-step @origin #!Resolve @pathStep PathStep @resolved Resolved> . ResolvedPathStep = <path-step @origin #:Resolve @pathStep PathStep @resolved Resolved> .
PathStep = <<rec> @stepType symbol [@detail any]> . PathStep = <<rec> @stepType symbol [@detail any]> .
# A `Route` describes a network path that can be followed to reach some target entity. # A `Route` describes a network path that can be followed to reach some target entity.

View File

@ -2,7 +2,7 @@ version 1 .
# Assertion in driver DS # Assertion in driver DS
# Causes creation of server and route # Causes creation of server and route
HttpBinding = <http-bind @host HostPattern @port int @method MethodPattern @path PathPattern @handler #!HttpRequest> . HttpBinding = <http-bind @host HostPattern @port int @method MethodPattern @path PathPattern @handler #:HttpRequest> .
# Assertion in driver DS # Assertion in driver DS
# Describes active server and route # Describes active server and route
@ -21,7 +21,7 @@ MethodPattern = @any #f / @specific @"Lowercase" symbol .
# Assertion in driver DS # Assertion in driver DS
HttpRequest = <http-request HttpRequest = <http-request
@sequenceNumber int @sequenceNumber int
@host string @host RequestHost
@port int @port int
@method @"Lowercase" symbol @method @"Lowercase" symbol
@path [string ...] @path [string ...]
@ -32,13 +32,24 @@ HttpRequest = <http-request
Headers = {@"Lowercase" symbol: string ...:...} . Headers = {@"Lowercase" symbol: string ...:...} .
QueryValue = @string string / <file @filename string @headers Headers @body bytes> . QueryValue = @string string / <file @filename string @headers Headers @body bytes> .
RequestBody = @present bytes / @absent #f . RequestBody = @present bytes / @absent #f .
RequestHost = @present string / @absent #f .
# Assertion to handler entity # Assertion to handler entity
HttpContext = <request @req HttpRequest @res #!HttpResponse> . HttpContext = <request @req HttpRequest @res #:HttpResponse> .
# 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.
#
@<TODO "trailers?"> @<TODO "trailers?">
# Messages
HttpResponse = HttpResponse =
# Messages.
/ <status @code int @message string> / <status @code int @message string>
/ <header @name symbol @value string> / <header @name symbol @value string>
/ <chunk @chunk Chunk> / <chunk @chunk Chunk>

View File

@ -1,4 +1,5 @@
version 1 . version 1 .
embeddedType EntityRef.Cap .
# https://noiseprotocol.org/ # 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. # 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 {} . 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 <resolve <noise ServiceSelector> #:A> at Gatekeeper
# 2. gatekeeper asserts <accepted #:B> at #:A
# 3. initiator asserts <initiator #:C> 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. # 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 # 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 # complete Noise "transport message"; when `complete`, the whole thing is likewise a complete
# "transport message". # "transport message".
#
# Retraction of the `Initiator` ends the session from the initiator-side; retraction of the
# `<accepted ...>` assertion ends the session from the responder-side.
SessionItem = Initiator / Packet .
# Assertion
Initiator = <initiator @initiatorSession #:Packet> .
# Message
Packet = @complete bytes / @fragmented [bytes ...] . Packet = @complete bytes / @fragmented [bytes ...] .
# When layering Syndicate protocol over noise, # When layering Syndicate protocol over noise,

View File

@ -16,4 +16,4 @@ TurnEvent = [@oid Oid @event Event].
Assert = <A @assertion Assertion @handle Handle>. Assert = <A @assertion Assertion @handle Handle>.
Retract = <R @handle Handle>. Retract = <R @handle Handle>.
Message = <M @body Assertion>. Message = <M @body Assertion>.
Sync = <S @peer #!#t>. Sync = <S @peer #:#t>.

View File

@ -2,7 +2,7 @@ version 1 .
embeddedType EntityRef.Cap . embeddedType EntityRef.Cap .
# Assertion: # Assertion:
StreamConnection = <stream-connection @source #!Source @sink #!Sink @spec any>. StreamConnection = <stream-connection @source #:Source @sink #:Sink @spec any>.
# Assertions: # Assertions:
StreamListenerReady = <stream-listener-ready @spec any>. StreamListenerReady = <stream-listener-ready @spec any>.
@ -13,7 +13,7 @@ StreamError = <error @message string>.
Source = Source =
# Assertions: # Assertions:
/ <sink @controller #!Sink> / <sink @controller #:Sink>
/ StreamError / StreamError
# Messages: # Messages:
@ -22,7 +22,7 @@ Source =
Sink = Sink =
# Assertions: # Assertions:
/ <source @controller #!Source> / <source @controller #:Source>
/ StreamError / StreamError
# Messages: # Messages:

View File

@ -51,7 +51,7 @@ Lit = <lit @value any>.
Pattern = PDiscard / PAtom / PEmbedded / PBind / PAnd / PNot / Lit / PCompound . Pattern = PDiscard / PAtom / PEmbedded / PBind / PAnd / PNot / Lit / PCompound .
PDiscard = <_>. PDiscard = <_>.
PAtom = =Boolean / =Float / =Double / =SignedInteger / =String / =ByteString / =Symbol . PAtom = =Boolean / =Double / =SignedInteger / =String / =ByteString / =Symbol .
PEmbedded = =Embedded . PEmbedded = =Embedded .
PBind = <bind @pattern Pattern>. PBind = <bind @pattern Pattern>.
PAnd = <and @patterns [Pattern ...]>. PAnd = <and @patterns [Pattern ...]>.

View File

@ -4,4 +4,4 @@ embeddedType EntityRef.Cap .
TcpRemote = <tcp-remote @host string @port int>. TcpRemote = <tcp-remote @host string @port int>.
TcpLocal = <tcp-local @host string @port int>. TcpLocal = <tcp-local @host string @port int>.
TcpPeerInfo = <tcp-peer @handle #!any @local TcpLocal @remote TcpRemote>. TcpPeerInfo = <tcp-peer @handle #:any @local TcpLocal @remote TcpRemote>.

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { SyndicateRollup } from '../../rollup.js'; import { SyndicateRollup } from '../../rollup.js';
const r = new SyndicateRollup('syndicate', { globalName: 'Syndicate' }); const r = new SyndicateRollup('syndicate', { globalName: 'Syndicate' });

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
export * from '@preserves/core'; export * from '@preserves/core';
@ -10,6 +10,7 @@ export * as DataspacePatterns from './gen/dataspacePatterns.js';
export * from './runtime/actor.js'; export * from './runtime/actor.js';
export * from './runtime/bag.js'; export * from './runtime/bag.js';
export * as Dataflow from './runtime/dataflow.js'; export * as Dataflow from './runtime/dataflow.js';
export { Field } from './runtime/dataflow.js';
export * from './runtime/dataspace.js'; export * from './runtime/dataspace.js';
export * from './runtime/mirror.js'; export * from './runtime/mirror.js';
export * as Pattern from './runtime/pattern.js'; export * as Pattern from './runtime/pattern.js';

View File

@ -1,13 +1,13 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { IdentitySet, Value, embeddedId, is, fromJS, stringify, Dictionary, KeyedSet } from '@preserves/core'; import { IdentitySet, Value, embeddedId, is, fromJS, stringify, KeyedSet, Tuple, Embeddable, IsEmbedded } from '@preserves/core';
import { Cell, Field, Graph } from './dataflow'; import { Cell, Field, Graph } from './dataflow.js';
import { Caveat, runRewrites } from './rewrite'; import { Caveat, runRewrites } from './rewrite.js';
import { ActorSpace } from './space'; import { ActorSpace } from './space.js';
import { ActionDescription, StructuredTask, TaskAction } from './task'; import { ActionDescription, StructuredTask, TaskAction } from './task.js';
import { randomId } from './randomid'; import { randomId } from './randomid.js';
import * as Q from '../gen/queuedTasks'; import * as Q from '../gen/queuedTasks.js';
import { Mirror, Reflectable, _asRef } from './mirror'; import { Mirror, Reflectable, _asRef } from './mirror';
import * as Refl from '../gen/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 LocalAction = () => void;
export type DetailedAction<T = AnyValue> = LocalAction & { detail: T }; export type DetailedAction<T = AnyValue> = LocalAction & { detail: T };
export type Assertable = Assertion | { __as_preserve__: <T>() => Value<T> } | { __as_preserve__: () => Assertion }; export type Assertable =
| Assertion
| { __as_preserve__: <T extends Embeddable>() => Value<T> }
| { __as_preserve__: () => Assertion }
;
export interface Entity { export interface Entity {
assert(assertion: Assertion, handle: Handle): void; assert(assertion: Assertion, handle: Handle): void;
@ -43,13 +47,9 @@ export interface Entity {
export type Cap = Ref; export type Cap = Ref;
export interface Ref { export class Ref implements Reflectable {
readonly relay: Facet; get [IsEmbedded](): true { return true; }
readonly target: Partial<Entity>;
readonly attenuation?: Caveat[];
}
export class RefImpl implements Ref, Reflectable {
readonly relay: Facet; readonly relay: Facet;
readonly target: Partial<Entity>; readonly target: Partial<Entity>;
readonly attenuation?: Caveat[]; readonly attenuation?: Caveat[];
@ -76,6 +76,10 @@ export class RefImpl implements Ref, Reflectable {
if ('sync' in this.target) sig = sig + 'S'; if ('sync' in this.target) sig = sig + 'S';
return `${this.relay.idChain()}<${sig}>${entityRepr}`; 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; return this._dataflowGraph;
} }
atExit(a: LocalAction): void { atExit(a: LocalAction): () => void {
this.exitHooks.push(a); this.exitHooks.push(a);
return () => {
const i = this.exitHooks.indexOf(a);
if (i !== -1) this.exitHooks.splice(i, 1);
};
} }
_terminateWith(reason: Exclude<ExitReason, null>) { _terminateWith(reason: Exclude<ExitReason, null>) {
@ -284,6 +292,10 @@ export class Facet implements Reflectable {
this._reflection?.mirror.setProp(this._reflection.childHandles, '' + child.id, void 0); this._reflection?.mirror.setProp(this._reflection.childHandles, '' + child.id, void 0);
} }
wrap<T extends Tuple<any>>(f: (... args: T) => void): (... args: T) => void {
return (... args) => this.turn(() => f(... args));
}
turn(a: LocalAction) { turn(a: LocalAction) {
Turn.for(this, a); Turn.for(this, a);
} }
@ -323,12 +335,17 @@ export class Facet implements Reflectable {
_halfLink(other: Facet): void { _halfLink(other: Facet): void {
const h = nextHandle++; const h = nextHandle++;
const peer = { relay: other, target: new StopOnRetract() }; const e = {
this.outbound.set(h, { handle: h, peer, crossSpace: null, established: true }); handle: h,
peer: new Ref(other, new StopOnRetract()),
crossSpace: null,
established: true,
};
this.outbound.set(h, e);
this._reflection?.mirror.setProp( this._reflection?.mirror.setProp(
this._reflection.assertionHandles, this._reflection.assertionHandles,
'' + h, '' + h,
Refl.FacetAssertion({ handle: h, target: peer })); Refl.FacetAssertion({ handle: h, target: e.peer }));
} }
_terminate(orderly: boolean): void { _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<Entity> { export class StopOnRetract implements Partial<Entity> {
retract(_handle: Handle): void { retract(_handle: Handle): void {
Turn.active.stop(); Turn.active.stop(Turn.activeFacet);
} }
actor = STOP_ON_RETRACT; actor = STOP_ON_RETRACT;
} }
@ -455,7 +472,7 @@ export class Turn {
} }
ref<T extends Partial<Entity>>(e: T): Ref { ref<T extends Partial<Entity>>(e: T): Ref {
return new RefImpl(this.activeFacet, e); return new Ref(this.activeFacet, e);
} }
facet(bootProc: LocalAction): Facet { facet(bootProc: LocalAction): Facet {
@ -465,11 +482,14 @@ export class Turn {
} }
// Alias for syndicatec code generator to use // Alias for syndicatec code generator to use
_stop(facet: Facet = this.activeFacet, continuation?: LocalAction) { _stop(facet: Facet, continuation?: LocalAction) {
this.stop(facet, continuation); 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); if (continuation) facet.onStop(continuation);
facet._terminate(true); facet._terminate(true);
} }
@ -507,7 +527,7 @@ export class Turn {
}); });
}, },
() => { () => {
const a = new KeyedSet<number, Ref>(); const a = new KeyedSet<Ref, number>();
initialAssertions.forEach(h => a.add(h)); initialAssertions.forEach(h => a.add(h));
return Q.ActionDescription.spawnActor({ detail, initialAssertions: a }); return Q.ActionDescription.spawnActor({ detail, initialAssertions: a });
}); });
@ -536,10 +556,10 @@ export class Turn {
crash(err: Error): void { crash(err: Error): void {
this.enqueue(this.activeFacet.actor.root, this.enqueue(this.activeFacet.actor.root,
() => this.activeFacet.actor._terminateWith({ ok: false, err }), () => this.activeFacet.actor._terminateWith({ ok: false, err }),
() => Q.ActionDescription.stopActor(Q.OptionalAny.some(Dictionary.fromJS({ () => Q.ActionDescription.stopActor(Q.OptionalAny.some<Ref>({
message: err.message, message: err.message,
stack: err.stack ? err.stack : false, stack: err.stack ? err.stack : false,
})))); })));
} }
field<V>(initial: V, name?: string): Field<V> { field<V>(initial: V, name?: string): Field<V> {

View File

@ -1,9 +1,9 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
// Bags and Deltas (which are Bags where item-counts can be negative). // 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 { export enum ChangeDescription {
PRESENT_TO_ABSENT = -1, PRESENT_TO_ABSENT = -1,
@ -12,10 +12,10 @@ export enum ChangeDescription {
PRESENT_TO_PRESENT = 2, PRESENT_TO_PRESENT = 2,
} }
export class Bag<T, V extends Value<T> = Value<T>> { export class Bag<T extends Embeddable, V extends Value<T> = Value<T>> {
_items: KeyedDictionary<V, number, T>; _items: KeyedDictionary<T, V, number>;
constructor(s?: KeyedSet<V, T>) { constructor(s?: KeyedSet<T, V>) {
this._items = new KeyedDictionary(); this._items = new KeyedDictionary();
if (s) s.forEach((v) => this._items.set(v, 1)); if (s) s.forEach((v) => this._items.set(v, 1));
} }
@ -68,7 +68,7 @@ export class Bag<T, V extends Value<T> = Value<T>> {
this._items.forEach((c, v) => f(c, v)); this._items.forEach((c, v) => f(c, v));
} }
snapshot(): KeyedDictionary<V, number, T> { snapshot(): KeyedDictionary<T, V, number> {
return this._items.clone(); return this._items.clone();
} }

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
// Property-based "dataflow" // Property-based "dataflow"

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Record, IdentityMap, KeyedDictionary, stringify } from '@preserves/core'; import { Record, IdentityMap, KeyedDictionary, stringify } from '@preserves/core';
import { Index, IndexObserver } from './skeleton.js'; import { Index, IndexObserver } from './skeleton.js';
@ -18,7 +18,7 @@ export type DataspaceOptions = {
}; };
export class DataspaceObserver implements IndexObserver<Turn> { export class DataspaceObserver implements IndexObserver<Turn> {
readonly captureMap = new KeyedDictionary<Array<AnyValue>, Handle, Ref>(); readonly captureMap = new KeyedDictionary<Ref, Array<AnyValue>, Handle>();
constructor( constructor(
public readonly target: Ref, public readonly target: Ref,

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
// Utilities for Maps of Sets // Utilities for Maps of Sets

View File

@ -1,7 +1,7 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
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 { AnyValue, Ref } from './actor.js';
import * as P from '../gen/dataspacePatterns.js'; import * as P from '../gen/dataspacePatterns.js';
@ -13,20 +13,20 @@ export function classOfValue(v: any): Shape | null {
if (Record.isRecord(v)) { if (Record.isRecord(v)) {
return constructorInfoSignature(Record.constructorInfo(v)); return constructorInfoSignature(Record.constructorInfo(v));
} else if (Array.isArray(v)) { } else if (Array.isArray(v)) {
return '' + v.length; return '[]';
} else if (Map.isMap(v)) { } else if (Dictionary.isDictionary(v)) {
return '{}'; return '{}';
} else { } else {
return null; return null;
} }
} }
export function classOfCtor(v: P.DCompound): Shape { export function classOfCtor(v: P.GroupType): Shape {
switch (v._variant) { switch (v._variant) {
case 'rec': case 'rec':
return canonicalString(v.label) + '/' + v.fields.length; return canonicalString(v.label);
case 'arr': case 'arr':
return '' + v.items.length; return '[]';
case 'dict': case 'dict':
return '{}'; return '{}';
} }
@ -34,55 +34,59 @@ export function classOfCtor(v: P.DCompound): Shape {
// Called by generated code in addition to functions in this module // Called by generated code in addition to functions in this module
export function constructorInfoSignature(ci: RecordConstructorInfo<Value>): string { export function constructorInfoSignature(ci: RecordConstructorInfo<Value>): string {
return canonicalString(ci.label) + '/' + ci.arity; return canonicalString(ci.label);
} }
export function step(v: AnyValue, index: AnyValue): AnyValue | undefined { export function step(v: AnyValue, index: AnyValue): AnyValue | undefined {
if (Map.isMap(v)) { const vMap = Dictionary.asMap<Ref>(v);
return v.get(index); if (vMap) {
return vMap.get(index);
} else { } else {
return (v as Array<AnyValue> /* includes Record! */)[index as number]; return (v as Array<AnyValue> /* includes Record! */)[index as number];
} }
} }
export type ConstantPositions = {
withValues: Array<Path>,
requiredToExist: Array<Path>,
}
export type PatternAnalysis = { export type PatternAnalysis = {
constPaths: Array<Path>, constPositions: ConstantPositions,
constValues: Array<AnyValue>, constValues: Array<AnyValue>,
capturePaths: Array<Path>, capturePaths: Array<Path>,
}; };
export function analysePattern(p: P.Pattern): PatternAnalysis { export function analysePattern(p: P.Pattern): PatternAnalysis {
const result: PatternAnalysis = { const result: PatternAnalysis = {
constPaths: [], constPositions: {
withValues: [],
requiredToExist: [],
},
constValues: [], constValues: [],
capturePaths: [], capturePaths: [],
}; };
const path: Path = []; const path: Path = [];
function walkKey(p: P.Pattern, key: AnyValue) {
path.push(key);
walk(p);
path.pop();
}
function walk(p: P.Pattern) { function walk(p: P.Pattern) {
switch (p._variant) { switch (p._variant) {
case 'DCompound': case 'group':
switch (p.value._variant) { p.entries.forEach((p, k) => {
case 'rec': p.value.fields.forEach(walkKey); break; path.push(k);
case 'arr': p.value.items.forEach(walkKey); break; walk(p);
case 'dict': p.value.entries.forEach(walkKey); break; path.pop();
} });
break; break;
case 'DBind': case 'bind':
result.capturePaths.push(path.slice()); result.capturePaths.push(path.slice());
walk(p.value.pattern); walk(p.pattern);
break; break;
case 'DDiscard': case 'discard':
result.constPositions.requiredToExist.push(path.slice());
break; break;
case 'DLit': case 'lit':
result.constPaths.push(path.slice()); result.constPositions.withValues.push(path.slice());
result.constValues.push(P.fromAnyAtom(p.value.value)); result.constValues.push(P.fromAnyAtom(p.value));
break; break;
} }
} }
@ -96,32 +100,20 @@ export function match(p: P.Pattern, v: AnyValue): Array<AnyValue> | false {
function walk(p: P.Pattern, v: AnyValue): boolean { function walk(p: P.Pattern, v: AnyValue): boolean {
switch (p._variant) { switch (p._variant) {
case 'DBind': { case 'bind': {
captures.push(v); captures.push(v);
return walk(p.value.pattern, v); return walk(p.pattern, v);
} }
case 'DDiscard': case 'discard':
return true; return true;
case 'DLit': case 'lit':
return is(p.value.value, v); return is(p.value, v);
case 'DCompound': { case 'group': {
const pcls = classOfCtor(p.value); const pcls = classOfCtor(p.type);
const vcls = classOfValue(v); const vcls = classOfValue(v);
if (pcls !== vcls) return false; if (pcls !== vcls) return false;
let items: Array<P.Pattern>; for (const [stepIndex, pp] of p.entries.entries()) {
switch (p.value._variant) { const vv = step(v, stepIndex);
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++);
if (vv === void 0 || !walk(pp, vv)) return false; if (vv === void 0 || !walk(pp, vv)) return false;
} }
return true; return true;
@ -135,19 +127,14 @@ export function match(p: P.Pattern, v: AnyValue): Array<AnyValue> | false {
export function isCompletelyConcrete(p: P.Pattern): boolean { export function isCompletelyConcrete(p: P.Pattern): boolean {
function walk(p: P.Pattern): boolean { function walk(p: P.Pattern): boolean {
switch (p._variant) { switch (p._variant) {
case 'DBind': return false; case 'bind': return false;
case 'DDiscard': return false; case 'discard': return false;
case 'DLit': return true; case 'lit': return true;
case 'DCompound': switch (p.value._variant) { case 'group':
case 'rec': return p.value.fields.every(isCompletelyConcrete); for (const pp of p.entries.values()) {
case 'arr': return p.value.items.every(isCompletelyConcrete); if (!walk(pp)) return false;
case 'dict': {
for (const pp of p.value.entries.values()) {
if (!walk(pp)) return false;
}
return true;
} }
} return true;
} }
} }
return walk(p); return walk(p);
@ -156,26 +143,19 @@ export function isCompletelyConcrete(p: P.Pattern): boolean {
export function withoutCaptures(p: P.Pattern): P.Pattern { export function withoutCaptures(p: P.Pattern): P.Pattern {
function walk(p: P.Pattern): P.Pattern { function walk(p: P.Pattern): P.Pattern {
switch (p._variant) { switch (p._variant) {
case 'DBind': return walk(p.value.pattern); case 'bind': return walk(p.pattern);
case 'DDiscard': return p; case 'discard': return p;
case 'DLit': return p; case 'lit': return p;
case 'DCompound': case 'group': {
switch (p.value._variant) { const newEntries = new KeyedDictionary<Ref, Value<Ref>, P.Pattern<Ref>>();
case 'rec': for (const [kk, pp] of p.entries) {
return P.Pattern.DCompound(P.DCompound.rec({ newEntries.set(kk, walk(pp));
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<Value<Ref>, P.Pattern<Ref>, Ref>();
for (const [k, v] of p.value.entries) {
newDict.set(k, walk(v));
}
return P.Pattern.DCompound(P.DCompound.dict(newDict));
}
} }
return P.Pattern.group({
type: p.type,
entries: newEntries,
});
}
} }
} }
return walk(p); return walk(p);
@ -185,57 +165,92 @@ export function withoutCaptures(p: P.Pattern): P.Pattern {
// Constructor helpers // Constructor helpers
export function bind(p?: P.Pattern): P.Pattern { 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 { export function discard(): P.Pattern {
return P.Pattern.DDiscard(P.DDiscard()); return P.Pattern.discard();
} }
export const _ = discard(); export const _ = discard();
function lit_seq_entries(vs: AnyValue[]): KeyedDictionary<Ref, AnyValue, P.Pattern<Ref>> {
const entries = new KeyedDictionary<Ref, AnyValue, P.Pattern<Ref>>();
vs.forEach((v, i) => entries.set(i, lit(v)));
return entries;
}
export function lit(v: AnyValue): P.Pattern { export function lit(v: AnyValue): P.Pattern {
if (Array.isArray(v)) { if (Array.isArray(v)) {
if ('label' in v) { if ('label' in v) {
return P.Pattern.DCompound(P.DCompound.rec({ return P.Pattern.group({
label: v.label, type: P.GroupType.rec(v.label),
fields: v.map(lit), entries: lit_seq_entries(v),
})); });
} else { } 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<Ref>(v);
if (vMap) {
const r = new KeyedDictionary<Ref, AnyValue, P.Pattern>();
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 { export function drop_lit(p: P.Pattern): AnyValue | null {
const e = new Error(); const e = new Error();
function walkEntries(target: AnyValue[], entries: EncodableDictionary<Ref, AnyValue, P.Pattern<Ref>>): 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 { function walk(p: P.Pattern): AnyValue {
switch (p._variant) { switch (p._variant) {
case 'DCompound': case 'group':
switch (p.value._variant) { switch (p.type._variant) {
case 'rec': { case 'rec': {
const v = [] as unknown as Record<AnyValue, AnyValue[], Ref>; const v = [] as unknown as Record<AnyValue, AnyValue[], Ref>;
v.label = p.value.label; v.label = p.type.label;
p.value.fields.forEach(tt => v.push(walk(tt))); walkEntries(v, p.entries);
return v; return v;
} }
case 'arr': case 'arr': {
return p.value.items.map(walk); const v = [] as AnyValue[];
case 'dict': { walkEntries(v, p.entries);
const v = new Dictionary<Ref, AnyValue>();
p.value.entries.forEach((pp, key) => v.set(key, walk(pp)));
return v; return v;
} }
case 'dict': {
const v = new DictionaryMap<Ref, AnyValue>();
p.entries.forEach((pp, key) => v.set(key, walk(pp)));
return v.simplifiedValue();
}
} }
case 'DLit': case 'lit':
return P.fromAnyAtom(p.value.value); return P.fromAnyAtom(p.value);
default: default:
throw e; 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 { 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<Ref, AnyValue, P.Pattern>(fields.map((p, i) => [i, p])),
});
} }
export function arr(... patterns: P.Pattern[]): P.Pattern { 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<Ref, AnyValue, P.Pattern>(patterns.map((p, i) => [i, p])),
});
} }
export function dict(... entries: [AnyValue, P.Pattern][]): P.Pattern { export function dict(... entries: [AnyValue, P.Pattern][]): P.Pattern {
return P.Pattern.DCompound(P.DCompound.dict(new Dictionary<Ref, P.Pattern>(entries))); return P.Pattern.group({
type: P.GroupType.dict(),
entries: new KeyedDictionary<Ref, AnyValue, P.Pattern>(entries),
});
} }

View File

@ -1,10 +1,10 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2021-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2021-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { AnyValue, Ref } from './actor.js'; 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 * 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'; import { Meta, Type, GenType, SchemaDefinition } from '@preserves/schema';
export type QuasiValueConstructorInfo = export type QuasiValueConstructorInfo =
@ -17,9 +17,7 @@ export type QuasiValue =
| { type: 'bind', inner: QuasiValue } | { type: 'bind', inner: QuasiValue }
| { type: 'discard' } | { type: 'discard' }
| { type: 'lit', value: AnyValue } | { type: 'lit', value: AnyValue }
| { type: 'rec', label: AnyValue, items: QuasiValue[] } | { type: 'group', groupType: GroupType, entries: [AnyValue, QuasiValue][] }
| { type: 'arr', items: QuasiValue[] }
| { type: 'dict', entries: [AnyValue, QuasiValue][] }
| { type: 'unquote', unquoted: QuasiValue } | { type: 'unquote', unquoted: QuasiValue }
; ;
@ -58,7 +56,8 @@ export function rec(label: AnyValue, ... items: QuasiValue[]): QuasiValue {
if (literals.length === items.length) { if (literals.length === items.length) {
return lit(Record(label, literals)); return lit(Record(label, literals));
} else { } 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) { if (literals.length === items.length) {
return lit(literals); return lit(literals);
} else { } 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 { export function dict(... entries: [AnyValue, QuasiValue][]): QuasiValue {
return { type: 'dict', entries }; return { type: 'group', groupType: GroupType.dict(), entries };
} }
export function quote(quoted: QuasiValue): QuasiValue { 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 'bind': return quote(bind.quasiValue(quoted.inner));
case 'discard': return quote(discard.quasiValue()); case 'discard': return quote(discard.quasiValue());
case 'lit': return rec(Symbol.for('lit'), lit(quoted.value)); case 'lit': return rec(Symbol.for('lit'), lit(quoted.value));
case 'arr': return rec(Symbol.for('arr'), arr( case 'group':
... quoted.items.map(quote))); return rec(Symbol.for('group'), lit(fromGroupType(quoted.groupType)), dict(
case 'rec': return rec(Symbol.for('rec'), lit(quoted.label), arr( ... quoted.entries.map(([k, qq]) => [k, quote(qq)] as [AnyValue, QuasiValue])));
... quoted.items.map(quote)));
case 'dict': return rec(Symbol.for('dict'), dict(
... quoted.entries.map(([k, qq]) => [k, quote(qq)] as [AnyValue, QuasiValue])));
case 'unquote': return quoted.unquoted; case 'unquote': return quoted.unquoted;
} }
} }
@ -94,13 +91,27 @@ export function unquote(unquoted: QuasiValue): QuasiValue {
return { type: 'unquote', unquoted }; return { type: 'unquote', unquoted };
} }
function entriesSeq<V>(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 { export function ctor(info: QuasiValueConstructorInfo, ... items: QuasiValue[]): QuasiValue {
if ('constructorInfo' in info) { if ('constructorInfo' in info) {
return rec(info.constructorInfo.label, ... items); return rec(info.constructorInfo.label, ... items);
} else if ('schema' in info) { } else if ('schema' in info) {
const definfo = info.schema(); const definfo = info.schema();
const schema = Meta.asSchema(definfo.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 defNameStr = definfo.definitionName.description!;
const ctorArgs = items.slice(); const ctorArgs = items.slice();
@ -158,7 +169,7 @@ export function ctor(info: QuasiValueConstructorInfo, ... items: QuasiValue[]):
if (d.type === 'discard') { if (d.type === 'discard') {
return d; return d;
} }
if (d.type !== 'dict') { if (d.type !== 'group' || d.groupType._variant !== 'dict') {
throw new Error(`Dictionary argument needed to ${defNameStr}`); throw new Error(`Dictionary argument needed to ${defNameStr}`);
} }
for (const [k, p] of d.entries) { for (const [k, p] of d.entries) {
@ -217,8 +228,8 @@ export function ctor(info: QuasiValueConstructorInfo, ... items: QuasiValue[]):
} }
function qArr(q: QuasiValue): QuasiValue[] { function qArr(q: QuasiValue): QuasiValue[] {
if (q.type === 'arr') { if (q.type === 'group' && q.groupType._variant === 'arr') {
return q.items; return entriesSeq(q.entries, discard());
} else if (q.type === 'lit' && Array.isArray(q.value)) { } else if (q.type === 'lit' && Array.isArray(q.value)) {
return q.value.map(lit); return q.value.map(lit);
} else { } else {
@ -284,10 +295,12 @@ function walk(q: QuasiValue): Pattern {
case 'bind': return P.bind(walk(q.inner)); case 'bind': return P.bind(walk(q.inner));
case 'discard': return P._; case 'discard': return P._;
case 'lit': return P.lit(q.value); case 'lit': return P.lit(q.value);
case 'arr': return P.arr(... q.items.map(walk)); case 'group': switch (q.groupType._variant) {
case 'rec': return P.rec(q.label, ... q.items.map(walk)); case 'arr': return P.arr(... entriesSeq(q.entries, discard()).map(walk));
case 'dict': return P.dict(... q.entries.map( case 'rec': return P.rec(q.groupType.label, ... entriesSeq(q.entries, discard()).map(walk));
([k, qq]) => [k, walk(qq)] as [AnyValue, Pattern])); 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'); case 'unquote': throw new Error('Unexpected unquote in QuasiValue');
} }
} }

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Bytes } from '@preserves/core'; import { Bytes } from '@preserves/core';
import * as node_crypto from 'crypto'; import * as node_crypto from 'crypto';

View File

@ -1,9 +1,9 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Turn } from "./actor.js"; import { Turn, Ref } from "./actor.js";
import { Bytes, Dictionary, DoubleFloat, embed, IdentityMap, is, isEmbedded, Record, SingleFloat, Tuple, stringify } from "@preserves/core"; import { Bytes, Dictionary, DictionaryMap, DoubleFloat, IdentityMap, KeyedDictionary, is, isEmbedded, Record, Tuple, stringify } from "@preserves/core";
import type { Assertion, Handle, Ref } from "./actor.js"; import type { Assertion, Handle } from "./actor.js";
import type { SturdyValue } from "../transport/sturdy.js"; import type { SturdyValue } from "../transport/sturdy.js";
import { import {
@ -19,6 +19,8 @@ import {
PEmbedded, PEmbedded,
Pattern, Pattern,
Rewrite, Rewrite,
TAttenuate,
TCompound,
TRef, TRef,
Template, Template,
_embedded, _embedded,
@ -39,7 +41,6 @@ export function match(p: Pattern, v: Assertion): Bindings | null {
case 'Boolean': return typeof v === 'boolean'; case 'Boolean': return typeof v === 'boolean';
case 'ByteString': return Bytes.isBytes(v); case 'ByteString': return Bytes.isBytes(v);
case 'Double': return DoubleFloat.isDouble(v); case 'Double': return DoubleFloat.isDouble(v);
case 'Float': return SingleFloat.isSingle(v);
case 'SignedInteger': return typeof v === 'number'; case 'SignedInteger': return typeof v === 'number';
case 'String': return typeof v === 'string'; case 'String': return typeof v === 'string';
case 'Symbol': return typeof v === 'symbol'; case 'Symbol': return typeof v === 'symbol';
@ -88,9 +89,10 @@ export function match(p: Pattern, v: Assertion): Bindings | null {
return true; return true;
} }
case 'dict':{ case 'dict':{
if (!Dictionary.isDictionary<Ref, Assertion>(v)) return false; const vMap = Dictionary.asMap<Ref, Assertion>(v);
if (!vMap) return false;
for (const [key, pp] of p.value.entries.entries()) { 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 (vv === void 0) return false;
if (!walk(pp, vv)) return false; if (!walk(pp, vv)) return false;
} }
@ -114,8 +116,7 @@ export function instantiate(t: Template, b: Bindings): Assertion {
if (!isEmbedded(v)) { if (!isEmbedded(v)) {
throw new Error(`Attempt to attenuate non-capability: ${stringify(v)}`); throw new Error(`Attempt to attenuate non-capability: ${stringify(v)}`);
} }
const r = v.embeddedValue; return attenuate(v, ... t.value.attenuation);
return embed(attenuate(r, ... t.value.attenuation));
} }
case 'TRef': { case 'TRef': {
const n = t.value.binding; const n = t.value.binding;
@ -136,9 +137,9 @@ export function instantiate(t: Template, b: Bindings): Assertion {
case 'arr': case 'arr':
return t.value.items.map(walk); return t.value.items.map(walk);
case 'dict': { case 'dict': {
const v = new Dictionary<Ref, Assertion>(); const v = new DictionaryMap<Ref, Assertion>();
t.value.entries.forEach((tt, key) => v.set(key, walk(tt))); 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)); 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 { export function attenuate(ref: Ref, ... a: Caveat[]): Ref {
if (a.length === 0) return 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 } { export function forwarder(ref: Ref): { proxy: Ref, revoker: Ref } {
@ -238,7 +244,7 @@ export function pArr(... items: Array<Pattern>): Pattern {
} }
export function pDict(... entries: [SturdyValue, Pattern][]): 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 { export function pLit(value: SturdyValue): Pattern {
@ -281,10 +287,6 @@ export function pDouble(): Pattern {
return Pattern.PAtom(PAtom.Double()); return Pattern.PAtom(PAtom.Double());
} }
export function pFloat(): Pattern {
return Pattern.PAtom(PAtom.Float());
}
export function pBoolean(): Pattern { export function pBoolean(): Pattern {
return Pattern.PAtom(PAtom.Boolean()); return Pattern.PAtom(PAtom.Boolean());
} }
@ -292,3 +294,27 @@ export function pBoolean(): Pattern {
export function pDiscard(): Pattern { export function pDiscard(): Pattern {
return Pattern.PDiscard(PDiscard()); return Pattern.PDiscard(PDiscard());
} }
export function tRec(label: SturdyValue, ... fields: Array<Template>): Template {
return Template.TCompound(TCompound.rec({ label, fields }));
}
export function tArr(... items: Array<Template>): Template {
return Template.TCompound(TCompound.arr(items));
}
export function tDict(... entries: [SturdyValue, Template][]): Template {
return Template.TCompound(TCompound.dict(new KeyedDictionary<_embedded, SturdyValue, Template>(entries)));
}
export function tLit(value: SturdyValue): Template {
return Template.Lit(Lit(value));
}
export function tRef(binding: number): Template {
return Template.TRef(TRef(binding));
}
export function tAttenuate(template: Template, ... attenuation: Caveat[]): Template {
return Template.TAttenuate(TAttenuate({ template, attenuation }));
}

View File

@ -1,12 +1,12 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Set, Dictionary, KeyedDictionary, IdentitySet, stringify, Value } from '@preserves/core'; import { Set, KeyedDictionary, IdentitySet, stringify, Value, Embeddable } from '@preserves/core';
import { AnyValue, Assertion, Ref } from './actor.js'; import { AnyValue, Assertion, Ref } from './actor.js';
import { Bag, ChangeDescription } from './bag.js'; import { Bag, ChangeDescription } from './bag.js';
import * as Stack from './stack.js'; import * as Stack from './stack.js';
import * as P from '../gen/dataspacePatterns.js'; import * as P from '../gen/dataspacePatterns.js';
import { Path, analysePattern, classOfCtor, classOfValue, step } from './pattern.js'; import { Path, analysePattern, classOfCtor, classOfValue, step, Shape, ConstantPositions } from './pattern.js';
enum EventType { enum EventType {
ADDED = +1, ADDED = +1,
@ -31,13 +31,15 @@ export class Index<T> {
readonly root: Node<T> = new Node(new Continuation(new Set())); readonly root: Node<T> = new Node(new Continuation(new Set()));
addObserver(pattern: P.Pattern, observer: IndexObserver<T>, parameter: T) { addObserver(pattern: P.Pattern, observer: IndexObserver<T>, parameter: T) {
let {constPaths, constValues, capturePaths} = analysePattern(pattern); let {constPositions, constValues, capturePaths} = analysePattern(pattern);
const continuation = this.root.extend(pattern); const continuation = this.root.extend(pattern);
let constValMap = continuation.leafMap.get(constPaths); let constValMap = continuation.leafMap.get(constPositions);
if (!constValMap) { if (!constValMap) {
constValMap = new Dictionary(); constValMap = new KeyedDictionary();
continuation.cachedAssertions.forEach((a) => { continuation.cachedAssertions.forEach((a) => {
const key = projectPaths(a, constPaths); if (projectPaths(a, constPositions.requiredToExist) === void 0) return;
const key = projectPaths(a, constPositions.withValues);
if (key === void 0) return;
let leaf = constValMap!.get(key); let leaf = constValMap!.get(key);
if (!leaf) { if (!leaf) {
leaf = new Leaf(); leaf = new Leaf();
@ -45,7 +47,7 @@ export class Index<T> {
} }
leaf.cachedAssertions.add(a); leaf.cachedAssertions.add(a);
}); });
continuation.leafMap.set(constPaths, constValMap); continuation.leafMap.set(constPositions, constValMap);
} }
let leaf = constValMap.get(constValues); let leaf = constValMap.get(constValues);
if (!leaf) { if (!leaf) {
@ -55,8 +57,10 @@ export class Index<T> {
let observerGroup = leaf.observerGroups.get(capturePaths); let observerGroup = leaf.observerGroups.get(capturePaths);
if (!observerGroup) { if (!observerGroup) {
const cachedCaptures = new Bag<Ref, Array<AnyValue>>(); const cachedCaptures = new Bag<Ref, Array<AnyValue>>();
leaf.cachedAssertions.forEach((a) => leaf.cachedAssertions.forEach((a) => {
cachedCaptures._items.update(projectPaths(a, capturePaths), n => n! + 1, 0)); const vs = projectPaths(a, capturePaths);
if (vs !== void 0) cachedCaptures._items.update(vs, n => n! + 1, 0);
});
observerGroup = new ObserverGroup(cachedCaptures); observerGroup = new ObserverGroup(cachedCaptures);
leaf.observerGroups.set(capturePaths, observerGroup); leaf.observerGroups.set(capturePaths, observerGroup);
} }
@ -65,9 +69,9 @@ export class Index<T> {
} }
removeObserver(pattern: P.Pattern, observer: IndexObserver<T>, parameter: T) { removeObserver(pattern: P.Pattern, observer: IndexObserver<T>, parameter: T) {
let {constPaths, constValues, capturePaths} = analysePattern(pattern); let {constPositions, constValues, capturePaths} = analysePattern(pattern);
const continuation = this.root.extend(pattern); const continuation = this.root.extend(pattern);
let constValMap = continuation.leafMap.get(constPaths); let constValMap = continuation.leafMap.get(constPositions);
if (!constValMap) return; if (!constValMap) return;
let leaf = constValMap.get(constValues); let leaf = constValMap.get(constValues);
if (!leaf) return; if (!leaf) return;
@ -82,7 +86,7 @@ export class Index<T> {
constValMap.delete(constValues); constValMap.delete(constValues);
} }
if (constValMap.size === 0) { if (constValMap.size === 0) {
continuation.leafMap.delete(constPaths); continuation.leafMap.delete(constPositions);
} }
} }
@ -142,13 +146,13 @@ export class Index<T> {
} }
} }
function dumpBag<T, V extends Value<T>>(b: Bag<T, V>, indent: string) { function dumpBag<T extends Embeddable, V extends Value<T>>(b: Bag<T, V>, indent: string) {
for (const [v, count] of b.entries()) { for (const [v, count] of b.entries()) {
console.log(indent + stringify(v) + ' = ' + count); console.log(indent + stringify(v) + ' = ' + count);
} }
} }
function dumpSet<V>(s: Set<V>, indent: string) { function dumpSet<V extends Embeddable>(s: Set<V>, indent: string) {
s.forEach(v => console.log(indent + stringify(v))); s.forEach(v => console.log(indent + stringify(v)));
} }
@ -156,7 +160,7 @@ type Selector = [number, AnyValue];
class Node<T> { class Node<T> {
readonly continuation: Continuation<T>; readonly continuation: Continuation<T>;
readonly edges: KeyedDictionary<Selector, { [shape: string]: Node<T> }, Ref> = new KeyedDictionary(); readonly edges: KeyedDictionary<Ref, Selector, { [shape: Shape]: Node<T> }> = new KeyedDictionary();
constructor(continuation: Continuation<T>) { constructor(continuation: Continuation<T>) {
this.continuation = continuation; this.continuation = continuation;
@ -168,19 +172,19 @@ class Node<T> {
function walkNode(node: Node<T>, popCount: number, stepIndex: AnyValue, p: P.Pattern): [number, Node<T>] function walkNode(node: Node<T>, popCount: number, stepIndex: AnyValue, p: P.Pattern): [number, Node<T>]
{ {
switch (p._variant) { switch (p._variant) {
case 'DDiscard': case 'discard':
case 'DLit': case 'lit':
return [popCount, node]; return [popCount, node];
case 'DBind': case 'bind':
return walkNode(node, popCount, stepIndex, p.value.pattern); return walkNode(node, popCount, stepIndex, p.pattern);
case 'DCompound': { case 'group': {
const selector: Selector = [popCount, stepIndex]; const selector: Selector = [popCount, stepIndex];
let table = node.edges.get(selector); let table = node.edges.get(selector);
if (!table) { if (!table) {
table = {}; table = {};
node.edges.set(selector, table); node.edges.set(selector, table);
} }
let cls = classOfCtor(p.value); let cls = classOfCtor(p.type);
let nextNode = table[cls]; let nextNode = table[cls];
if (!nextNode) { if (!nextNode) {
nextNode = new Node(new Continuation( nextNode = new Node(new Continuation(
@ -189,16 +193,11 @@ class Node<T> {
table[cls] = nextNode; table[cls] = nextNode;
} }
popCount = 0; popCount = 0;
function walkKey(pp: P.Pattern, stepIndex: AnyValue) { p.entries.forEach((pp, stepIndex) => {
path.push(stepIndex); path.push(stepIndex);
[popCount, nextNode] = walkNode(nextNode, popCount, stepIndex, pp); [popCount, nextNode] = walkNode(nextNode, popCount, stepIndex, pp);
path.pop(); path.pop();
} });
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;
}
return [popCount + 1, nextNode]; return [popCount + 1, nextNode];
} }
} }
@ -226,8 +225,10 @@ class Node<T> {
function walkContinuation(continuation: Continuation<T>) { function walkContinuation(continuation: Continuation<T>) {
m_cont(continuation, outerValue); m_cont(continuation, outerValue);
continuation.leafMap.forEach((constValMap, constPaths) => { continuation.leafMap.forEach((constValMap, constPositions) => {
let constValues = projectPaths(outerValue, constPaths); if (projectPaths(outerValue, constPositions.requiredToExist) === void 0) return;
let constValues = projectPaths(outerValue, constPositions.withValues);
if (constValues === void 0) return;
let leaf = constValMap.get(constValues); let leaf = constValMap.get(constValues);
if (!leaf && operation === EventType.ADDED) { if (!leaf && operation === EventType.ADDED) {
leaf = new Leaf(); leaf = new Leaf();
@ -236,12 +237,13 @@ class Node<T> {
if (leaf) { if (leaf) {
m_leaf(leaf, outerValue); m_leaf(leaf, outerValue);
leaf.observerGroups.forEach((observerGroup, capturePaths) => { leaf.observerGroups.forEach((observerGroup, capturePaths) => {
m_observerGroup(observerGroup, projectPaths(outerValue, capturePaths)); const vs = projectPaths(outerValue, capturePaths);
if (vs !== void 0) m_observerGroup(observerGroup, vs);
}); });
if (operation === EventType.REMOVED && leaf.isEmpty()) { if (operation === EventType.REMOVED && leaf.isEmpty()) {
constValMap.delete(constValues); constValMap.delete(constValues);
if (constValMap.size === 0) { if (constValMap.size === 0) {
continuation.leafMap.delete(constPaths); continuation.leafMap.delete(constPositions);
} }
} }
} }
@ -267,7 +269,7 @@ class Node<T> {
class Continuation<T> { class Continuation<T> {
readonly cachedAssertions: Set<Ref>; readonly cachedAssertions: Set<Ref>;
readonly leafMap: KeyedDictionary<Array<Path>, Dictionary<Ref, Leaf<T>>, Ref> = new KeyedDictionary(); readonly leafMap: KeyedDictionary<Ref, ConstantPositions, KeyedDictionary<Ref, Assertion, Leaf<T>>> = new KeyedDictionary();
constructor(cachedAssertions: Set<Ref>) { constructor(cachedAssertions: Set<Ref>) {
this.cachedAssertions = cachedAssertions; this.cachedAssertions = cachedAssertions;
@ -286,7 +288,7 @@ class Continuation<T> {
class Leaf<T> { class Leaf<T> {
readonly cachedAssertions: Set<Ref> = new Set(); readonly cachedAssertions: Set<Ref> = new Set();
readonly observerGroups: KeyedDictionary<Array<Path>, ObserverGroup<T>, Ref> = new KeyedDictionary(); readonly observerGroups: KeyedDictionary<Ref, Array<Path>, ObserverGroup<T>> = new KeyedDictionary();
isEmpty(): boolean { isEmpty(): boolean {
return this.cachedAssertions.size === 0 && this.observerGroups.size === 0; return this.cachedAssertions.size === 0 && this.observerGroups.size === 0;
@ -320,15 +322,21 @@ class ObserverGroup<T> {
} }
} }
// Total by assumption that path is valid for v function projectPath(v: AnyValue, path: Path): AnyValue | undefined {
function projectPath(v: AnyValue, path: Path): AnyValue {
for (let index of path) { for (let index of path) {
v = step(v, index)!; const next = step(v, index);
if (next === void 0) return void 0;
v = next;
} }
return v; return v;
} }
// Total by assumption that paths are valid for v function projectPaths(v: AnyValue, paths: Array<Path>): AnyValue[] | undefined {
function projectPaths(v: AnyValue, paths: Array<Path>): AnyValue[] { const result = [];
return paths.map((path) => projectPath(v, path)); for (const path of paths) {
const w = projectPath(v, path);
if (w === void 0) return void 0;
result.push(w);
}
return result;
} }

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2023-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { IdentityMap, IdentitySet, embeddedId, forEachEmbedded } from '@preserves/core'; import { IdentityMap, IdentitySet, embeddedId, forEachEmbedded } from '@preserves/core';
import type { Actor, Assertion, ExitReason, Handle, Ref } from './actor.js'; import type { Actor, Assertion, ExitReason, Handle, Ref } from './actor.js';

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
export type NonEmptyStack<T> = { item: T, rest: Stack<T> }; export type NonEmptyStack<T> = { item: T, rest: Stack<T> };
export type Stack<T> = null | NonEmptyStack<T>; export type Stack<T> = null | NonEmptyStack<T>;

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2021-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2021-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { State } from '../gen/service'; import { State } from '../gen/service';
import { Actor, AnyValue, LocalAction, Turn } from './actor'; import { Actor, AnyValue, LocalAction, Turn } from './actor';

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2023-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import type { Facet } from './actor.js'; import type { Facet } from './actor.js';

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2021-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2021-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
export * as dataspace from './gen/dataspace.js'; export * as dataspace from './gen/dataspace.js';
export * as dataspacePatterns from './gen/dataspacePatterns.js'; export * as dataspacePatterns from './gen/dataspacePatterns.js';

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Bytes, underlying } from '@preserves/core'; import { Bytes, underlying } from '@preserves/core';
import * as node_crypto from 'crypto'; import * as node_crypto from 'crypto';
@ -18,6 +18,7 @@ export const newKey: () => Promise<Bytes> =
const HMAC_BLAKE2s = makeHMAC(BLAKE2s); const HMAC_BLAKE2s = makeHMAC(BLAKE2s);
export async function mac(secretKey: Bytes, data: Bytes): Promise<Bytes> { export function mac(secretKey: Bytes, data: Bytes): Bytes {
return Bytes.from(HMAC_BLAKE2s(underlying(secretKey), underlying(data))); return Bytes.from(HMAC_BLAKE2s(underlying(secretKey), underlying(data))
.subarray(0, KEY_LENGTH));
} }

View File

@ -0,0 +1,307 @@
/// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Actor, Ref, Handle, Assertion, Entity, Turn } from '../runtime/actor.js';
import { Value, Embedded, mapEmbeddeds, IdentityMap, KeyedDictionary, stringify } from '@preserves/core';
import * as IO from '../gen/protocol.js';
import { fromCaveat, WireRef } from '../gen/sturdy.js';
import { attenuate } from '../runtime/rewrite.js';
export class WireSymbol {
count = 0;
constructor (
public side: Membrane,
public oid: IO.Oid,
public ref: Ref,
) {}
drop(): void {
this.count--;
if (this.count === 0) {
this.side.byOid.delete(this.oid);
this.side.byRef.delete(this.ref);
}
}
};
export type WhichTable = "byOid" | "byRef";
export class Membrane {
readonly byOid = new IdentityMap<IO.Oid, WireSymbol>();
readonly byRef = new IdentityMap<Ref, WireSymbol>();
grab<Table extends WhichTable>(table: Table,
key: Parameters<Membrane[Table]['get']>[0],
transient: boolean,
f: () => WireSymbol): WireSymbol;
grab<Table extends WhichTable>(table: Table,
key: Parameters<Membrane[Table]['get']>[0],
transient: boolean,
f: null): WireSymbol | null;
grab<Table extends WhichTable>(table: Table,
key: Parameters<Membrane[Table]['get']>[0],
transient: boolean,
f: (() => WireSymbol) | null): WireSymbol | null {
let e = this[table].get(key as any);
if (e === void 0) {
if (f === null) return null;
e = f();
this.byRef.set(e.ref, e);
this.byOid.set(e.oid, e);
}
if (!transient) e.count++;
return e;
}
}
export const INERT_REF = new Ref(
Actor.boot(() => Turn.active.stop(Turn.activeFacet)).root,
{});
export interface ProxyInbound {
proxyPacket(packet: IO.Packet<Embedded<WireRef>>): void;
}
export interface ProxyOutbound {
send(remoteOid: IO.Oid, event: IO.Event<Embedded<WireRef>>): void;
proxyAssertion(targetRemoteOid: IO.Oid, assertion: Assertion, handle: Handle): Value<Embedded<WireRef>>;
proxyRetract(handle: Handle): void;
proxyMessage(assertion: Assertion): Value<Embedded<WireRef>>;
proxySync(targetRemoteOid: IO.Oid, peer: Ref): Embedded<WireRef>;
}
export abstract class LayerBoundary implements ProxyOutbound, ProxyInbound {
readonly inboundAssertions = new IdentityMap<Handle, {
localHandle: Handle,
pins: Array<WireSymbol>,
}>();
readonly outboundAssertions = new IdentityMap<Handle, Array<WireSymbol>>();
readonly exported = new Membrane();
readonly imported = new Membrane();
constructor(public trustPeer = true, public nextLocalOid: IO.Oid = 0) {}
abstract send(remoteOid: IO.Oid, event: IO.Event<Embedded<WireRef>>): void;
proxyAssertion(targetRemoteOid: IO.Oid, assertion: Assertion, handle: Handle): Value<Embedded<WireRef>> {
const pins: Array<WireSymbol> = [];
const rewritten = mapEmbeddeds(assertion, r => this.rewriteRefOut(r, false, pins));
this.grabImportedOid(targetRemoteOid, pins);
this.outboundAssertions.set(handle, pins);
return rewritten;
}
proxyRetract(handle: Handle): void {
(this.outboundAssertions.get(handle) ?? []).forEach(e => e.drop());
this.outboundAssertions.delete(handle);
}
proxyMessage(assertion: Assertion): Value<Embedded<WireRef>> {
const pins: Array<WireSymbol> = [];
return mapEmbeddeds(assertion, r => this.rewriteRefOut(r, true, pins));
}
proxySync(targetRemoteOid: IO.Oid, peer: Ref): Embedded<WireRef> {
const peerEntity = new SyncPeerEntity(peer);
this.grabImportedOid(targetRemoteOid, peerEntity.pins);
return this.rewriteRefOut(Turn.ref(peerEntity), false, peerEntity.pins);
}
grabImportedOid(oid: IO.Oid, pins: Array<WireSymbol>): void {
const e = this.imported.grab("byOid", oid, false, null);
if (e === null) {
throw new Error("Internal error: import table missing entry for oid " + oid);
}
pins.push(e);
}
grabExportedOid(oid: IO.Oid, pins: Array<WireSymbol>): Ref {
const e = this.exported.grab("byOid", oid, false, null);
if (e === null) return INERT_REF;
pins.push(e);
return e.ref;
}
rewriteRefOut(r: Ref, transient: boolean, pins: Array<WireSymbol>): Embedded<WireRef> {
if (r.target instanceof ProxyEntity && r.target.relay === this) {
if (r.attenuation === void 0 || r.attenuation.length === 0) {
// No extra conditions on this reference since it was sent to us.
this.grabImportedOid(r.target.oid, pins);
return new Embedded<WireRef>(WireRef.yours({ oid: r.target.oid, attenuation: [] }));
} else {
// This reference has been attenuated since it was sent to us.
// Do we trust the peer to enforce such attenuation on our behalf?
if (this.trustPeer) {
this.grabImportedOid(r.target.oid, pins);
return new Embedded<WireRef>(WireRef.yours({ oid: r.target.oid, attenuation: r.attenuation }));
} else {
// fall through: treat the attenuated ref as a local ref, and re-export it.
}
}
}
const e = this.exported.grab(
"byRef", r, transient, () => {
if (transient) throw new Error("Cannot send transient reference");
return new WireSymbol(this.exported, this.nextLocalOid++, r);
});
pins.push(e);
return new Embedded<WireRef>(WireRef.mine(e.oid));
}
rewriteRefIn(nw: Embedded<WireRef>, pins: Array<WireSymbol>): Ref {
const n = nw.value;
switch (n._variant) {
case 'yours': {
const e = this.exported.grab("byOid", n.oid, false, null);
if (e === null) {
return INERT_REF;
} else {
pins.push(e);
const r = e.ref;
if (n.attenuation.length === 0) {
return r;
} else {
type AttenuatedRef = Ref & { __attenuations?: KeyedDictionary<Ref, Assertion, any> };
const ar = r as AttenuatedRef;
if (ar.__attenuations === void 0) {
ar.__attenuations = new KeyedDictionary();
}
return ar.__attenuations.getOrSet(n.attenuation.map(fromCaveat), () =>
attenuate(r, ... n.attenuation));
}
}
}
case 'mine': {
const e = this.imported.grab("byOid", n.oid, false, () =>
new WireSymbol(this.imported, n.oid, Turn.ref(new ProxyEntity(this, n.oid))));
pins.push(e);
return e.ref;
}
}
}
rewriteIn(a: Value<Embedded<WireRef>>): [Assertion, Array<WireSymbol>]
{
const pins: Array<WireSymbol> = [];
const rewritten = mapEmbeddeds(a, r => this.rewriteRefIn(r, pins));
return [rewritten, pins];
}
handle(localOid: IO.Oid, m: IO.Event<Embedded<WireRef>>): void {
switch (m._variant) {
case 'Assert': {
const [a, pins] = this.rewriteIn(m.value.assertion);
const r = this.grabExportedOid(localOid, pins);
this.inboundAssertions.set(m.value.handle, {
localHandle: Turn.active.assert(r, a),
pins,
});
break;
}
case 'Retract': {
const remoteHandle = m.value.handle;
const h = this.inboundAssertions.get(remoteHandle);
if (h === void 0) throw new Error(`Peer retracted invalid handle ${remoteHandle}`);
this.inboundAssertions.delete(remoteHandle);
h.pins.forEach(e => e.drop());
Turn.active.retract(h.localHandle);
break;
}
case 'Message': {
const [a, pins] = this.rewriteIn(m.value.body);
if (pins.length > 0) throw new Error("Cannot receive transient reference");
const r = this.exported.byOid.get(localOid)?.ref;
if (r) Turn.active.message(r, a);
break;
}
case 'Sync': {
const pins: Array<WireSymbol> = [];
const r = this.grabExportedOid(localOid, pins);
const k = this.rewriteRefIn(m.value.peer, pins);
Turn.active.sync(r).then(() => {
Turn.active.message(k, true);
pins.forEach(e => e.drop());
});
break;
}
}
}
proxyPacket(packet: IO.Packet<Embedded<WireRef>>): void {
switch (packet._variant) {
case 'Turn':
packet.value.forEach(v => this.handle(v.oid, v.event));
break;
case 'Error':
throw new Error(`Remote peer terminated relay: ${stringify(packet.value)}`);
case 'Extension':
// Ignore unknown extensions.
break;
}
}
}
export class ProxyEntity implements Entity {
readonly relay: ProxyOutbound;
readonly oid: IO.Oid;
constructor(relay: ProxyOutbound, oid: IO.Oid) {
this.relay = relay;
this.oid = oid;
}
send(m: IO.Event<Embedded<WireRef>>): void {
this.relay.send(this.oid, m);
}
assert(assertion: Assertion, handle: Handle): void {
this.send(IO.Event.Assert(IO.Assert({
assertion: this.relay.proxyAssertion(this.oid, assertion, handle),
handle
})))
}
retract(handle: Handle): void {
this.relay.proxyRetract(handle);
this.send(IO.Event.Retract(IO.Retract(handle)));
}
message(body: Assertion): void {
this.send(IO.Event.Message(IO.Message(this.relay.proxyMessage(body))));
}
sync(peer: Ref): void {
this.send(IO.Event.Sync(IO.Sync(this.relay.proxySync(this.oid, peer))));
}
}
export class SyncPeerEntity implements Entity {
readonly peer: Ref;
readonly handleMap = new IdentityMap<Handle, Handle>();
pins: Array<WireSymbol> = [];
constructor(peer: Ref) {
this.peer = peer;
}
assert(assertion: Assertion, handle: Handle): void {
this.handleMap.set(handle, Turn.active.assert(this.peer, assertion));
}
retract(handle: Handle): void {
Turn.active.retract(this.handleMap.get(handle)!);
this.handleMap.delete(handle);
}
message(body: Assertion): void {
// We get to vanish from the indexes now
this.pins.forEach(e => e.drop());
Turn.active.message(this.peer, body);
}
sync(peer: Ref): void {
Turn.active._sync(this.peer, peer);
}
}

View File

@ -1,23 +1,23 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import * as S from '../gen/sturdy.js'; import * as S from '../gen/sturdy.js';
import { Decoder, DecoderState, Encoder, EncoderState, GenericEmbedded, neverEmbeddedType, EmbeddedType, Value, EmbeddedWriter } from '@preserves/core'; import { Decoder, DecoderState, Encoder, EncoderState, neverEmbeddedType, EmbeddedType, Value, Embedded, EmbeddedWriter } from '@preserves/core';
export const wireRefEmbeddedType: EmbeddedType<S.WireRef> & EmbeddedWriter<S.WireRef> = { export const wireRefEmbeddedType: EmbeddedType<Embedded<S.WireRef>> & EmbeddedWriter<Embedded<S.WireRef>> = {
decode(s: DecoderState): S.WireRef { decode(s: DecoderState): Embedded<S.WireRef> {
return S.asWireRef(new Decoder<any>(s).next()); return new Embedded<S.WireRef>(S.asWireRef(new Decoder<any>(s).next()));
}, },
encode(s: EncoderState, v: S.WireRef): void { encode(s: EncoderState, v: Embedded<S.WireRef>): void {
new Encoder<any>(s, neverEmbeddedType).push(S.fromWireRef(v)); new Encoder<any>(s, neverEmbeddedType).push(S.fromWireRef(v.value));
}, },
fromValue(v: Value<GenericEmbedded>): S.WireRef { fromValue(v: Value): Embedded<S.WireRef> {
return S.asWireRef(v as Value<S._embedded>); return new Embedded<S.WireRef>(S.asWireRef(v as Value<S._embedded>));
}, },
toValue(v: S.WireRef): Value<GenericEmbedded> { toValue(v: Embedded<S.WireRef>): Value {
return S.fromWireRef(v) as Value<GenericEmbedded>; return S.fromWireRef(v.value) as Value;
} }
}; };

View File

@ -1,136 +1,15 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Actor, Assertion, Entity, Facet, Handle, Ref, Turn } from '../runtime/actor.js'; import { Assertion, Facet, Ref, Turn } from '../runtime/actor.js';
import { BytesLike, Decoder, Dictionary, embed, encode, IdentityMap, mapEmbeddeds, stringify, underlying, Value } from '@preserves/core'; import { BytesLike, Decoder, encode, Embedded, stringify, underlying } from '@preserves/core';
import * as IO from '../gen/protocol.js'; import * as IO from '../gen/protocol.js';
import { wireRefEmbeddedType } from './protocol.js'; import { wireRefEmbeddedType } from './protocol.js';
import { attenuate } from '../runtime/rewrite.js'; import { WireRef } from '../gen/sturdy.js';
import { fromCaveat, WireRef } from '../gen/sturdy.js'; import { LayerBoundary } from './membrane.js';
const FLUSH = Symbol.for('flush'); const FLUSH = Symbol.for('flush');
export class WireSymbol {
count = 0;
constructor (
public side: Membrane,
public oid: IO.Oid,
public ref: Ref,
) {}
drop(): void {
this.count--;
if (this.count === 0) {
this.side.byOid.delete(this.oid);
this.side.byRef.delete(this.ref);
}
}
};
export class SyncPeerEntity implements Entity {
readonly relay: Relay;
readonly peer: Ref;
readonly handleMap = new IdentityMap<Handle, Handle>();
pins: Array<WireSymbol> = [];
constructor(relay: Relay, peer: Ref) {
this.relay = relay;
this.peer = peer;
}
assert(assertion: Assertion, handle: Handle): void {
this.handleMap.set(handle, Turn.active.assert(this.peer, assertion));
}
retract(handle: Handle): void {
Turn.active.retract(this.handleMap.get(handle)!);
this.handleMap.delete(handle);
}
message(body: Assertion): void {
// We get to vanish from the indexes now
this.pins.forEach(e => e.drop());
Turn.active.message(this.peer, body);
}
sync(peer: Ref): void {
Turn.active._sync(this.peer, peer);
}
}
export class RelayEntity implements Entity {
readonly relay: Relay;
readonly oid: IO.Oid;
constructor(relay: Relay, oid: IO.Oid) {
this.relay = relay;
this.oid = oid;
}
send(m: IO.Event<WireRef>): void {
this.relay.send(this.oid, m);
}
assert(assertion: Assertion, handle: Handle): void {
this.send(IO.Event.Assert(IO.Assert({
assertion: this.relay.register(this.oid, assertion, handle),
handle
})))
}
retract(handle: Handle): void {
this.relay.deregister(handle);
this.send(IO.Event.Retract(IO.Retract(handle)));
}
message(body: Assertion): void {
this.send(IO.Event.Message(IO.Message(this.relay.register(null, body, null))));
}
sync(peer: Ref): void {
const peerEntity = new SyncPeerEntity(this.relay, peer);
this.relay.grabImportedOid(this.oid, peerEntity.pins);
const ior = this.relay.rewriteRefOut(Turn.ref(peerEntity), false, peerEntity.pins);
this.send(IO.Event.Sync(IO.Sync(ior)));
}
}
export type WhichTable = "byOid" | "byRef";
export class Membrane {
readonly byOid = new IdentityMap<IO.Oid, WireSymbol>();
readonly byRef = new IdentityMap<Ref, WireSymbol>();
grab<Table extends WhichTable>(table: Table,
key: Parameters<Membrane[Table]['get']>[0],
transient: boolean,
f: () => WireSymbol): WireSymbol;
grab<Table extends WhichTable>(table: Table,
key: Parameters<Membrane[Table]['get']>[0],
transient: boolean,
f: null): WireSymbol | null;
grab<Table extends WhichTable>(table: Table,
key: Parameters<Membrane[Table]['get']>[0],
transient: boolean,
f: (() => WireSymbol) | null): WireSymbol | null {
let e = this[table].get(key as any);
if (e === void 0) {
if (f === null) return null;
e = f();
this.byRef.set(e.ref, e);
this.byOid.set(e.oid, e);
}
if (!transient) e.count++;
return e;
}
}
export const INERT_REF: Ref = {
relay: Actor.boot(() => Turn.active.stop()).root,
target: {},
};
export type PacketWriter = (bs: Uint8Array) => void; export type PacketWriter = (bs: Uint8Array) => void;
export interface RelayOptions { export interface RelayOptions {
@ -143,22 +22,13 @@ export interface RelayOptions {
nextLocalOid?: IO.Oid; nextLocalOid?: IO.Oid;
} }
export class Relay { export class Relay extends LayerBoundary {
readonly facet: Facet; readonly facet: Facet;
readonly selfRef: Ref; readonly selfRef: Ref;
readonly w: PacketWriter; readonly w: PacketWriter;
readonly inboundAssertions = new IdentityMap<Handle, {
localHandle: Handle,
pins: Array<WireSymbol>,
}>();
readonly outboundAssertions = new IdentityMap<Handle, Array<WireSymbol>>();
readonly exported = new Membrane();
readonly imported = new Membrane();
readonly peer: Ref | null; readonly peer: Ref | null;
nextLocalOid: IO.Oid = 0; pendingTurn: IO.Turn<Embedded<WireRef>> = [];
pendingTurn: IO.Turn<WireRef> = [];
debug: boolean; debug: boolean;
trustPeer: boolean;
readonly decoder = new Decoder(void 0, { readonly decoder = new Decoder(void 0, {
includeAnnotations: false, includeAnnotations: false,
@ -166,11 +36,12 @@ export class Relay {
}); });
constructor(options: RelayOptions) { constructor(options: RelayOptions) {
super(options.trustPeer, options.nextLocalOid);
this.facet = Turn.activeFacet; this.facet = Turn.activeFacet;
this.selfRef = Turn.ref(this); this.selfRef = Turn.ref(this);
this.w = options.packetWriter; this.w = options.packetWriter;
this.debug = options.debug ?? false; this.debug = options.debug ?? false;
this.trustPeer = options.trustPeer ?? true;
this.facet.preventInertCheck(); this.facet.preventInertCheck();
options.setup(this); options.setup(this);
@ -180,105 +51,8 @@ export class Relay {
} }
this.peer = (options.initialOid !== void 0) this.peer = (options.initialOid !== void 0)
? this.rewriteRefIn(WireRef.mine(options.initialOid), []) ? this.rewriteRefIn(new Embedded<WireRef>(WireRef.mine(options.initialOid)), [])
: null; : null;
if (options.nextLocalOid !== void 0) {
this.nextLocalOid = (options.nextLocalOid === 0) ? 1 : options.nextLocalOid;
}
}
register(targetRemoteOid: IO.Oid, assertion: Assertion, handle: Handle): Value<WireRef>;
register(targetRemoteOid: null, assertion: Assertion, handle: null): Value<WireRef>;
register(targetRemoteOid: IO.Oid | null, assertion: Assertion, handle: Handle | null): Value<WireRef> {
const transient = (handle === null);
const pins: Array<WireSymbol> = [];
const rewritten = mapEmbeddeds(assertion, r => embed(this.rewriteRefOut(r, transient, pins)));
if (handle !== null) {
if (targetRemoteOid !== null /* belt and suspenders */) {
this.grabImportedOid(targetRemoteOid, pins);
}
this.outboundAssertions.set(handle, pins);
}
return rewritten;
}
deregister(handle: Handle): void {
(this.outboundAssertions.get(handle) ?? []).forEach(e => e.drop());
this.outboundAssertions.delete(handle);
}
grabImportedOid(oid: IO.Oid, pins: Array<WireSymbol>) {
const e = this.imported.grab("byOid", oid, false, null);
if (e === null) {
throw new Error("Internal error: import table missing entry for oid " + oid);
}
pins.push(e);
}
grabExportedOid(oid: IO.Oid, pins: Array<WireSymbol>): Ref {
const e = this.exported.grab("byOid", oid, false, null);
if (e === null) return INERT_REF;
pins.push(e);
return e.ref;
}
rewriteRefOut(r: Ref, transient: boolean, pins: Array<WireSymbol>): WireRef {
if (r.target instanceof RelayEntity && r.target.relay === this) {
if (r.attenuation === void 0 || r.attenuation.length === 0) {
// No extra conditions on this reference since it was sent to us.
this.grabImportedOid(r.target.oid, pins);
return WireRef.yours({ oid: r.target.oid, attenuation: [] });
} else {
// This reference has been attenuated since it was sent to us.
// Do we trust the peer to enforce such attenuation on our behalf?
if (this.trustPeer) {
this.grabImportedOid(r.target.oid, pins);
return WireRef.yours({ oid: r.target.oid, attenuation: r.attenuation });
} else {
// fall through: treat the attenuated ref as a local ref, and re-export it.
}
}
}
const e = this.exported.grab(
"byRef", r, transient, () => {
if (transient) throw new Error("Cannot send transient reference");
return new WireSymbol(this.exported, this.nextLocalOid++, r);
});
pins.push(e);
return WireRef.mine(e.oid);
}
rewriteRefIn(n: WireRef, pins: Array<WireSymbol>): Ref {
switch (n._variant) {
case 'yours': {
const e = this.exported.grab("byOid", n.oid, false, null);
if (e === null) {
return INERT_REF;
} else {
pins.push(e);
const r = e.ref;
if (n.attenuation.length === 0) {
return r;
} else {
type AttenuatedRef = Ref & { __attenuations?: Dictionary<any, Ref> };
const ar = r as AttenuatedRef;
if (ar.__attenuations === void 0) {
ar.__attenuations = new Dictionary();
}
return ar.__attenuations.getOrSet(n.attenuation.map(fromCaveat), () =>
attenuate(r, ... n.attenuation));
}
}
}
case 'mine': {
const e = this.imported.grab("byOid", n.oid, false, () =>
new WireSymbol(this.imported, n.oid, Turn.ref(new RelayEntity(this, n.oid))));
pins.push(e);
return e.ref;
}
}
} }
message(body: Assertion) { message(body: Assertion) {
@ -292,7 +66,7 @@ export class Relay {
} }
} }
send(remoteOid: IO.Oid, m: IO.Event<WireRef>): void { send(remoteOid: IO.Oid, m: IO.Event<Embedded<WireRef>>): void {
if (this.pendingTurn.length === 0) { if (this.pendingTurn.length === 0) {
Turn.active.message(this.selfRef, FLUSH); Turn.active.message(this.selfRef, FLUSH);
} }
@ -300,63 +74,16 @@ export class Relay {
} }
accept(bs: BytesLike): void { accept(bs: BytesLike): void {
Turn.for(this.facet, () => { this.facet.turn(() => {
this.decoder.write(bs); this.decoder.write(bs);
while (true) { while (true) {
const rawTurn = this.decoder.try_next(); const rawPacket = this.decoder.try_next();
if (rawTurn === void 0) break; if (rawPacket === void 0) break;
const wireTurn = IO.toTurn(rawTurn); const wirePacket = IO.toPacket(rawPacket);
if (wireTurn === void 0) throw new Error("Bad IO.Turn"); if (wirePacket === void 0) throw new Error("Bad IO.Packet");
if (this.debug) console.log('IN', stringify(rawTurn)); if (this.debug) console.log('IN', stringify(rawPacket));
wireTurn.forEach(v => this.handle(v.oid, v.event)); this.proxyPacket(wirePacket);
} }
}); });
} }
rewriteIn(a: Value<WireRef>): [Assertion, Array<WireSymbol>]
{
const pins: Array<WireSymbol> = [];
const rewritten = mapEmbeddeds(a, r => embed(this.rewriteRefIn(r, pins)));
return [rewritten, pins];
}
handle(localOid: IO.Oid, m: IO.Event<WireRef>) {
switch (m._variant) {
case 'Assert': {
const [a, pins] = this.rewriteIn(m.value.assertion);
const r = this.grabExportedOid(localOid, pins);
this.inboundAssertions.set(m.value.handle, {
localHandle: Turn.active.assert(r, a),
pins,
});
break;
}
case 'Retract': {
const remoteHandle = m.value.handle;
const h = this.inboundAssertions.get(remoteHandle);
if (h === void 0) throw new Error(`Peer retracted invalid handle ${remoteHandle}`);
this.inboundAssertions.delete(remoteHandle);
h.pins.forEach(e => e.drop());
Turn.active.retract(h.localHandle);
break;
}
case 'Message': {
const [a, pins] = this.rewriteIn(m.value.body);
if (pins.length > 0) throw new Error("Cannot receive transient reference");
const r = this.exported.byOid.get(localOid)?.ref;
if (r) Turn.active.message(r, a);
break;
}
case 'Sync': {
const pins: Array<WireSymbol> = [];
const r = this.grabExportedOid(localOid, pins);
const k = this.rewriteRefIn(m.value.peer, pins);
Turn.active.sync(r).then(() => {
Turn.active.message(k, true);
pins.forEach(e => e.drop());
});
break;
}
}
}
} }

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
// Basically Macaroons [1] in a Dataspace context // Basically Macaroons [1] in a Dataspace context
// //
@ -10,8 +10,9 @@
// California: Internet Society, 2014. // California: Internet Society, 2014.
import { mac } from './cryptography.js'; import { mac } from './cryptography.js';
import { Bytes, decode, encode, is, neverEmbeddedType, Value } from '@preserves/core'; import { Bytes, decode, encode, is, neverEmbeddedType, Value, fromJS } from '@preserves/core';
import * as S from '../gen/sturdy.js'; import * as S from '../gen/sturdy.js';
import * as G from '../gen/gatekeeper.js';
export * from '../gen/sturdy.js'; export * from '../gen/sturdy.js';
export type SturdyValue = Value<S._embedded>; export type SturdyValue = Value<S._embedded>;
@ -37,16 +38,42 @@ export function sturdyDecode(bs: Bytes): SturdyValue {
}); });
} }
export async function mint(oid: SturdyValue, secretKey: Bytes): Promise<S.SturdyRef> { export function sturdyBind(
return S.SturdyRef(S.Parameters({ oid: SturdyValue,
oid, secretKey: Bytes,
sig: await mac(secretKey, sturdyEncode(oid)), target: S._embedded,
caveats: S.CaveatsField.absent(), observer?: S._embedded,
})); ): G.Bind {
return G.Bind({
description: G.Description({
stepType: fromJS(S.SturdyStepType()) as symbol,
detail: fromJS(S.SturdyDescriptionDetail({ oid, key: secretKey })),
}),
target,
observer: (observer === void 0) ? G.BindObserver.absent() : G.BindObserver.present(observer),
});
} }
async function chainMac(key: Bytes | Promise<Bytes>, caveats: S.Caveat[]): Promise<Bytes> { type RefAndBind = { ref: S.SturdyRef, bind: G.Bind };
return caveats.reduce(async (key, c) => mac(await key, sturdyEncode(S.fromCaveat(c))), key); export function mint(oid: SturdyValue, secretKey: Bytes): S.SturdyRef;
export function mint(oid: SturdyValue, secretKey: Bytes, target: S._embedded, observer?: S._embedded): RefAndBind;
export function mint(
oid: SturdyValue,
secretKey: Bytes,
target?: S._embedded,
observer?: S._embedded,
): S.SturdyRef | RefAndBind {
const ref = S.SturdyRef(S.Parameters({
oid,
sig: mac(secretKey, sturdyEncode(oid)),
caveats: S.CaveatsField.absent(),
}));
if (target === void 0) return ref;
return { ref, bind: sturdyBind(oid, secretKey, target, observer) };
}
function chainMac(key: Bytes, caveats: S.Caveat[]): Bytes {
return caveats.reduce((key, c) => mac(key, sturdyEncode(S.fromCaveat(c))), key);
} }
export function caveatChain(r: S.SturdyRef): S.Caveat[] { export function caveatChain(r: S.SturdyRef): S.Caveat[] {
@ -57,16 +84,16 @@ export function caveatChain(r: S.SturdyRef): S.Caveat[] {
} }
} }
export async function attenuate(r: S.SturdyRef, ... a: S.Caveat[]): Promise<S.SturdyRef> { export function attenuate(r: S.SturdyRef, ... a: S.Caveat[]): S.SturdyRef {
if (a.length === 0) return r; if (a.length === 0) return r;
return S.SturdyRef(S.Parameters({ return S.SturdyRef(S.Parameters({
oid: r.parameters.oid, oid: r.parameters.oid,
caveats: S.CaveatsField.present([... caveatChain(r), ... a]), caveats: S.CaveatsField.present([... caveatChain(r), ... a]),
sig: await chainMac(r.parameters.sig, a), sig: chainMac(r.parameters.sig, a),
})); }));
} }
export async function validate(r: S.SturdyRef, secretKey: Bytes): Promise<boolean> { export function validate(r: S.SturdyRef, secretKey: Bytes): boolean {
const sig = await chainMac(await mac(secretKey, sturdyEncode(r.parameters.oid)), caveatChain(r)); const sig = chainMac(mac(secretKey, sturdyEncode(r.parameters.oid)), caveatChain(r));
return is(sig, r.parameters.sig); return is(sig, r.parameters.sig);
} }

View File

@ -1,4 +1,4 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
export const randomBytes = void 0; export const randomBytes = void 0;

View File

@ -1,12 +1,12 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { KeyedSet } from '@preserves/core'; import { GenericEmbedded, KeyedSet } from '@preserves/core';
import { Bag, ChangeDescription } from '../src/runtime/bag'; import { Bag, ChangeDescription } from '../src/runtime/bag';
describe('bag', () => { describe('bag', () => {
it('should be initializable from a set', () => { it('should be initializable from a set', () => {
const b = new Bag(new KeyedSet<string>(['a', 'b', 'c'])); const b = new Bag(new KeyedSet<GenericEmbedded, string>(['a', 'b', 'c']));
expect(b.size).toBe(3); expect(b.size).toBe(3);
expect(b.get('a')).toBe(1); expect(b.get('a')).toBe(1);
expect(b.get('z')).toBe(0); expect(b.get('z')).toBe(0);
@ -28,7 +28,7 @@ describe('bag', () => {
}); });
it('should count down', () => { it('should count down', () => {
const b = new Bag(new KeyedSet<string>(['a'])); const b = new Bag(new KeyedSet<GenericEmbedded, string>(['a']));
expect(b.change('a', 1)).toBe(ChangeDescription.PRESENT_TO_PRESENT); expect(b.change('a', 1)).toBe(ChangeDescription.PRESENT_TO_PRESENT);
expect(b.change('a', -1)).toBe(ChangeDescription.PRESENT_TO_PRESENT); expect(b.change('a', -1)).toBe(ChangeDescription.PRESENT_TO_PRESENT);
expect(b.size).toBe(1); expect(b.size).toBe(1);

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Canonicalizer, embeddedId, FlexSet } from '@preserves/core'; import { Canonicalizer, embeddedId, FlexSet } from '@preserves/core';
import { Cell, Field, Graph } from '../src/runtime/dataflow'; import { Cell, Field, Graph } from '../src/runtime/dataflow';

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { is, preserves } from '@preserves/core'; import { is, preserves } from '@preserves/core';

View File

@ -1,6 +1,6 @@
{ {
"name": "@syndicate-lang/create", "name": "@syndicate-lang/create",
"version": "0.19.0", "version": "0.25.0",
"description": "Create a new Syndicate/js package", "description": "Create a new Syndicate/js package",
"author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>", "author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>",
"homepage": "https://github.com/syndicate-lang/syndicate-js/tree/main/packages/create", "homepage": "https://github.com/syndicate-lang/syndicate-js/tree/main/packages/create",

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2023-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import yargs from 'yargs/yargs'; import yargs from 'yargs/yargs';

View File

@ -1,22 +0,0 @@
((typescript-mode
. ((eval
. (progn
;; For TIDE:
(setq tide-tsserver-executable
(concat
(let ((d (dir-locals-find-file ".")))
(if (stringp d) d (car d)))
"node_modules/typescript/lib/tsserver.js"))
;; For LSP:
(require 'lsp-javascript)
(let ((node-modules (concat
(let ((d (dir-locals-find-file ".")))
(if (stringp d) d (car d)))
"node_modules/")))
(lsp-dependency 'typescript-language-server
`(:system ,(concat node-modules
"typescript-language-server/lib/cli.mjs")))
(lsp-dependency 'typescript
`(:system ,(concat node-modules
"typescript/lib/tsserver.js")))))
))))

View File

@ -6,7 +6,7 @@
<link href="style.css" rel="stylesheet"> <link href="style.css" rel="stylesheet">
<script src="node_modules/@preserves/core/dist/preserves.js"></script> <script src="node_modules/@preserves/core/dist/preserves.js"></script>
<script src="node_modules/@syndicate-lang/core/dist/syndicate.js"></script> <script src="node_modules/@syndicate-lang/core/dist/syndicate.js"></script>
<script src="node_modules/@syndicate-lang/html/dist/syndicate-html.js"></script> <script src="node_modules/@syndicate-lang/html2/dist/syndicate-html2.js"></script>
<script src="node_modules/@syndicate-lang/ws-relay/dist/syndicate-ws-relay.js"></script> <script src="node_modules/@syndicate-lang/ws-relay/dist/syndicate-ws-relay.js"></script>
<script src="index.js"></script> <script src="index.js"></script>
</head> </head>

View File

@ -3,7 +3,7 @@
"version": "0.0.0", "version": "0.0.0",
"license": "GPL-3.0+", "license": "GPL-3.0+",
"devDependencies": { "devDependencies": {
"@preserves/schema-cli": "0.992.5", "@preserves/schema-cli": "0.995.201",
"@syndicate-lang/ts-plugin": "*", "@syndicate-lang/ts-plugin": "*",
"@syndicate-lang/tsc": "*", "@syndicate-lang/tsc": "*",
"rollup": "^2.60", "rollup": "^2.60",
@ -12,9 +12,9 @@
"typescript-language-server": "^3.0" "typescript-language-server": "^3.0"
}, },
"dependencies": { "dependencies": {
"@preserves/core": "0.992.4", "@preserves/core": "0.995.200",
"@syndicate-lang/core": "*", "@syndicate-lang/core": "*",
"@syndicate-lang/html": "*", "@syndicate-lang/html2": "*",
"@syndicate-lang/ws-relay": "*" "@syndicate-lang/ws-relay": "*"
}, },
"scripts": { "scripts": {
@ -26,6 +26,6 @@
"rollup": "rollup -c", "rollup": "rollup -c",
"rollup:watch": "rollup -c -w", "rollup:watch": "rollup -c -w",
"clean": "rm -rf lib/ src.ts/ src/gen/ index.js index.js.map", "clean": "rm -rf lib/ src.ts/ src/gen/ index.js index.js.map",
"serve": "python -m http.server" "serve": "syndicate-server -c syndicate-server.config.pr"
} }
} }

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2023-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import sourcemaps from 'rollup-plugin-sourcemaps'; import sourcemaps from 'rollup-plugin-sourcemaps';
@ -9,7 +9,7 @@ export default {
external: [ external: [
'@preserves/core', '@preserves/core',
'@syndicate-lang/core', '@syndicate-lang/core',
'@syndicate-lang/html', '@syndicate-lang/html2',
'@syndicate-lang/ws-relay', '@syndicate-lang/ws-relay',
], ],
output: { output: {
@ -20,7 +20,7 @@ export default {
globals: { globals: {
'@preserves/core': 'Preserves', '@preserves/core': 'Preserves',
'@syndicate-lang/core': 'Syndicate', '@syndicate-lang/core': 'Syndicate',
'@syndicate-lang/html': 'SyndicateHtml', '@syndicate-lang/html2': 'SyndicateHtml2',
'@syndicate-lang/ws-relay': 'SyndicateWsRelay', '@syndicate-lang/ws-relay': 'SyndicateWsRelay',
}, },
}, },

View File

@ -1,15 +1,15 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2023-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Dataspace, Ref, Sturdy, Reader, Schemas, Embedded, randomId, fromJS } from "@syndicate-lang/core"; import { Dataspace, Ref, Sturdy, Reader, Schemas, Embedded, randomId, fromJS } from "@syndicate-lang/core";
import html from "@syndicate-lang/html"; import { boot as bootHtml, Widget } from "@syndicate-lang/html2";
import wsRelay from "@syndicate-lang/ws-relay"; import wsRelay from "@syndicate-lang/ws-relay";
import { ExampleDefinition } from './gen/example'; import { ExampleDefinition } from './gen/example';
import G = Schemas.gatekeeper; import G = Schemas.gatekeeper;
export function main() { export function main() {
Dataspace.boot(ds => { Dataspace.boot(ds => {
html.boot(ds); bootHtml(ds);
wsRelay.boot(ds, true /* remove this `true` to turn off client/server debug logging */); wsRelay.boot(ds, true /* remove this `true` to turn off client/server debug logging */);
bootApp(ds); bootApp(ds);
}); });
@ -19,7 +19,7 @@ function bootApp(ds: Ref) {
spawn named 'app' { spawn named 'app' {
at ds { at ds {
/* /*
* This example expects a syndicate-server instance running on port 9001 on the * This example expects a syndicate-server instance running on port 8000 on the
* server hosting index.html, exposing a dataspace entity via a capability called * server hosting index.html, exposing a dataspace entity via a capability called
* `"syndicate"` with empty "secret". See syndicate-server.config.pr. * `"syndicate"` with empty "secret". See syndicate-server.config.pr.
*/ */
@ -28,7 +28,7 @@ function bootApp(ds: Ref) {
const route = G.Route<Ref>({ const route = G.Route<Ref>({
"transports": [fromJS(Schemas.transportAddress.WebSocket( "transports": [fromJS(Schemas.transportAddress.WebSocket(
`ws://${document.location.hostname}:9001/`))], `ws://${document.location.hostname}:8000/`))],
"pathSteps": [G.asPathStep(fromJS(Sturdy.asSturdyRef( "pathSteps": [G.asPathStep(fromJS(Sturdy.asSturdyRef(
new Reader<Ref>( new Reader<Ref>(
'<ref {oid: "syndicate" sig: #[acowDB2/oI+6aSEC3YIxGg==]}>').next())))], '<ref {oid: "syndicate" sig: #[acowDB2/oI+6aSEC3YIxGg==]}>').next())))],
@ -42,13 +42,9 @@ function bootApp(ds: Ref) {
at remoteDs { at remoteDs {
assert ExampleDefinition(this_instance); assert ExampleDefinition(this_instance);
during ExampleDefinition($who: string) => { during ExampleDefinition($who: string) => {
const ui = new html.Anchor(); new Widget(t =>
at ds { t`<p>We see <span class="example-definition">${who}</span></p>`)
assert ui.html( .setParent('#main');
'#main',
html.template`<p>We see <span class="example-definition">${who}</span></p>`,
who);
}
} }
} }
} }

View File

@ -1,12 +1,18 @@
; Start the server with # Start the server with
; #
; syndicate-server -c ./syndicate-server.config.pr # syndicate-server -c ./syndicate-server.config.pr
;--------------------------------------------------------------------------- # ---------------------------------------------------------------------------
; Expose the gatekeeper on port 9001: # Expose the gatekeeper and HTTP on port 8000:
<require-service <relay-listener <tcp "0.0.0.0" 9001> $gatekeeper>> <require-service <relay-listener <tcp "0.0.0.0" 8000> $gatekeeper $config>>
<require-service <http-router $config>>
; Create a dataspace entity, and register it with the gatekeeper with name `"syndicate"` and an <require-service <http-static-files "." 0>>
; empty secret key: ? <service-object <http-static-files "." 0> ?handler> [
$config += <http-bind #f 8000 get [...] $handler>
]
# Create a dataspace entity, and register it with the gatekeeper with name `"syndicate"` and an
# empty secret key:
let ?ds = dataspace let ?ds = dataspace
<bind <ref {oid: "syndicate" key: #x""}> $ds #f> <bind <ref {oid: "syndicate" key: #x""}> $ds #f>

View File

@ -1,6 +1,6 @@
#!/usr/bin/env -S node -r esm #!/usr/bin/env -S node -r esm
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
try { try {
require('../lib/index.js').main(process.argv.slice(2)); require('../lib/index.js').main(process.argv.slice(2));

View File

@ -1,6 +1,6 @@
{ {
"name": "@syndicate-lang/fs", "name": "@syndicate-lang/fs",
"version": "0.24.0", "version": "0.33.0",
"description": "Reflect contents of a portion of the file system as assertions", "description": "Reflect contents of a portion of the file system as assertions",
"homepage": "https://github.com/syndicate-lang/syndicate-js/tree/main/packages/fs", "homepage": "https://github.com/syndicate-lang/syndicate-js/tree/main/packages/fs",
"license": "GPL-3.0+", "license": "GPL-3.0+",
@ -27,16 +27,16 @@
"syndicate-fs": "./bin/syndicate-fs.js" "syndicate-fs": "./bin/syndicate-fs.js"
}, },
"peerDependencies": { "peerDependencies": {
"@preserves/core": "0.992.4" "@preserves/core": "0.995.200"
}, },
"dependencies": { "dependencies": {
"@syndicate-lang/core": "^0.23.0", "@syndicate-lang/core": "^0.32.0",
"@syndicate-lang/service": "^0.24.0", "@syndicate-lang/service": "^0.33.0",
"chokidar": "^3.5.3" "chokidar": "^3.5.3"
}, },
"devDependencies": { "devDependencies": {
"@preserves/schema-cli": "0.992.5", "@preserves/schema-cli": "0.995.201",
"@syndicate-lang/ts-plugin": "^0.24.0", "@syndicate-lang/ts-plugin": "^0.34.0",
"@syndicate-lang/tsc": "^0.24.0" "@syndicate-lang/tsc": "^0.34.0"
} }
} }

View File

@ -2,7 +2,7 @@ version 1 .
Config = @core CoreConfig & @awaitWriteFinish AwaitWriteFinishConfig . Config = @core CoreConfig & @awaitWriteFinish AwaitWriteFinishConfig .
CoreConfig = { CoreConfig = {
dataspace: #!any, dataspace: #:any,
label: any, label: any,
path: string, path: string,
} . } .

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2023-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Bytes, Observe, Ref, Turn, stringify } from "@syndicate-lang/core"; import { Bytes, Observe, Ref, Turn, stringify } from "@syndicate-lang/core";
import { QuasiValue as Q } from "@syndicate-lang/core"; import { QuasiValue as Q } from "@syndicate-lang/core";

View File

@ -1,6 +1,6 @@
{ {
"name": "@syndicate-lang/html", "name": "@syndicate-lang/html",
"version": "0.24.0", "version": "0.33.0",
"description": "DOM/HTML UI for Syndicate/JS", "description": "DOM/HTML UI for Syndicate/JS",
"homepage": "https://github.com/syndicate-lang/syndicate-js/tree/main/packages/html", "homepage": "https://github.com/syndicate-lang/syndicate-js/tree/main/packages/html",
"license": "GPL-3.0+", "license": "GPL-3.0+",
@ -25,10 +25,10 @@
"veryclean": "yarn run clean && rm -rf node_modules" "veryclean": "yarn run clean && rm -rf node_modules"
}, },
"dependencies": { "dependencies": {
"@syndicate-lang/core": "^0.23.0" "@syndicate-lang/core": "^0.32.0"
}, },
"devDependencies": { "devDependencies": {
"@syndicate-lang/ts-plugin": "^0.24.0", "@syndicate-lang/ts-plugin": "^0.34.0",
"@syndicate-lang/tsc": "^0.24.0" "@syndicate-lang/tsc": "^0.34.0"
} }
} }

View File

@ -1,5 +1,5 @@
/// SPDX-License-Identifier: GPL-3.0-or-later /// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2023 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { SyndicateRollup } from '../../rollup.js'; import { SyndicateRollup } from '../../rollup.js';
const r = new SyndicateRollup('syndicate-html', { globalName: 'SyndicateHtml' }); const r = new SyndicateRollup('syndicate-html', { globalName: 'SyndicateHtml' });

Some files were not shown because too many files have changed in this diff Show More