{"id":13440033,"url":"https://github.com/gluon-lang/gluon","last_synced_at":"2025-05-14T22:06:13.819Z","repository":{"id":35797393,"uuid":"40078838","full_name":"gluon-lang/gluon","owner":"gluon-lang","description":"A static, type inferred and embeddable language written in Rust.","archived":false,"fork":false,"pushed_at":"2024-12-06T11:24:24.000Z","size":12730,"stargazers_count":3305,"open_issues_count":164,"forks_count":149,"subscribers_count":57,"default_branch":"master","last_synced_at":"2025-05-07T21:58:25.874Z","etag":null,"topics":["compiler","embeddable","functional","gluon","language","programming-language","repl","rust","type-inference"],"latest_commit_sha":null,"homepage":"https://gluon-lang.org","language":"Rust","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/gluon-lang.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","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":"2015-08-02T12:35:56.000Z","updated_at":"2025-05-06T09:36:36.000Z","dependencies_parsed_at":"2023-02-12T06:45:19.255Z","dependency_job_id":"7e384483-f6ad-4819-bf24-2435a2204446","html_url":"https://github.com/gluon-lang/gluon","commit_stats":{"total_commits":3422,"total_committers":59,"mean_commits":58.0,"dds":"0.14202220923436581","last_synced_commit":"8fc42d7de560547f05ad3127bec6e511f85fea10"},"previous_names":[],"tags_count":47,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gluon-lang%2Fgluon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gluon-lang%2Fgluon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gluon-lang%2Fgluon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gluon-lang%2Fgluon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gluon-lang","download_url":"https://codeload.github.com/gluon-lang/gluon/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254235694,"owners_count":22036963,"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":["compiler","embeddable","functional","gluon","language","programming-language","repl","rust","type-inference"],"created_at":"2024-07-31T03:01:19.171Z","updated_at":"2025-05-14T22:06:08.785Z","avatar_url":"https://github.com/gluon-lang.png","language":"Rust","funding_links":[],"categories":["Libraries","Rust","Uncategorized","库 Libraries","库","计算机编程 数据结构与算法","compiler","Compilers and Interpreters","Functional"],"sub_categories":["Scripting","Uncategorized","脚本 Scripting","脚本编写","网络服务_其他","Serious Projects"],"readme":"# gluon\n\n[![Build Status](https://github.com/gluon-lang/gluon/actions/workflows/rust.yml/badge.svg)](https://github.com/gluon-lang/gluon/actions) [![crates.io](https://meritbadge.herokuapp.com/gluon)](https://crates.io/crates/gluon)  [![Documentation](https://docs.rs/gluon/badge.svg)](https://docs.rs/crate/gluon) [![Book](https://img.shields.io/badge/gluon-book-yellow.svg)](https://gluon-lang.org/doc/crates_io/book/index.html) [![std](https://img.shields.io/badge/gluon-std-green.svg)](http://gluon-lang.org/doc/nightly/std/index.html)\n\nGluon is a small, statically-typed, functional programming language designed for application embedding.\nI\n## Features\n\n* **Statically-typed** - Static typing makes it easier to write safe and efficient interfaces between gluon and the host application.\n\n* **Type inference** - Type inference ensures that types rarely have to be written explicitly giving all the benefits of static types with none of the typing.\n\n* **Simple embedding** - Marshalling values to and from gluon requires next to no boilerplate, allowing functions defined in [Rust][] to be [directly passed to gluon][easy_embed].\n\n* **UTF-8 by default** - Gluon supports Unicode out of the box with utf-8 encoded strings and Unicode codepoints as characters.\n\n* **Separate heaps** - Gluon is a garbage-collected language but uses a separate heap for each executing gluon thread. This keeps each heap small, reducing the overhead of the garbage collector.\n\n* **Thread-safe** - Gluon is written in Rust, which guarantees thread safety. Gluon keeps the same guarantees, allowing multiple gluon programs to run in parallel ([example][parallel])\\*\n\n[easy_embed]:https://gluon-lang.org/doc/crates_io/book/embedding-api.html\n[parallel]:https://github.com/gluon-lang/gluon/blob/master/tests/parallel.rs\n\n\\* Parallel execution of gluon programs is a recent addition and may still have issues such as deadlocks.\n\n## Examples\n\n### Hello world\n\n```f#,rust\nlet io = import! std.io\nio.print \"Hello world!\"\n```\n\n### Factorial\n\n```f#,rust\nlet factorial n : Int -\u003e Int =\n    if n \u003c 2\n    then 1\n    else n * factorial (n - 1)\n\nfactorial 10\n```\n\n### 24\n\n[24 game]:https://github.com/gluon-lang/gluon/blob/master/examples/24.glu\n```f#,rust,ignore\n// # 24\n//\n// From http://rosettacode.org/wiki/24_game\n//\n// Write a program that randomly chooses and displays four digits, each from 1 ──► 9 (inclusive) with repetitions allowed.\n//\n// The program should prompt for the player to enter an arithmetic expression using just those, and all of those four digits, used exactly once each. The program should check then evaluate the expression.\n//\n// The goal is for the player to enter an expression that (numerically) evaluates to 24.\n//\n// * Only the following operators/functions are allowed: multiplication, division, addition, subtraction\n// * Division should use floating point or rational arithmetic, etc, to preserve remainders.\n// * Brackets are allowed, if using an infix expression evaluator.\n// * Forming multiple digit numbers from the supplied digits is disallowed. (So an answer of 12+12 when given 1, 2, 2, and 1 is wrong).\n// * The order of the digits when given does not have to be preserved.\n//\n//\n// ## Notes\n//\n//     The type of expression evaluator used is not mandated. An RPN evaluator is equally acceptable for example.\n//     The task is not for the program to generate the expression, or test whether an expression is even possible.\n\n\n// The `import!` macro are used to load and refer to other modules.\n// It gets replaced by the value returned by evaluating that module (cached of course, so that\n// multiple `import!`s to the same module only evaluates the module once)\nlet io @ { ? } = import! std.io\nlet prelude = import! std.prelude\nlet { Result } = import! std.result\nlet array @ { ? } = import! std.array\nlet int = import! std.int\nlet string = import! std.string\nlet list @ { List, ? } = import! std.list\nlet random = import! std.random\nlet string = import! std.string\n\n// Since imports in gluon returns regular values we can load specific parts of a module using pattern matches.\nlet char @ { ? } = import! std.char\n\nlet { (\u003c\u003e) } = import! std.semigroup\nlet { flat_map } = import! std.monad\n\nlet { (*\u003e), (\u003c*), wrap } = import! std.applicative\n\nlet { for } = import! std.traversable\n\ntype Op = | Add | Sub | Div | Mul\ntype Expr = | Int Int | Binop Expr Op Expr\n\nlet parse : String -\u003e Result String Expr =\n    // Gluon has a small parser combinator library which makes it easy to define an expression parser\n    let parser @ {\n        between,\n        satisfy,\n        satisfy_map,\n        spaces,\n        token,\n        digit,\n        skip_many1,\n        recognize,\n        lazy_parser,\n        chainl1,\n        (\u003c?\u003e),\n        ? } = import! std.parser\n    let { (\u003c|\u003e) } = import! std.alternative\n\n    let lex x = x \u003c* spaces\n\n    let integer =\n        // `do` expression provide a way to write monads in a way similiar to procedural code\n        do i = lex (recognize (skip_many1 digit))\n        match int.parse i with\n        | Ok x -\u003e wrap x\n        | Err _ -\u003e parser.fail \"Unable to parse integer\"\n\n    let operator =\n        satisfy_map (\\c -\u003e\n            match c with\n            | '*' -\u003e Some Mul\n            | '+' -\u003e Some Add\n            | '-' -\u003e Some Sub\n            | '/' -\u003e Some Div\n            | _ -\u003e None)\n            \u003c?\u003e \"operator\"\n\n    rec\n    let atom _ =\n        parser.functor.map Int integer\n            \u003c|\u003e between (lex (token '(')) (lex (token ')')) (lazy_parser expr)\n\n    let binop _ =\n        let op_parser =\n            do op = lex operator\n            wrap (\\l r -\u003e Binop l op r)\n        chainl1 (atom ()) op_parser\n\n    let expr _ = binop ()\n    in\n\n    // Gluon makes it possible to partially apply functions which we use here to scope all parser functions\n    // inside the `let parse` binding above.\n    let parse : String -\u003e Result String Expr = parser.parse (expr () \u003c* spaces)\n    parse\n\n/// Validates that `expr` contains exactly the same integers as `digits`\nlet validate digits expr : Array Int -\u003e Expr -\u003e Bool =\n    let integers xs expr : List Int -\u003e Expr -\u003e List Int =\n        match expr with\n        | Int i -\u003e Cons i xs\n        | Binop l _ r -\u003e integers (integers xs l) r\n    let ints = integers Nil expr\n\n    list.sort (list.of digits) == list.sort ints\n\nlet eval expr : Expr -\u003e Int =\n    match expr with\n    | Int i -\u003e i\n    | Binop l op r -\u003e\n        let f =\n            // Operators are just functions and can be referred to like any other identifier\n            // by wrapping them in parentheses\n            match op with\n            | Add -\u003e (+)\n            | Sub -\u003e (-)\n            | Div -\u003e (/)\n            | Mul -\u003e (*)\n        f (eval l) (eval r)\n\ndo digits =\n    let gen_digit = random.thread_rng.gen_int_range 1 10\n    do a = gen_digit\n    do b = gen_digit\n    do c = gen_digit\n    do d = gen_digit\n    wrap [a, b, c, d]\n\nlet print_digits = for digits (\\d -\u003e\n        seq io.print \" \"\n        io.print (show d))\nseq io.print \"Four digits:\" *\u003e print_digits *\u003e io.println \"\"\n\nlet guess_loop _ =\n    do line = io.read_line\n    // Exit the program if the line is just whitespace\n    if string.is_empty (string.trim line) then\n        wrap ()\n    else\n        match parse line with\n        | Err err -\u003e io.println err *\u003e guess_loop ()\n        | Ok expr -\u003e\n            if validate digits expr then\n                let result = eval expr\n                if result == 24\n                then io.println \"Correct!\"\n                else io.println (\"Incorrect, \" \u003c\u003e int.show.show result \u003c\u003e \" != 24\") *\u003e guess_loop ()\n            else\n                io.println\n                    \"Expression is not valid, you must use each of the four numbers exactly once!\"\n                    *\u003e guess_loop ()\n\nguess_loop ()\n```\n\n[Source][24 game]\n\n## Getting started\n\n### Try online\n\nYou can try gluon in your browser at https://gluon-lang.org/try/. ([Github](https://github.com/gluon-lang/try_gluon))\n\n### Install\n\nGluon can be installed by using one of the prebuilt executables at [Github](https://github.com/gluon-lang/gluon/releases) or you can use Cargo in order to install the `gluon_repl` crate:\n\n```\ncargo install gluon_repl\n```\n\n### REPL\n\nGluon has a small executable that can be used to run gluon programs directly or in a small REPL. The REPL can be started by passing the `-i` flag to the built repl executable which can be run with `cargo run -p gluon_repl -- -i`.\n\nREPL features:\n* Evaluating expressions (expressions of type IO will be evaluated in the IO context).\n* Bind variables by writing `let \u003cpattern\u003e \u003cidentifier\u003e* = \u003cexpr\u003e` (omitting `in \u003cexpr\u003e` from a normal let binding)\n    Example:\n\n         let f x = x + 1\n         let { x, y = z } = { x = 1, y = 2 }\n         f z\n\n* Printing help about available commands with `:h`\n* Loading files with `:l path_to_file` the result of evaluating the expression in the loaded file is stored in a variable named after the filename without an extension.\n* Checking the types of expressions with `:t expression`\n*   Printing information about a name with `:i name`.\u003cbr\u003e\n    Example:\n\n        :i std.prelude.List\n        type std.prelude.List a = | Nil | Cons a (std.prelude.List a)\n        /// A linked list type\n\n* Tab-completion of identifiers and record fields\n    ![repl completion](http://i.imgur.com/IXLQFtV.gif)\n* Exit the REPL by writing `:q`\n\n## Tools\n\n### Language server\n\nGluon has a [language server](https://github.com/gluon-lang/gluon_language-server) which provides code completion and formatting support. Installation is done with `cargo install gluon_language-server`.\n\n### Visual Studio Code Extension\n\nThe [gluon extension][] for Visual Studio Code provides syntax highlighting and completion. To install it, search for `gluon` among the extensions. ([Github](https://github.com/gluon-lang/gluon_language-server))\n\n![example](http://i.imgur.com/44bH0ww.gif)\n\n[gluon extension]:https://marketplace.visualstudio.com/items?itemName=Marwes.gluon\n\n### Vim plugin\n\n[vim-gluon](https://github.com/gluon-lang/vim-gluon) provides syntax highlighting and indentation.\n\nThe gluon language server has been tested to work with https://github.com/autozimu/LanguageClient-neovim and https://github.com/prabirshrestha/vim-lsp.\n\n#### Example configuration (autozimu/LanguageClient-neovim)\n```vim\nlet g:LanguageClient_serverCommands = {\n    \\ 'gluon': ['gluon_language-server'],\n    \\ }\n\n\" Automatically start language servers.\nlet g:LanguageClient_autoStart = 1\n\nnnoremap \u003csilent\u003e K :call LanguageClient_textDocument_hover()\u003cCR\u003e\nnnoremap \u003csilent\u003e gd :call LanguageClient_textDocument_definition()\u003cCR\u003e\n```\n\n## Documentation\n\n[The Gluon Book](https://gluon-lang.org/doc/crates_io/book/index.html)\n\n[Gluon Standard Library API Reference](https://gluon-lang.org/doc/crates_io/std/std.html)\n\n[Rust API Docs](https://docs.rs/gluon/*/gluon/index.html)\n\n\n## Usage\n\n### Rust\n\nGluon requires a recent Rust compiler to build (1.9.0 or later) and is available at [crates.io](https://crates.io/crates/gluon). It can easily be included in a Cargo project by adding the lines below.\n\n```toml\n[dependencies]\ngluon = \"0.18.2\"\n```\n\n### Other languages\nCurrently, the easiest way to interact with the gluon virtual machine is through Rust but a rudimentary [C api][] exists which will be extended in the future to bring it closer to the Rust API.\n\n[C api]: https://github.com/gluon-lang/gluon/blob/master/c-api/src/lib.rs\n\n## Contributing\n\nThere are many ways to contribute to gluon. The two simplest ways are opening issues or working on issues marked as [beginner][]. For more extensive information about contributing, you can look at [CONTRIBUTING.md][]. Contributing also has details on **running/getting-started-with tests** for gluon.\n\n[beginner]:https://github.com/gluon-lang/gluon/labels/Beginner\n[CONTRIBUTING.md]:https://github.com/gluon-lang/gluon/blob/master/CONTRIBUTING.md\n\n## Goals\nThese goals may change or be refined over time as I experiment with what is possible with the language.\n\n* **Embeddable** - Similiar to [Lua][Lua] - it is meant to be included in another program that may use the virtual machine to extend its own functionality.\n\n* **Statically typed** - The language uses a [Hindley-Milner based type system][hm] with some extensions, allowing simple and general type inference.\n\n* **Tiny** - By being tiny, the language is easy to learn and has a small implementation footprint.\n\n* **Strict** - Strict languages are usually easier to reason about, especially considering that it is what most people are accustomed to. For cases where laziness is desired, an explicit type is provided.\n\n* **Modular** - The library is split into its parser, type checker, and virtual machine + compiler. Each of these components can be used independently of each other, allowing applications to pick and choose exactly what they need.\n\n[hm]:https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system\n[prelude]:https://github.com/gluon-lang/gluon/blob/master/std/prelude.glu\n\n## Inspiration\n\nThis language takes its primary inspiration from [Lua][Lua], [Haskell][Haskell] and [OCaml][OCaml].\n\n[Lua]: http://www.lua.org\n[Haskell]: http://www.haskell.org\n[OCaml]: http://www.ocaml.org\n[Rust]: http://www.rust-lang.org\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgluon-lang%2Fgluon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgluon-lang%2Fgluon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgluon-lang%2Fgluon/lists"}