{"id":31061746,"url":"https://github.com/wbbradley/ace","last_synced_at":"2025-09-15T11:39:26.694Z","repository":{"id":65407964,"uuid":"184154262","full_name":"wbbradley/ace","owner":"wbbradley","description":"A statically-typed strictly-evaluated garbage-collected readable programming language.","archived":false,"fork":false,"pushed_at":"2024-07-08T02:19:51.000Z","size":27099,"stargazers_count":46,"open_issues_count":3,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-07-09T03:16:49.042Z","etag":null,"topics":["compiler","ffi","garbage-collect","hindley-milner","lambda-calculus","llvm","llvm-compiler","newtypes","polymorphism","programming-language","static-typing","system-f","type-safety","typeclass","zion"],"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/wbbradley.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":null}},"created_at":"2019-04-29T22:42:36.000Z","updated_at":"2024-07-08T02:20:56.000Z","dependencies_parsed_at":"2023-04-23T23:34:17.011Z","dependency_job_id":null,"html_url":"https://github.com/wbbradley/ace","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/wbbradley/ace","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wbbradley%2Face","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wbbradley%2Face/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wbbradley%2Face/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wbbradley%2Face/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wbbradley","download_url":"https://codeload.github.com/wbbradley/ace/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wbbradley%2Face/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275252458,"owners_count":25432095,"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","status":"online","status_checked_at":"2025-09-15T02:00:09.272Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","ffi","garbage-collect","hindley-milner","lambda-calculus","llvm","llvm-compiler","newtypes","polymorphism","programming-language","static-typing","system-f","type-safety","typeclass","zion"],"created_at":"2025-09-15T11:39:20.086Z","updated_at":"2025-09-15T11:39:26.673Z","avatar_url":"https://github.com/wbbradley.png","language":"C++","readme":"# Ace Language\n\n\n## Overview\n\nThe language was born in the mind of a learner. It was good. The learner wanted to know about\nprogramming languages. He learned deeply. He learned about lambda calculus and type theory. He\nlearned about System-F and typeclasses. He learned about unification and compilers. He built lexers\nand parsers with his hands. He generated code with LLVM. He learned many things. The work was hard\nbut good. It ended in 2020.\n\nThe language was like Haskell and C together. It had garbage collection. It was eager. It checked\ntypes. It was pure but could change when needed. It had operators you could extend. It had\ntypeclasses. It managed resources well. It matched patterns and checked branches. It knew about\ntypes without being told.\n\nIt was a good language. It was called Ace.\n\n## Quick Start\n\nNote: these instructions are likely no longer functional.\n\nTo play with Ace in Docker, try this.\n\n```\ngit clone https://github.com/wbbradley/ace.git\ncd ace\n\n# Get a docker image set up ready to run a build (assumes Docker is running).\n./docker-build.sh \u0026\u0026 ./docker-run.sh bash\n\n# The prior command should open up a bash prompt within a new docker container.\n# Build and install Ace inside this container.\nmake install\n\n# The prior command should have installed Ace to /usr/local. Set up the\n# $ACE_ROOT environment variable.\nexport ACE_ROOT=\"/usr/local/share/ace\"\n\n# Build and run a simple test program\ncd\necho 'fn main() { print(\"Hello world.\") }' \u003e hello_world.ace\nace hello_world\n\n# Read more\nman ace\n```\n\n## Description\n\nAce is a statically typed procedural/functional language. It is a work in\nprogress. Please reach out if you'd like to get involved.\n\n### Syntax\n\n```\nfn main() {\n  print(\"Hello world.\")\n}\n```\n\nThe syntax resembles C or Python (with braces.) The type system is based on\n[System F](https://en.wikipedia.org/wiki/System_F) with extensions for Type\nClasses, newtypes and pattern matching. There is no macro system but there is a\nrich syntax available via reader macros within the parser.\n\n#### Examples\n\n##### Deterministic cleanup\n\n```\nfn main() {\n  let filename = \"some-file.txt\"\n  # 'with' gives guarantees that the value can clean itself up. See std.WithElseResource.\n  with let f = open(filename) {\n    for line in readlines(f) {\n      print(strip(line))\n    }\n  } else errno {\n    print(\"Failed to open ${filename}: ${errno}\")\n  }\n}\n```\n\n##### For comprehensions and iterators\n\n```\nimport itertools {zip}\n\nfn main() {\n  # Multiply some zipped Ints and put them into a Vector\n  print([x * y for (x, y) in zip([1..3], [4..])])\n  # prints [4, 10, 18]...\n}\n```\n\n##### Lambdas (anonymous function expressions)\n\n```\nfn main() {\n  let double = fn (x) =\u003e x * 2\n  assert(double(25) == 50)\n}\n```\n\n##### Lambda shorthand\n\n```\nfn main() {\n  let double = |x| =\u003e x * 2\n  assert(double(25) == 50)\n}\n```\n\n### Semantics\n\nThe evaluation of Ace is strict, not lazy. The call-by-value method of passing\narguments is used.\n\n### Mutability\n\nThere is no explicit notion of immutability, however it is implicit unless\n`var` is used. `var` declarations wrap initialization values in a mutable\nreference cell. Under the covers, this is the `std.Ref` type. The primary way\nto maintain mutable state is to use `var`.\n\n```\nfn main() {\n  # Create a value with let. By default it is immutable.\n  let y = 4\n  # Try to change it...\n  y = 5          // error: type error\n\n  # Create a variable with var. It is mutable.\n  var x = 5\n  print(\"${x}\")  // Prints \"5\"\n\n  # Change what is in the memory cell described by x...\n  x = 7\n  print(\"${x}\")  // Prints \"7\"\n\n  # Try putting some other type of thing in there...\n  x = \"hey!\"     // error: type error. Int != string.String\n}\n```\n\n\n### Encapsulation\n\nThere is no class-based encapsulation in Ace. Encapsulation can be achieved by\n\n1. using modules to implement Abstract Data Types, exposing only the functions\n   relevant to the creation, use, and lifetime of a type.\n2. not letting local variables escape from functions (or blocks), or by using\n   module-local functions.\n\n#### Modularity\n\nAce lacks support for shared libraries or any shareable intermediate\nrepresentation. Code complexity and leaky abstractions can still be avoided by\nlimiting which symbols are exposed from source modules.\n\n### Type System\n\nTypes are inferred but type annotations are also allowed/encouraged as\ndocumentation and sometimes necessary when types cannot be inferred. Ace\nrejects [intermediate type defaulting](https://kseo.github.io/posts/2017-01-04-type-defaulting-in-haskell.html) by design. Although, if a good\ndesign for that comes along, it might happen.\n\n### Polymorphism\n\nPolymorphism comes in two flavors.\n\nType-based polymorphism exists at compile time in the ability to use type\nvariables which are re-bound per function invocation. At run-time, there are a\ncouple different notions of polymorphism. First, Ace supports sum types by\nallowing the declaration of types with multiple data constructors.  This then\nrelies on `match` statements (pattern matching) to branch on the run-time\nvalue. This form of polymorphism may feel unfamiliar to folks coming from \"OOP\"\nlanguages that rely on inheritance and/or abstract classes with any number of\nderived implementations.\n\nSince Ace treats functions as values and allows closure over function\ndefinitions (`fn`), you can `return` new behaviors as functions. Users of those\nfunctions will get statically checked run-time varying behavior (aka run-time\npolymorphism). For example, the `Iterable` type-class requires the definition\nof a single function which will itself return a function which can be called\nrepeatedly to iterate. It has a signature like\n\n```\nclass Iterable collection item {\n  fn iter(collection) fn () Maybe item\n}\n```\n\nSo, on top of the type being returned by the iterator being compile-time\npolymorphic, the usage of such `Iterables` at run-time also involves a run-time\nclosure that may have any number of behaviors or \"shapes\" in how it operates.\nThus, it is polymorphic, but conforms to the specification that it must return\na `Maybe` type. In this case, the `Maybe` type has two data constructors,\n`Just` and `Nothing`. If an iterator returns `Nothing`, it indicates that it is\ndone iterating.\n\nAll code that is reachable from `main` is specialized and monomorphized prior\nto the final code generation phase. Code generation creates LLVM IR, which is\npassed through clang to perform static linking, optimization, and lowering to\nthe target host.\n\n### Learning more\n\nThe best way to learn more at this time is to read through the\n`tests/test_*.ace` code.\n\nTODO: struct types do not support pattern matching. proposed solution: eliminate\nstructs, but add names to newtypes.\n\n[![HitCount](http://hits.dwyl.com/wbbradley/ace.svg)](http://hits.dwyl.com/wbbradley/ace)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwbbradley%2Face","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwbbradley%2Face","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwbbradley%2Face/lists"}