| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 /// Minimal AST used to represent constant and initializer expressions. | |
| 6 /// | |
| 7 /// The AST definitions here are kept small by removing anything that we don't | |
| 8 /// need for the purpose of summarization: | |
| 9 /// | |
| 10 /// * A tree representing constants will not contain nodes that are not | |
| 11 /// allowed. If a parsed program contains a subexpression that is invalid, | |
| 12 /// we'll represent it with an `Invalid` node. | |
| 13 /// | |
| 14 /// * A tree representing initializers will only contain the subset of the | |
| 15 /// initializer expression that is needed to infer the type of the initialized | |
| 16 /// variable. For example, function closures, arguments to constructors, and | |
| 17 /// other similar bits are hidden using `Opaque` nodes. | |
| 18 library summary.src.expressions; | |
| 19 | |
| 20 // We reuse the scanner constants to represent all binary and unary operators. | |
| 21 import 'visitor.dart'; | |
| 22 | |
| 23 export 'visitor.dart'; | |
| 24 | |
| 25 /// A cast expression. | |
| 26 class As extends Expression { | |
| 27 final Expression exp; | |
| 28 final TypeRef type; | |
| 29 As(this.exp, this.type); | |
| 30 | |
| 31 bool get isAs => true; | |
| 32 accept(v) => v.visitAs(this); | |
| 33 toString() => '$exp as $type'; | |
| 34 } | |
| 35 | |
| 36 /// All binary expressions, including if-null. | |
| 37 class Binary extends Expression { | |
| 38 final Expression left; | |
| 39 final Expression right; | |
| 40 final int operator; | |
| 41 Binary(this.left, this.right, this.operator); | |
| 42 | |
| 43 bool get isBinary => true; | |
| 44 accept(v) => v.visitBinary(this); | |
| 45 toString() => '$left _ $right'; | |
| 46 } | |
| 47 | |
| 48 /// A literal like `false`. | |
| 49 class BoolLiteral extends Expression { | |
| 50 final bool value; | |
| 51 BoolLiteral(this.value); | |
| 52 | |
| 53 accept(v) => v.visitBool(this); | |
| 54 toString() => '$value'; | |
| 55 } | |
| 56 | |
| 57 /// Expressions like `a ? b : c`. | |
| 58 class Conditional extends Expression { | |
| 59 final Expression test; | |
| 60 final Expression trueBranch; | |
| 61 final Expression falseBranch; | |
| 62 Conditional(this.test, this.trueBranch, this.falseBranch); | |
| 63 | |
| 64 bool get isConditional => true; | |
| 65 accept(v) => v.visitConditional(this); | |
| 66 toString() => '$test ? $trueBranch : $falseBranch'; | |
| 67 } | |
| 68 | |
| 69 /// A `const Foo()` creation. | |
| 70 class ConstCreation extends Expression { | |
| 71 final ConstructorName constructor; | |
| 72 | |
| 73 /// Passed arguments, which can be expressions (if the argument is positional) | |
| 74 /// or a [NamedArg]. | |
| 75 final List<Expression> positionalArgs; | |
| 76 final List<NamedArg> namedArgs; | |
| 77 ConstCreation(this.constructor, this.positionalArgs, this.namedArgs); | |
| 78 | |
| 79 accept(v) => v.visitConstCreation(this); | |
| 80 } | |
| 81 | |
| 82 /// The type and possibly name of a constructor. | |
| 83 class ConstructorName { | |
| 84 final TypeRef type; | |
| 85 final String name; | |
| 86 ConstructorName(this.type, this.name); | |
| 87 | |
| 88 toString() => "ctor: $type.$name"; | |
| 89 } | |
| 90 | |
| 91 /// A literal like `1.2`. | |
| 92 class DoubleLiteral extends Expression { | |
| 93 final double value; | |
| 94 DoubleLiteral(this.value); | |
| 95 | |
| 96 accept(v) => v.visitDouble(this); | |
| 97 toString() => '$value'; | |
| 98 } | |
| 99 | |
| 100 /// Root of all expressions | |
| 101 abstract class Expression { | |
| 102 bool get isAs => false; | |
| 103 bool get isBinary => false; | |
| 104 bool get isConditional => false; | |
| 105 bool get isIdentical => false; | |
| 106 bool get isIs => false; | |
| 107 bool get isLoad => false; | |
| 108 bool get isOpaqueOp => false; | |
| 109 bool get isRef => false; | |
| 110 bool get isUnary => false; | |
| 111 | |
| 112 accept(Visitor v); | |
| 113 } | |
| 114 | |
| 115 /// An identical expression: `identical(a, b)`. | |
| 116 // TODO(sigmund): consider merging it into binary? | |
| 117 class Identical extends Expression { | |
| 118 final Expression left; | |
| 119 final Expression right; | |
| 120 Identical(this.left, this.right); | |
| 121 | |
| 122 bool get isIdentical => true; | |
| 123 accept(v) => v.visitIdentical(this); | |
| 124 toString() => 'identical($left, $right)'; | |
| 125 } | |
| 126 | |
| 127 /// A literal like `1`. | |
| 128 class IntLiteral extends Expression { | |
| 129 final int value; | |
| 130 IntLiteral(this.value); | |
| 131 | |
| 132 accept(v) => v.visitInt(this); | |
| 133 toString() => '$value'; | |
| 134 } | |
| 135 | |
| 136 /// An erroneous expression, typically encapsulates code that is not expected | |
| 137 /// in a constant context. | |
| 138 class Invalid extends Expression { | |
| 139 String hint; | |
| 140 Invalid({this.hint}); | |
| 141 accept(v) => v.visitInvalid(this); | |
| 142 | |
| 143 toString() => '(err: $hint)'; | |
| 144 } | |
| 145 | |
| 146 /// An instance check expression. | |
| 147 class Is extends Expression { | |
| 148 final Expression exp; | |
| 149 final TypeRef type; | |
| 150 Is(this.exp, this.type); | |
| 151 | |
| 152 bool get isIs => true; | |
| 153 accept(v) => v.visitIs(this); | |
| 154 toString() => '$exp is $type'; | |
| 155 } | |
| 156 | |
| 157 /// An entry in a map literal. | |
| 158 class KeyValuePair { | |
| 159 final Expression key; | |
| 160 final Expression value; | |
| 161 KeyValuePair(this.key, this.value); | |
| 162 | |
| 163 toString() => '(p: $key, $value)'; | |
| 164 } | |
| 165 | |
| 166 /// A list literal like: `[1, 2]`. | |
| 167 class ListLiteral extends Expression { | |
| 168 final TypeRef elementType; | |
| 169 final List<Expression> values; | |
| 170 final bool isConst; | |
| 171 ListLiteral(this.elementType, this.values, this.isConst); | |
| 172 | |
| 173 accept(v) => v.visitList(this); | |
| 174 toString() => '(list<$elementType>$values)'; | |
| 175 } | |
| 176 | |
| 177 /// A property extraction expression, such as: `(e).foo` | |
| 178 // TODO(sigmund): consider merging it into binary? | |
| 179 class Load extends Expression { | |
| 180 final Expression left; | |
| 181 final String name; | |
| 182 Load(this.left, this.name); | |
| 183 | |
| 184 bool get isLoad => true; | |
| 185 accept(v) => v.visitLoad(this); | |
| 186 toString() => '$left.$name'; | |
| 187 } | |
| 188 | |
| 189 /// A map literal like: `{'a': 2}`. | |
| 190 class MapLiteral extends Expression { | |
| 191 final List<TypeRef> types; | |
| 192 final List<KeyValuePair> values; | |
| 193 final bool isConst; | |
| 194 | |
| 195 MapLiteral(this.types, this.values, this.isConst) { | |
| 196 assert(types.length <= 2); | |
| 197 } | |
| 198 | |
| 199 accept(v) => v.visitMap(this); | |
| 200 toString() => '(map<${types.map((t) => "$t").join(", ")}>: $values)'; | |
| 201 } | |
| 202 | |
| 203 /// Representation for a named argument. | |
| 204 class NamedArg { | |
| 205 final String name; | |
| 206 final Expression value; | |
| 207 NamedArg(this.name, this.value); | |
| 208 } | |
| 209 | |
| 210 /// The `null` literal. | |
| 211 class NullLiteral extends Expression { | |
| 212 NullLiteral(); | |
| 213 | |
| 214 accept(v) => v.visitNull(this); | |
| 215 toString() => 'null'; | |
| 216 } | |
| 217 | |
| 218 /// An opaque expression with possibly a known type. | |
| 219 class Opaque extends Expression { | |
| 220 final TypeRef type; | |
| 221 final String hint; | |
| 222 | |
| 223 Opaque({this.type, this.hint}); | |
| 224 | |
| 225 accept(v) => v.visitOpaque(this); | |
| 226 | |
| 227 toString() { | |
| 228 var sb = new StringBuffer(); | |
| 229 sb.write('(o:'); | |
| 230 if (hint != null) sb.write(' $hint'); | |
| 231 if (type != null) sb.write(' $type'); | |
| 232 return '$sb)'; | |
| 233 } | |
| 234 } | |
| 235 | |
| 236 /// Marker that some part of the AST was abstracted away. | |
| 237 /// | |
| 238 /// This node does not provide additional information, other than indicating | |
| 239 /// that the AST does not include the full initializer. For example, | |
| 240 /// this is in assignments, pre and postfix operators, and cascades to indicate | |
| 241 /// that we ignored part of those complex expressions. | |
| 242 class OpaqueOp extends Expression { | |
| 243 final Expression exp; | |
| 244 final String hint; | |
| 245 OpaqueOp(this.exp, {this.hint}); | |
| 246 | |
| 247 bool get isOpaqueOp => true; | |
| 248 accept(v) => v.visitOpaqueOp(this); | |
| 249 } | |
| 250 | |
| 251 /// A name reference. | |
| 252 class Ref extends Expression { | |
| 253 final String name; | |
| 254 final Ref prefix; | |
| 255 | |
| 256 Ref(this.name, [this.prefix]) { | |
| 257 assert(prefixDepth <= 2); | |
| 258 } | |
| 259 | |
| 260 bool get isRef => true; | |
| 261 | |
| 262 int get prefixDepth => prefix == null ? 0 : prefix.prefixDepth; | |
| 263 accept(v) => v.visitRef(this); | |
| 264 toString() => 'r:${prefix == null ? "" : "$prefix."}$name'; | |
| 265 } | |
| 266 | |
| 267 /// A literal like `"foo"`. | |
| 268 class StringLiteral extends Expression { | |
| 269 final String value; | |
| 270 StringLiteral(this.value); | |
| 271 | |
| 272 accept(v) => v.visitString(this); | |
| 273 toString() => '$value'; | |
| 274 } | |
| 275 | |
| 276 /// A literal like `#foo.bar`. | |
| 277 class SymbolLiteral extends Expression { | |
| 278 final String value; | |
| 279 SymbolLiteral(this.value); | |
| 280 | |
| 281 accept(v) => v.visitSymbol(this); | |
| 282 toString() => '#$value'; | |
| 283 } | |
| 284 | |
| 285 /// A reference to a type (used for opaque nodes, is checks, and as checks). | |
| 286 /// | |
| 287 /// Note that types are not nodes in the expression tree. | |
| 288 class TypeRef { | |
| 289 final Ref name; | |
| 290 final List<TypeRef> typeArguments; | |
| 291 TypeRef(this.name, this.typeArguments); | |
| 292 | |
| 293 toString() { | |
| 294 var args = typeArguments == null ? "" : "<${typeArguments.join(', ')}>"; | |
| 295 return 't:$name$args'; | |
| 296 } | |
| 297 } | |
| 298 | |
| 299 /// All unary expressions, such as `-1` or `!b` | |
| 300 class Unary extends Expression { | |
| 301 final Expression exp; | |
| 302 final int operator; | |
| 303 Unary(this.exp, this.operator); | |
| 304 | |
| 305 bool get isUnary => true; | |
| 306 accept(v) => v.visitUnary(this); | |
| 307 toString() => '_ $exp'; | |
| 308 } | |
| OLD | NEW |