In V0.1 execution is done by taking the current type of each subexpression and pushing it down. A specific problem of this is that we may get an answer for a semicolon (statement) expression without ever determining whether the left argument is non-Empty. A vaguer problem is that sometimes we want to push the parameter up. Indeed "case" depends on it, since it takes the intersection of the parameters to get the resulting parameter (which works mostly because failure sets the parameter to Any as well as setting result to Empty).
So clearly we need to give subexpressions a range of types and compress the range to give the final result. Then, for example, the statement/; op can only move the bottom of its range above Empty when the both operands have done so.
In V0.1 execution is done by taking the current type of each subexpression and pushing it down. A specific problem of this is that we may get an answer for a semicolon (statement) expression without ever determining whether the left argument is non-Empty. A vaguer problem is that sometimes we want to push the parameter up. Indeed "case" depends on it, since it takes the intersection of the parameters to get the resulting parameter (which works mostly because failure sets the parameter to Any as well as setting result to Empty). So clearly we need to give subexpressions a range of types and compress the range to give the final result. Then, for example, the statement/; op can only move the bottom of its range above Empty when the both operands have done so.