1. 23 Apr, 2022 1 commit
  2. 14 Dec, 2021 1 commit
    • Yorick Peterse's avatar
      Add note about not accepting all types of changes · 6e6a7b1f
      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.
      6e6a7b1f
  3. 15 Feb, 2021 1 commit
    • Yorick Peterse's avatar
      Support building with Rust 1.50 · d9b18a71
      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().
      d9b18a71
  4. 14 Feb, 2021 1 commit
    • Yorick Peterse's avatar
      Move and/or from Object to Boolean · 06b0c830
      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.
      06b0c830
  5. 12 Feb, 2021 1 commit
  6. 11 Feb, 2021 2 commits
    • Yorick Peterse's avatar
      Don't implement ToArray for Array · 17a342b6
      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.
      17a342b6
    • Yorick Peterse's avatar
      Simplify the Error trait · 80cd6cba
      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`.
      80cd6cba
  7. 07 Feb, 2021 1 commit
    • Yorick Peterse's avatar
      Use a "match" for detecting keywords · 69406505
      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.
      69406505
  8. 05 Feb, 2021 1 commit
  9. 27 Jan, 2021 1 commit
  10. 26 Jan, 2021 2 commits
    • Yorick Peterse's avatar
      Compile release builds with panic=abort · ec1caa33
      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.
      ec1caa33
    • Yorick Peterse's avatar
      Refactor std::test and remove panic handlers · d7034d52
      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.
      d7034d52
  11. 24 Jan, 2021 1 commit
  12. 23 Jan, 2021 3 commits
  13. 22 Jan, 2021 1 commit
    • Yorick Peterse's avatar
      Rework the IO Error type · 9a33f792
      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
      9a33f792
  14. 21 Jan, 2021 1 commit
    • Yorick Peterse's avatar
      Move more instructions over to external functions · 54ef5882
      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.
      54ef5882
  15. 18 Jan, 2021 2 commits
    • Yorick Peterse's avatar
      Added some docs on external functions · f7e086cf
      Yorick Peterse authored
      f7e086cf
    • Yorick Peterse's avatar
      Add the ability to define/use external functions · 2c3c75fd
      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 ...
      2c3c75fd
  16. 16 Jan, 2021 1 commit
  17. 10 Jan, 2021 2 commits
    • Yorick Peterse's avatar
      Allow return/try/throw in lambdas · b655eb1b
      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.
      b655eb1b
    • Yorick Peterse's avatar
      Fix setting the exit status in the CLI · 1c437385
      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).
      1c437385
  18. 09 Jan, 2021 1 commit
  19. 31 Dec, 2020 1 commit
  20. 30 Dec, 2020 3 commits
    • Yorick Peterse's avatar
      Rename the "object" keyword to "class" · a2ff11d2
      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.
      a2ff11d2
    • Yorick Peterse's avatar
      Infer block return types as Any · 23a8a1bb
      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`).
      23a8a1bb
    • Yorick Peterse's avatar
      Fix soundness hole when using type parameters · e88d3667
      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.
      e88d3667
  21. 28 Dec, 2020 2 commits
  22. 23 Dec, 2020 5 commits
  23. 21 Dec, 2020 2 commits
    • Yorick Peterse's avatar
      Merge ffi::types into ffi and remove constants · 814d8e9d
      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).
      814d8e9d
    • Yorick Peterse's avatar
      Refactor constants containing non-primitive values · bf5c6b62
      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.
      bf5c6b62
  24. 20 Dec, 2020 2 commits
    • Yorick Peterse's avatar
      Add ByteArray.filled() · c7f4e904
      Yorick Peterse authored
      Similar to Array.filled(), this method is used to create a ByteArray
      filled with a given byte.
      c7f4e904
    • Yorick Peterse's avatar
      Don't desugar ?T at the parser level · 9ea8b1e5
      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.
      9ea8b1e5
  25. 19 Dec, 2020 1 commit