{"id":16116805,"url":"https://github.com/serprex/befunge","last_synced_at":"2025-09-27T15:31:07.348Z","repository":{"id":846210,"uuid":"572772","full_name":"serprex/Befunge","owner":"serprex","description":"lang befunge 93 fast","archived":false,"fork":false,"pushed_at":"2023-10-15T12:44:44.000Z","size":322,"stargazers_count":18,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-26T10:45:16.051Z","etag":null,"topics":["befunge","esolang"],"latest_commit_sha":null,"homepage":"https://serprex.github.io/Befunge","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"github/github-services","license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/serprex.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}},"created_at":"2010-03-21T16:53:20.000Z","updated_at":"2023-08-17T19:09:37.000Z","dependencies_parsed_at":"2024-10-09T20:26:11.726Z","dependency_job_id":"e6a36431-6ac5-4938-a6ac-05f364470398","html_url":"https://github.com/serprex/Befunge","commit_stats":{"total_commits":269,"total_committers":2,"mean_commits":134.5,"dds":"0.29368029739776946","last_synced_commit":"25de488e74f8c55b0d2faee7e9fabdb213114408"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serprex%2FBefunge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serprex%2FBefunge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serprex%2FBefunge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serprex%2FBefunge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/serprex","download_url":"https://codeload.github.com/serprex/Befunge/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234444600,"owners_count":18833658,"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":["befunge","esolang"],"created_at":"2024-10-09T20:26:06.380Z","updated_at":"2025-09-27T15:31:06.986Z","avatar_url":"https://github.com/serprex.png","language":"JavaScript","funding_links":[],"categories":["Languages"],"sub_categories":["Esoteric"],"readme":"This is my collection of Befunge VMs. I'll explain their evolution chronologically\n\n### marsh\nMarch 2010 I created marsh\n\nIt included such microoptimizations as postprocessing the assembly of GCC since GCC was generating 'set `rax` to `L1`, jump to `L2`, which indirectly jumps to `rax`'.  Also included a spawn script which would replace the 2000 spaces in the binary with befunge sourcecode, allowing self hosting befunge executables\n\nA month later I optimized indexing by having one dimension be a power of 2. The choices are 128x25 vs 80x32. The latter is much smaller, but somewhat unintuitive as the memory layout puts vertical text side by side. I also observed that if I duplicated the VM 4 times I could reduce the instruction dispatch to not check direction. Changing direction works by changing VMs.\n\n#### Intermission\nDuring this time I moved out, read _Fountainhead_ \u0026 _Atlas Shrugged_, \u0026 began college\n\n### bejit\nCome December I made a first jab at bejit. It was a sea of malloc without any peepholing, \u0026 it outraced marsh with ease. Soon after I started on an optimizer which would iterate the entire 10240 loop cache cells when replacing a node. There were so many bugs. By February I gave up, rewrote it to use bytecode without optimizations, found performance comparable to marsh. Optimizations fixed that, \u0026 I moved on\n\n#### Years go by, until September 2015\nDuring this time I've dropped out of college, moved back to my hometown, got into elementsthegame, made openEtG, was laid off shortly after buying a home, had recently transitioned from flooring back into programming. I began working offline on a Befunge to Python bytecode JIT while the summer was spent stripping \u0026 staining the house (don't paint cedar). I really have to thank the help I received with the house. Also I started using vim\n\n### funge.py\nI don't remember what made me want to get back into mucking with Python bytecode, but I'd been itching to do something like this but CLR \u0026 JVM are both snobs about non static stack depth. I soon learnt that it was pretty important to handle underflow (CPython will segfault), \u0026 that meant tracking stack depth\n\nI realized that g's bound checking could be optimized to only check 0\u003c=x\u003c2560, so this was backported to marsh \u0026 bejit too\n\nIn February it took 3 attempts to reduce the verbosity of the opcode definitions, the idea behind templating would be that the opcode blocks are then mostly constant \u0026 I can skip many LOAD/ADD/STORE instructions. The only variable portion would be the jump offsets. I was in a rut trying to optimize the compiler in ways that would make beer6 faster. Beer6 being a special benchmark since it triggers a couple hundred recompiles. A fork was made to experiment with peepholing\n\nI also got thinking in February how the Python bytecode could be optimized. I found abarnert had a repo experimenting with it, so I joined in to make a strategic effort in optimizing funge.py\n\nI was trying to work out how to remove stack guards. I also decided that funge.py would use unbounded space. Being able to remove bounds checking made it come without perf loss. Templating had to be gutted in order for instructions to be able to handle partial const propagation. Instructions were moved into classes to start grouping the data that was getting too scattered. Found that perf was better in using classes to resolve differences rather than lookups on op. Mutating __class__ was a little slower but it was a net win\n\nHaving been working with Befunge now for half a year, I started thinking how to make a Befunge IDE in vim. bef.vim could use a lot of work, I was really let down by just how slow vimscript is\n\nIn May I let wfunge.py be the only funge.py. There were some fun microoptimizations with the new bytecode, such as it being better to load a 0 than duplicate the non-zero stack depth \u0026 unary not it\n\n### bejit-elvm\nIn November 2016 I found out that \\ was broken in all my implementations for stacks of depth 1. I also worked out how marsh/bejit could have tighter code by leaving a stack empty rather than pushing a 0 on it. I also found ELVM, a neat project, so I made bejit-elvm because their interpreter was like most interpreters. Also spent some time improving their constant constructions to include factoring alongside base 9 encoding\n\n### funge.js\nI set things down until March, \u0026 write this readme when WASM became available in Firefox \u0026 Chrome. Over the course of a couple weeks an optimizing wasm jit was made. Instead of tracking partial application it tracks which stack an operator should get its values from\n\n### barfs\nOn December 1st 2018 I release barfs in a state I don't even know why I included it. The JIT was broken, so it only worked with evalcfg. A month later I went to San Francisco for an interview \u0026 my life completely changed. It took a few months for paperwork to resolve, but I spent that time drinking wine, watching films, \u0026 trying to make progress on Luwa (I didn't)\n\nThree years later I'm doing great since I no longer have to explain to people that I don't like shaking hands. Decide one weekend to take another stab at barfs. Cranelift documentation seems to've improved, or maybe it just took awhile to sink in for me. Bit of trouble figuring out they migrated away from extended basic blocks. I fix the long standing issue #2 in funge.js, wow it's hard to debug code that relies on me having memorized all the wasm opcodes, took me awhile to figure out depi is a set of flags for which stack slots are taken as input, took until I was laying down to play with my cat to pick up on numbers like 3/7 implying flags. Also I got a black cat she's adorable\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fserprex%2Fbefunge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fserprex%2Fbefunge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fserprex%2Fbefunge/lists"}