@@ -2141,6 +2141,8 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21412141
21422142 /**
21432143 * Provides the input to `Make3`.
2144+ *
2145+ * TODO: Eventually align the AST signature with that of the shared CFG library.
21442146 */
21452147 signature module InputSig3 {
21462148 /**
@@ -2149,6 +2151,9 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21492151 */
21502152 default predicate cachedStageRevRef ( ) { none ( ) }
21512153
2154+ /** A boolean type. */
2155+ class BoolType extends Type ;
2156+
21522157 /** An AST node. */
21532158 class AstNode {
21542159 /** Gets a textual representation of this AST node. */
@@ -2161,13 +2166,63 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21612166 /** Gets the type annotation that applies to `n`, if any. */
21622167 TypeMention getTypeAnnotation ( AstNode n ) ;
21632168
2169+ /** An expression. */
2170+ class Expr extends AstNode ;
2171+
2172+ /** A ternary conditional expression. */
2173+ class ConditionalExpr extends Expr {
2174+ /** Gets the condition of this expression. */
2175+ Expr getCondition ( ) ;
2176+
2177+ /** Gets the true branch of this expression. */
2178+ Expr getThen ( ) ;
2179+
2180+ /** Gets the false branch of this expression. */
2181+ Expr getElse ( ) ;
2182+ }
2183+
2184+ /** A binary expression. */
2185+ class BinaryExpr extends Expr {
2186+ /** Gets the left operand of this binary expression. */
2187+ Expr getLeftOperand ( ) ;
2188+
2189+ /** Gets the right operand of this binary expression. */
2190+ Expr getRightOperand ( ) ;
2191+ }
2192+
2193+ /** A short-circuiting logical AND expression. */
2194+ class LogicalAndExpr extends BinaryExpr ;
2195+
2196+ /** A short-circuiting logical OR expression. */
2197+ class LogicalOrExpr extends BinaryExpr ;
2198+
2199+ /**
2200+ * An assignment expression, either compound or simple.
2201+ *
2202+ * Examples:
2203+ *
2204+ * ```
2205+ * x = y
2206+ * sum += element
2207+ * ```
2208+ */
2209+ class Assignment extends BinaryExpr ;
2210+
2211+ /** A simple assignment expression, for example `x = y`. */
2212+ class AssignExpr extends Assignment ;
2213+
2214+ /** A parenthesized expression. */
2215+ class ParenExpr extends AstNode {
2216+ AstNode getExpr ( ) ;
2217+ }
2218+
21642219 /** A variable, for example a local variable or a field. */
21652220 class Variable {
21662221 /** Gets the AST node that defines this variable. */
21672222 AstNode getDefiningNode ( ) ;
21682223
21692224 /** Gets an access to this variable. */
2170- AstNode getAnAccess ( ) ;
2225+ Expr getAnAccess ( ) ;
21712226
21722227 /** Gets a textual representation of this element. */
21732228 string toString ( ) ;
@@ -2177,28 +2232,22 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21772232 }
21782233
21792234 /**
2180- * An assignment where type information can flow from one operand to the
2181- * other.
2235+ * A `let` declaration, for example a local variable declaration.
21822236 */
2183- class Assignment extends AstNode {
2237+ class LetDeclaration extends AstNode {
21842238 /**
2185- * Holds if this assignment is a coercion site, meaning that the type of the right
2239+ * Holds if this declaration is a coercion site, meaning that the type of the right
21862240 * operand may have to be coerced to the type of the left operand.
21872241 */
21882242 predicate isCoercionSite ( ) ;
21892243
2190- /** Gets the left operand of this binary expression . */
2244+ /** Gets the left operand of this declaration . */
21912245 AstNode getLeftOperand ( ) ;
21922246
2193- /** Gets the right operand of this binary expression . */
2247+ /** Gets the right operand of this declaration . */
21942248 AstNode getRightOperand ( ) ;
21952249 }
21962250
2197- /** A parenthesized expression. */
2198- class ParenExpr extends AstNode {
2199- AstNode getExpr ( ) ;
2200- }
2201-
22022251 /**
22032252 * Holds if the types of `n1` at `path1` and `n2` at `path2` are certainly equal.
22042253 */
@@ -2249,10 +2298,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
22492298 (
22502299 exists ( Variable v | n1 = v .getAnAccess ( ) and n2 = v .getDefiningNode ( ) )
22512300 or
2252- exists ( Assignment a |
2253- not a .isCoercionSite ( ) and
2254- n1 = a .getLeftOperand ( ) and
2255- n2 = a .getRightOperand ( )
2301+ exists ( LetDeclaration let |
2302+ not let .isCoercionSite ( ) and
2303+ n1 = let .getLeftOperand ( ) and
2304+ n2 = let .getRightOperand ( )
22562305 )
22572306 or
22582307 n1 = n2 .( ParenExpr ) .getExpr ( )
@@ -2273,6 +2322,16 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
22732322 )
22742323 }
22752324
2325+ private Type inferLogicalOperationType ( AstNode n , TypePath path ) {
2326+ (
2327+ exists ( LogicalAndExpr lae | n = [ lae , lae .getLeftOperand ( ) , lae .getRightOperand ( ) ] ) or
2328+ exists ( LogicalOrExpr loe | n = [ loe , loe .getLeftOperand ( ) , loe .getRightOperand ( ) ] ) //or
2329+ // exists(LogicalNotExpr lne | n = [lne, lne.getOperand()])
2330+ ) and
2331+ result instanceof BoolType and
2332+ path .isEmpty ( )
2333+ }
2334+
22762335 /** Gets the inferred certain type of `n` at `path`. */
22772336 cached
22782337 Type inferCertainType ( AstNode n , TypePath path ) {
@@ -2283,6 +2342,8 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
22832342 or
22842343 result = inferCertainTypeInput ( n , path )
22852344 or
2345+ result = inferLogicalOperationType ( n , path )
2346+ or
22862347 infersCertainTypeAt ( n , path , result .getATypeParameter ( ) )
22872348 }
22882349
@@ -2336,9 +2397,16 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
23362397 or
23372398 path1 .isEmpty ( ) and
23382399 path2 .isEmpty ( ) and
2339- exists ( Assignment a |
2340- a .getLeftOperand ( ) = n1 and
2341- a .getRightOperand ( ) = n2
2400+ (
2401+ exists ( Assignment a |
2402+ a .getLeftOperand ( ) = n1 and
2403+ a .getRightOperand ( ) = n2
2404+ )
2405+ or
2406+ exists ( LetDeclaration let |
2407+ let .getLeftOperand ( ) = n1 and
2408+ let .getRightOperand ( ) = n2
2409+ )
23422410 )
23432411 or
23442412 typeEqualityInput ( n1 , path1 , n2 , path2 )
0 commit comments