{"id":26881118,"url":"https://github.com/dlurton/anode","last_synced_at":"2025-05-07T23:04:53.121Z","repository":{"id":148002318,"uuid":"96179930","full_name":"dlurton/anode","owner":"dlurton","description":"Anode Programming Language","archived":false,"fork":false,"pushed_at":"2018-01-24T09:15:56.000Z","size":2890,"stargazers_count":9,"open_issues_count":5,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-07T23:04:48.961Z","etag":null,"topics":["compiler","language","llvm","parsers","pratt-parser","programming-language","repl"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dlurton.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":"2017-07-04T05:49:53.000Z","updated_at":"2024-09-29T09:51:19.000Z","dependencies_parsed_at":"2023-05-28T05:15:16.414Z","dependency_job_id":null,"html_url":"https://github.com/dlurton/anode","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/dlurton%2Fanode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dlurton%2Fanode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dlurton%2Fanode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dlurton%2Fanode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dlurton","download_url":"https://codeload.github.com/dlurton/anode/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252968114,"owners_count":21833251,"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","language","llvm","parsers","pratt-parser","programming-language","repl"],"created_at":"2025-03-31T14:53:08.489Z","updated_at":"2025-05-07T23:04:53.108Z","avatar_url":"https://github.com/dlurton.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Anode Programming Language\n\n[![Build Status](https://travis-ci.org/dlurton/anode.svg?branch=master)](https://travis-ci.org/dlurton/anode)\n\nAnode is yet another embryonic programming language using LLVM as a back-end.\n\nThere's a basic REPL.  Statements entered there will be parsed and then:\n\n - The AST will be displayed.\n - If all passes against the AST succeed LLVM IR will be generated and displayed.\n - The statement will be executed and the result will be displayed.\n \nIt's also possible to execute scripts directly, i.e.\n\n    ./bin/\u003cbuild type\u003e/anode path/to/source_file.an\n    \nWhere `\u003cbuild type\u003e` is either `Release` or `Debug`.\n\nA `.an` file may also include a shebang line, i.e.\n\n    #!/path/to/anode/executable \n \n\nGoals of the language:\n\n- Will be initially targeted at application developers (as opposed to systems developers)\n- Easy to just jump in and start doing stuff like Python\n- Strongly typed like C#/Java\n- High performance (utilizes LLVM back-end which has an extensive suite of compiler optimizations)  \n- Don't needlessly exclude features (post/pre increment operators, ternary operator, generics, etc)\n\nThe compiler and compiled code use the [Boehm-Demers-Weiser conservative garbage collector](https://github.com/ivmai/bdwgc). \n\nExamination of [simple_tests.cpp](https://github.com/dlurton/anode/blob/master/src/tests/simple_tests.cpp) and the [these files](https://github.com/dlurton/anode/tree/master/src/tests/suites) \nwill give a complete and up-to-date picture of supported syntax and features, however, here's a summary:\n\n- Single-line comment:\n    ```\n    # this is a single line comment\n    ```\n- Nestable, multi-line comment:\n    ```\n    (# this is a multiline comment\n        (# this is a nested comment which doesn't break the outer comment. #) \n    #)\n    ```\n- Data types: `bool`, `int` and `float`.\n- Literal ints (`123`), floats (`123.0`) and booleans (`true` or `false`).\n- Global variable declarations: `someVariable:int`\n    - Variables are strongly typed.\n    - Variables must be declared before use.\n    - New variables are always initialized to 0.\n    - Variables may have an initializer: `someVariable:int = 1 + 2 * anyExpressionHere`\n- Binary Operators:\n    - +, -, /, *, =, !=, ==, \u003e, \u003e=, \u003c, \u003c=, \u0026\u0026, ||\n - Casting:\n    - Implicit casting happens when there is no precision loss between float and int:\n    - For example in the expression:  `1.0 + 2` the `2` is cast to a `float` and the expression's result is a `float`.\n    - Explicit casting is required when there is a precision loss, for example:\n        ```         \n        someFloatValue:float = 3.14\n        someIntValue:int = cast\u003cint\u003e(someFloatvalue)\n        ```\n      The the fractional portion of `someFloatValue` is truncated and `someIntValue` becomes `3`.\n - Compound Expressions:\n    ```\n    someInt:int = { 1 2 3 }\n    ``` \n    The last expression within the compound expression (`3`) is the value assigned to `someInt`.\n - Ternary expressions: `(? condition, trueValue, falseValue )`\n    - When `condition` evaluates to true, `trueValue` is evaluated otherwise `falseValue` is evaluated.\n    - This is short circuiting!\n - If expressions:\n    - Like ternary expressions but more powerful because they also serve as traditional if statements.  \n    - For example `a = if(a == b) 1 else 2\"` works just like ternary. \n    - Also note that due to how compound expressions return the last value, more complex logic can be used to determine the \n    values returned by each branch.  For example:  `a = if(a == b) { 1 2 } else { 3 4 }` In this case `a` will become `2` \n    when `a == b` or `4` when `a != b`.\n - Built-in assert function: `assert(someExpression)`\n    - This is not an actual function, it's part of the syntax!\n    - If `someExpression` is non-zero, execution continues unimpeded\n    - If `someExpression` is zero, an error message is printed to stderr including the anode source file, line number, and expression that \n        evaluated to false and the process is terminated.\n    - This expression is/will be heavily used during testing of Andoe languages features. \n - While loops:\n    - `while(condition) expression` or `while(condition) { expression1 expression2 ...}`\n - Classes:\n    ```\n        class Widget {\n            id:int\n            weight:float\n            quantity:int\n            func calculateTotalWeight:float() quantity * weight\n        }\n    ```\n - Heap allocated, garbage collected objects: `someWidget:Widget = new Widget()`\n    - `someWidget` is a reference.    \n - Dot operator:\n    `someWidget.weight = 12.53`\n - Class fields with a class type:\n    ```\n    class WidgetPair {\n        first:Widget\n        second:Widget \n    }\n    aPairOfWidgets:WidgetPair\n    aPairOfWidgets.first.id = 1\n    aPairOfWidgets.second.id = 2\n    ```\n - Can define functions: `func someFunction:int() 10 + 12` (if there is only one expression in the function body)\n    - Or use curly braces when there is more than one expression in the function body: \n    ```\n        func someFunction:int() { \n            someGlobal = someGlobal + 1 \n            someGlobal + 12 \n        }\n    ```\n    - The result of the last expression in the function body is the return value.\n    - Functions may return nothing: `func someFunction:void() someExpression` in which cast the last expression in the function body is ignored.\n    - Local variables also can be defined within functions.\n    - Functions may be invoked:  `anInt:int = someFunction()`    \n    - Primitive types may be used as function arguments:\n        - `func someFunc:void(arg1:int, arg2:float, arg3:bool) someExpression`\n - Namespaces\n```\n    namespace Foo::Bar {\n        class SomeClass { ... }\n    } \n    anInstance:Foo::Bar::SomeClass = new Foo::Bar::SomeClass()\n```\n- If a namespace contains only a single item, curly braces may be omitted:\n```\n    namespace Foo::Bar \n        class SomeClass { }\n```\n - Templates!  Anode's templates are most similar in function to D's mixins but are not as yet as flexible. \n Templates can be used as a means of reducing code duplication.  \"Expanding\" the template essentially causes the template's contents to be\n  copied to the expansion site just as if the code had been copied and pasted.  Templates may have arguments. Currently, only types may \n  be used as arguments for templates.  The snippet below gives the \n `FooDocumentItem` and `BarDocumentItem` classes the `documentItemId` field and `assignDocumentItemId()` method.\n```\n    template CommonDocumentItemMembers { \n        documentItemId:int\n        func assignDocumentItemId() {\n            ...generate unique documentItemId...\n        }\n    }\n    class FooDocumentItem {\n        expand CommonDocumentItemMembers\n    }\n    class BarDocumentItem {\n        expand CommonDocumentItemMembers\n    }\n```\n- Templates can be used to create variations of the same class.   Also note that templates consisting of only a single \nexpression do not need to be wrapped in `{}`.\n```\n    template SomeTemplate\u003cTArg\u003e \n    class SomeClass {\n        someValue:TArg\n    }\n\n    namespace SomeNamespaceInt expand SomeTemplate\u003cint\u003e\n    namespace SomeNamespaceFloat expand SomeTemplate\u003cfloat\u003e\n    \n    a:SomeNamespaceInt::SomeClass = ...\n    b:SomeNamespaceFloat::SomeClass = ...\n    a.someValue = 10    # a.someValue is an int\n    b.someValue = 1.01  # b.someValue is a float\n ```\n - Or of the same function: (note that once function overloading is completed, the expansion sites may exist in the same namespace)\n```\n    template AbsoluteValue\u003cTNumber\u003e {\n        func abs(n:TNumber) (? n \u003e 0 ; n; 0 - n;) \n    }\n    namespace math::int_funcs expand AbsoluteValue\u003cint\u003e\n    namespace math::float_funcs expand AbsoluteValue\u003cfloat\u003e\n```\n - Generics! Generic functions are based on the template feature.  Classes that are placed within an anonymous template\n can be referenced along with their type arguments similar to C++, Java or C#.\n ``` \n     template \u003cTItem\u003e\n     class Node {\n         item:TItem\n         next:Node\n     }\n     \n     \n     n1:Node\u003cint\u003e = new Node\u003cint\u003e()\n     n1.next = new Node\u003cint\u003e()\n     n1.item = 10\n     n1.next.item = 11\n ```\n \n#### Really Really Rough Feature Backlog\n\nThese are listed in roughly the order they will be implemented.  The basic plan is to implement a core set of features found in most \nlanguages and that are needed for basic usefulness and then come back and add some (perhaps functional) special sauce. \n\n- Generate and invoke \"object_init\" which initializes class fields to their defaults when instantiated.\n- Strings and their various operations\n- Explicit return, for when an exit before the last expression of the function body is desired.  Will use keyword `ret`\n- `for` loop\n- `switch` maybe with pattern matching.\n- Bitwise operators\n- Unary operators (`++`, `--`, `!` etc)\n- Compound assignment(`*=`, `+-`, `/=`, etc)\n- Pass class instances by value\n- Declare references to objects (something like `anObjectReference:SomeClass*`) \n- Pass any type by reference \n- Function overloading\n- Member functions\n- Member access levels (`private`, `public`, `protected` etc)\n- Constructors \n- Inheritance\n- Exceptions\n- Virtual functions\n- Interfaces / abstract functions\n- Generics\n- Lambdas\n- Modules\n- Pre-compile groups of modules into shared libraries for faster loading and interop with other languages such as C \n- Compiler generated metadata about all compiled language constructs\n  - Can be used by the compiler when importing a module *and* for reflection\n- Reflection\n- Multiple return value / unpacking:  `(firstValue:int, secondValue:int) = functionReturningPair()`\n  - Probably uses tuples\n- Numerous other ideas too amorphous to mention\n\n#### Other desired features of unspecified importance\n\n- `debug_assert` function, similar to the `assert` function, but is removed during release builds.\n\n## Building\n\n### Prerequisites\n\nThe following must be installed and available prior to building Anode.\n\n - [cmake](https://cmake.org/) (3.4.3 or later) \n - gcc 6 or clang-4.0 or later. clang-4.0 is recommended.\n    - Note that if building on Ubuntu 14.04 (and possibly later), gcc-6 is always required--even when building with clang because \n    clang needs more recent libstdc++ headers in order to provide up-to-date C++14 support.  (Headers from gcc-4.8 do not work.)\n - libuuid\n - cmake 3.4.3 or later\n - autoconf\n - libatomic (if using a version of gcc that doesn't have atomic operations built-in, required by libgc)\n - libtool\n - About 50gb+ of free disk space (for building LLVM, mainly)\n\n### Building Dependencies\n\nA subset of Anode's dependencies must be built from source before Anode itself can be built. In the case\nof LLVM, this is because Anode builds against LLVMs master branch in order to keep up more easily with LLVM's frequent\nAPI changes.  The other dependencies are either non-standard in linux distributions, (e.g. liblinenoise-ng) or are more\nrecent versions than is frequently found in linux distributions (e.g. libgc). \n    \nThe build scripts will clone the repositories of each of these dependencies and build them with the necessary options, \nplacing all the source codes and intermediate files into `externs/scratch`. If successful, the libraries and headers of each dependency \nwill be installed in sub-directories of `externs/release` or `externs/debug`, depending on if a release build has been selected.\n\n### First Time Building\n\nUse the script `tools/build-all-debug` or `tools/build-all-release` to build all dependencies and Anode in Debug or Release modes, \nrespectively.\n\n### Building Anode\n\nAfter building the first time, you can build just Anode like so:\n\n    ./tools/build-anode \n    \nThe default is to perform a release build if the environment variable `ANODE_BUILD_TYPE` is not set.  To perform a debug build, set\n`ANODE_BUILD_TYPE` to `Debug` before executing `./tools/build-anode`\n\nTo run the all the tests, from the `cmake-build-debug` or `cmake-build-release` directories, execute:\n\n    ctest --output-on-failure\n\nBuilding the source documentation requires doxygen.  This is not currently built by any of the build scripts.\n\n    cd $project_root/src\n    doxygen doxygen.cfg\n    \nDocumentation will be generated and stored in the project root.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdlurton%2Fanode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdlurton%2Fanode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdlurton%2Fanode/lists"}