-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cf1645a
commit c3dfbba
Showing
4 changed files
with
373 additions
and
215 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,327 @@ | ||
--- | ||
author: Yorick Peterse | ||
title: "Inko 0.13.0 released" | ||
date: "2023-10-13 14:15:40 UTC" | ||
--- | ||
|
||
We're pleased to announce the release of Inko 0.13.0. This release includes a | ||
new C FFI, specialization of generic types and methods, and more. | ||
|
||
## Table of contents | ||
{:.no_toc} | ||
|
||
* TOC | ||
{:toc} | ||
|
||
This release includes many changes not listed in this announcement. For the full | ||
list of changes, refer to the [changelog](https://github.com/inko-lang/inko/blob/main/CHANGELOG.md#0130-2023-10-16) | ||
for this release. | ||
|
||
## A new C FFI and conditional compilation | ||
|
||
<div class="note" markdown="0"> | ||
<div class="icon" markdown="0">🎉</div> | ||
<div class="text" markdown="1"> | ||
|
||
Thanks to the [NLnet foundation][nlnet] for [sponsoring][nlnet-announcement] the | ||
development of this feature | ||
|
||
</div> | ||
</div> | ||
|
||
With version 0.13.0, Inko once again has a functioning FFI for interacting with | ||
C libraries. The FFI is a compile-time FFI, instead of using e.g. | ||
[libffi](https://sourceware.org/libffi/). We also include support for | ||
conditional compilation at the `import` level. | ||
|
||
For example, to use the `ceil()` function from libm, you'd write the following | ||
code: | ||
|
||
```inko | ||
# This imports a C library. | ||
import extern "m" | ||
# This "attaches" a function defined in a C library. | ||
fn extern ceil(value: Float64) -> Float64 | ||
class async Main { | ||
fn async main { | ||
ceil(1.123 as Float64) as Float | ||
} | ||
} | ||
``` | ||
|
||
Variadic functions are also supported: | ||
|
||
```inko | ||
fn extern printf(format: Pointer[UInt8], ...) -> Int32 | ||
class async Main { | ||
fn async main { | ||
printf("Hello %s\n".to_pointer, "Inko".to_pointer) | ||
} | ||
} | ||
``` | ||
|
||
C libraries imported are linked _dynamically_ by default, but static linking can | ||
be enabled using `inko build --static`. The libc and libm libraries are _always_ | ||
linked dynamically, even with the `--static` flag. We dynamically link by | ||
default as many Linux distributions only ship dynamic versions of libraries, | ||
requiring extra work to get the static libraries; assuming they're available in | ||
the first place. Dynamically linking some libraries while statically linking | ||
others isn't supported. | ||
|
||
Conditional compilation is used to restrict imports to specific | ||
configurations/platforms. To import a module for 64 bits Linux platforms, you'd | ||
write the following: | ||
|
||
```inko | ||
import foo if linux and amd64 | ||
``` | ||
|
||
Conditionally compiled code in arbitrary places (e.g. in the middle of a method) | ||
isn't supported. This keeps the complexity required to make this work | ||
manageable, and forces you to push platform/configuration specific code into | ||
dedicated modules. | ||
|
||
For more details, refer to [the FFI documentation](https://docs.inko-lang.org/manual/main/guides/ffi/), | ||
the [conditional compilation documentation](https://docs.inko-lang.org/manual/main/guides/conditional_compilation/), | ||
and/or commit [df66fef7](https://github.com/inko-lang/inko/commit/df66fef7). | ||
|
||
## Specialization of types and methods | ||
|
||
<div class="note" markdown="0"> | ||
<div class="icon" markdown="0">🎉</div> | ||
<div class="text" markdown="1"> | ||
|
||
Thanks to the [NLnet foundation][nlnet] for [sponsoring][nlnet-announcement] the | ||
development of this feature | ||
|
||
</div> | ||
</div> | ||
|
||
Before version 0.13.0, Inko used pointer tagging and runtime checks to handle | ||
generic types. For example, integers used pointer tagging for 63 bits integers | ||
and resort to heap allocating integers that needed the full 64 bits. References | ||
also used pointer tagging, such that generic code could (at runtime) determine | ||
if a value should be dropped, or if its reference count should be adjusted. | ||
Floats were always boxed, requiring a total of 32 bytes for a float (8 bytes for | ||
the pointer, and 24 bytes for the heap allocated value). | ||
|
||
As of 0.13.0, the compiler generates specialized versions of generic types and | ||
methods. `Int` and `Float` are no longer boxed, there's no more pointer tagging, | ||
and no more runtime checks. | ||
|
||
The implementation uses a slightly different approach from other compilers: | ||
instead of specializing types and methods over every type assigned to a generic | ||
type parameter, types are grouped into "shapes" and we specialize over these | ||
shapes. By grouping types together, we can provide a better balance between fast | ||
compile times and good runtime performance. Unboxed types such as `Int`, | ||
`Float`, `Bool`, and `Nil` get their own shape, and thus their own versions of | ||
types and methods. `String` also gets its own shape. References use two shapes, | ||
one for immutable references and one for mutable references. Owned values are | ||
all grouped into the same shape. This means that for example `Array[User]` and | ||
`Array[Kitten]` use the same specialization of the `Array` type. | ||
|
||
Compared to the old runtime approach this new approach results in larger | ||
executables (though this depends on the program in question), but with better | ||
runtime performance. | ||
|
||
See [this section in the | ||
documentation](https://docs.inko-lang.org/manual/main/internals/compiler/#generics) | ||
and commit [3057ba7e](https://github.com/inko-lang/inko/commit/3057ba7e) for | ||
more details. | ||
|
||
## Private types and methods are private to their namespace | ||
|
||
When types and methods are defined as private, they are no longer private to the | ||
module they are defined in. Instead, they are private to the _namespace_ the | ||
surrounding module belongs to. Thus, a type `Foo` defined in `std.foo` is | ||
available to the modules `std.bar`, `std.foo.bar`, but not to `quix.foo`. | ||
|
||
This approach allows related modules (e.g. those provided by the standard | ||
library) to depend on shared private types and methods. In addition, it makes it | ||
possible for unit tests to test private types and methods. | ||
|
||
See commit [81bae997](https://github.com/inko-lang/inko/commit/81bae997) for | ||
more details. | ||
|
||
## Array is implemented in Inko | ||
|
||
The `Array` type is implemented entirely in Inko, instead of acting as a wrapper | ||
around a type provided by the Rust-based runtime library. This makes maintenance | ||
easier, allows `Array` types to be specialized, and removes the need for runtime | ||
library calls for array operations, such as pushing a value into the array. | ||
|
||
See commit [13e8e557](https://github.com/inko-lang/inko/commit/13e8e557) for | ||
more details. | ||
|
||
## "length" is replaced with "size" | ||
|
||
Various types expose methods to get the number of values they store. These | ||
methods used to be called "length", but have been renamed to "size". For | ||
`String` methods that operate on extended grapheme clusters, the term "chars" is | ||
used to better reflect that the operation acts on grapheme clusters instead of | ||
bytes. | ||
|
||
See commit [2771a63e](https://github.com/inko-lang/inko/commit/2771a63e) for | ||
more details. | ||
|
||
## Enum is renamed to Stream | ||
|
||
The type `std.iter.Enum` is now called `std.iter.Stream`, to not confuse | ||
users into thinking it's somehow related to enum classes created using `class | ||
enum`. | ||
|
||
See commit [70728b63](https://github.com/inko-lang/inko/commit/70728b63) for | ||
more details. | ||
|
||
## Reworked parsing and formatting of integers | ||
|
||
Instead of using dedicated methods such as `Int.from_base10` and | ||
`Int.from_base16`, parsing is now done using `Int.parse`. The format to parse is | ||
specified using a `std.int.Format` passed as a second argument: | ||
|
||
```inko | ||
import std.int.Format | ||
Int.parse('123', Format.Decimal) # => 123 | ||
``` | ||
|
||
The same is true for formatting an `Int`: | ||
|
||
```inko | ||
import std.int.Format | ||
123.format(Format.Decimal) # => "123" | ||
``` | ||
|
||
See commit [95434442](https://github.com/inko-lang/inko/commit/95434442) for | ||
more details. | ||
|
||
## Arrays can be sorted | ||
|
||
The methods `Array.sort` and `Array.sort_by` have been added. These methods are | ||
used for sorting an `Array` in place, provided the values stored in the `Array` | ||
implement the trait `std.cmp.Compare`: | ||
|
||
```inko | ||
let nums = [0, 3, 3, 5, 9, 1] | ||
nums.sort | ||
nums # => [0, 1, 3, 3, 5, 9] | ||
``` | ||
|
||
The sorting algorithm used by these methods is a stable, recursive merge sort. | ||
While faster stable sorting algorithms exist (e.g. Timsort), they're much more | ||
complicated to implement compared to merge sort, and as such it's easier to | ||
implement them incorrectly. In the future we may switch to a different | ||
algorithm, if this proves necessary. | ||
|
||
See commit [31a8a17a](https://github.com/inko-lang/inko/commit/31a8a17a) for | ||
more details. | ||
|
||
## Float implements the Compare trait | ||
|
||
The `Float` type now implements `std.cmp.Compare` in accordance to the | ||
`totalOrder` predicate as defined in the IEEE 754 (2008 revision) specification. | ||
Per this specification, values are ordered in the following order: | ||
|
||
1. negative quiet NaN | ||
1. negative signaling NaN | ||
1. negative infinity | ||
1. negative numbers | ||
1. negative subnormal numbers | ||
1. negative zero | ||
1. positive zero | ||
1. positive subnormal numbers | ||
1. positive numbers | ||
1. positive infinity | ||
1. positive signaling NaN | ||
1. positive quiet NaN | ||
|
||
See commit [95434442](https://github.com/inko-lang/inko/commit/95434442) for | ||
more details. | ||
|
||
## The syntax for imports is changed | ||
|
||
The syntax to separate modules and symbols in `import` statements is changed: | ||
instead of `::`, you now have to use `.`: | ||
|
||
```inko | ||
# Before: | ||
import std::foo::(A, B) | ||
# After: | ||
import std.foo.(A, B) | ||
``` | ||
|
||
See commit [8026b29d](https://github.com/inko-lang/inko/commit/8026b29d) for | ||
more details. | ||
|
||
## Working with unique values is made a little easier | ||
|
||
You can now use `self` in `recover` expressions, and values of type `uni ref T` | ||
/ `uni mut T` (temporary borrows of a `uni T` value) can now be passed to | ||
arguments that expect a `ref T` or `mut T`, if the compiler can guarantee this | ||
is safe. [This issue](https://github.com/inko-lang/inko/issues/570) contains | ||
some more details about this change. | ||
|
||
See commits [007495be](https://github.com/inko-lang/inko/commit/007495be) and | ||
[be0d8304](https://github.com/inko-lang/inko/commit/be0d8304) for more details. | ||
|
||
## Running `inko pkg init` is no longer necessary | ||
|
||
When running package commands that alter the package manifest (`inko.pkg`), you | ||
no longer need to run `inko pkg init` to ensure the manifest file exists, as | ||
these commands now create this file automatically. | ||
|
||
See commit [6f7a3780](https://github.com/inko-lang/inko/commit/6f7a3780) for | ||
more details. | ||
|
||
## The package manager supports multiple major versions of the same package | ||
|
||
The dependency graph of your project can now contain multiple different major | ||
versions for the same package. This means package A can depend on version | ||
1.2.3 of the "json" package, while package B can depend on version 2.3.4 of | ||
the same package. It's not possible for the same package to depend on multiple | ||
different major versions of another package, i.e you can't depend on both | ||
version 1.2.3 and 2.3.4 of the "json" package. | ||
|
||
This change makes dependency management less painful, as upgrading a package to | ||
a different major version no longer results in a cascade of major version | ||
updates for any package that depend on it (and so on). | ||
|
||
See commit [256e8166](https://github.com/inko-lang/inko/commit/256e8166) for | ||
more details. | ||
|
||
## Official support for FreeBSD | ||
|
||
Inko now officially supports FreeBSD, and is tested against in our continuous | ||
integration setup. The minimum version we support is 13.2, though older versions | ||
may also work. | ||
|
||
We considered also supporting OpenBSD, but decided against it. The effort | ||
required is just not worth it, given the overlap between people using OpenBSD | ||
and people interested in using Inko is likely small or even non-existing. | ||
|
||
See commit [ba7217ba](https://github.com/inko-lang/inko/commit/ba7217ba) for | ||
more details. | ||
|
||
## The Inko website now lists available third-party packages | ||
|
||
While not related to the release itself, but still worth highlighting: the | ||
website now includes a [page that lists available third-party | ||
packages](/packages). While the page is quite basic, it makes discovering Inko | ||
packages a little easier. | ||
|
||
## Following and supporting Inko | ||
|
||
If Inko sounds like an interesting language, consider joining the [Discord | ||
channel](https://discord.gg/seeURxHxCb). You can also follow along on the | ||
[/r/inko subreddit](https://www.reddit.com/r/inko/). If you'd like to support | ||
the continued development of Inko, please consider donating using [GitHub | ||
Sponsors](https://github.com/sponsors/YorickPeterse). | ||
|
||
[nlnet]: https://nlnet.nl/ | ||
[nlnet-announcement]: /news/inko-0-12-0-released/#header-inko-receives-funding-from-nlnet |
Oops, something went wrong.