Skip to content

Checking hell

Jonathan edited this page Oct 5, 2018 · 5 revisions

FireflyLang compiler is very restrictive, this means that unless you check something against a Rule for example, you could not tell the compiler in some other way that the value matches the Rule conditions, example:

fun main() {
  val numbers = seq(5, 7, 9)
  numbers[0] // Works because compiler could ensure that 0 follows the InRange(0, 3) rule.
  val numbers2: Seq<Int, *> = seq(5, 7, 9)
  numbers2[1] // Does not work because there is not explicit size and compiler could not ensure that numbers2 has an element at index 1. 
}

In these scenarios, a human could easily identify that 1 does not exceeds numbers2 size, but compiler couldn't and there is no way to bypass this check, this leads to codes like that one:

val values = ...
val position = request("position")
if (position is Positive && values is Vec<*, position + 1>) {
  val value = values[position] // *
}

Note that we check values against Vec<*, position + 1>, that works because a Vec<*, 1> fits into a Vec<*, 2>, so the compiler could safely assume that all validations that applies to Vec<*, 1> consistently applies to Vec<*, 2>. That is not possible in all cases, compiler does some tricks to ensure correctness, we will talk more about that in compiler secrets session.

A simple way to workaround that is to use option operator (?), this will generate a Rule check and give you a Result<T, RuleNotSatisfied> object to work with, let's rewrite the same code using option operator.

val values = ...
val position = request("position")
val value = values[position]? //Result<*, RuleNotSatisfied>

TODO

Clone this wiki locally