{"id":13480248,"url":"https://github.com/google/rune","last_synced_at":"2025-04-11T19:45:31.209Z","repository":{"id":37777565,"uuid":"423747351","full_name":"google/rune","owner":"google","description":"Rune is a programming language developed to test ideas for improving security and efficiency.","archived":false,"fork":false,"pushed_at":"2024-11-16T12:12:34.000Z","size":1307,"stargazers_count":1928,"open_issues_count":2,"forks_count":47,"subscribers_count":28,"default_branch":"main","last_synced_at":"2025-04-08T20:07:44.951Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/google.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2021-11-02T07:36:32.000Z","updated_at":"2025-03-26T11:56:38.000Z","dependencies_parsed_at":"2024-05-13T22:48:54.625Z","dependency_job_id":"cc4ef49d-ac8c-4a0d-b3ed-99567aa695c1","html_url":"https://github.com/google/rune","commit_stats":{"total_commits":157,"total_committers":12,"mean_commits":"13.083333333333334","dds":"0.28025477707006374","last_synced_commit":"7b6cb7f1da357fa5307b3604ae85ee126061a445"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google%2Frune","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google%2Frune/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google%2Frune/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google%2Frune/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/google","download_url":"https://codeload.github.com/google/rune/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248469129,"owners_count":21108963,"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":[],"created_at":"2024-07-31T17:00:36.281Z","updated_at":"2025-04-11T19:45:31.185Z","avatar_url":"https://github.com/google.png","language":"C","funding_links":[],"categories":["C"],"sub_categories":[],"readme":"# ᚣ The Rune Programming Language\n\n_A faster, safer, and more productive systems programming language_\n\nThis is not an officially supported Google product.\n\n**NOTE: Rune is an unfinished language. Feel free to kick tires and evaluate the\ncool new security and efficiency features of Rune, but, for now, it is not\nrecommended for any production use case.**\n\n- [ᚣ The Rune Programming Language](#ᚣ-the-rune-programming-language)\n- [What is Rune?](#what-is-rune)\n- [Rune in Action](#rune-in-action)\n  - [Dedicated \"secret\" types](#dedicated-secret-types)\n  - [A _\"DB-embedded\"_ language: relational data-structures and optimal memory-efficiency](#a-db-embedded-language-relational-data-structures-and-optimal-memory-efficiency)\n    - [How does this work?](#how-does-this-work)\n- [Installation](#installation)\n  - [Compiling the Rune compiler:](#compiling-the-rune-compiler)\n\n# What is Rune?\n\nRune is a Python-inspired efficient systems programming language designed to\ninteract well with C and C++ libraries. Rune has many security features such as\nmemory safety, and constant-time processing of secrets. Rune aims to be faster\nthan C++ for most memory-intensive applications, due to its Structure-of-Array\n\\([SoA](https://en.wikipedia.org/wiki/AoS_and_SoA#:~:text=AoS%20vs.,AoS%20case%20easier%20to%20handle.)\\)\nmemory management.\n\nIt provides many of its features by deeply integrating features similar to the\n[\"DataDraw\"](https://datadraw.sourceforge.net) tool into the primitives and\nconstructs of the language. DataDraw is a code-generation tool that generates\nhighly-optimized C code which outperforms e.g., the C++ STL given a declarative\ndescription of data-structures and relationships between them. For more\ninformation, see the [DataDraw 3.0\nManual](https://datadraw.sourceforge.net/manual.pdf).\n\nAdditional documentation:\n\n-   [Rune Overview](g3doc/index.md)\n-   [Rune for Python programmers](g3doc/rune4python.md)\n-   [DataDraw 3.0 Manual](https://datadraw.sourceforge.net/manual.pdf)\n-   [DataDraw GitHub repository](https://github.com/waywardgeek/datadraw)\n\n# Rune in Action\n\nLet's take a look at two examples that showcase many of the unique features of Rune:\n\n1. A simple example of a secret type, and how it can be used to protect against timing attacks.\n2. A more complex example of a data-structure with nullable, self-referential recursive references.\n    - _(This can present footguns in many languages, but it is trivial in Rune)_\n\n## Dedicated \"secret\" types\n\nConsider the following example for treatment of secrets:\n\n```go\n// Check the MAC (message authentication code) for a message.  A MAC is derived\n// from a hash over the `macSecret` and message.  It ensures the message has not\n// been modified, and was sent by someone who knows `macSecret`.\nfunc checkMac(macSecret: secret(string), message: string, mac: string) -\u003e bool {\n    computedMac = computeMac(macSecret, message)\n    return mac == computedMac\n}\n\nfunc computeMac(macSecret: string, message: string) -\u003e string {\n  // A popular MAC algorithm.\n  return hmacSha256(macSecret, message)\n}\n```\n\nCan you see the potential security flaw? In most languages, an attacker with\naccurate timing data can forge a MAC on a message of their choice, causing a\nserver to accept it as genuine.\n\nAssume the attacker can tell how long it takes for `mac == computedMac` to run.\nIf the first byte of an attacker-chosen `mac` is wrong for the attacker-chosen\n`message`, the loop terminates after just one comparison. With 256 attempts,\nthe attacker can find the first byte of the expected MAC for the\nattacker-controlled `message`. Repeating this process, the attacker can forge\nan entire MAC.\n\nUsers of Rune are protected, because the compiler sees that `macSecret` is\nsecret, and thus the result of `hmacSha256` is secret. The string comparison\noperator, when either operand is secret, will run in constant time, revealing no\ntiming information to the attacker. Care must still be taken in Rune, but many\ncommon mistakes like this are detected by the compiler, and either fixed or\nflagged as an error.\n\n## A _\"DB-embedded\"_ language: relational data-structures and optimal memory-efficiency\n\nAs for the speed and safety of Rune's memory management, consider a simple\n`Human` class. This can be tricky to model in some languages, yet is trivial in\nboth SQL and Rune.\n\n```rs\nclass Human(self: Human, name: string, mother: Human? = null(self), father: Human? = null(self)) {\n  self.name = name\n\n  // The methods \"appendMotheredHuman\" and \"appendFatheredHuman\" are generated\n  // by code \"transformers\", a key factor in Rune's performance.\n  //\n  // We'll learn more about these methods in the next section (\"How does this work?\").\n  if !isnull(mother) {\n    mother.appendMotheredHuman(self)\n  }\n  if !isnull(father) {\n    father.appendFatheredHuman(self)\n  }\n\n  func printFamilyTree(self, level: u32) {\n    for i in range(level) {\n      print \"    \"\n    }\n    println self.name\n    for child in self.motheredHumans() {\n      child.printFamilyTree(level + 1)\n    }\n    for child in self.fatheredHumans() {\n      child.printFamilyTree(level + 1)\n    }\n  }\n}\n\n// Relation statements are similar to \"Foreign Key\" constraints in SQL.\n// They are used to define the relationships between data-structures.\n//\n// The \"cascade\" keyword means that when a Human is destroyed, all of\n// its children are recursively destroyed.\n// (In other words, manual invalidation of pointers is not required)\n//\n// This ability is also provided by code transformers.  See\n// builtin/doublylinked.rn\nrelation DoublyLinked Human:\"Mother\" Human:\"Mothered\" cascade\nrelation DoublyLinked Human:\"Father\" Human:\"Fathered\" cascade\n\n// Let's create a family tree.\nadam = Human(\"Adam\")\neve = Human(\"Eve\")\ncain = Human(\"Cain\", eve, adam)\nabel = Human(\"Abel\", eve, adam)\nalice = Human(\"Alice\", eve, adam)\nbob = Human (\"Bob\", eve, adam)\nmalory = Human(\"Malory\", alice, abel)\nabel.destroy()\nadam.printFamilyTree(0u32)\neve.printFamilyTree(0u32)\n```\n\nWhen run, this prints:\n\n```\nAdam\n    Cain\n    Alice\n    Bob\nEve\n    Cain\n    Alice\n    Bob\n```\n\n### How does this work?\n\nNote that Abel and Malory are not listed. This is because we didn't just kill\nAbel, we destroyed Abel, and this caused all of Abel's children to be\nrecursively destroyed. Also note that Rune now supports null safety. Null safety does not mean null does not exist in the language. It means types by default cannot be null. This can be overridden with \\\u003ctype\\\u003e? in the type constraint.\n\nRelation statements are similar to columns in SQL tables. A table with a Mother\nand Father column has two many-to-one relations in a database.\n\nRelation statements give the Rune compiler critical hints for memory\noptimization. Objects which the compiler can prove are always in\ncascade-delete relationships do not need to be reference counted. The relation\nstatements also inform the compiler to update Human's destructor to recursively\ndestroy children. **Rune programmers never write destructors**, removing this\nfootgun from the language.\n\nTo understand why Rune's generated SoA code is so efficient, consider the arrays\nof properties created for the Human example above:\n\n```typescript\nnextFree = [null(Human)]\nmotherHuman = [null(Human)]\nprevHumanMotheredHuman = [null(Human)]\nnextHumanMotheredHuman = [null(Human)]\nfirstMotheredHuman = [null(Human)]\nlastMotheredHuman = [null(Human)]\nfatherHuman = [null(Human)]\nprevHumanFatheredHuman = [null(Human)]\nnextHumanFatheredHuman = [null(Human)]\nfirstFatheredHuman = [null(Human)]\nlastFatheredHuman = [null(Human)]\nname = [\"\"]\n```\n\nA total of 12 arrays are allocated for the Human class in SoA memory layout. In\n`printFamilyTree`, we only access 5 of them. In AoS memory layout, all 12\nfields would be loaded into cache during the tree traversal, and all fields\nwould be 64 bits on a 64-bit machine. In Rune, only the string references are\n64-bits by default. As a result, **Rune loads only 25% as much data into\ncache** during the traversal, improving memory load times, while simultaneously\nimproving cache hit rates.\n\nThis is why Rune's `binary_trees.rn` code already runs faster than any other\nsingle-threaded result in the [Benchmark\nGames](https://benchmarksgame-team.pages.debian.net/benchmarksgame/index.html).\n(Rune is not yet multi-threaded). The only close competitor is C++, where the\nauthor uses the little-known `std::pmr::monotonic_buffer_resource` class from the `\u003cmemory_resource\u003e` library.\nNot only is Rune's SoA memory layout faster, but its solution is more generic:\nwe can create/destroy Node objects arbitrarily, unlike the C++ benchmark based\non `std::pmr::monotonic_buffer_resource`. When completed, we expect Rune to win most memory-intensive\nbenchmarks.\n\n# Installation\n\n## Compiling the Rune compiler:\n\nYou'll need 6 dependencies installed to compile Rune:\n\n-   Bison (parser generator)\n-   Flex (lexer generator)\n-   GNU multi-precision package gmp\n-   Clang version 10\n-   Datadraw, an SoA data-structure generator for C\n-   CTTK, a constant-time big integer arithmetic library\n    The first four can be installed with one command:\n\n```sh\n$ sudo apt-get install bison flex libgmp-dev clang clang-14\n```\n\nInstalling Datadraw requires cloning [the source from\ngithub](https://github.com/waywardgeek/datadraw).\n\n```sh\n$ git clone https://github.com/waywardgeek/datadraw.git\n$ sudo apt-get install build-essential\n$ cd datadraw\n$ ./autogen.sh\n$ ./configure\n$ make\n$ sudo make install\n```\n\nHopefully that all goes well... After dependencies are installed, to build\nrune:\n\n```sh\n$ git clone https://github.com/google/rune.git\n$ git clone https://github.com/pornin/CTTK.git\n$ cp CTTK/inc/cttk.h CTTK\n$ cd rune\n$ make\n```\n\nCTTK was written by Thomas Pornin. It provides constant-time big-integer\narithmetic.\n\nIf `make` succeeds, test the Rune compiler in the rune directory with:\n\n```sh\n$ ./runtests.sh\n```\n\nSome tests are currently expected to fail, but most should pass. To install\nrune under /usr/local/rune:\n\n```sh\n$ sudo make install\n```\n\nTest your installation:\n\n```sh\n$ echo 'println \"Hello, World!\"' \u003e hello.rn\n$ rune -g hello.rn\n$ ./hello\n```\n\nYou can debug your binary executable with gdb:\n\n```sh\n$ gdb ./hello\n```\n\nTODO: add instructions on how to debug the compiler itself, especially the datadraw debug functionality.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoogle%2Frune","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgoogle%2Frune","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoogle%2Frune/lists"}