{"id":13610183,"url":"https://github.com/cdiggins/heron-language","last_synced_at":"2025-04-27T15:35:23.214Z","repository":{"id":79180763,"uuid":"70511923","full_name":"cdiggins/heron-language","owner":"cdiggins","description":"A pure functional type-inferred language based on JavaScript","archived":false,"fork":false,"pushed_at":"2023-05-07T16:07:37.000Z","size":18908,"stargazers_count":57,"open_issues_count":0,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-05T01:11:20.518Z","etag":null,"topics":["3d","3d-graphics","heron","javascript","language","programming-language","type-inference","typed-language","webgl"],"latest_commit_sha":null,"homepage":"https://cdiggins.github.io/heron-language","language":"HTML","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/cdiggins.png","metadata":{"files":{"readme":"README.md","changelog":"history.md","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}},"created_at":"2016-10-10T17:28:31.000Z","updated_at":"2025-02-11T15:48:53.000Z","dependencies_parsed_at":"2024-04-16T08:41:14.703Z","dependency_job_id":null,"html_url":"https://github.com/cdiggins/heron-language","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/cdiggins%2Fheron-language","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdiggins%2Fheron-language/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdiggins%2Fheron-language/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdiggins%2Fheron-language/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cdiggins","download_url":"https://codeload.github.com/cdiggins/heron-language/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251163086,"owners_count":21545873,"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":["3d","3d-graphics","heron","javascript","language","programming-language","type-inference","typed-language","webgl"],"created_at":"2024-08-01T19:01:42.205Z","updated_at":"2025-04-27T15:35:18.184Z","avatar_url":"https://github.com/cdiggins.png","language":"HTML","readme":"# Heron Programming Language\n\n![heron-logo-screenshot](https://user-images.githubusercontent.com/1759994/236684195-4cd18d88-8cfd-4744-8c50-590aed2892b0.png)\n\nSee a demo of 3D geometry in the browser at: [https://cdiggins.github.io/heron-language](https://cdiggins.github.io/heron-language)\n\n# About Heron \n\nHeron is a small cross-platform language that was designed for ease of use, performance, and safety with a JavaScript like syntax. Heron emphasizes pure functional programming code, but looks like a traditional imperative or object-oriented code. \n\nThe Heron implementation was written in TypeScript and uses the [Myna parsing library](https://github.com/cdiggins/myna-parser)\nand the [cdiggins/type-inference](https://github.com/cdiggins/type-inference) project. \n\n# Type Inference\n\nThe most interesting feature of Heron is the fact that it supports type-inference of polymorphic higher-order functions. \n\n![heron-example](https://user-images.githubusercontent.com/1759994/236684430-ee00d3c9-6fa6-4f3f-9511-7e319ca367c5.png)\n\nThe [type inference module was developed as its own standalone library](https://github.com/cdiggins/type-inference) so that it can be reused in other projects. \n\n# Citation\n\nTo formally cite this project please use: \n\n```\n@software{Heron Language,\n  author = {Diggins, Christopher},\n  title = {Heron Programming Language},\n  url = {https://github.com/cdiggins/heron-language},\n  year = {2018},\n}\n```\n\n## Status - Retired \n\nHeron is not under active development. Many features and design ideas from Heron have influenced the [Plato language](https://github.com/cdiggins/plato).\n\n## Heron Design Goals\n\nHeron is intended as a language for expressing libraries of algorithms, that can be reused within other languages as opposed to a language for writing full applications. \n\nHeron is a fully statically typed language that does not require type annotations in most cases (it supports type inference), so it looks and feels like a dynamic language, with the potential efficiency, safety, and tooling of a compiled language. \n\nThe Heron design is influenced most heavily by JavaScript, Haskell, C#, Scala, GLSL, and Scheme, but other languages play a role as well. Heron has a powerful module system built into the language, and a language versioning scheme for maintaining backwards compatibility while the language evolves. \n\nCurrent development on Heron is focused on numerical array processing, such as required in sound and image processing, and data visualization in 2D and 3D. The reference implementation generates JavaScript, but a C++ generator is planned as well.\n\nHeron is built on the principle of emphasizing functional programming, immutable data structures, and type safety while minimizing complexity.\n\n## Implementation\n\nThe v0.1 implementation of Heron is written in TypeScript and generates JavaScript. A Heron to C++ compiler is being planned. \n\nThe language implementation is quite small and simple compared to  other strongly typed languages. \n \nPlease [reach out to me](mailto:cdiggins@gmail.com) if you have a use case for Heron in other contexts and perhaps we can work together. \n\n# Files and Modules\n\n```\nlanguage heron:std:0.1;\n\nmodule heron:intrinsics:0.1\n{\n    function main() {\n        print(\"Hello world\");\n    }\n}\n```\n\nAt the top of every Heron source code file is a language version statement. This is intended to facilitate backwards compatibility and smooth language evolution. The language version statement has the form `language name:dialect:version;`. The language name is always `heron` and for now the only supported dialect is the `std`. The current language version is `0.1`.\n\nAll code must be defined within a named module. In Heron v0.1 files can contain only one module. \n\nLike the language version statement module names have three parts separated by colon character (e.g. `organization:project:version`). The first part is the organization name, the second is the project/library name, and the third is the version identifier. A module name part can be a combination of letters, numbers, hypen, underscore, or dot characters.\n \n## Top Level Forms\n\nAt the top-level scope of a module the following definitions are allowed: \n\n* Functions\n* Intrinsic  \n* Variables\n* Imports\n* Types \n\n### Function Definitions\n\nHeron supports named functions and anonymous functions. Both function forms support either expression bodies or statement bodies.\n\n```\n// Named function with statement body\nfunction sum(xs) {\n    var result = 0;\n    for (var x in xs)\n        result += x;\n    return result;\n}\n\n// Anonymous function with statement body\nvar sum = (xs) =\u003e {\n    var result = 0;\n    for (var x in xs)\n        result += x;\n    return result;        \n}\n\n// Named function with expression body\nfunction sum(xs) = \n    xs.reduce(0, op+);\n\n// Anonymous function with expression body\nvar sum = (xs) =\u003e \n    xs.reduce(0, op+);\n```\n\n#### Function Overloads\n\nUnlike JavaScript and TypeScript Heron allows the same name to be used for multiple functions. Like other strongly typed language, multiple functions may have the same name if they differ by the inferred type signature. \n\nWhen multiple function can be chosen from a single name, the function with the type parameter that best matches the types of the expressions is chosen. If there is ambiguity, the most general type is chosen. This means that if you have an overloaded set of fucntions with ambiguity (like `op+`) then at least one function should have a generic implementation.   \n\n#### Operator Overloads \n\nMost binary operators can be overloaded. The Heron compiler maps operator calls to functions that have the letters `op` before the operator symbol (e.g. `op+`, `op\u003c=`, `op..` etc.). This allows operators to be passed as function arguments. For several examples of operator definitions see the `intrinsics.heron` file. \n\n### Intrinsics \n\nAn intrinsic is a primitive function that the compiler has built-in knowledge of. Intrinsics usually have type annotations provided, otherwise the most generic type signature is assumed (e.g. `Func\u003cT0, T1, TR\u003e`).\n\nThe module named `heron:intrinsics:0.1` is implicitly loaded in every file of a project, without having to be explicitly imported. \n\n### Module Variable Declarations \n\nVariables declared at the module level cannot be rebinded. Apart from that module variables are the same as regular variables.\n\n### Imports \n\nImport statements can occur anywhere, but affect the whole module. All definitions from the imported module are resolved as if they were declared within the importing module level scope. \n\nImported modules must have the same or lesser language version than the importing module. (e.g. Heron 2.3.2 can import Heron 2.2.4 but not Heron 2.5.0). Version 1.0.0 and above of Heron is not guaranteed to be backwards compatible with pre-1.0.0 versions of Heron. \n\n## Statements\n\nHeron has the following statements:\n\n* Variable declarations\n* While statements\n* Do/while statements\n* For statement\n* Compound Statement\n* If statement \n* Empty statement \n\n### For Statements\n\nThe for loop in Heron is similar to a for-each statement in many languages, or the for-of statement in JavaScript. \n\n`for (var x in 0..100) print(x);`\n\nA singled named variable is assigned each value of the array expression in order. In the above example the range operator is used to create am array of values from 0 to 99 inclusively. \n\n## Expressions\n\nHeron has the following expression forms: \n\n* Binary arithmetical operators `+ - * / %`\n* Binary comparison operators `\u003c \u003e \u003c= \u003e= == !=`\n* Boolean operators `\u0026\u0026 || ^^`\n* Array indexing: access `xs[i]` and assignment `xs[i] = x`\n* Postfix increment and decrement `++ --`\n* Ternary conditional operator `?:`\n* Lambda expression `(args) =\u003e body`\n* Regular function call: `f(arg0, arg1, ..., argN)`\n* Method call syntax `arg0.f(arg1, ..., argN)`\n* Propery syntax `arg0.f`\n* Variable binding expression `var name in expr`\n* Assignment `= += = *= /= %=`\n\n## Function Calls and Object Oriented Syntax\n\nHeron is explicitly not an object oriented language, but supports a dot syntax enabling method and property chaining.\n\nIn Heron every function is a static function (there is no implicit `this` variable) but you can also call any function using a dot syntax, with the first argument on the left of the function. If the the function is a unary function (has only one argument) then when using dot syntax the parentheses are omitted, giving it the appearance of a computed property. \n\n```\nfunction sqr(x) = x * x;\nfunction multiply(x, y) = x * y;\n\n// The following two are equivalent and print 36\nprint(sqr(6)); \nprint(6.sqr); \n\n// The following two are equivalent and print 42\nprint(multiply(6, 7));\nprint(6.multiply(7))\n\n// The following is a compilation error, it would be equivalent to writing `sqr(6)()`\nprint(6.sqr())\n```\n\n# The Heron Type System \n\nHeron is a strongly typed programming language. This means that all variables have a type that is determined at compile-time. \n\n## Type Inference \n\nVariable types are deduced from the types of the expressions assigned to them. Function argument types are deduced from how the arguments are used within the function: the mosts specific type satisfying all constraints (i.e. the usage) is assigned.   \n\n## Supported Types \n\nHeron v0.1 supports the following types:\n\n```\n    Float\n    Float2\n    Float3\n    Float4\n    Int\n    Bool\n    Array\u003cT\u003e\n    ArrayBuilder\u003cT\u003e\n    Func\u003cT0, T1, ..., TN, R\u003e\n    Mesh\n```\n\nThese are declared in the intrinsics module, but in v0.1 new types can't' be added without adding support in the compiler.\n\n## Type Casts\n\nThe following casts happen implicitly:\n\n```\n    Float \u003c- Int\n    Float2 \u003c- Float\n    Float3 \u003c- Float, Float2\n    Float4 \u003c- Float, Float2, Float3    \n```\n\n## Arrays\n\nArrays cannot be modified: you cannot assign new values or add or remove values. You can only do that with an `ArrayBuilder` instance which can be constructed from an `Array`. \n\nArrays support two basic operations:  \n\n```\n    intrinsic count\u003cT\u003e(xs: Array\u003cT\u003e): Int;\n    intrinsic at\u003cT\u003e(xs: Array\u003cT\u003e, i: Int): T;     \n``` \n\nThe basic array constructor takes the number of items in the array and a function that generates values in the array for each index: \n\n```\n    intrinsic array\u003cT\u003e(n: Int, f: Func\u003cInt, T\u003e): Array\u003cT\u003e;\n```\n\nThe range operator is defined as follows:\n\n```\n    function op.. (from: Int, upto: Int): Array\u003cInt\u003e\n        = array(upto - from, (i) =\u003e i + from);\n```\n\nIn the default implementation is a rich set of arrays operations defined as a library. See the [source code](input/array.heron) for the implementations of different functions.\n\n### Common Immutable Array Operations\n\nThere most used building block operations used when processing arrays: \n\n```\n    map(xs: Array\u003cT\u003e, f: Func\u003cT, U\u003e): Array\u003cU\u003e;\n    filter(xs: Array\u003cT\u003e, f: Func\u003cT, Bool\u003e): Array\u003cT\u003e;\n    reduce(xs: Array\u003cT\u003e, U init, Func\u003cT, U, U\u003e f): U;\n    zip(xs: Array\u003cT\u003e, ys: Array\u003cU\u003e, f: Func\u003cT, U, V\u003e): Array\u003cV\u003e;\n    slice(xs: Array\u003cT\u003e, from: Int, to: Int): Array\u003cT\u003e;\n```\n\n## ArrayBuilder \n\nAn array builder is another immutable data type that allows the user to set values on an array using familiar indexing assignment syntax, and supports adding elements to the end of the array. \n\nAn `ArrayBuilder` supports the same operations as an `Array` with additional operations:\n\n```\n    push\u003cT\u003e(xs: ArrayBuilder\u003cT\u003e, x: T): ArrayBuilder\u003cT\u003e;\n    set\u003cT\u003e(xs: ArrayBuilder\u003cT\u003e, i: Int, x: T): ArrayBuilder\u003cT\u003e;\n```\n\nNote that \"setting\" or \"pushing\" onto an `ArrayBuilder` instance, creates a new instance: it does not affect the original.\n\nAn `ArrayBuilder` supports an index assignment syntax:\n\n```\n    xs[i] = 42\n```\n\nWhich is rewritten by the compiler as:\n\n```\n    xs = xs.set(i, 42);\n```\n\nAn `ArrayBuilder` can be constructed from an `Array` as follows:\n\n```\n    intrinsic mutable\u003cT\u003e(xs: Array\u003cT\u003e): ArrayBuilder\u003cT\u003e;\n```\n\nExample of using `ArrayBuilder`:\n\n```\n    var xs = [1,2,3].mutable\n    xs[0] = 5;\n    print(xs[0]); // 5\n\n    xs = xs.setAt(0, -1);\n    print(xs[0]); // -1\n\n    xs.setAt(0, 3); \n    print(xs[0]); // Still -1\n    \n    xs = xs.push(9);\n    print(xs.count); // 4\n```\n\n### QuickSort: An ArrayBuilder Example\n\nThe following is an example of a quick-sort algorithm written using the `ArrayBuilder` \n\n```\n    function partition(a, lo, hi) {\n        var p = a[lo];\n        var i = lo - 1;\n        var j = hi + 1;\n        while (true) {\n            do { i++; } while (a[i] \u003c p);\n            do { j--; } while (a[j] \u003e p);\n            if (i \u003e= j) return j;\n            swapElements(a, i, j);\n        }\n    }\n\n    function qsort(a, lo, hi) {\n        if (lo \u003c hi) {\n            var p = partition(a, lo, hi);\n            qsort(a, lo, p);\n            qsort(a, p+1, hi);\n        }\n        return a;\n    }\n\n    function sort(xs) \n        = xs.mutable.qsort(0, xs.count-1).immutable;    \n```    \n\n# Appendices\n\n* [A comparison of Heron to JavaScript / TypeScript](comparison.md)\n* [A brief history of the Heron language](history.md)\n","funding_links":[],"categories":["Uncategorized"],"sub_categories":["Uncategorized"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdiggins%2Fheron-language","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcdiggins%2Fheron-language","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdiggins%2Fheron-language/lists"}