Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/kixiron/crunch-lang
A strongly & statically typed systems level language focused on ease of use, portability and speed, built for the modern age.
https://github.com/kixiron/crunch-lang
Last synced: about 12 hours ago
JSON representation
A strongly & statically typed systems level language focused on ease of use, portability and speed, built for the modern age.
- Host: GitHub
- URL: https://github.com/kixiron/crunch-lang
- Owner: Kixiron
- License: other
- Created: 2019-06-09T03:01:29.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2021-06-01T19:13:27.000Z (over 3 years ago)
- Last Synced: 2024-07-24T10:55:32.020Z (4 months ago)
- Language: Rust
- Homepage:
- Size: 8.21 MB
- Stars: 52
- Watchers: 5
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: Changelog.md
- License: LICENSE-APACHE
Awesome Lists containing this project
README
# Crunch
![CI](https://github.com/Kixiron/crunch-lang/workflows/CI/badge.svg)
![Security Audit](https://github.com/Kixiron/crunch-lang/workflows/Security%20Audit/badge.svg)
[![Coverage Status](https://coveralls.io/repos/github/Kixiron/crunch-lang/badge.svg?branch=master)](https://coveralls.io/github/Kixiron/crunch-lang?branch=master)
![Lines of Code](https://tokei.rs/b1/github/Kixiron/crunch-lang)
[![GitHub Issues](https://img.shields.io/github/issues/Kixiron/crunch-lang)](https://github.com/Kixiron/crunch-lang/issues)Crunch is a strongly & statically typed systems level language focused on ease of use, portability and speed, built for the modern age.
## Building Crunch
First, have the nightly toolchains of [`rustup`](https://rustup.rs/) and `cargo` installed, then run the following commands
```sh
git clone https://github.com/Kixiron/crunch-lang
cd crunch-lang
cargo build
```## About
Crunch is a language that believes in strength through types. It's based on the belief that compilers, at their core, are information driven and that the more information the compiler has to reason about your program with, the more efficiently, aggressively and safely it can optimize your program.
For example, slice indexing is something often implemented as a runtime check, because it's nearly impossible to verify that indexing an arbitrary slice with an arbitrary integer will be successful, but if the slice was statically constrained to have a length of `> x && < y` and the integer used to index also has the same constraint, then indexing will always be within bounds.
Another big goal is provable infallibility, or the ability to statically prove that portions or even the entirety of your program are completely safe from irrecoverable crashes.Crunch takes a lot of inspiration from functional languages and attempts to bring some functional concepts, for example sum types, into the realm of imperative programming.
Crunch has types, enumerations and traits
```
:: A single user
type User
username: String
email: String
privileges: Privileges
end:: Privileges of a user
enum Privileges
None
Read
Write
end:: An admin user
type Admin
username: String
email: String
end:: An account we can store
trait Account
fn name(&self) -> &str
empty
endfn email(&self) -> &str
empty
end
end:: Implement the `Account` trait on the `User` and `Admin` types
extend User with Account
fn name(&self) -> &str
&self.username
endfn email(&self) -> &str
&self.email
end
endextend Admin with Account
fn name(&self) -> &str
&self.username
endfn email(&self) -> &str
&self.email
end
end:: This doesn't have to be done in actual code, but it's an example
import std.collections.Vecfn filter_admins(users: slice[dyn Account & Clone]) -> Vec[dyn Account]
let admin_names: arr[1, &str] := arr["Administrator"]
let mut non_admins := Vec.new()for user in users
:: A normal `if` example
if !admin_names.contains(user.name())
:: A `slice` isn't owned data, so we have to make a copy
:: of it before we can take ownership of it
non_admins.push(user.clone())
end:: An example with pattern matching and match statements
match user.name()
:: `admin` binds the value given to the match,
:: and the `where` clause determines if the arm matches
admin where admin_names.contains(&admin) =>
println("Found an admin named {}", admin)
end:: `_` is used as a catch-all, and `empty` just means that nothing happens
_ => empty
end
end:: Crunch has implicit returns, so the last 'trailing' expression
:: will be treated as a return value
non_admins
end:: An alternative way to write the above function would be this
:: the type of `users` breaks down to this: Each element can be a `User`
:: or an `Admin` and must also implement the `Clone` trait
fn filter_admins(users: slice[(User | Admin) & Clone]) -> Vec[dyn Account]
users.iter().filter_map(
do |account|
match account
:: If the account is of type `User`, return it
user: User =>
Some(user)
end:: If the account is of type `Admin`, don't return it
admin: Admin =>
None
end
end
end
)
.collect()
end
```Crunch has no null, so all nullability comes from the `Option` type and must be explicitly handled
```
enum Option[T]
Some(T)
None
end
```Part of Crunch's focus is also on static analysis methods such as SMT solving and Symbolic Execution. These serve as mechanisms for the compiler to reason about your code and to provide otherwise impossible optimizations, like this short example
```
:: Unoptimized code
fn func()
let y := std.io.read()
let z := y * 2if z == 12
panic()
else
println("Worked!")
end
end:: Optimized code
fn func()
let y := std.io.read():: The code has changed, but the behavior has not
if y == 6
panic()
else
println("Worked!")
end
end
```These kinds of logical analysis also allow for other more complex optimizations, like dropping unused fields from types (with limitations for safety reasons)
```
type PartiallyUnused
used_field: u32
unused_field: u32
endfn main()
let instance = PartiallyUnused is
used_field: 100
unused_field: 200
endprintln("{}", instance.used_field)
end
```In that example only `used_field` is used, so for the instance `instance`, `unused_field` would never be present in the final binary. This optimization is applied at a program-scale, so it only happens to an instance of a struct if it's extra fields are *never* used throughout the entire lifetime of the type.
Crunch is not only a types-first language, however. It firmly believes that the future of computing lies in concurrency at scale, and strives for such with first-class asynchronous programming and structured concurrency. The standard library will not only have a default asynchronous runtime, but will also define traits for other custom runtimes to use so that users can freely use whatever runtime they wish with next to no change in their code.