Correctly type spliced expressions
Summary:
Up to this point, we've been typing spliced expressions without special logic: That is, this works and typechecks without error:
```
Code`4 + __splice__(4)`
```
However, we want to do a couple of things here. We want to enforce that one can only splice in Expression Trees. We also want to extract the inferred type out of the Expression Tree. So in the following example:
```
$x = Code`4`;
Code`4 + __splice__($x)`
```
We want to enforce that `$x` is an Expression Tree. We also want to infer that `__splice__($x)` has the int type.
We can accomplish this by:
Making the declaration of ExprTree the following:
```
final class ExprTree<TVisitor, TResult, TInfer>{
public function __construct(
private (function(TVisitor): TResult) $x,
private (function(): TInfer) $err,
) {}
}
```
Desugar an Expression Tree into
```
() ==> {
// Spliced Expression Assignments
return new ExprTree(
(... $v) ==> { ... // Desugared tree }
() ==> { // Original expression }
);
}
```
Since the original expression does not need to be run or compiled in codegen path, we can replace that with a lambda that simply throws an Exception. In the typechecker path, we will then infer the correct types.
This diff implements the desugaring as well as the enforcement that spliced expressions are ExprTrees and extracts the inferred type TInfer. It does not implement the enforcement that one can only splice in Expression Trees with the same visitor yet.
Reviewed By: Wilfred
Differential Revision:
D24281195
fbshipit-source-id:
3d5aa3e1cf1f97f2d8d28bce1ebfb00ad423f0c2