{"id":13780504,"url":"https://github.com/motet-a/toy","last_synced_at":"2026-01-21T03:08:37.346Z","repository":{"id":91114365,"uuid":"98462201","full_name":"motet-a/toy","owner":"motet-a","description":"Tiny JavaScriptish interpreter","archived":false,"fork":false,"pushed_at":"2019-04-12T18:02:54.000Z","size":26,"stargazers_count":14,"open_issues_count":0,"forks_count":6,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-08-03T18:15:09.552Z","etag":null,"topics":["c","compiler","interpreter","javascript"],"latest_commit_sha":null,"homepage":null,"language":"C","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/motet-a.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}},"created_at":"2017-07-26T20:14:52.000Z","updated_at":"2023-01-30T23:33:04.000Z","dependencies_parsed_at":"2024-01-18T08:45:44.940Z","dependency_job_id":"88b88177-a180-4303-8919-75e4199fc15a","html_url":"https://github.com/motet-a/toy","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/motet-a%2Ftoy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/motet-a%2Ftoy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/motet-a%2Ftoy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/motet-a%2Ftoy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/motet-a","download_url":"https://codeload.github.com/motet-a/toy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225056832,"owners_count":17414218,"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":["c","compiler","interpreter","javascript"],"created_at":"2024-08-03T18:01:16.527Z","updated_at":"2026-01-21T03:08:37.340Z","avatar_url":"https://github.com/motet-a.png","language":"C","funding_links":[],"categories":["C"],"sub_categories":[],"readme":"# toy\n\nThis is a tiny interpreter (with a bytecode compiler and a stack-based\nvirtual machine) for a lilliputian subset of JavaScript, written in C\nand... JavaScript itself. It fits in less than 2500 lines of code.\n\nThe parser and the bytecode generator (in `compile.js`) are written in\nToy-compatible JavaScript. It was just too painful to write those in\nC.  Since you can run them with Node.js or Toy itself, they\nself-compile (into `compiler_code.c`) and are magically bundled inside\nthe `toy` executable.\n\n## Interesting features\n\n- Closures\n- Compiles itself (see above)\n- Little mark-and-sweep garbage collector\n\n## Unsupported JavaScript features\n\n- ES201{5,6,7}\n- Functions with many arguments (use lists, dictionnaries or\n  curryfication instead)\n- Prototypes\n- Exceptions\n- `undefined` (seriously, who needs `undefined`? `null` is sufficient)\n- Optional semicolons\n- Booleans (use 0 and 1, or anything else truthy or falsy)\n- `for`, `switch`, `do`\n- `else` (just write `if` statements. Thousands of `if` statements.)\n- Regexps\n\n## Compile and run\n\nYou need Node.js, a C compiler and GNU make. Just run `make` and try\nthe examples.\n\n## Various observations\n\nFirst of all, because I hate naming things _à la_ JavaScript:\n\n  - an _object_, a _hash map_ or a _hash table_ is _dictionnary_\n  - an _array_ is a _list_\n\nFor the sake of simplicity, the whole thing is really slow.\n\nThe dictionnary implementation is a shame.\n\nLists are implemented with those dictionnaries. This is really\nstraightforward since we need dictionnaries and JavaScript lists\nbehaves mostly the same. It’s obviously slow.\n\nSince the garbage collector does not visit the stack, each object has\na reference counter which prevents it from being collected if that\ncounter is nonzero. Moreover, the GC must not run at any time, but\nonly between two instructions (see the call to\n`request_garbage_collection();` in `vm.c`).\n\nVariables are compiled as-is. The VM interprets scoping rules and\ncatches variable definition errors at run-time. The compiler is really\nstraightforward.\n\nI just hope you are not crazy enough to use this hack in production.\n\n## Why?\n\nIt was fun. Enjoy :wink:\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmotet-a%2Ftoy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmotet-a%2Ftoy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmotet-a%2Ftoy/lists"}