{"id":24609661,"url":"https://github.com/bjoernloetters/lambda-m","last_synced_at":"2025-05-05T23:46:40.134Z","repository":{"id":88394246,"uuid":"140117918","full_name":"BjoernLoetters/lambda-m","owner":"BjoernLoetters","description":"A lazy and untyped experimental programming language","archived":false,"fork":false,"pushed_at":"2018-07-08T13:49:19.000Z","size":64,"stargazers_count":10,"open_issues_count":3,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-31T00:51:13.556Z","etag":null,"topics":["functional-programming","haskell","lambda-calculus","macros","metaprogramming","pattern-matching","programming","programming-language"],"latest_commit_sha":null,"homepage":"","language":"Haskell","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/BjoernLoetters.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":"support/vscode/package.json","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-07T21:31:01.000Z","updated_at":"2022-11-08T06:29:40.000Z","dependencies_parsed_at":"2023-03-12T13:16:06.726Z","dependency_job_id":null,"html_url":"https://github.com/BjoernLoetters/lambda-m","commit_stats":null,"previous_names":["bjoernloetters/lambda-m"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BjoernLoetters%2Flambda-m","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BjoernLoetters%2Flambda-m/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BjoernLoetters%2Flambda-m/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BjoernLoetters%2Flambda-m/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BjoernLoetters","download_url":"https://codeload.github.com/BjoernLoetters/lambda-m/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252596331,"owners_count":21773842,"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":["functional-programming","haskell","lambda-calculus","macros","metaprogramming","pattern-matching","programming","programming-language"],"created_at":"2025-01-24T18:16:30.679Z","updated_at":"2025-05-05T23:46:40.113Z","avatar_url":"https://github.com/BjoernLoetters.png","language":"Haskell","readme":"# λ\u003csub\u003eM\u003c/sub\u003e\n\n## Index\n\n1. [Introduction](#introduction)\n2. [Motivation](#motivation)\n3. [The Language Syntax](#the-language-syntax)\n4. [Data Constructors and Pattern Matching](#data-constructors-and-pattern-matching)\n5. [The Macro System](#the-macro-system)\n6. [Build Instructions](#build-instructions)\n7. [A Note about Performance](#a-note-about-performance)\n8. [Syntax Highlighting in Visual Studio Code](#syntax-highlighting-in-visual-studio-code)\n9. [Contribution](#contribution)\n\n## Introduction\n\nλ\u003csub\u003eM\u003c/sub\u003e is a lazy and untyped experimental programming language with a very small kernel (hereinafter referred to as kernel language).\n\nThis project was created in the summer of 2018 as part of the module \"Kernel Languages\" at the university of applied science [Technische Hochschule Mittelhessen](https://www.thm.de/).\n\n## Motivation\n\nAnyone who already worked with a concatenative programming language like [Factor](https://github.com/factor/factor) or [Consize](https://github.com/denkspuren/consize) knows the genericity that comes with their metaprogramming ability. In those languages it is possible to redefine the whole language with itself, leading to a very small kernel implementation. Furthermore this is possible without sacrificing expressiveness.\n\nThe lambda calculus in its original form is also a kernel language. Nevertheless, it is missing the ability to reflect on and change itself. Which in turn means, that the expressiveness of the lambda calculus is very limited. The goal of λ\u003csub\u003eM\u003c/sub\u003e is to fix this limitation.\n\n## The Language Syntax\n\n```\nterm = let | data | macro | abs ;\n\nlet = \"let\", bindings, \"in\", term ;\nbindings = binding, { \",\", binding } ;\nbinding = app, \"=\", term ;\n\ndata = \"data\", constructors, \"in\", term ;\nconstructors = app, { \"|\", app } ;\n\nmacro = \"macro\", binding, \"in\", term ;\n\nabs = app, [ \"=\u003e\", term ] ;\n\napp = match, { match } ;\n\nmatch = value, [ \"match\", \"{\", cases, \"}\" ] ;\ncases = { case } ;\ncase = \"case\", app, \"=\u003e\", term ;\n\nvalue = string | list | character | number | tuple | variable ;\nvalues = [ value, { \",\", value } ] ;\n\nstring = '\"', { ? any character ? }, '\"' ;\nlist = \"[\", values, \"]\" ;\n\ncharacter = \"'\", ? any character ? \"'\" ;\nnumber = digit, { digit } ;\n\ntuple = \"(\", values, \")\" ;\n\nvariable = alphanumeric | symbolic ;\nalphanumeric = letter, { letter | digit }, { \"'\" } ;\nsymbolic = symbol, { symbol | digit }, { \"'\" } ;\n\ndigit = \"0\" | \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\" \n      | \"7\" | \"8\" | \"9\" ; \n\nsymbol = \"+\" | \"*\" | \"~\" | \"#\" | \"-\" | \":\" | \".\" \n       | \"$\" | \"%\" | \"\u0026\" | \"/\" | \"\\\" | \"=\" | \"?\"\n       | \"!\" | \"^\" | \"°\" | \"\u003c\" | \"\u003e\" | \"|\" | \"@\" ;\n\nletter = \"A\" | \"B\" | \"C\" | \"D\" | \"E\" | \"F\" | \"G\"\n       | \"H\" | \"I\" | \"J\" | \"K\" | \"L\" | \"M\" | \"N\"\n       | \"O\" | \"P\" | \"Q\" | \"R\" | \"S\" | \"T\" | \"U\"\n       | \"V\" | \"W\" | \"X\" | \"Y\" | \"Z\" \n       | \"a\" | \"b\" | \"c\" | \"d\" | \"e\" | \"f\" | \"g\"\n       | \"h\" | \"i\" | \"j\" | \"k\" | \"l\" | \"m\" | \"n\"\n       | \"o\" | \"p\" | \"q\" | \"r\" | \"s\" | \"t\" | \"u\"\n       | \"v\" | \"w\" | \"x\" | \"y\" | \"z\" ;\n```\n\n## Data Constructors and Pattern Matching\n\nThere are no built-in data types\u0026ast; other than numbers, characters and tuples. Which means, that even booleans are introduced by the prelude. In order to still be able to add and use control structures like `if` it is possible to match on arbitrary data. For further explanation consider the following example.\n\n\u003e \u0026ast; To be precise, there are no data types (neither statically nor dynamically) in λ\u003csub\u003eM\u003c/sub\u003e at all. Whenever we talk about the datatype of a value, we conceptually talk about the kind of that value. We use the phrase \"datatype\" to identify values with common properties. For that reason, a `data`-definition does not introduce a type constructor (as it common in languages with algebraic data types). One could call those `data`-definitions \"algebraic data constructors\".\n\n```\ndata True | False in\n\nlet if = test =\u003e then =\u003e else =\u003e test match {\n    case True  =\u003e then\n    case False =\u003e else\n} in\n\nif True 0 1\n```\n\nThe example above shows how `if` may be implemented only using pattern matching. The result of the expression above is always `0`. \n\nA more complex pattern match can be seen in the following example: \n```\ndata Cons head tail | Nil in\n\n[1, ('a', \"hello\"), (3), ()] match {\n    case [x, ('b', string), 3, _]  =\u003e \"hello\"\n    case [x, ('a', string), _, ()] =\u003e \"world\"\n}\n```\n\nThe result of this example should be `\"world\"`, since the first pattern does not match (the first value of the twos-tuple is `'a'` but the pattern expects it to be `'b'`). An underscore `_` behaves like a variable binder, but ignores the value.\n\nStrings and list literals are translated to a sequence of `Cons` applications, meaning that `\"hello\"` is translated to `Cons 'h' (Cons 'e' (Cons 'l' (Cons 'l' (Cons 'o' Nil))))`. Without strings and list literals a pattern match may also be written like:\n\n```\ndata Cons head tail | Nil in\n\nCons 1 (Cons 2 (Cons 3 Nil)) match {\n    case Cons 1 (Cons 2 (Cons 3 Nil)) =\u003e Cons 3 (Cons 2 (Cons 1 Nil))\n}\n```\n\n## The Macro System\n\nThe main feature of λ\u003csub\u003eM\u003c/sub\u003e is its ability to change its own syntax and semantics with the help of the `macro`-system. One can imagine a macro as a function which accepts the rest of the program as a string and returns the replacement for the rest of the program as a syntax tree of λ\u003csub\u003eM\u003c/sub\u003e. To be able to read from files or to perform other side effects a macro returns the syntax tree wrapped in an IO monad.\n\nThe following example shows a program, which evaluates to `42`. Regardless of the string `\"hello world\"` which follows after the `in`, the macro replaces the rest of the program by `42` (represented by the syntax tree node `Num 42`).\n```\nmacro f = content =\u003e returnIO (Num 42) in \n\n\"hello world\"\n```\n\nThe full syntax tree of λ\u003csub\u003eM\u003c/sub\u003e can be seen in the [prelude](bootstrap/prelude.lm).\n\n## Build Instructions\n\n1. Install the [Haskell Platform](https://www.haskell.org/downloads)\n2. Clone this project\n3. Open up a terminal and switch to the project root\n4. Execute the command `cabal run`\n\nAfter the prompt `\u003e` has appeared, you can enter arbitrary terms. Side effects may be executed with the command `:x \u003cterm\u003e`.\n\n## A Note about Performance\n\nIn its current version λ\u003csub\u003eM\u003c/sub\u003e is very slow, since it implements a statically typed version of itself with parser combinators (as it can be seen in the [prelude](bootstrap/prelude.lm)). In Addition, strings are encoded as lists of characters, which is very convenient but also very slow.\n\nIf you are interested in performance optimizations, feel free to apply some improvements. ;-)\n\n## Syntax Highlighting in Visual Studio Code\n\nThere is a directory [support/vscode](https://github.com/kuchenkruste/lambda-m/tree/master/support/vscode) which contains TextMate files for syntax highlighting in [Visual Studio Code](https://github.com/Microsoft/vscode). Simply copy this directory into the extension directory of your VS Code installation and you should be able to choose syntax highlighting for \"Lambda-M\" (you may have to restart VS Code though).\n\n![Example Syntax Highlighting](example-syntax-highlighting.png)\n\n## Contribution\n\nIf you are interested in this project do not hesitate to fork and request merge. I will review your work as soon as possible.\n\nIf you have any trouble regarding this project please make use of the issue system.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbjoernloetters%2Flambda-m","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbjoernloetters%2Flambda-m","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbjoernloetters%2Flambda-m/lists"}