| 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 /// Algorithm to serialize expressions into the format used by summaries. | |
| 6 library summary.src.expression_serializer; | |
| 7 | |
| 8 import 'package:front_end/src/fasta/scanner/token_constants.dart'; | |
| 9 | |
| 10 import 'model.dart'; | |
| 11 | |
| 12 /// Translate a parser binary operation into an operation in the summary format. | |
| 13 UnlinkedExprOperation _binaryOpFor(int operatorKind) { | |
| 14 switch (operatorKind) { | |
| 15 case AMPERSAND_TOKEN: | |
| 16 return UnlinkedExprOperation.bitAnd; | |
| 17 case AMPERSAND_AMPERSAND_TOKEN: | |
| 18 return UnlinkedExprOperation.and; | |
| 19 case BANG_EQ_TOKEN: | |
| 20 return UnlinkedExprOperation.notEqual; | |
| 21 case BAR_TOKEN: | |
| 22 return UnlinkedExprOperation.bitOr; | |
| 23 case BAR_BAR_TOKEN: | |
| 24 return UnlinkedExprOperation.or; | |
| 25 case CARET_TOKEN: | |
| 26 return UnlinkedExprOperation.bitXor; | |
| 27 case EQ_EQ_TOKEN: | |
| 28 return UnlinkedExprOperation.equal; | |
| 29 case GT_TOKEN: | |
| 30 return UnlinkedExprOperation.greater; | |
| 31 case GT_EQ_TOKEN: | |
| 32 return UnlinkedExprOperation.greaterEqual; | |
| 33 case GT_GT_TOKEN: | |
| 34 return UnlinkedExprOperation.bitShiftRight; | |
| 35 case LT_TOKEN: | |
| 36 return UnlinkedExprOperation.less; | |
| 37 case LT_EQ_TOKEN: | |
| 38 return UnlinkedExprOperation.lessEqual; | |
| 39 case LT_LT_TOKEN: | |
| 40 return UnlinkedExprOperation.bitShiftLeft; | |
| 41 case MINUS_TOKEN: | |
| 42 return UnlinkedExprOperation.subtract; | |
| 43 case PERCENT_TOKEN: | |
| 44 return UnlinkedExprOperation.modulo; | |
| 45 case PERIOD_TOKEN: | |
| 46 return UnlinkedExprOperation.extractProperty; | |
| 47 case PLUS_TOKEN: | |
| 48 return UnlinkedExprOperation.add; | |
| 49 case QUESTION_QUESTION_TOKEN: | |
| 50 return UnlinkedExprOperation.ifNull; | |
| 51 case SLASH_TOKEN: | |
| 52 return UnlinkedExprOperation.divide; | |
| 53 case STAR_TOKEN: | |
| 54 return UnlinkedExprOperation.multiply; | |
| 55 case TILDE_SLASH_TOKEN: | |
| 56 return UnlinkedExprOperation.floorDivide; | |
| 57 default: | |
| 58 throw "Unhandled openratorKind $operatorKind"; | |
| 59 } | |
| 60 } | |
| 61 | |
| 62 /// Translate a parser unary operation into an operation in the summary format. | |
| 63 UnlinkedExprOperation _unaryOpFor(int operatorKind) { | |
| 64 switch (operatorKind) { | |
| 65 case BANG_TOKEN: | |
| 66 return UnlinkedExprOperation.not; | |
| 67 case MINUS_TOKEN: | |
| 68 return UnlinkedExprOperation.negate; | |
| 69 default: | |
| 70 throw "Unhandled operator kind $operatorKind"; | |
| 71 } | |
| 72 } | |
| 73 | |
| 74 /// Visitor over the minimal expression AST to convert them into stack-like | |
| 75 /// expressions used in the summary format. | |
| 76 class Serializer extends RecursiveVisitor { | |
| 77 UnlinkedExprBuilder expression; | |
| 78 final Scope scope; | |
| 79 final bool forConst; | |
| 80 | |
| 81 Serializer(this.scope, this.forConst); | |
| 82 | |
| 83 handleAs(As n) { | |
| 84 throw new UnimplementedError(); // TODO(paulberry): fix the code below. | |
| 85 // handleType(a.type); | |
| 86 // expression.operations.add(UnlinkedExprOperation.typeCast); | |
| 87 } | |
| 88 | |
| 89 handleBinary(Binary n) { | |
| 90 expression.operations.add(_binaryOpFor(n.operator)); | |
| 91 } | |
| 92 | |
| 93 handleBool(BoolLiteral n) { | |
| 94 expression.operations.add(n.value | |
| 95 ? UnlinkedExprOperation.pushTrue | |
| 96 : UnlinkedExprOperation.pushFalse); | |
| 97 } | |
| 98 | |
| 99 handleConditional(Conditional n) { | |
| 100 expression.operations.add(UnlinkedExprOperation.conditional); | |
| 101 } | |
| 102 | |
| 103 handleConstCreation(ConstCreation n) { | |
| 104 var ctor = n.constructor; | |
| 105 var type = handleType(ctor.type); | |
| 106 if (ctor.name != null) { | |
| 107 throw new UnimplementedError(); // TODO(paulberry): fix the code below. | |
| 108 //var classRef = handleRef(ctor.type.name, push: false); | |
| 109 //var top = scope.top; | |
| 110 //var ref = new LazyEntityRef(ctor.name, top) | |
| 111 // ..reference = (scope.serializeReference(classRef.reference, ctor.name)
) | |
| 112 // ..typeArguments = type.typeArguments | |
| 113 // ..wasExpanded = true; | |
| 114 //expression.references.add(ref); | |
| 115 } else { | |
| 116 expression.references.add(type); | |
| 117 } | |
| 118 expression.ints.add(n.namedArgs.length); | |
| 119 expression.ints.add(n.positionalArgs.length); | |
| 120 expression.strings.addAll(n.namedArgs.map((a) => a.name)); | |
| 121 expression.operations.add(UnlinkedExprOperation.invokeConstructor); | |
| 122 } | |
| 123 | |
| 124 handleDouble(DoubleLiteral n) { | |
| 125 expression.operations.add(UnlinkedExprOperation.pushDouble); | |
| 126 expression.doubles.add(n.value); | |
| 127 } | |
| 128 | |
| 129 handleIdentical(Identical n) { | |
| 130 expression.references.add(handleRef(new Ref('identical'), push: false)); | |
| 131 expression.ints.add(0); | |
| 132 expression.ints.add(2); | |
| 133 expression.ints.add(0); | |
| 134 expression.operations.add(UnlinkedExprOperation.invokeMethodRef); | |
| 135 } | |
| 136 | |
| 137 handleInt(IntLiteral n) { | |
| 138 var ints = expression.ints; | |
| 139 var operations = expression.operations; | |
| 140 int value = n.value; | |
| 141 assert(value >= 0); | |
| 142 if (value >= (1 << 32)) { | |
| 143 int numOfComponents = 0; | |
| 144 expression.ints.add(numOfComponents); | |
| 145 void pushComponents(int value) { | |
| 146 if (value >= (1 << 32)) { | |
| 147 pushComponents(value >> 32); | |
| 148 } | |
| 149 numOfComponents++; | |
| 150 ints.add(value & 0xFFFFFFFF); | |
| 151 } | |
| 152 | |
| 153 pushComponents(value); | |
| 154 ints[ints.length - 1 - numOfComponents] = numOfComponents; | |
| 155 operations.add(UnlinkedExprOperation.pushLongInt); | |
| 156 } else { | |
| 157 operations.add(UnlinkedExprOperation.pushInt); | |
| 158 ints.add(value); | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 handleInvalid(Invalid n) { | |
| 163 expression.isValidConst = false; | |
| 164 throw new UnimplementedError(); // TODO(paulberry): fix the code below. | |
| 165 // expression.operations.add(UnlinkedExprOperation.pushInvalidor); | |
| 166 } | |
| 167 | |
| 168 handleIs(Is n) { | |
| 169 throw new UnimplementedError(); // TODO(paulberry): fix the code below. | |
| 170 // handleType(i.type); | |
| 171 // expression.operations.add(UnlinkedExprOperation.typeCheck); | |
| 172 } | |
| 173 | |
| 174 handleList(ListLiteral n) { | |
| 175 expression.ints.add(n.values.length); | |
| 176 if (n.elementType == null) { | |
| 177 expression.operations.add(UnlinkedExprOperation.makeUntypedList); | |
| 178 } else { | |
| 179 handleType(n.elementType); | |
| 180 expression.operations.add(UnlinkedExprOperation.makeTypedList); | |
| 181 } | |
| 182 } | |
| 183 | |
| 184 handleLoad(Load n) { | |
| 185 expression.strings.add(n.name); | |
| 186 expression.operations.add(UnlinkedExprOperation.extractProperty); | |
| 187 } | |
| 188 | |
| 189 handleMap(MapLiteral n) { | |
| 190 expression.ints.add(n.values.length); | |
| 191 if (n.types.isEmpty) { | |
| 192 expression.operations.add(UnlinkedExprOperation.makeUntypedMap); | |
| 193 } else { | |
| 194 n.types.forEach(handleType); | |
| 195 expression.operations.add(UnlinkedExprOperation.makeTypedMap); | |
| 196 } | |
| 197 } | |
| 198 | |
| 199 handleNull(NullLiteral n) { | |
| 200 expression.operations.add(UnlinkedExprOperation.pushNull); | |
| 201 } | |
| 202 | |
| 203 handleOpaque(Opaque n) { | |
| 204 if (n.type != null) { | |
| 205 handleType(n.type); | |
| 206 expression.operations.add(UnlinkedExprOperation.pushTypedAbstract); | |
| 207 } else { | |
| 208 expression.operations.add(UnlinkedExprOperation.pushUntypedAbstract); | |
| 209 } | |
| 210 } | |
| 211 | |
| 212 handleOpaqueOp(OpaqueOp n) { | |
| 213 // nothing to do, recursive visitor serialized subexpression. | |
| 214 } | |
| 215 | |
| 216 handleRef(Ref n, {push: true}) { | |
| 217 var ref = n.prefix == null | |
| 218 ? new LazyEntityRef(n.name, scope) | |
| 219 : new NestedLazyEntityRef( | |
| 220 handleRef(n.prefix, push: false), n.name, scope); | |
| 221 if (push) { | |
| 222 expression.references.add(ref); | |
| 223 expression.operations.add(UnlinkedExprOperation.pushReference); | |
| 224 } | |
| 225 return ref; | |
| 226 } | |
| 227 | |
| 228 handleString(StringLiteral n) { | |
| 229 expression.strings.add(n.value); | |
| 230 expression.operations.add(UnlinkedExprOperation.pushString); | |
| 231 } | |
| 232 | |
| 233 handleSymbol(SymbolLiteral n) { | |
| 234 expression.strings.add(n.value); | |
| 235 expression.operations.add(UnlinkedExprOperation.makeSymbol); | |
| 236 } | |
| 237 | |
| 238 handleType(TypeRef n) { | |
| 239 var t = handleRef(n.name, push: false); | |
| 240 var args = n.typeArguments ?? []; | |
| 241 t.typeArguments = args.map((a) => handleType(a)).toList(); | |
| 242 return t; | |
| 243 } | |
| 244 | |
| 245 handleUnary(Unary n) { | |
| 246 expression.operations.add(_unaryOpFor(n.operator)); | |
| 247 } | |
| 248 | |
| 249 run(Expression root) { | |
| 250 expression = new UnlinkedExprBuilder( | |
| 251 isValidConst: forConst, | |
| 252 operations: [], | |
| 253 assignmentOperators: [], | |
| 254 ints: [], | |
| 255 doubles: [], | |
| 256 strings: [], | |
| 257 references: []); | |
| 258 root.accept(this); | |
| 259 expression.references.forEach((r) => (r as LazyEntityRef).expand()); | |
| 260 return expression; | |
| 261 } | |
| 262 } | |
| OLD | NEW |