{"id":15692268,"url":"https://github.com/healeycodes/quill","last_synced_at":"2025-05-08T02:24:16.212Z","repository":{"id":112378215,"uuid":"373937545","full_name":"healeycodes/quill","owner":"healeycodes","description":"A Rust port of the Ink programming language (thesephist/ink)","archived":false,"fork":false,"pushed_at":"2021-06-29T05:11:44.000Z","size":2473,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-15T00:51:13.520Z","etag":null,"topics":["abstract-syntax-tree","event-loop","interpreter","programming-language"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/healeycodes.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-06-04T19:10:36.000Z","updated_at":"2022-03-25T13:10:59.000Z","dependencies_parsed_at":"2023-05-14T04:00:23.698Z","dependency_job_id":null,"html_url":"https://github.com/healeycodes/quill","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/healeycodes%2Fquill","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/healeycodes%2Fquill/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/healeycodes%2Fquill/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/healeycodes%2Fquill/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/healeycodes","download_url":"https://codeload.github.com/healeycodes/quill/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252985193,"owners_count":21835936,"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":["abstract-syntax-tree","event-loop","interpreter","programming-language"],"created_at":"2024-10-03T18:30:22.164Z","updated_at":"2025-05-08T02:24:16.180Z","avatar_url":"https://github.com/healeycodes.png","language":"Rust","readme":"# ✒️ Quill\n\n_This project is paused for now as I've got everything out of it that I wanted to (to learn some Rust, to learn the Ink source code). However, pull-requests/fixes are welcome and I will thoughtfully engage with them._\n\n\u003cbr\u003e\n\nQuill is a tree-walk interpreter – it's an in-progress Rust port of [thesephist/ink](https://github.com/thesephist/ink) (a minimal programming language inspired by modern JavaScript and Go, with functional style). It uses Tokio async/await for an experimental event loop and passes callbacks via Tokio channels.\n\nThere are bugs, and the least-complete section is the runtime (e.g. the HTTP functionality, file read/write, etc.).\n\nThe variable/function naming, as well as the code design organization, tries to stick closely to the Go project. This way, patches that are added to Ink and be ported here. Many comments are lifted straight from the Go project (they start with `GoInk:`).\n\nYou may also be interested in [thesephist/schrift](https://github.com/thesephist/schrift) which is a more experimental runtime for Ink, focused on perf and instrumentation. Or the [The Ink blog](https://dotink.co/).\n\n\u003cbr\u003e\n\nAn example Ink program that Quill can interpret:\n\n```ink\nlog := msg =\u003e out(string(msg) + char(10))\n\n` vars `\na := 'Hello, World!'\nlog(a)\na := true\nlog(a)\n\n` lists `\nb := [1, 2, 3]\nlog(b)\n\n` recursive via tail call optimization `\nfactorial := n =\u003e n :: {\n    0 -\u003e 1\n    _ -\u003e n * factorial(n-1)\n}\nfactorial(5)\n\n` event loop examples `\nw := (t, c) =\u003e wait(t, () =\u003e log(c))\nw(0.1, 'a')\nw(0.2, 'b')\nw(0.3, 'c')\nw(0.35, 'd')\nw(0.4, 'e')\nw(0.45, 'f')\n\n` this prints before the wait() calls `\nlog(string(time()))\n\n` a map `\nobservation := {\n    weather: 'Sunny',\n    'observedAt': {\n        time: time()\n    }\n}\n\nlog(observation.weather)\n\n` composite value to_string `\nlog(observation.observedAt)\n```\n\nOutputs:\n\n```\nHello, World!\ntrue\n{0: 1, 1: 2, 2: 3}\n1624863950232.9634\nSunny\n{time: 1624863950234.2705}\na\nb\nc\nd\ne\nf\n()\n```\n\n\u003cbr\u003e\n\n## Debug options\n\n.. are currently forced on. So you'll get output like you were running Ink with `--verbose` and see debug information for the lexer, parser, and a frame dump.\n\ne.g.\n\n```\ndebug: lex -\u003e identifier 'log' [41:1]\ndebug: lex -\u003e '(' [41:4]\ndebug: lex -\u003e identifier 'observation' [41:5]\ndebug: lex -\u003e '.' [41:16]\ndebug: lex -\u003e identifier 'observedAt' [41:17]\n-- snip --\ndebug: parse -\u003e Call (Identifier 'w') on (Number 0.45, String f)\ndebug: parse -\u003e Call (Identifier 'log') on (Call (Identifier 'string') on (Call (Identifier 'time') on ()))\n-- snip --\ndebug: frame dump {\n        a -\u003e true\n        observation -\u003e {observedAt: {time: 1624863950234.2705}, weather: 'Sunny'}\n        string -\u003e Native Function (string)\n        w -\u003e ier 'log') on (Identifier 'c'))))..\n        out -\u003e Native Function (out)\n        factorial -\u003e \u003e (Binary (Identifier 'n') '*' (Call (Identifier 'factorial') on (Binary (Identifier 'n') '-' (Number 1))))})..\n        time -\u003e Native Function (time)\n        char -\u003e Native Function (char)\n        wait -\u003e Native Function (wait)\n        b -\u003e {0: 1, 1: 2, 2: 3}\n        log -\u003e ' (Call (Identifier 'char') on (Number 10))))..\n} -prnt-\u003e *\n```\n\n\u003cbr\u003e\n\n## My motivations for this project\n\nTo learn:\n\n- Rust (this is my first Rust project) \u003csub\u003e[0]\u003c/sub\u003e\n- More about lexing, parsing, and evaluating an abstract syntax tree (AST)\n- More about Ink's guts — how it's put together, where my Ink code comes alive, etc.\n\n\u003csub\u003e[0]\u003c/sub\u003e this means the number of lines of code and the complexity of it is not in an ideal place. Call it a first draft.\n\n\u003cbr\u003e\n\n## Things that are working\n\nLexing, parsing, and evaluation.\n\nThere is an experimental event loop which implements `wait()` to prove that it works. It uses Tokio async/await and channels for callbacks.\n\nIn terms of Ink's files, progress could also be measured like this:\n\n- ink.go `5%`\n- error.go `90%`\n- eval.go `95%`\n- lexer.go `100%`\n- log.go `90%`\n- parser.go `100%`\n- runtime.go `2%`\n\n\u003cbr\u003e\n\n## Current Bug \n\nThere are issues with defining (e.g. changing indexes of lists and keys of composite values).\n\n:building_construction::building_construction::building_construction:\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhealeycodes%2Fquill","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhealeycodes%2Fquill","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhealeycodes%2Fquill/lists"}