{"id":17267397,"url":"https://github.com/calvin-l/pppl","last_synced_at":"2025-03-26T11:14:04.126Z","repository":{"id":145023858,"uuid":"395485592","full_name":"Calvin-L/pppl","owner":"Calvin-L","description":"The Persistent Parallel Programming Language","archived":false,"fork":false,"pushed_at":"2021-08-28T18:21:03.000Z","size":31,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-01-31T12:23:56.713Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","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/Calvin-L.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}},"created_at":"2021-08-13T01:21:13.000Z","updated_at":"2021-08-28T18:21:05.000Z","dependencies_parsed_at":null,"dependency_job_id":"948fcdfb-184d-499b-8152-aa8b69f859f2","html_url":"https://github.com/Calvin-L/pppl","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Calvin-L%2Fpppl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Calvin-L%2Fpppl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Calvin-L%2Fpppl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Calvin-L%2Fpppl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Calvin-L","download_url":"https://codeload.github.com/Calvin-L/pppl/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245641437,"owners_count":20648644,"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","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":[],"created_at":"2024-10-15T08:10:33.525Z","updated_at":"2025-03-26T11:14:04.090Z","avatar_url":"https://github.com/Calvin-L.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Persistent Parallel Programming Language (PPPL)\n\nPPPL is pronounced \"pipple\".  It's a programming system with some bold new\nideas.\n\nWhen I made the project I accidentally typed an extra \"p\", so for historical\nreasons the executable is named `ppppl`.  I guess we could backronym that to\n\"Perfect Persistent Parallel Programming Language\"?\n\n\n## Concepts\n\nYou are likely reading this on a computer.  That's not new.\n\nYour computer has something called _pmemory_ (pronounced \"memory\"; think\n\"pneumatic\").  If you have never run a PPPL program, your computer still has\npmemory; it just happens to be empty right now.\n\nPmemory has two parts.  One is a program, and the other is a single value.\nPrograms are described below.\n\nPmemory is persistent.  It will be there when you restart your computer, and\nall the actions your program takes are permanent.\n\n\n### What you, a human, can do\n\n - Overwrite your computer's pmemory's program (see `pppl load` below)\n - Let the computer make progresss running your program (see `pppl run` below)\n - Read and write your computer's pmemory's value (see `pppl read` and\n   `pppl write` below)\n\nObvously, you can do many other things as well, such as \"write an email\" or\n\"make lunch\".  The list above is not meant to be restrictive; it is just to\ninform you of some options you might not have known you have.\n\n\n### What PPPL can do\n\nA PPPL program is a list of blocks.  For example, here's a single block that\ncounts up to 100:\n\n```\ndef up:\n    require x \u003c 100;\n    x := x + 1;\n```\n\nVariable names are shorthand for those keys in the single pmemory value, which\nis named `.`.  So: `x == .[\"x\"]`.\n\nEach block can have requirements like `x \u003c 100`.  The block will not run if its\nrequirements are not satisfied.  It also won't run if it would produce an\nexception (for instance, if `x` is not an integer).\n\nThe effects of a block happen atomically.  For instance, here's a block that\nswaps `x` and `y`:\n\n```\ndef swap:\n    x := y;\n    y := x;\n```\n\nPPPL works like this:\n\n```python\nwhile True:\n    atomically:\n        pick a block whose requirements are satisfied\n        execute the side-effects of that block\n```\n\nThe current implementation is single-threaded.  To achieve true parallelism,\nrun multiple copies of `ppppl run` at once (see commands below).\n\n\n#### Data Parallelism\n\nSometimes doing two different things in parallel isn't enough.  Sometimes you\nneed to do the same thing in parallel with many pieces of data.\n\n```\ndef inc(x in m):\n    m[x] := m[x] + 1;\n```\n\nBlocks can take parameters, such as `x in m` above.  If `m` is a dictionary,\nthen `inc` can be run with `x` set to any key of `m`.\n\n\n#### Doing Things in Sequence\n\nIn some programming langauges, you have to do a lot of work to spawn threads\nand exploit multiple cores.  In PPPL, parallelism is the default!  ...But\nyou'll have to do a lot of work to force sequential execution if you need it.\n\n```\ndef step1:\n    require pc == 0;\n    pc := pc + 1;\n\ndef step2:\n    require pc == 1;\n    pc := pc + 1;\n\ndef step3:\n    require pc == 2;\n    pc := pc + 1;\n```\n\n\n#### Expression Summary\n\n```\nBooleans\n\n    true, false,\n    ==, !=,\n    \u0026\u0026, ||, !,\n    if _ then _ else _\n\nNumbers\n\n    +, -, *, /, %,\n    \u003e, \u003c, \u003e=, \u003c=\n\nDictionaries\n\n    {}          (the empty map)\n    x in m      (test key presence)\n    m[x]        (lookup value by key)\n```\n\n\n## Concrete Instructions\n\nFirst, compile this project:\n\n    cargo build --release\n\nThen load a program:\n\n    cat examples/div3.pppl\n    ./target/release/ppppl load examples/div3.pppl\n\nThen run it:\n\n    ./target/release/ppppl run\n\nIt's always safe to have multiple `run` commands going at once.  In fact,\nthat's how to achieve parallelism with the current implementation.\n\nWhile it's running, you might want to interact with it a bit:\n\n    ./target/release/ppppl write 'x := 1000;'\n    ./target/release/ppppl read done\n    ./target/release/ppppl read q\n    ./target/release/ppppl read r\n\n`examples/div3.pppl` computes division by 3 very slowly.  When it finishes, it\nwrites `done := true;` and the result of `x/3` is in `q` and `r`.\n\nYou can \"restart\" the program by writing a new value to `x`---although, this\nis something that is implemented in the `begin` block, and is not part of PPPL\nby default.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcalvin-l%2Fpppl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcalvin-l%2Fpppl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcalvin-l%2Fpppl/lists"}