{"id":16627099,"url":"https://github.com/ttulka/stroke","last_synced_at":"2025-03-28T03:15:17.487Z","repository":{"id":241521171,"uuid":"806401725","full_name":"ttulka/stroke","owner":"ttulka","description":"Stroke {/|\\} esoteric structured programming language","archived":false,"fork":false,"pushed_at":"2024-05-28T21:01:09.000Z","size":76,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-05-28T21:34:13.312Z","etag":null,"topics":["esolang","javascript","programming-language","stroke"],"latest_commit_sha":null,"homepage":"https://esolangs.org/wiki/Stroke","language":"JavaScript","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/ttulka.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":"2024-05-27T06:13:27.000Z","updated_at":"2024-05-28T21:34:16.179Z","dependencies_parsed_at":"2024-05-28T21:44:25.049Z","dependency_job_id":null,"html_url":"https://github.com/ttulka/stroke","commit_stats":null,"previous_names":["ttulka/stroke"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttulka%2Fstroke","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttulka%2Fstroke/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttulka%2Fstroke/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttulka%2Fstroke/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ttulka","download_url":"https://codeload.github.com/ttulka/stroke/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245960813,"owners_count":20700781,"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":["esolang","javascript","programming-language","stroke"],"created_at":"2024-10-12T04:13:22.069Z","updated_at":"2025-03-28T03:15:17.456Z","avatar_url":"https://github.com/ttulka.png","language":"JavaScript","readme":"# Stroke\n\n\u003cimg src=\"logo.png\" style=\"width: 20%; float: right; margin: 1rem 0 1rem 2rem; border-radius: 1rem; max-width: 250px; float: right\" align=\"right\" width=\"250\"\u003e\n\n**Stroke**, also `{/|\\}`, is an esoteric structured programming language.\n\nWith only three instructions, it aims to be the simplest structured programming language ever.\n\nIt uses conditional loops and an unbounded number of binary variables, along with flipping their values.\n\nStroke is *almost* Turing complete, unlike its bigger brother [Stroke+-](https://github.com/ttulka/strokepm) which truly is.\n\n## Language\n\nStroke code consists only of stroke symbols `/`, `|`, `\\`, and white spaces to separate them. \n\nAll other symbols are ignored.\n\n### Instructions\n\n| Instr      | Name       | Meaning |\n| ---------- | ---------- | ------- |\n| `/ var`    | Loop start | Enters a new loop if *var* is non-zero |\n| `\\`        | Loop end   | Jumps back to the matching loop start |\n| `\\|` × *n* | Flip value | Flips the value of the variable *n*-1 |\n\nAll instructions and their attributes are separated by one or more white spaces.\n\nThe example code in Stroke:\n\n```stroke\n| \n/ | \n  | \n  || \n\\ \n|||\n```\n\ncan be translated into the following pseudocode:\n\n```\nflip var0\nwhile var0\n  flip var0\n  flip var1\nflip var2\n```\n\nOptionally, the instruction for output `!` may be implemented.\n\n### Variables\n\nA Stroke program runs on a theoretically infinite tape of binary cells that are randomly accessible via variables denoted by consecutive vertical stroke symbols (`|`) in unary form starting from zero. For instance, `|` flips the variable indexed by 0, `||` flips the variable indexed by 1, `|||` flips the variable indexed by 2, and so on.\n\nA variable occurring in code directly after a loop start will be just read (and checked to be non-zero), while a variable anywhere else in the code will flip its binary value.\n\nThe binary tape can simulate integers of arbitrary size, e.g. 4-bit unsigned:\n\n```\n  variable index   0  1  2  3  4  5  6  7  8  9  10 11 ...\n       bit index   3  2  1  0  3  2  1  0  3  2  1  0  ...\nvirtual variable   \\   A    /  \\   B    /  \\   C    /  ...\n```\n\n## Examples\n\nThe following examples operate on virtual 4-bit variables *A*, *B*, and *C*.\n\n### Empty program\n\nThe simplest program is the empty program:\n\n```stroke\n```\n\n### Infinite loop\n\nAs variable *0* is never reset, the program loops forever:\n\n```stroke\n| / | \\\n```\n\n### Conditional branching\n\nConditional branching (IF) can be simulated via loops:\n\n```stroke\nIF A:\n|||||||       running\n/ | |         first bit not zero\n    |||||     result\n    ||||||    shall reset bit\n    |||||||   stop\n\\\n/ |||||| |||||| | \\  reset bit\n/ |||||||            still running\n    / || ||          second bit not zero\n    |||||            result\n    ||||||           shall reset bit\n    |||||||          stop\n    \\\n    / |||||| |||||| || \\  reset bit\n    / |||||||             still running\n    / ||| |||             third bit not zero\n        |||||             result\n        ||||||            shall reset bit\n        |||||||           stop\n    \\\n    / |||||| |||||| ||| \\  reset bit\n    / |||||||              still running\n        / |||| ||||        fourth bit not zero\n        |||||              result\n        ||||||             shall reset bit\n        \\\n        / |||||| |||||| |||| \\  reset bit\n        |||||||                 stop (all bits checked)\n    \\\n    \\\n\\\n/ ||||| |||||  \n  \n  do something conditionally...\n\n\\\n```\n\n### Equality check\n\nCompares *A* and *B* bit by bit:\n\n```stroke\nEQ A B =\u003e v8:\n||||||||| ||||||||||||| |||||||||||\n/ | | ||||||||||||\n    / ||||| ||||| |||||||||| |||||||||||| \\\n    / |||||||||| |||||||||| ||||| \\\n    / |||||||||||| |||||||||||| ||||||||| ||||||||||||| \\\n    |||||||||| |||||||||||\n\\\n/ |||||||||| |||||||||| | \\\n/ ||||||||||| ||||||||||| \n    / ||||| ||||| |||||||||| ||||||||| |||||||||||||\n    / |||||||||| |||||||||| ||||| \\\n\\\n/ ||||||||||||| |||||||||||\n    / || || ||||||||||||\n    / |||||| |||||| |||||||||| |||||||||||| \\\n    / |||||||||| |||||||||| |||||| \\\n    / |||||||||||| |||||||||||| ||||||||| ||||||||||||| \\\n    |||||||||| |||||||||||\n    \\\n    / |||||||||| |||||||||| || \\\n    / ||||||||||| |||||||||||\n    / |||||| |||||| |||||||||| ||||||||| ||||||||||||| \\\n    / |||||||||| |||||||||| |||||| \\\n    \\\n    / ||||||||||||| |||||||||||\n    / ||| ||| ||||||||||||\n        / ||||||| ||||||| |||||||||| |||||||||||| \\\n        / |||||||||| |||||||||| ||||||| \\\n        / |||||||||||| |||||||||||| ||||||||| ||||||||||||| \\\n        |||||||||| |||||||||||\n    \\\n    / |||||||||| |||||||||| ||| \\\n    / ||||||||||| |||||||||||\n        / ||||||| ||||||| |||||||||| ||||||||| ||||||||||||| \\\n        / |||||||||| |||||||||| ||||||| \\\n    \\\n    / ||||||||||||| |||||||||||\n        / |||| |||| ||||||||||||\n        / |||||||| |||||||| |||||||||| |||||||||||| \\\n        / |||||||||| |||||||||| |||||||| \\ \n        / |||||||||||| |||||||||||| ||||||||| \\\n        |||||||||| |||||||||||\n        |||||||||||||\n        \\\n        / |||||||||| |||||||||| |||| \\\n        / ||||||||||| |||||||||||\n        / |||||||| |||||||| |||||||||| ||||||||| \\\n        / |||||||||| |||||||||| |||||||| \\\n        |||||||||||||\n        \\\n    \\\n    \\\n\\\n\\ ||||||||| |||||||||\n\n  do something if equal...\n\n/\n```\n\n### Increment and decrement\n\nThe following program increments *A* and decrements *B*:\n\n```stroke\nINC A:    \n||||||       carry\n/ |||| |||| ||||| |||||| \\\n/ ||||| ||||| |||||| \n    / ||| ||| ||||| |||||| \\\n    / ||||| ||||| ||||||\n    / || || ||||| |||||| \\\n    / ||||| ||||| ||||||\n        / | | |||||| \\\n        / |||||| |||||| | \\\n    \\\n    / |||||| |||||| || \\\n    \\\n    / |||||| |||||| ||| \\\n\\\n/ |||||| |||||| |||| \\\n\nDEC B:\n|||||||||\n/ |||||||| |||||||| ||||||||| \\\n/ ||||||||| ||||||||\n/ ||||||| ||||||| ||||||||| \\\n/ ||||||||| ||||||| \n    / |||||| |||||| ||||||||| \\\n    / ||||||||| |||||| \n    / ||||| ||||| ||||||||| \\\n    / ||||||||| |||||\n        |||||||||\n    \\\n    \\\n\\\n\\\n```\n\n### Addition\n\nHaving conditional branching, increment, and decrement intact, \n  a program to add *A* and *B* is just a simple composition:\n\n```stroke\nADD A B =\u003e A:\nIF B\n   INC A\n   DEC B\n```\n\n### Fibonacci sequence\n\n```stroke\nFIB:\nx \n/ x   forever\n  IF B\n     DEC B\n     INC C\n  IF A\n     DEC A\n     INC B\n  IF C\n     DEC C\n     INC A\n     INC B  \n\\\n```\n\n### Hello World\n\nFor computing \"Hello World\" the tape must be interpreted as a string. \n  It can achieved by defining a binary alphabet:\n\n| Symbol | Binary |\n| ------ | ------ |\n| ` `    | 000    |\n| `d`    | 001    |\n| `e`    | 010    |\n| `H`    | 011    |\n| `l`    | 100    |\n| `o`    | 101    |\n| `r`    | 110    |\n| `W`    | 111    |\n\nThe following program sets the tape to `011010100100101000111101110100001`\n  which corresponds to \"Hello World\":\n\n```stroke\n|| ||| ||||| ||||||| |||||||||| \n||||||||||||| ||||||||||||||| \n||||||||||||||||||| \n|||||||||||||||||||| \n||||||||||||||||||||| \n|||||||||||||||||||||| \n|||||||||||||||||||||||| \n||||||||||||||||||||||||| \n|||||||||||||||||||||||||| \n|||||||||||||||||||||||||||| \n|||||||||||||||||||||||||||||||||\n```\n\n## Computational class\n\nThe minimalistic nature of Stroke has its price: it had to give up Turing completeness.\n\nAs every variable (bit) must be represented in code as a sequence of `|` the program cannot access an infinite number of bits as required for Turing completeness.\n\nHowever, variables of arbitrary size can be used which brings the language very close to being Turing complete according to [the structured program theorem](https://en.wikipedia.org/wiki/Structured_program_theorem), as conditional branching (selection) can easily be simulated via loops.\n\nIn short, Stroke can do everything a Turing complete language can but only with limited data.\n\n## JavaScript interpreter\n\n```sh\nnpm i stroke-lang\n```\n\n```js\nconst stroke = require('stroke-lang')\n\nstroke('| / | | || \\\\ |||')  // \"011\"\n```\n\n## License\n\n[MIT](LICENSE)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fttulka%2Fstroke","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fttulka%2Fstroke","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fttulka%2Fstroke/lists"}