{"id":13838029,"url":"https://github.com/brendanzab/language-garden","last_synced_at":"2025-04-05T04:12:57.403Z","repository":{"id":60097150,"uuid":"534979791","full_name":"brendanzab/language-garden","owner":"brendanzab","description":"A garden of small programming language implementations 🪴","archived":false,"fork":false,"pushed_at":"2024-10-24T05:26:13.000Z","size":1207,"stargazers_count":174,"open_issues_count":0,"forks_count":5,"subscribers_count":6,"default_branch":"main","last_synced_at":"2024-10-24T23:27:19.928Z","etag":null,"topics":["compilation","compilers","dependent-types","elaboration","l-systems","programming-languages","typechecking"],"latest_commit_sha":null,"homepage":"","language":"OCaml","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/brendanzab.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":"2022-09-10T11:39:27.000Z","updated_at":"2024-10-24T18:13:08.000Z","dependencies_parsed_at":"2023-01-29T16:31:38.476Z","dependency_job_id":"94962902-2161-4575-a681-1c29df77522d","html_url":"https://github.com/brendanzab/language-garden","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/brendanzab%2Flanguage-garden","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brendanzab%2Flanguage-garden/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brendanzab%2Flanguage-garden/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brendanzab%2Flanguage-garden/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brendanzab","download_url":"https://codeload.github.com/brendanzab/language-garden/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247284951,"owners_count":20913704,"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":["compilation","compilers","dependent-types","elaboration","l-systems","programming-languages","typechecking"],"created_at":"2024-08-04T15:01:34.150Z","updated_at":"2025-04-05T04:12:57.380Z","avatar_url":"https://github.com/brendanzab.png","language":"OCaml","funding_links":[],"categories":["OCaml"],"sub_categories":[],"readme":"# Language garden 🌱\n\nSome toy programming language implementations, mostly implemented in OCaml.\n\nThese projects are mostly my attempt to understand different techniques and\napproaches to implementing programming languages. Perhaps from these seedlings\nsomething new and interesting might germinate?\n\n## The garden path\n\n### Elaboration\n\nElaboration is an approach to implementing language front-ends where a complicated,\nuser friendly _surface language_ is type checked and lowered to a simpler, typed\n_core language_. This approach to type checking is particularly popular and\nuseful for implementing dependently typed programming languages, but is more\nwidely applicable as well.\n\nSimply typed:\n\n- [**elab-stlc-bidirectional**](./elab-stlc-bidirectional):\n  An elaborator for a simply typed lambda calculus that uses bidirectional\n  typing to allow some type annotations to be omitted.\n- [**elab-stlc-bidirectional-stratify**](./elab-stlc-bidirectional):\n  An elaborator that partially stratifies a combined type and term language into\n  a simply typed core language.\n- [**elab-stlc-abstract**](./elab-stlc-abstract):\n  An LCF-style elaborator that moves the construction of well-typed terms behind\n  a trusted interface.\n- [**elab-stlc-unification**](./elab-stlc-unification):\n  An elaborator for a simply typed lambda calculus where type annotations can be omitted.\n- [**elab-stlc-letrec-unification**](./elab-stlc-letrec-unification):\n  Extends the simply typed lambda calculus with recursive let bindings.\n- [**elab-stlc-variant-unification**](./elab-stlc-variant-unification):\n  Extends the simply typed lambda calculus with structural variant types,\n  inferring types eagerly using constraint based unification.\n\nPolymorphically typed:\n\n- [**elab-system-f-bidirectional**](./elab-system-f-bidirectional):\n  An elaborator for a higher-rank polymorphic lambda calculus.\n\nDependently typed:\n\n- [**elab-dependent**](./elab-dependent/):\n  An elaborator for a small dependently typed lambda calculus.\n- [**elab-dependent-sugar**](./elab-dependent-sugar/):\n  An elaborator for a small dependently typed lambda calculus with syntactic sugar.\n- [**elab-record-patching**](./elab-record-patching/):\n  An elaborator of a dependently typed lambda calculus with singletons and record patching.\n\n### Compilation\n\nThese are related to compilation. Mainly to stack-machines, but I’m interested\nin exploring more approaches in the future, and other compilation passes\nrelated to compiling functional programming languages.\n\n- [**compile-arith**](./compile-arith/):\n  Compiling arithmetic expressions to stack machine instructions and A-Normal Form.\n- [**compile-arithcond**](./compile-arithcond/):\n  Compiling arithmetic and conditional expressions to stack machine instructions and A-Normal Form.\n- [**compile-closure-conv**](./compile-closure-conv):\n  Typed closure conversion and lambda lifting for a simply typed lambda calculus\n  with booleans and integers.\n\n### Languages\n\nMiscellaneous programming language experiments.\n\n- [**lang-datalog**](./lang-datalog/):\n  A simple Datalog interpreter.\n- [**lang-declarative-graphics**](./lang-declarative-graphics/):\n  Declarative DSL for 2-dimensional graphics.\n- [**lang-doc-templates**](./lang-doc-templates/):\n  A programmable document template language that elaborates to a typed lambda calculus.\n- [**lang-fractal-growth**](./lang-fractal-growth/):\n  Experiments with using grammars and rewriting systems to model fractal growth.\n- [**lang-fractal-tree-rewriting**](./lang-fractal-tree-rewriting/):\n  Plant growth modelled as tree rewriting systems.\n- [**lang-lc-interpreters**](./lang-lc-interpreters/):\n  A comparison of lambda calculus interpreters using different approaches to\n  name binding.\n- [**lang-shader-graphics**](./lang-shader-graphics/):\n  An embedded DSL for describing procedural graphics, based on signed distance\n  functions. These can be rendered on the CPU or compiled to GLSL shaders.\n\n### Work in progress projects\n\nWhile most of the above projects need more work put into them, the following\nprojects need more work put into them and a more incomplete in comparison.\n\n- [**wip-elab-builtins**](./wip-elab-builtins/):\n  An elaborator that supports built-in types and operations.\n- [**wip-compile-stlc**](./wip-compile-stlc):\n  A type preserving compiler for the simply typed lambda calculus.\n- [**wip-compile-stratify**](./wip-compile-stratify/):\n  Compiling a dependently typed lambda calculus into a stratified intermediate\n  language.\n- [**wip-compile-uncurry**](./wip-compile-uncurry/):\n  Compiling single-parameter functions to multiparameter functions.\n\n## Background\n\nAs I’ve been working in the area of programming languages I’ve often found\nmyself in the position of:\n\n- Explaining the same idea or technique over and over, but not having a minimal\n  example I can point to.\n- Re-implementing an existing technique (either from a paper, or based on some\n  other existing code I’ve seen) in my own way, as a way of learning and\n  understanding it more deeply.\n- Wanting a place to experiment with an approach before committing to using it\n  in a larger project, which can take time and may amount to nothing.\n- Trying to recall a technique I’d spent time learning a long ago.\n- Having an idea for a small language experiment that does not need to be part\n  of a standalone project, but may require some build system setup.\n\nMy hope is that by collecting some of these projects and experiments together\ninto a single repository they might be useful to others and my future self.\n\nI’m also trying to get better at interleaved breadth-first/depth-first search as part of my learning process -\nsomewhat like the search strategy employed by [miniKanren](http://minikanren.org/).\nMy goal is not to become an expert of one thing,\nbut to be able to be good at combining ideas from different places and perspective.\n\n## Related work\n\nThe metaphor of a “garden” as related to knowledge work was inspired by the rising\npopularity of “digital gardening” (which apparently originates from\n[Hypertext Gardens](https://www.eastgate.com/garden/Enter.html)).\nWhile this project is less directly interconnected than other digital gardens,\nI still like the idea of each project being a “seedling” that can be nurtured\nand tended to over an extended period of time,\nwith the learning from one project being transferred to the others.\nPerhaps a “language nursery” would have been a more fitting name.\n\nI’ve also been particularly inspired by Mark Barbone’s [small, self-contained gists](https://gist.github.com/mb64/)\nimplementing small type systems and solvers, and Andras Kovacs’ excellent\n[elaboration-zoo](https://github.com/AndrasKovacs/elaboration-zoo/) (which was\ninstrumental in helping me get my head around how to implement elaborators).\n\nIf you like this repository, you might find these interesting as well:\n\n- [github:andrejbauer/plzoo](https://github.com/andrejbauer/plzoo/):\n  Andrej Bauer’s minimnal programming language demonstrations\n- [github:AndrasKovacs/elaboration-zoo](https://github.com/AndrasKovacs/elaboration-zoo/):\n  Minimal implementations for dependent type checking and elaboration by Andras Kovacs\n- [github:mspertus/TAPL](https://github.com/mspertus/TAPL): Updated type system\n  implementations from Benjamin Pierce's “Types and Programming Languages”\n- [github:pigworker/Samizdat](https://github.com/pigworker/Samizdat):\n  Conor McBride’s programming scrapbook\n- [github:tomprimozic/type-systems](https://github.com/tomprimozic/type-systems)\n  Implementations of various type systems in OCaml\n\nOther project gardens:\n\n- [github:cu1ch3n/type-inference-zoo](https://github.com/cu1ch3n/type-inference-zoo)\n  Implementations of various type inference algorithms and interactive playground\n- [github:jake-87/project-garden](https://github.com/jake-87/project-garden/):\n  A garden for small projects\n- [github:jakob-schuster/language-scrapyard](https://github.com/jakob-schuster/language-scrapyard):\n  Scrappy implementations of programming language ideas\n- [github:qexat/PLAGE](https://github.com/qexat/PLAGE/):\n  Programming Language Adjacent General Experiments\n- [github:RiscInside/LanguageEtudes](https://github.com/RiscInside/LanguageEtudes/):\n  Single-file typechecker/interpreter/compiler implementations\n- [github:yeslogic/fathom-experiments](https://github.com/yeslogic/fathom-experiments/):\n  Fathom related experiments\n- [sourcehut:icefox/determination](https://hg.sr.ht/~icefox/determination):\n  Type checkers for System F and System Fω\n\n## Conventions and style choices\n\n### Provide lots of type annotations\n\nThe predominant style in OCaml of leaving off type annotations\nmakes understanding and porting code far more difficult.\nInstead I try to add type annotations to most top-level type signatures.\n\n### Avoid opening modules\n\nWhen `open` is used I find it hard to figure out where identifiers are coming from without an editor.\nInstead I prefer using an explicitly qualified path where possible.\n\n### Group related variants with a common prefix\n\nIn the past I’ve often found it hard to find related nodes in an AST\nwhen trying to understand other people’s code.\nFor example, the following variants might all refer to different parts of a dependent pair type:\n\n```ocaml\ntype tm =\n  ...\n  | Sig of string * tm * tm\n  | Pair of tm * tm\n  | Fst of tm\n  | Snd of tm\n```\n\nInstead I prefer to use the following constructors:\n\n```ocaml\ntype tm =\n  ...\n  | Pair_type of string * tm * tm\n  | Pair_lit of tm * tm\n  | Pair_fst of tm\n  | Pair_snd of tm\n```\n\n### Use types to disambiguate variant names\n\nOCaml’s variant constructors aren’t namespaced under the type like in Rust or Lean,\nso reusing the same variant name will result in ambiguities\nif you are relying on global type inference.\nGenerally OCaml programmers will either:\n\n1. Wrap every type in a module\n2. Come up with an ad-hoc prefix for to prevent the conflict\n\nI find the former convention often results in duplicated datatype definitions\n(mutually dependent modules require explicit module signatures),\nand the latter is a little arbitrary and ugly.\n\nInstead I’ve decided to just disambiguate variants using the type.\nI realise this might make the code a more difficult to understand\nand if I come up with a better compromise I might revisit this in the future.\n\n## Development setup\n\n### With Nix\n\nUsing [Lix] (recommended) or [Nix] is not required, but can be useful for setting up a development\nshell with the packages and tools used in this project. With [Nix flakes]\nenabled:\n\n```sh\nnix run .#arith -- compile --target=anf \u003c\u003c\u003c \"1 + 2 * 27\"\n```\n\n[nix-direnv] can be used to load development tools into your shell\nautomatically. Once it’s installed, run the following commands to enable it in\nthe project directory:\n\n```sh\necho \"use flake\" \u003e .envrc\ndirenv allow\n```\n\nYou’ll want to locally exclude the `.envrc`, or add it to your global gitignore.\n\nAfter that, [dune] can be used to build, test, and run the projects:\n\n```sh\ndune build\ndune test\ndune exec arith -- compile --target=anf \u003c\u003c\u003c \"1 + 2 * 27\"\n```\n\n[dune]: https://dune.build\n[Lix]: https://lix.systems/\n[Nix]: https://nixos.org\n[Nix flakes]: https://nixos.wiki/wiki/Flakes\n[nix-direnv]: https://github.com/nix-community/nix-direnv\n\n### With opam\n\nAlternatively, [opam] package definitions are provided in the [`./opam`](./opam)\ndirectory. They drive the Nix flake, so _should_ be up to date. I don’t use opam\nhowever, so I’m not sure what the workflow is.\n\n[opam]: opam.ocaml.org\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrendanzab%2Flanguage-garden","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrendanzab%2Flanguage-garden","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrendanzab%2Flanguage-garden/lists"}