{"id":27698478,"url":"https://github.com/chedim/petri","last_synced_at":"2026-03-03T14:33:13.071Z","repository":{"id":247476817,"uuid":"825940344","full_name":"chedim/petri","owner":"chedim","description":"A soup-making language","archived":false,"fork":false,"pushed_at":"2024-07-18T16:15:40.000Z","size":113,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-09T12:03:42.177Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chedim.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2024-07-08T19:54:39.000Z","updated_at":"2024-07-18T16:15:43.000Z","dependencies_parsed_at":"2024-07-18T19:03:52.524Z","dependency_job_id":"33ef4ebf-4db3-4500-8dd9-40c3e7cbe6b5","html_url":"https://github.com/chedim/petri","commit_stats":null,"previous_names":["chedim/petri"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/chedim/petri","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chedim%2Fpetri","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chedim%2Fpetri/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chedim%2Fpetri/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chedim%2Fpetri/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chedim","download_url":"https://codeload.github.com/chedim/petri/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chedim%2Fpetri/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":283503072,"owners_count":26846504,"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-11-09T02:00:05.828Z","response_time":62,"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":[],"created_at":"2025-04-25T16:43:45.195Z","updated_at":"2025-11-09T12:03:42.831Z","avatar_url":"https://github.com/chedim.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Petri\n```\nA language for developing probabalistic soup applications that consist of small code bits that consume and transform data similarly to proteins.\n```\n\n## Language Status\nIdea Formulation\n\n## Language Idea\nPetri is a functional programming language in which applications are developed by writing `funclets`, autonomously invoked functions that are placed into `dishes`, virtual environments that contain data objects required to be processed by the program and programm's funclets that consume existing and create new objects. \n\n## Object identification\n`id` field is reserved for object identification.\n\n## Object Consumption\nWhenever a new object is added, all permutations of all paths to existing in the object keys are used to generate a set of sha-256 hashes. Hashes that not already present in the dish are then used to lookup funclets that can partially or fully consume that object. Then a single matching funclet is chosen probabilistically (based on present in the dish amounts of copies of matched funclets) and passed corresponding values that are removed from the object. If, after that operation, the object contains more data, a new attempt to consume it is made. Unconsumed by that process data is then stored for later consumption.\n\nWhenever a new funclet is created, its argument names are used to generate a sha-256 hash that is used to perform a lookup on previously unconsumed data in order to find the data that can be immediately consumed by the funclet. A single found object is then consumed randomly.\n\n### Multi-Object Consumption\nMulti-Object consumption is performed in the order object patterns are defined in a multi-object funclet. That is, the second object in the argument list _will be matched only after a match been found for the first argument_. Internally, the funclet is represented as a series of single-object funclets that wrap funclet's code:\n```\no1(f0..n), o2(f0..n) -\u003e {\n  o1.fx = o2.id;\n} -\u003e o1, o2;\n```\nequals to:\n```\n// here, `--\u003e` means \"funclet without a body\"\no1(f0..n) --\u003e \n  o2(f0..n) -\u003e {\n    o1.fx = o2.id;\n  } -\u003e o1, o2;\n```\n\n### Overflow Gates\nAn overflow gate is activated when a specified number of matching objects exists in the dish whenever a new matching object is added:\n```\nuser(inQueue):50 --\u003e serverRedirect() + user;\n```\n\n## Returned Objects\nA funclet may return an array of existing or new objects that will be added back into the dish and processed in it, including itself. \nIf a funclet returns an object with the same id as the part of a bigger object that was passed to it as a partial match, then that part is inserted back into the object from which the passed data has originated.\n\n### Linking Operator\n`+` binary operator can be used to add a field that points to another object:\n```\nuser(inQueue), seat(isFree) -\u003e {\n  delete seat.isFree\n  set seat.isBisy;            // unfolds into `seat.isBisy = Date.now()`\n} -\u003e user+seat, seat;         // user.seat == seat\n```\n### Cutting Operator\n`-` binary operator can be used to cut one object out of another:\n```\nuser(left) -\u003e {\n  seat = user.seat;\n  set seat.isFree;\n} -\u003e user - seat, seat;         // user.seat == undefined\n```\n\n### Multiply Operator\n`*` can be used to create multiple copies of the same object:\n```\ndish(started) --\u003e command(accept, users: 10);                   // accept is auto-set to current timestamp\n\ncommand(accept, users) --\u003e seat(\n  isFree: command.accept\n) * command.users;\n```\n\n## Object Deletion\nObjects are deleted automatically in following cases:\n- a funclet object that processed some data will be removed from the dish unless it returns itself using the `this` keyword. Therefore, amount of present in the dish funclets becomes an important consideration when developing an application and a useful tool for load and performancd management.\n- as soon as all data in an object has been consumed, it is removed from the dish.\n- delete is explicitly caled on any of the object matches:\n```\n    user(loggedOut) -\u003e delete user\n```\n\n## Syntax\n```\nfile := funclet (';' funclet)*\nfunclet := 'static'? objectList (('-\u003e' code) ('-\u003e' returnList)? | ('--\u003e' returnList)?)\nobjectList := objectPattern (',' objectPattern)*\nobjectPattern := path '(' argumentList? ')' (':' number)?\npath := name ('.' name)*\nname := [a-zA-Z_][a-zA-Z0-9_]*\nargumentList := path (',' path)*\ncode := codeBlock | statement\ncodeBlock := '{' statement (';' statement)* '}'\nstatement := setField | assignment | unsetField\nsetField := 'set' path\nassignment := path '=' expression\nunsetField := 'unset' path\nexpression := valueExpression | path | newObject\nnewObject := name '(' fieldAssignments? ')'\nfieldAssignments := fieldAssignment (',' fieldAssignment)*\nfieldAssignment := name ':' valueExpression\nvalueExpression := stringExpression | numericExpression | booleanExpression\nstringExpression := // todo\nnumericExpression := // todo\nbooleanExpression := // todo\n```\n## External Objects\nExternal objects can be used to represent external inputs. Whenever a funclet that consumes fields from these objects is created, the corresponding input is opened and listened for events that are then represented as external objects. The input is closed automatically whenever there's no correspondng to it funclets in the dish.\n- `dish.started`\n- `console.in`\n- `system.fs.root`\n- `system.net.socket`\n- `system.key.press`\n- `system.mouse.press`\n- `system.process.signal`\n- ...\n\n## External Funclets\nLike external objects, external funclets are automatically created whenever corresponding objects are added into the dish:\n- `console.message`\n- `file.name`\n- `tcp.packet`\n- `sound.message`\n- `process.signal`\n- ...\n\n## Dish Exchange Format\n( to run a dish across multiple nodes)\n```json\n[\n  [objects],[funclets]\n]\n```\n\n\n## ToDo\n[x] refine multi-object consumption\n[] refine time dilation\n[] refine object reactivity\n[] finish the syntax\n[] develop virtual machine\n[] develop stdlib\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchedim%2Fpetri","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchedim%2Fpetri","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchedim%2Fpetri/lists"}