- 23 Apr, 2022 1 commit
-
-
Yorick Peterse authored
-
- 14 Dec, 2021 1 commit
-
-
Yorick Peterse authored
In preparation for working on Inko full-time, I'm adding this note. This should hopefully prevent people from spending a lot of time on changes, only for me to turn them down. In the long term we may relax the contribution policy, if we find it won't cost us more effort than it brings benefits.
-
- 15 Feb, 2021 1 commit
-
-
Yorick Peterse authored
Rust 1.50 includes some changes related to UNIX file descriptors, essentially making -1 a reserved value. This means we need to use a different value to indicate a file that has already been closed. We don't want to use Option<File> here as this would require double checking: once to unwrap the option, and once at the OS level to check if the file descriptor is valid. If/when we move to single ownership this won't be a problem, as we can just drop the entire File when an object is dropped. In addition, we fix some atomic operation deprecations, due to Rust 1.50 deprecating the use of compare_and_swap() in favour of compare_exchange().
-
- 14 Feb, 2021 1 commit
-
-
Yorick Peterse authored
In practise these methods are only used with booleans. By defining these methods only on Boolean, objects are free to define their own methods using these names.
-
- 12 Feb, 2021 1 commit
-
-
Yorick Peterse authored
This reverts commit 17a342b6.
-
- 11 Feb, 2021 2 commits
-
-
Yorick Peterse authored
Converting an Array to an Array doesn't make much sense, as the input is already an Array. In addition, users may think `to_array` creates a new Array when in reality it just returns `self`. Cloning the entire array and its values would be expensive, and wouldn't bring any benefits.
-
Yorick Peterse authored
Error no longer requires a `message` method, instead only requiring the `ToString` implementation. This simplifies implementing the trait for custom error types, and means the user doesn't have to ask themselves whether they should use `to_string` or `message`.
-
- 07 Feb, 2021 1 commit
-
-
Yorick Peterse authored
This is much simpler compared to the previous perfect hashing approach, and also performs better due to not needing as many method calls. In the future the compiler may optimise this further, but it's good enough for the time being.
-
- 05 Feb, 2021 1 commit
-
-
Yorick Peterse authored
-
- 27 Jan, 2021 1 commit
-
-
Yorick Peterse authored
-
- 26 Jan, 2021 2 commits
-
-
Yorick Peterse authored
This reduces the binary size by about 200 KB, and is possible now that we no longer catch Rust panics in the VM. In addition, aborting immediately ensures we don't end up making the panic worse by running cleanup routines or other code. In dev mode we still use panic=unwind, as this may make debugging in certain cases easier.
-
Yorick Peterse authored
The std::test module has been refactored to no longer depend on global state. Instead, each module must define a `tests` method that takes a `Tests` type as its argument. This type is used for registering test groups and tests, without relying on global state (using a process). In addition, the assertion methods are now located in std::test itself, and use the naming pattern `assert_X`. They also throw instead of panicking, requiring the use of `try`. These changes are made to reduce the places where we panic, to provide a nicer unit testing interface, and to not rely on global state (provided through a process). As part of these changes, support for panic handlers has been removed. Panics are meant for errors that you can't recover from, but panic handlers contradict that goal. In addition, they introduce a fair bit of complexity, and were never truly guaranteed to run. The removal of panic handlers simplifies the VM, makes it more clear what panics are for, and allows the VM to be compiled with `panic=abort`. To handle panics, one should use a system monitoring service of some sort, such as runit or systemd. Because panics are the result of software bugs, you can't handle these at runtime. This means the only sane response is to log it somewhere, and restart the entire program. A well written program won't panic, so this shouldn't pose a problem in practise. In addition, external monitoring solutions will always be more reliable than an in-process monitoring/logging solution, as they aren't affected by the mayhem caused in the process being monitored. This fixes #205.
-
- 24 Jan, 2021 1 commit
-
-
Yorick Peterse authored
-
- 23 Jan, 2021 3 commits
-
-
Yorick Peterse authored
Now that std::env.executable is available, the fixture method "inko_executable" is unnecessary.
-
Yorick Peterse authored
This method allows one to get the path to the current executable.
-
Yorick Peterse authored
This adds std::os::Command and various related types. The Command type is used as a builder type for spawning a child process. The API is loosely based on Rust's Command API, albeit with some differences here and there.
-
- 22 Jan, 2021 1 commit
-
-
Yorick Peterse authored
The type std::io::Error now is a custom class, wrapping both an IO error code and message. The error code makes it easier to determine at runtime what lead to a failure. Storing the message in addition to the error allows for custom error messages where needed. This fixes #236
-
- 21 Jan, 2021 1 commit
-
-
Yorick Peterse authored
The instructions moved over are instructions that aren't frequently used, or likely can't be made faster in the future with a JIT (when/if we add one). As such, these have been moved out of the interpreter loop, reducing the instruction set to 98 instructions.
-
- 18 Jan, 2021 2 commits
-
-
Yorick Peterse authored
-
Yorick Peterse authored
Inko's instruction set was nearing almost 190 instructions, many of which are high-level instructions (e.g. writing to STDOUT). We want to add the ability to spawn OS commands, which would need (based on our current estimates) around 5 VM instructions. Every time an instruction is added, it adds more code to the main interpreter loop. We also need to extend the compiler to support the new instructions, and only have limited type-checking applied when these instructions are used. To solve these problems, we introduce the concept of external functions. An external function is a function with a fixed signature, registered in the VM to a name. The Inko runtime can load these functions using the ExternalFunctionLoad instruction, then call them using the ExternalFunctionCall instruction. Loading these functions is done using the syntax `extern def` like so: extern def stdout_write_string(input: String) !! String -> Integer These functions are then called ...
-
- 16 Jan, 2021 1 commit
-
-
Yorick Peterse authored
It's now less extreme/strict about the use of keyword arguments, based on our experience with Inko's standard library use of them thus far.
-
- 10 Jan, 2021 2 commits
-
-
Yorick Peterse authored
Lambdas now allow the use of the keywords `return`, `try`, and `throw`. This removes the need for the more verbose `local try` and `local throw` keywords, and allows early returns in lambdas; something that wasn't possible before.
-
Yorick Peterse authored
The CLI wouldn't set the exit status if a program terminated without a panic or CLI related error (e.g. an invalid flag).
-
- 09 Jan, 2021 1 commit
-
-
Yorick Peterse authored
Having to type out "lambda" makes using lambdas annoying. Using "fn" makes this more pleasant, and keeps the keyword in line with the "do" keyword used for closures.
-
- 31 Dec, 2020 1 commit
-
-
Yorick Peterse authored
The Inko type checker now correctly disallows the use of the constructor syntax for built-in types, such as ByteArray and Array.
-
- 30 Dec, 2020 3 commits
-
-
Yorick Peterse authored
Back when Inko was more dynamic/prototype based, the use of `object` made more sense. As we're planning on changing the memory layout to resemble a more traditional class based approach, the use of "object" instead of "class" can be confusing. In addition, users coming from other languages may wonder why we're not just using "class" instead of "object". This commit changes the "object" keyword to "class", solving these problems.
-
Yorick Peterse authored
When using a closure or lambda in a type signature, leaving out the return type infers it as Any; not Nil. Inferring the type as Nil can lead to soundness problems, such as this: import std::mirror import std::stdio::stdout def example(callback: do) -> Nil { callback.call } let result = example { 10 } stdout.print(mirror.reflect(result).inspect) This will print `10` to STDOUT, instead of `Nil`. By inferring `callback` as `do -> Any` instead of `do -> Nil` we can solve this, as the above `example` method wouldn't compile (as `Any` isn't compatible with `Nil`).
-
Yorick Peterse authored
When using type parameters inside a block, other types were incorrectly treated as being compatible with the parameter (assuming its requirements are met). This can lead to soundness issues, such as the following: def push!(A)(values: Array!(A)) { values.push(10) } push(Array.new('foo')) Here `push` is unsound because the exact type of `A` isn't known until runtime, meaning it's not safe to push `10` into the array. To solve this, we introduce the concept of "rigid type parameters". These are type parameters that can't be further inferred as/assigned new types, and other types aren't compatible with these type parameters. The term "rigid type parameter" originates from Haskell. Rigid type parameters are also called "skolem type parameter", but we don't use that term because it's unlikely to be widely known or understood.
-
- 28 Dec, 2020 2 commits
-
-
Yorick Peterse authored
When generating the type name of a type parameter, the name of the type parameter is now always included. This makes it a bit easier to read type errors, as you're not left wondering if a type is a trait or a type parameter.
-
Yorick Peterse authored
This adds support for looking up type parameter methods in the Inko type checker.
-
- 23 Dec, 2020 5 commits
-
-
Yorick Peterse authored
Early local returns in closures/lambdas are basically impossible to use, as all control flow goes through closures and thus can't return from nested closures (but not the surrounding method). This commit removes all support for `local return`, in favour of just using implicit returns.
-
Yorick Peterse authored
While still experimental, there may be cases where it can prove useful.
-
Yorick Peterse authored
-
Yorick Peterse authored
-
Yorick Peterse authored
-
- 21 Dec, 2020 2 commits
-
-
Yorick Peterse authored
The contents of std::ffi::types have been moved into std::ffi. The various Type constants (VOID, Pointer, etc) have all been removed in favour of the module methods that returned these types. The corresponding unit tests have been updated to not depend on constants containing complex objects (e.g. an FFI library).
-
Yorick Peterse authored
In preparation for #212, a variety of constants containing non-primitive data (e.g. arrays) have been refactored away. Some cases remain, such as std::test::DEFAULT_CLIENT. These requires further changes that we'll make in separate commits.
-
- 20 Dec, 2020 2 commits
-
-
Yorick Peterse authored
Similar to Array.filled(), this method is used to create a ByteArray filled with a given byte.
-
Yorick Peterse authored
While semantically ?T and Option!(T) are the same, syntactically they are not. In addition, desugaring ?T at the parser level means a consumer of the AST can't determine if ?T or Option!(T) was used. This changes the self-hosting parser so it produces an OptionType AST node, instead of desugaring ?T into a Constant node.
-
- 19 Dec, 2020 1 commit
-
-
Yorick Peterse authored
-