Expression Trees: Syntax Supported

Expression tree DSLs can use most of the expression and statement syntax in Hack.

For a full list of supported syntax, see also expr_tree.hhi.

Literals

Example Visitor Runtime Typing
true $v->visitBool($position, true) MyDsl::boolType()
1 $v->visitInt($position, 1) MyDsl::intType()
1.23 $v->visitFloat($position, 1.23) MyDsl::floatType()
"foo" $v->visitString($position, "foo") MyDsl::stringType()
null $v->visitString($position) MyDsl::nullType()
N/A N/A MyDsl::voidType()

Binary Operators

Operator names are based on the appearance of the symbol, as different DSLs may choose different semantics for an operator.

Example Visitor Runtime Typing
$x + $y $v->visitBinop($position, ..., '__plus', ...) __plus method on $x
$x - $y $v->visitBinop($position, ..., '__minus', ...) __minus method on $x
$x * $y $v->visitBinop($position, ..., '__star', ...) __star method on $x
$x / $y $v->visitBinop($position, ..., '__slash', ...) __slash method on $x
$x % $y $v->visitBinop($position, ..., '__percent', ...) __percent method on $x
$x && $y $v->visitBinop($position, ..., '__ampamp', ...) __ampamp method on $x
$x || $y $v->visitBinop($position, ..., '__barbar', ...) __barbar method on $x
$x < $y $v->visitBinop($position, ..., '__lessThan', ...) __lessThan method on $x
$x <= $y $v->visitBinop($position, ..., '__lessThanEqual', ...) __lessThanEqual method on $x
$x > $y $v->visitBinop($position, ..., '__greaterThan', ...) __greaterThan method on $x
$x >= $y $v->visitBinop($position, ..., '__greaterThanEqual', ...) __greaterThanEqual method on $x
$x === $y $v->visitBinop($position, ..., '__tripleEquals', ...) __tripleEquals method on $x
$x !== $y $v->visitBinop($position, ..., '__notTripleEquals', ...) __notTripleEquals method on $x
$x . $y $v->visitBinop($position, ..., '__dot', ...) __dot method on $x
$x & $y $v->visitBinop($position, ..., '__amp', ...) __amp method on $x
$x | $y $v->visitBinop($position, ..., '__bar', ...) __bar method on $x
$x ^ $y $v->visitBinop($position, ..., '__caret', ...) __caret method on $x
$x << $y $v->visitBinop($position, ..., '__lessThanLessThan', ...) __lessThanLessThan method on $x
$x >> $y $v->visitBinop($position, ..., '__greaterThanGreaterThan', ...) __greaterThanGreaterThan method on $x

Ternary Operators

Example Visitor Runtime Typing
$x ? $y : $z $v->visitTernary($position, ..., ..., ...) $x->__bool() ? $y : $z

Unary Operators

Example Visitor Runtime Typing
!$x $v->visitUnop($position, ..., '__exclamationMark') __exclamationMark method on $x
-$x $v->visitUnop($position, ..., '__negate') __negate method on $x
~$x $v->visitUnop($position, ..., '__tilde') __tilde method on $x
$x++ $v->visitUnop($position, ..., '__postfixPlusPlus') __postfixPlusPlus method on $x
$x-- $v->visitUnop($position, ..., '__postfixMinusMinus') __postfixMinusMinus method on $x

Local Variables

Example Visitor Runtime Typing
$x $v->visitLocal($position, '$x') Same as normal Hack

You can see here that the visitor runtime does not know the type of $x, it just sees a call to visitLocal with the variable name as a string '$x'.

Note that expression trees do not allow free variables. You can only use local variables that have been previously assigned or introduced with a lambda.

Lambdas

Example Visitor Runtime Typing
(Foo $x) ==> $y $v->visitLambda($position, vec['$x'], vec[...]) Same as normal Hack

Note that the visitor runtime does not see the type of $x.

Statements

Example Visitor Runtime Typing
$x = $y; $v->visitAssign($position, ..., ...) Same as normal Hack
return $x; $v->visitReturn($position, ...) Same as normal Hack
return; $v->visitReturn($position, null) Same as normal Hack
if (...) {...} else {...} $v->visitIf($position, ..., ..., ...) if (...->__bool()) {...} else {...}
while (...) {...} $v->visitWhile($position, ..., vec[...]) while (...->__bool()) {...}
for (...; ...; ...) {...} $v->visitFor($position, vec[...], ..., vec[...], vec[...]) for (...; ...->__bool(); ...) {...}
break; $v->visitBreak($position) Same as normal Hack
continue; $v->visitContinue($position) Same as normal Hack

Calls

Example Visitor Runtime Typing
foo(...) $v->visitCall($position, $v->visitGlobalFunction($position, foo<>), vec[...]) MyDsl::symbolType(foo<>)()
Foo::bar(...) $v->visitCall($position, $v->visitStaticMethod($position, Foo::bar<>), vec[...]) MyDsl::symbolType(Foo::bar<>)()

Note that the function or method must have a Hack definition, so the typechecker can verify that it's being called with appropriate arguments.

XHP Literals

Example Visitor Runtime Typing
<foo ...>...</foo> $v->visitXhp($position, :foo::class, dict[...], vec[...]) <foo ...>...</foo>

Property Access

Example Visitor Runtime Typing
(...)->foo $v->visitPropertyAccess($position, ..., 'foo') (...)->foo

Splicing

Example Visitor Runtime Typing
${$x} $v->splice($position, 'key0', $x) Extract the inferred type out of the third type argument of Spliceable

Unsupported Features

Expression trees may only contain expressions between the backticks.

MyDsl`1`; // OK: 1 is an expression
MyDsl`while(true) {}`; // Bad: statement
MyDsl`() ==> { while true() {} }`; // OK: statements are allowed in lambdas
MyDsl`class Foo {}`; // Bad: top-level declaration.
Was This Page Useful?
Thank You!
Thank You! If you'd like to share more feedback, please file an issue.