@@ -2114,6 +2114,8 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21142114
21152115 /**
21162116 * Provides the input to `Make3`.
2117+ *
2118+ * TODO: Eventually align the AST signature with that of the shared CFG library.
21172119 */
21182120 signature module InputSig3 {
21192121 /**
@@ -2122,6 +2124,9 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21222124 */
21232125 default predicate cachedStageRevRef ( ) { none ( ) }
21242126
2127+ /** A boolean type. */
2128+ class BoolType extends Type ;
2129+
21252130 /** An AST node. */
21262131 class AstNode {
21272132 /** Gets a textual representation of this AST node. */
@@ -2134,13 +2139,63 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21342139 /** Gets the type annotation that applies to `n`, if any. */
21352140 TypeMention getTypeAnnotation ( AstNode n ) ;
21362141
2142+ /** An expression. */
2143+ class Expr extends AstNode ;
2144+
2145+ /** A ternary conditional expression. */
2146+ class ConditionalExpr extends Expr {
2147+ /** Gets the condition of this expression. */
2148+ Expr getCondition ( ) ;
2149+
2150+ /** Gets the true branch of this expression. */
2151+ Expr getThen ( ) ;
2152+
2153+ /** Gets the false branch of this expression. */
2154+ Expr getElse ( ) ;
2155+ }
2156+
2157+ /** A binary expression. */
2158+ class BinaryExpr extends Expr {
2159+ /** Gets the left operand of this binary expression. */
2160+ Expr getLeftOperand ( ) ;
2161+
2162+ /** Gets the right operand of this binary expression. */
2163+ Expr getRightOperand ( ) ;
2164+ }
2165+
2166+ /** A short-circuiting logical AND expression. */
2167+ class LogicalAndExpr extends BinaryExpr ;
2168+
2169+ /** A short-circuiting logical OR expression. */
2170+ class LogicalOrExpr extends BinaryExpr ;
2171+
2172+ /**
2173+ * An assignment expression, either compound or simple.
2174+ *
2175+ * Examples:
2176+ *
2177+ * ```
2178+ * x = y
2179+ * sum += element
2180+ * ```
2181+ */
2182+ class Assignment extends BinaryExpr ;
2183+
2184+ /** A simple assignment expression, for example `x = y`. */
2185+ class AssignExpr extends Assignment ;
2186+
2187+ /** A parenthesized expression. */
2188+ class ParenExpr extends AstNode {
2189+ AstNode getExpr ( ) ;
2190+ }
2191+
21372192 /** A variable, for example a local variable or a field. */
21382193 class Variable {
21392194 /** Gets the AST node that defines this variable. */
21402195 AstNode getDefiningNode ( ) ;
21412196
21422197 /** Gets an access to this variable. */
2143- AstNode getAnAccess ( ) ;
2198+ Expr getAnAccess ( ) ;
21442199
21452200 /** Gets a textual representation of this element. */
21462201 string toString ( ) ;
@@ -2150,28 +2205,22 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21502205 }
21512206
21522207 /**
2153- * An assignment where type information can flow from one operand to the
2154- * other.
2208+ * A `let` declaration, for example a local variable declaration.
21552209 */
2156- class Assignment extends AstNode {
2210+ class LetDeclaration extends AstNode {
21572211 /**
2158- * Holds if this assignment is a coercion site, meaning that the type of the right
2212+ * Holds if this declaration is a coercion site, meaning that the type of the right
21592213 * operand may have to be coerced to the type of the left operand.
21602214 */
21612215 predicate isCoercionSite ( ) ;
21622216
2163- /** Gets the left operand of this binary expression . */
2217+ /** Gets the left operand of this declaration . */
21642218 AstNode getLeftOperand ( ) ;
21652219
2166- /** Gets the right operand of this binary expression . */
2220+ /** Gets the right operand of this declaration . */
21672221 AstNode getRightOperand ( ) ;
21682222 }
21692223
2170- /** A parenthesized expression. */
2171- class ParenExpr extends AstNode {
2172- AstNode getExpr ( ) ;
2173- }
2174-
21752224 /**
21762225 * Holds if the types of `n1` at `path1` and `n2` at `path2` are certainly equal.
21772226 */
@@ -2222,10 +2271,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
22222271 (
22232272 exists ( Variable v | n1 = v .getAnAccess ( ) and n2 = v .getDefiningNode ( ) )
22242273 or
2225- exists ( Assignment a |
2226- not a .isCoercionSite ( ) and
2227- n1 = a .getLeftOperand ( ) and
2228- n2 = a .getRightOperand ( )
2274+ exists ( LetDeclaration let |
2275+ not let .isCoercionSite ( ) and
2276+ n1 = let .getLeftOperand ( ) and
2277+ n2 = let .getRightOperand ( )
22292278 )
22302279 or
22312280 n1 = n2 .( ParenExpr ) .getExpr ( )
@@ -2246,6 +2295,16 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
22462295 )
22472296 }
22482297
2298+ private Type inferLogicalOperationType ( AstNode n , TypePath path ) {
2299+ (
2300+ exists ( LogicalAndExpr lae | n = [ lae , lae .getLeftOperand ( ) , lae .getRightOperand ( ) ] ) or
2301+ exists ( LogicalOrExpr loe | n = [ loe , loe .getLeftOperand ( ) , loe .getRightOperand ( ) ] ) //or
2302+ // exists(LogicalNotExpr lne | n = [lne, lne.getOperand()])
2303+ ) and
2304+ result instanceof BoolType and
2305+ path .isEmpty ( )
2306+ }
2307+
22492308 /** Gets the inferred certain type of `n` at `path`. */
22502309 cached
22512310 Type inferCertainType ( AstNode n , TypePath path ) {
@@ -2256,6 +2315,8 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
22562315 or
22572316 result = inferCertainTypeInput ( n , path )
22582317 or
2318+ result = inferLogicalOperationType ( n , path )
2319+ or
22592320 infersCertainTypeAt ( n , path , result .getATypeParameter ( ) )
22602321 }
22612322
@@ -2309,9 +2370,16 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
23092370 or
23102371 path1 .isEmpty ( ) and
23112372 path2 .isEmpty ( ) and
2312- exists ( Assignment a |
2313- a .getLeftOperand ( ) = n1 and
2314- a .getRightOperand ( ) = n2
2373+ (
2374+ exists ( Assignment a |
2375+ a .getLeftOperand ( ) = n1 and
2376+ a .getRightOperand ( ) = n2
2377+ )
2378+ or
2379+ exists ( LetDeclaration let |
2380+ let .getLeftOperand ( ) = n1 and
2381+ let .getRightOperand ( ) = n2
2382+ )
23152383 )
23162384 or
23172385 typeEqualityInput ( n1 , path1 , n2 , path2 )
0 commit comments