-
Notifications
You must be signed in to change notification settings - Fork 0
Checking hell
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