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