{"id":19839981,"url":"https://github.com/sjbiaga/pisc","last_synced_at":"2025-10-24T11:32:31.990Z","repository":{"id":214324753,"uuid":"736221376","full_name":"sjbiaga/pisc","owner":"sjbiaga","description":"Pi-calculus to Scala translator","archived":false,"fork":false,"pushed_at":"2025-10-21T12:52:50.000Z","size":1438,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-21T14:42:07.085Z","etag":null,"topics":["agents","ambient-calculus","asynchronous","bioambients","cancellation","cats-effect","concurrency","encodings","exponential-distribution","if-then-else","metaprogramming","parser-combinators","pi-calculus","replication","scala","scalameta","simulation","stm","stochastic","traces"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sjbiaga.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-12-27T10:05:53.000Z","updated_at":"2025-10-21T12:54:13.000Z","dependencies_parsed_at":"2024-01-01T13:23:12.700Z","dependency_job_id":"b2d98a0f-655a-44a5-bcaf-5dcbcfdc92d5","html_url":"https://github.com/sjbiaga/pisc","commit_stats":null,"previous_names":["sjbiaga/pisc"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sjbiaga/pisc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sjbiaga%2Fpisc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sjbiaga%2Fpisc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sjbiaga%2Fpisc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sjbiaga%2Fpisc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sjbiaga","download_url":"https://codeload.github.com/sjbiaga/pisc/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sjbiaga%2Fpisc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280787588,"owners_count":26391141,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-24T02:00:06.418Z","response_time":73,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agents","ambient-calculus","asynchronous","bioambients","cancellation","cats-effect","concurrency","encodings","exponential-distribution","if-then-else","metaprogramming","parser-combinators","pi-calculus","replication","scala","scalameta","simulation","stm","stochastic","traces"],"created_at":"2024-11-12T12:25:03.946Z","updated_at":"2025-10-24T11:32:31.981Z","avatar_url":"https://github.com/sjbiaga.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"Pi-calculus in SCala aka PISC ala RISC\n======================================\n\nThe π-calculus maps one to one on `Scala` for-comprehensions\n\"inside\" the Cats Effect's `IO[_]` monad.\n\nAsynchronous [π-calculus](https://github.com/sjbiaga/pisc/tree/main-async) is a variant.\n[Stochastic π-calculus](https://github.com/sjbiaga/pisc/tree/stochastic) is in alpha stage.\n[Polyadic π-calculus](https://github.com/sjbiaga/pisc/tree/polyadic) is also supported.\nAsynchronous [Polyadic π-calculus](https://github.com/sjbiaga/pisc/tree/polyadic-async) is also supported.\n[Ambient Calculus](https://github.com/sjbiaga/pisc/tree/ambient) is nicely done, too. In a\nsimilar way - somehow combining π-calculus with ambients - is implemented\n[π-calculus with transactions](https://github.com/sjbiaga/pisc/tree/transactions).\n[Stochastic π-calculus with transactions](https://github.com/sjbiaga/pisc/tree/stochastic-bio-transactions)\nis a combination.\n[BioAmbients](https://github.com/sjbiaga/pisc/tree/bioambients) is another fruitful\ncombination of ambients with stochastic π-calculus.\n\nAfter code generation, the π-calculus \"processes\" could be\nprogrammatically typed as `Scala` code using `CE` `IO`.\n\nThe for-comprehensions vertically put the prefix (after \"`for`\")\nand the composition/summation (before \"`yield`\").\n\nChannels for names work as [CE tutorial](https://typelevel.org/cats-effect/docs/tutorial)'s\nproducer/consumer but no queue, only `takers` and `offerers`.\n\nComposition: parallel modelled with - `NonEmptyList.fromListUnsafe(...).parSequence.void`.\n\nSummation: non-deterministic choice modelled with - `parSequence` and `Semaphore.tryAcquire.ifM`.\n\n[Guarded] Replication: modelled with - `parSequence` and `lazy val` [or `def`].\n\nThe source code is divided in two: the parser in `Calculus.scala` and the\n`Scala` source code generator in `Program.scala`.\n\n\nCalculus\n--------\n\nThe π-calculus process expressions are exactly as in the literature, with\nboth ASCII and UTF-8 characters, and slight variations. There is \"match\" and\n\"mismatch\", but also there is `if then else` or the sugared Elvis operator.\nForcibly, _restriction_ is \"considered\" a _prefix_, besides input/output\nprefixes per se.\n\nThe BNF formal grammar for processes is the following.\n\n    LINE           ::= EQUATION | DEFINITION | DIRECTIVE\n    EQUATION       ::= INVOCATION \"=\" CHOICE\n    DEFINITION     ::= \"⟦\u003cCODE\u003e\" [ TEMPLATE ] \"\u003cCODE\u003e⟧\" PARAMS [ POINTERS ] \"=\" CHOICE\n    DIRECTIVE      ::= \"⟦\" KEY = ( VALUE | \"(\" VALUE { \",\" VALUE } \")\" ) \"⟧\"\n    CHOICE         ::= PARALLEL { \"+\" PARALLEL }\n    PARALLEL       ::= SEQUENTIAL { \"|\" SEQUENTIAL }\n    SEQUENTIAL     ::= PREFIXES [ LEAF | \"(\" CHOICE \")\" ]\n    LEAF           ::= \"[\" NAME (\"=\"|\"≠\") NAME \"]\" CHOICE\n                     | \"if\" NAME (\"=\"|\"≠\") NAME \"then\" CHOICE \"else\" CHOICE\n                     | NAME (\"=\"|\"≠\") NAME \"?\" CHOICE \":\" CHOICE\n                     | \"!\" PACE [ \".\" μ \".\" ] CHOICE\n                     | CAPITAL\n                     | INVOCATION\n                     | INSTANTIATION\n    CAPITAL        ::= IDENTIFIER [ \"(\" [ NAMES ] \")\" ] ( POINTERS | \"{\" \"}\" )\n    INSTANTIATION  ::= \"⟦\u003cCODE\u003e\" INSTANCE \"\u003cCODE\u003e⟧\" [ POINTERS ]\n    INVOCATION     ::= [ QUAL ] IDENTIFIER PARAMS\n    PARAMS         ::= [ \"(\" NAMES \")\" ]\n    POINTERS       ::= \"{\" NAMES \"}\"\n    NAMES          ::= NAME { \",\" NAME }\n    NAMESʹ         ::= [ NAME ] { \",\" [ NAME ] }\n\nThe BNF formal grammar for prefixes is the following.\n\n    PREFIXES       ::= { PREFIX }\n    PREFIX         ::= μ \".\"\n                     | \"ν\" \"(\" NAMES \")\"\n    μ              ::= \"τ\" [ EXPRESSION ]\n                     | NAME \"\u003c\" [ [\"ν\"] NAME ] \"\u003e\" [ EXPRESSION ]\n                     | NAME \"(\" NAME \")\" [ EXPRESSION ]\n                     | NAME \u003cCONS\u003e \"(\" NAMESʹ \")\" [ EXPRESSION ]\n    PACE           ::= NATURAL_NUMBER [ \",\" TIME_UNIT ]\n    EXPRESSION     ::= \"/*\" ... \"*/\"\n\nLexically, `ident` is a channel name - (an identifier) starting with lowercase letter;\ncapital `IDENT` is an agent identifier starting with uppercase letter. Both may contain\nsingle and double quotes.\n\nA source file with the \"`.pisc`\" extension consists of equations, binding an agent identifier\nwith an optional list of \"formal\" (bound names) parameters, to a process expression. Because\nthe use of parentheses in a _restriction_ would lead to ambiguities, it is forced to start\nwith the UTF-8 character \"ν\". \"()\" is _inaction_ or the _empty sum_.\n\"τ\" is the _silent transition_.\n\nLines starting with a hash `#` character are (line) comments. Blank lines are ignored.\nLines starting with an `@` character are intermixed as `Scala` code. Lines ending with\nbackslash continue on the next line.\n\nSummation (`CHOICE`) has lower precedence than composition (`PARALLEL`).\n\nThe output prefix uses angular parentheses and has the form `NAME\u003cNAME\u003e.`, while\nthe input prefix uses the round parentheses and has the form `NAME(NAME).`. A _`name`_\nin parentheses can also be a (constant) `String` literal, a (boxed in a) `BigDecimal` number,\nor a [`Scalameta`](https://scalameta.org) term as a `Scala` comment between `/*` and `*/`.\n\nA match has the form `[NAME=NAME]` and a mismatch the same, but\nusing the `NOT EQUAL TO` Unicode `≠` character. `NAME=NAME` or `NAME≠NAME` is a\n_test_, that can be used also as `if NAME(=|≠)NAME then CHOICE else CHOICE` or\nas the syntactic sugar `NAME(=|≠)NAME ? CHOICE : CHOICE` Elvis ternary operator.\n\nStack safe is the [guarded] _replication_ unary operator `! [ \".\" μ \".\" ] CHOICE`;\nthe guard `\".\" μ \".\"` is optional, and it starts with a `\".\"` so that it is\ndistinguished from other prefixes.\n\nThe name before parentheses (angular or round) must be a channel name.\n\nFor output, the name in angular parentheses is optional, if empty being `null`.\nThis may be used to cease guarded replication with _input_ prefix guard: i.e.,\nif a `null` is received, the (stack-safe, recursive) replication stops.\n\nNote that input/output prefixes and the silent transition are followed by a dot,\nwhereas restriction is not; also, inaction, invocation, (mis)match, `if then else`,\nElvis operator, and replication are \"leaves\".\n\nBetween \"τ\" and \".\" in a silent transition, there can be a `Scalameta` term for\nwhich a `for` generator `_ \u003c- IO { term }` is inserted _after_ the transition,\nor any list of `Enumerator`s which are added _after_ the transition. Any symbol\nthat is found in these terms is considered a _free_ name.\n\nBetween output prefix closing angular parenthesis and \".\", there can be a\n`Scalameta` term as an `IO[Any]` piece of code, that is executed under supervision\n(so that cancellation does not outlive the `cats.effect.std.Supervisor[IO]`),\njust after ending the output but before returning from it.\n\nBetween input prefix closing round parenthesis and \".\", there can be a\n`Scalameta` function-term as a `T`-parameterized `T =\u003e IO[T]` piece of code,\nthat is applied the prior result from the input, obtaining the `IO[T]` that is\nexecuted under supervision (so that cancellation does not outlive the\n`cats.effect.std.Supervisor[IO]`) providing the actual result, just after ending\nthe input but before returning from it.\n\nIf `null` is received, that function will not run. Otherwise, if its result is\n`null`, this may be used to cease guarded replication with _output_ prefix guard:\ni.e., should just this one input prefix remain, the (stack-safe, recursive)\nreplication stops.\n\nAnd if, for each guarded replication, care is taken of to *stop* each, then the\nentire program exits; unless prevented by non-exiting - self or mutual - recursive\nagent invocations or unguarded replication.\n\nNot part of the original π-calculus, an (agent) invocation expression - unless\nit is binding in an equation -, may be preceded by a sequence of characters wrapped\nbetween curly braces: these will be joined using the dot \"`.`\" character, standing for\na qualified package identifier. Thus, agents in different translated \"`.scala`\" files\ncan be reused; the lexical category is `qual`.\n\nUnlike the rest of the agents, the `Main` agent has the command line arguments\nspliced as `vararg` parameter(s).\n\n\nProgram\n-------\n\nA new name - will be available in the Scala scope:\n\n    for\n      x \u003c- ν\n      .\n      .\n      .\n    yield\n      ()\n\nThe inaction - `IO.unit`.\n\nA long prefix path - \"`ν(x).x\u003c5\u003e.x(y).τ.x(z).z\u003cy\u003e.`\":\n\n    for\n      x \u003c- ν\n      _ \u003c- x(BigDecimal(5))\n      y \u003c- x()\n      _ \u003c- τ\n      z \u003c- x()\n      _ \u003c- z(y)\n      .\n      .\n      .\n    yield\n      ()\n\nOne can intercalate \"`println`\"s:\n\n    for\n      x \u003c- ν\n      _ \u003c- IO.println(s\"new x=$x\")\n      _ \u003c- x(5)\n      _ \u003c- IO.println(\"output x(5)\")\n      y \u003c- x()\n      _ \u003c- IO.println(\"input x(y)\")\n      _ \u003c- τ\n      _ \u003c- IO.println(\"silent transition\")\n      z \u003c- x()\n      _ \u003c- z(y)\n      .\n      .\n      .\n    yield\n      ()\n\nA [mis]match `[x = y] P` translates as:\n\n    for\n      .\n      .\n      .\n      _ \u003c- if !(x == y) then IO.unit else\n           for\n             . // P\n             .\n             .\n           yield\n             ()\n    yield\n      ()\n\nAn `if then else` translates `if x = y then P else Q` as:\n\n    for\n      .\n      .\n      .\n      _ \u003c- ( if (x == y)\n             then\n               for // P\n                 .\n                 .\n                 .\n               yield\n                 ()\n             else\n               for // Q\n                 .\n                 .\n                 .\n               yield\n                 ()\n           )\n    yield\n      ()\n\nEach replication operator uses a unique variable pattern\nnamed `_\u003cuuid\u003e` to translate lazily `! P` as:\n\n    for\n      _\u003cuuid\u003e \u003c- IO {\n        lazy val _\u003cuuid\u003e: IO[Any] =\n          NonEmptyList\n            .fromListUnsafe(\n              List(\n                .  // P\n                .\n                .\n              ,\n                for\n                  _ \u003c- IO.unit\n                  _ \u003c- _\u003cuuid\u003e\n                yield\n                  ()\n              )\n            )\n            .parSequence\n        _\u003cuuid\u003e\n      }\n      _ \u003c- _\u003cuuid\u003e\n    yield\n      ()\n\nwhere `uuid` is some generated `java.util.UUID`.\n\nAgent identifiers (literals) start with uppercase, while\nchannel names start with lowercase.\n\n\nApps (examples)\n---------------\n\nThe `examples` folder *must* have three sub-folders:\n\n    ./examples/\n       pisc/\n       in/\n       out/\n\nThe root project folder contains three files: `pi.scala`, `pi_.scala`, and `main.scala.in`.\n\n!!!Warning: do not delete them!!!\n\nOne can edit'em, though they're ready to generate a main `App`.\n\nTo get and run the examples, one can `source` the functions from `bin/pi.sh`.\n\nTo run an example, `cd` to `examples` and execute:\n\n    ./examples $ pi ex.scala\n\nor - if stopping output prefix replication -, add an underscore:\n\n    ./examples $ pi_ ex.scala\n\nTo get the final source file `ex.scala` (from `out/ex.scala.out`), run:\n\n    ./examples $ pio ex\n\nTo get the intermediary `in/ex.scala.in` file, execute the `run` command in the `sbt` shell:\n\n    sbt:π-Calculus2Scala\u003e run ex\n\nwhere `example/pisc/ex.pisc` contains the π-calculus source (equations binding agents to process\nexpressions).\n\nIn order to allow multiple `App`s, edit `examples/ex[12].scala` and add a top-level `package ex[12]` line.\n\nIf there are more `App`s' with agents that depend one to another, pass the `--interactive` option and all source files:\n\n    ./examples $ pi --interactive ex1.scala ex2.scala\n\nNote that [Scala Cli](https://scala-cli.virtuslab.org/) must be installed.\n\n\nDotArrow\n--------\n\n[`DotArrow`](https://github.com/sjbiaga/pisc-dotarrow) is the codename\nfor \"_mobile code_\". It is implemented in a very simplistic fashion.\n\n\nBranches\n--------\n\n- [π-calculus](https://github.com/sjbiaga/pisc/tree/main)\n\n- [π-calculus async](https://github.com/sjbiaga/pisc/tree/main-async)\n\n- [Polyadic π-calculus](https://github.com/sjbiaga/pisc/tree/polyadic)\n\n- [Polyadic π-calculus async](https://github.com/sjbiaga/pisc/tree/polyadic-async)\n\n- [Ambient Calculus](https://github.com/sjbiaga/pisc/tree/ambient)\n\n- [Ambient Calculus async](https://github.com/sjbiaga/pisc/tree/ambient-async)\n\n- [π-calculus with biological transactions](https://github.com/sjbiaga/pisc/tree/transactions)\n\n- [Stochastic π-calculus](https://github.com/sjbiaga/pisc/tree/stochastic) using supervisor/`IO.canceled`\n\n- [Stochastic π-calculus](https://github.com/sjbiaga/pisc/tree/stochastic-flatMap) with `flatMap`s/`null` comparison\n\n- [Stochastic π-calculus with biological transactions](https://github.com/sjbiaga/pisc/tree/stochastic-bio-transactions) using supervisor/`IO.canceled`\n\n- [Stochastic π-calculus with biological transactions](https://github.com/sjbiaga/pisc/tree/stochastic-bio-transactions-flatMap) with `flatMap`s/`null` comparison\n\n- [BioAmbients](https://github.com/sjbiaga/pisc/tree/bioambients) using supervisor/`IO.canceled`\n\n- [BioAmbients](https://github.com/sjbiaga/pisc/tree/bioambients-flatMap) with `flatMap`s/`null` comparison\n\n- [BioAmbients async](https://github.com/sjbiaga/pisc/tree/bioambients-async) using supervisor/`IO.canceled`\n\n- [BioAmbients async](https://github.com/sjbiaga/pisc/tree/bioambients-flatMap-async) with `flatMap`s/`null` comparison\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsjbiaga%2Fpisc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsjbiaga%2Fpisc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsjbiaga%2Fpisc/lists"}