| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.resolution.enum_creator; | 5 library dart2js.resolution.enum_creator; |
| 6 | 6 |
| 7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../core_types.dart' show | 8 import '../core_types.dart' show CoreTypes; |
| 9 CoreTypes; | |
| 10 import '../dart_types.dart'; | 9 import '../dart_types.dart'; |
| 11 import '../elements/elements.dart'; | 10 import '../elements/elements.dart'; |
| 12 import '../elements/modelx.dart'; | 11 import '../elements/modelx.dart'; |
| 13 import '../tokens/keyword.dart' show | 12 import '../tokens/keyword.dart' show Keyword; |
| 14 Keyword; | |
| 15 import '../tokens/precedence.dart'; | 13 import '../tokens/precedence.dart'; |
| 16 import '../tokens/precedence_constants.dart' as Precedence; | 14 import '../tokens/precedence_constants.dart' as Precedence; |
| 17 import '../tokens/token.dart'; | 15 import '../tokens/token.dart'; |
| 18 import '../tree/tree.dart'; | 16 import '../tree/tree.dart'; |
| 19 import '../util/util.dart'; | 17 import '../util/util.dart'; |
| 20 | 18 |
| 21 // TODO(johnniwinther): Merge functionality with the `TreePrinter`. | 19 // TODO(johnniwinther): Merge functionality with the `TreePrinter`. |
| 22 class AstBuilder { | 20 class AstBuilder { |
| 23 final int charOffset; | 21 final int charOffset; |
| 24 | 22 |
| 25 AstBuilder(this.charOffset); | 23 AstBuilder(this.charOffset); |
| 26 | 24 |
| 27 Modifiers modifiers({bool isConst: false, | 25 Modifiers modifiers( |
| 28 bool isFinal: false, | 26 {bool isConst: false, bool isFinal: false, bool isStatic: false}) { |
| 29 bool isStatic: false}) { | |
| 30 List identifiers = []; | 27 List identifiers = []; |
| 31 int flags = 0; | 28 int flags = 0; |
| 32 if (isConst) { | 29 if (isConst) { |
| 33 identifiers.add(identifier('const')); | 30 identifiers.add(identifier('const')); |
| 34 flags |= Modifiers.FLAG_CONST; | 31 flags |= Modifiers.FLAG_CONST; |
| 35 } | 32 } |
| 36 if (isFinal) { | 33 if (isFinal) { |
| 37 identifiers.add(identifier('final')); | 34 identifiers.add(identifier('final')); |
| 38 flags |= Modifiers.FLAG_FINAL; | 35 flags |= Modifiers.FLAG_FINAL; |
| 39 } | 36 } |
| 40 if (isStatic) { | 37 if (isStatic) { |
| 41 identifiers.add(identifier('static')); | 38 identifiers.add(identifier('static')); |
| 42 flags |= Modifiers.FLAG_STATIC; | 39 flags |= Modifiers.FLAG_STATIC; |
| 43 } | 40 } |
| 44 return new Modifiers.withFlags( | 41 return new Modifiers.withFlags( |
| 45 new NodeList(null, linkedList(identifiers), null, ''), | 42 new NodeList(null, linkedList(identifiers), null, ''), flags); |
| 46 flags); | |
| 47 } | 43 } |
| 48 | 44 |
| 49 Token keywordToken(String text) { | 45 Token keywordToken(String text) { |
| 50 return new KeywordToken(Keyword.keywords[text], charOffset); | 46 return new KeywordToken(Keyword.keywords[text], charOffset); |
| 51 } | 47 } |
| 52 | 48 |
| 53 Token stringToken(String text) { | 49 Token stringToken(String text) { |
| 54 return new StringToken.fromString( | 50 return new StringToken.fromString( |
| 55 Precedence.IDENTIFIER_INFO, text, charOffset); | 51 Precedence.IDENTIFIER_INFO, text, charOffset); |
| 56 } | 52 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 71 } | 67 } |
| 72 | 68 |
| 73 Link linkedList(List elements) { | 69 Link linkedList(List elements) { |
| 74 LinkBuilder builder = new LinkBuilder(); | 70 LinkBuilder builder = new LinkBuilder(); |
| 75 elements.forEach((e) => builder.addLast(e)); | 71 elements.forEach((e) => builder.addLast(e)); |
| 76 return builder.toLink(); | 72 return builder.toLink(); |
| 77 } | 73 } |
| 78 | 74 |
| 79 NodeList argumentList(List<Node> nodes) { | 75 NodeList argumentList(List<Node> nodes) { |
| 80 return new NodeList(symbolToken(Precedence.OPEN_PAREN_INFO), | 76 return new NodeList(symbolToken(Precedence.OPEN_PAREN_INFO), |
| 81 linkedList(nodes), | 77 linkedList(nodes), symbolToken(Precedence.CLOSE_PAREN_INFO), ','); |
| 82 symbolToken(Precedence.CLOSE_PAREN_INFO), | |
| 83 ','); | |
| 84 } | 78 } |
| 85 | 79 |
| 86 Return returnStatement(Expression expression) { | 80 Return returnStatement(Expression expression) { |
| 87 return new Return( | 81 return new Return(keywordToken('return'), |
| 88 keywordToken('return'), | 82 symbolToken(Precedence.SEMICOLON_INFO), expression); |
| 89 symbolToken(Precedence.SEMICOLON_INFO), | |
| 90 expression); | |
| 91 } | 83 } |
| 92 | 84 |
| 93 FunctionExpression functionExpression(Modifiers modifiers, | 85 FunctionExpression functionExpression( |
| 94 String name, | 86 Modifiers modifiers, String name, NodeList argumentList, Statement body, |
| 95 NodeList argumentList, | 87 [TypeAnnotation returnType]) { |
| 96 Statement body, | |
| 97 [TypeAnnotation returnType]) { | |
| 98 return new FunctionExpression( | 88 return new FunctionExpression( |
| 99 identifier(name), | 89 identifier(name), |
| 100 argumentList, | 90 argumentList, |
| 101 body, | 91 body, |
| 102 returnType, | 92 returnType, |
| 103 modifiers, | 93 modifiers, |
| 104 null, // Initializer. | 94 null, // Initializer. |
| 105 null, // get/set. | 95 null, // get/set. |
| 106 null // Async modifier. | 96 null // Async modifier. |
| 107 ); | 97 ); |
| 108 } | 98 } |
| 109 | 99 |
| 110 EmptyStatement emptyStatement() { | 100 EmptyStatement emptyStatement() { |
| 111 return new EmptyStatement(symbolToken(Precedence.COMMA_INFO)); | 101 return new EmptyStatement(symbolToken(Precedence.COMMA_INFO)); |
| 112 } | 102 } |
| 113 | 103 |
| 114 LiteralInt literalInt(int value) { | 104 LiteralInt literalInt(int value) { |
| 115 return new LiteralInt(stringToken('$value'), null); | 105 return new LiteralInt(stringToken('$value'), null); |
| 116 } | 106 } |
| 117 | 107 |
| 118 LiteralString literalString(String text, | 108 LiteralString literalString(String text, |
| 119 {String prefix: '"', | 109 {String prefix: '"', String suffix: '"'}) { |
| 120 String suffix: '"'}) { | 110 return new LiteralString( |
| 121 return new LiteralString(stringToken('$prefix$text$suffix'), | 111 stringToken('$prefix$text$suffix'), new DartString.literal(text)); |
| 122 new DartString.literal(text)); | |
| 123 } | 112 } |
| 124 | 113 |
| 125 LiteralList listLiteral(List<Node> elements, {bool isConst: false}) { | 114 LiteralList listLiteral(List<Node> elements, {bool isConst: false}) { |
| 126 return new LiteralList( | 115 return new LiteralList( |
| 127 null, | 116 null, |
| 128 new NodeList(symbolToken(Precedence.OPEN_SQUARE_BRACKET_INFO), | 117 new NodeList( |
| 129 linkedList(elements), | 118 symbolToken(Precedence.OPEN_SQUARE_BRACKET_INFO), |
| 130 symbolToken(Precedence.CLOSE_SQUARE_BRACKET_INFO), | 119 linkedList(elements), |
| 131 ','), | 120 symbolToken(Precedence.CLOSE_SQUARE_BRACKET_INFO), |
| 121 ','), |
| 132 isConst ? keywordToken('const') : null); | 122 isConst ? keywordToken('const') : null); |
| 133 } | 123 } |
| 134 | 124 |
| 135 Node createDefinition(Identifier name, Expression initializer) { | 125 Node createDefinition(Identifier name, Expression initializer) { |
| 136 if (initializer == null) return name; | 126 if (initializer == null) return name; |
| 137 return new SendSet(null, name, | 127 return new SendSet( |
| 128 null, |
| 129 name, |
| 138 new Operator(symbolToken(Precedence.EQ_INFO)), | 130 new Operator(symbolToken(Precedence.EQ_INFO)), |
| 139 new NodeList.singleton(initializer)); | 131 new NodeList.singleton(initializer)); |
| 140 } | 132 } |
| 141 | 133 |
| 142 VariableDefinitions initializingFormal(String fieldName) { | 134 VariableDefinitions initializingFormal(String fieldName) { |
| 143 return new VariableDefinitions.forParameter( | 135 return new VariableDefinitions.forParameter( |
| 144 new NodeList.empty(), | 136 new NodeList.empty(), |
| 145 null, | 137 null, |
| 146 Modifiers.EMPTY, | 138 Modifiers.EMPTY, |
| 147 new NodeList.singleton( | 139 new NodeList.singleton( |
| 148 new Send(identifier('this'), identifier(fieldName)))); | 140 new Send(identifier('this'), identifier(fieldName)))); |
| 149 } | 141 } |
| 150 | 142 |
| 151 NewExpression newExpression(String typeName, | 143 NewExpression newExpression(String typeName, NodeList arguments, |
| 152 NodeList arguments, | 144 {bool isConst: false}) { |
| 153 {bool isConst: false}) { | |
| 154 return new NewExpression(keywordToken(isConst ? 'const' : 'new'), | 145 return new NewExpression(keywordToken(isConst ? 'const' : 'new'), |
| 155 new Send(null, identifier(typeName), arguments)); | 146 new Send(null, identifier(typeName), arguments)); |
| 156 } | 147 } |
| 157 | 148 |
| 158 Send reference(Identifier identifier) { | 149 Send reference(Identifier identifier) { |
| 159 return new Send(null, identifier); | 150 return new Send(null, identifier); |
| 160 } | 151 } |
| 161 | 152 |
| 162 Send indexGet(Expression receiver, Expression index) { | 153 Send indexGet(Expression receiver, Expression index) { |
| 163 return new Send(receiver, | 154 return new Send(receiver, new Operator(symbolToken(Precedence.INDEX_INFO)), |
| 164 new Operator(symbolToken(Precedence.INDEX_INFO)), | 155 new NodeList.singleton(index)); |
| 165 new NodeList.singleton(index)); | |
| 166 } | 156 } |
| 167 | 157 |
| 168 LiteralMapEntry mapLiteralEntry(Expression key, Expression value) { | 158 LiteralMapEntry mapLiteralEntry(Expression key, Expression value) { |
| 169 return new LiteralMapEntry(key, symbolToken(Precedence.COLON_INFO), value); | 159 return new LiteralMapEntry(key, symbolToken(Precedence.COLON_INFO), value); |
| 170 } | 160 } |
| 171 | 161 |
| 172 LiteralMap mapLiteral(List<LiteralMapEntry> entries, {bool isConst: false}) { | 162 LiteralMap mapLiteral(List<LiteralMapEntry> entries, {bool isConst: false}) { |
| 173 return new LiteralMap( | 163 return new LiteralMap( |
| 174 null, // Type arguments. | 164 null, // Type arguments. |
| 175 new NodeList(symbolToken(Precedence.OPEN_CURLY_BRACKET_INFO), | 165 new NodeList( |
| 176 linkedList(entries), | 166 symbolToken(Precedence.OPEN_CURLY_BRACKET_INFO), |
| 177 symbolToken(Precedence.CLOSE_CURLY_BRACKET_INFO), | 167 linkedList(entries), |
| 178 ','), | 168 symbolToken(Precedence.CLOSE_CURLY_BRACKET_INFO), |
| 169 ','), |
| 179 isConst ? keywordToken('const') : null); | 170 isConst ? keywordToken('const') : null); |
| 180 } | 171 } |
| 181 } | 172 } |
| 182 | 173 |
| 183 // TODO(johnniwinther): Avoid creating synthesized ASTs for enums when SSA is | 174 // TODO(johnniwinther): Avoid creating synthesized ASTs for enums when SSA is |
| 184 // removed. | 175 // removed. |
| 185 class EnumCreator { | 176 class EnumCreator { |
| 186 final DiagnosticReporter reporter; | 177 final DiagnosticReporter reporter; |
| 187 final CoreTypes coreTypes; | 178 final CoreTypes coreTypes; |
| 188 final EnumClassElementX enumClass; | 179 final EnumClassElementX enumClass; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 212 | 203 |
| 213 VariableDefinitions indexDefinition = builder.initializingFormal('index'); | 204 VariableDefinitions indexDefinition = builder.initializingFormal('index'); |
| 214 | 205 |
| 215 FunctionExpression constructorNode = builder.functionExpression( | 206 FunctionExpression constructorNode = builder.functionExpression( |
| 216 builder.modifiers(isConst: true), | 207 builder.modifiers(isConst: true), |
| 217 enumClass.name, | 208 enumClass.name, |
| 218 builder.argumentList([indexDefinition]), | 209 builder.argumentList([indexDefinition]), |
| 219 builder.emptyStatement()); | 210 builder.emptyStatement()); |
| 220 | 211 |
| 221 EnumConstructorElementX constructor = new EnumConstructorElementX( | 212 EnumConstructorElementX constructor = new EnumConstructorElementX( |
| 222 enumClass, | 213 enumClass, builder.modifiers(isConst: true), constructorNode); |
| 223 builder.modifiers(isConst: true), | |
| 224 constructorNode); | |
| 225 | 214 |
| 226 EnumFormalElementX indexFormal = new EnumFormalElementX( | 215 EnumFormalElementX indexFormal = new EnumFormalElementX(constructor, |
| 227 constructor, | 216 indexDefinition, builder.identifier('index'), indexVariable); |
| 228 indexDefinition, | |
| 229 builder.identifier('index'), | |
| 230 indexVariable); | |
| 231 | 217 |
| 232 FunctionSignatureX constructorSignature = new FunctionSignatureX( | 218 FunctionSignatureX constructorSignature = new FunctionSignatureX( |
| 233 requiredParameters: [indexFormal], | 219 requiredParameters: [indexFormal], |
| 234 requiredParameterCount: 1, | 220 requiredParameterCount: 1, |
| 235 type: new FunctionType(constructor, const VoidType(), | 221 type: new FunctionType( |
| 236 <DartType>[intType])); | 222 constructor, const VoidType(), <DartType>[intType])); |
| 237 constructor.functionSignature = constructorSignature; | 223 constructor.functionSignature = constructorSignature; |
| 238 enumClass.addMember(constructor, reporter); | 224 enumClass.addMember(constructor, reporter); |
| 239 | 225 |
| 240 List<FieldElement> enumValues = <FieldElement>[]; | 226 List<FieldElement> enumValues = <FieldElement>[]; |
| 241 VariableList variableList = | 227 VariableList variableList = |
| 242 new VariableList(builder.modifiers(isStatic: true, isConst: true)); | 228 new VariableList(builder.modifiers(isStatic: true, isConst: true)); |
| 243 variableList.type = enumType; | 229 variableList.type = enumType; |
| 244 int index = 0; | 230 int index = 0; |
| 245 List<Node> valueReferences = <Node>[]; | 231 List<Node> valueReferences = <Node>[]; |
| 246 List<LiteralMapEntry> mapEntries = <LiteralMapEntry>[]; | 232 List<LiteralMapEntry> mapEntries = <LiteralMapEntry>[]; |
| 247 for (Link<Node> link = node.names.nodes; | 233 for (Link<Node> link = node.names.nodes; !link.isEmpty; link = link.tail) { |
| 248 !link.isEmpty; | |
| 249 link = link.tail) { | |
| 250 Identifier name = link.head; | 234 Identifier name = link.head; |
| 251 AstBuilder valueBuilder = new AstBuilder(name.token.charOffset); | 235 AstBuilder valueBuilder = new AstBuilder(name.token.charOffset); |
| 252 | 236 |
| 253 // Add reference for the `values` field. | 237 // Add reference for the `values` field. |
| 254 valueReferences.add(valueBuilder.reference(name)); | 238 valueReferences.add(valueBuilder.reference(name)); |
| 255 | 239 |
| 256 // Add map entry for `toString` implementation. | 240 // Add map entry for `toString` implementation. |
| 257 mapEntries.add(valueBuilder.mapLiteralEntry( | 241 mapEntries.add(valueBuilder.mapLiteralEntry( |
| 258 valueBuilder.literalInt(index), | 242 valueBuilder.literalInt(index), |
| 259 valueBuilder.literalString('${enumClass.name}.${name.source}'))); | 243 valueBuilder.literalString('${enumClass.name}.${name.source}'))); |
| 260 | 244 |
| 261 Expression initializer = valueBuilder.newExpression( | 245 Expression initializer = valueBuilder.newExpression(enumClass.name, |
| 262 enumClass.name, | |
| 263 valueBuilder.argumentList([valueBuilder.literalInt(index)]), | 246 valueBuilder.argumentList([valueBuilder.literalInt(index)]), |
| 264 isConst: true); | 247 isConst: true); |
| 265 SendSet definition = valueBuilder.createDefinition(name, initializer); | 248 SendSet definition = valueBuilder.createDefinition(name, initializer); |
| 266 | 249 |
| 267 EnumFieldElementX field = new EnumFieldElementX( | 250 EnumFieldElementX field = new EnumFieldElementX( |
| 268 name, enumClass, variableList, definition, initializer); | 251 name, enumClass, variableList, definition, initializer); |
| 269 enumValues.add(field); | 252 enumValues.add(field); |
| 270 enumClass.addMember(field, reporter); | 253 enumClass.addMember(field, reporter); |
| 271 index++; | 254 index++; |
| 272 } | 255 } |
| 273 | 256 |
| 274 VariableList valuesVariableList = | 257 VariableList valuesVariableList = |
| 275 new VariableList(builder.modifiers(isStatic: true, isConst: true)); | 258 new VariableList(builder.modifiers(isStatic: true, isConst: true)); |
| 276 valuesVariableList.type = coreTypes.listType(enumType); | 259 valuesVariableList.type = coreTypes.listType(enumType); |
| 277 | 260 |
| 278 Identifier valuesIdentifier = builder.identifier('values'); | 261 Identifier valuesIdentifier = builder.identifier('values'); |
| 279 // TODO(johnniwinther): Add type argument. | 262 // TODO(johnniwinther): Add type argument. |
| 280 Expression initializer = builder.listLiteral( | 263 Expression initializer = |
| 281 valueReferences, isConst: true); | 264 builder.listLiteral(valueReferences, isConst: true); |
| 282 | 265 |
| 283 Node definition = builder.createDefinition(valuesIdentifier, initializer); | 266 Node definition = builder.createDefinition(valuesIdentifier, initializer); |
| 284 | 267 |
| 285 EnumFieldElementX valuesVariable = new EnumFieldElementX( | 268 EnumFieldElementX valuesVariable = new EnumFieldElementX(valuesIdentifier, |
| 286 valuesIdentifier, enumClass, valuesVariableList, | 269 enumClass, valuesVariableList, definition, initializer); |
| 287 definition, initializer); | |
| 288 | 270 |
| 289 enumClass.addMember(valuesVariable, reporter); | 271 enumClass.addMember(valuesVariable, reporter); |
| 290 | 272 |
| 291 // TODO(johnniwinther): Support return type. Note `String` might be prefixed | 273 // TODO(johnniwinther): Support return type. Note `String` might be prefixed |
| 292 // or not imported within the current library. | 274 // or not imported within the current library. |
| 293 FunctionExpression toStringNode = builder.functionExpression( | 275 FunctionExpression toStringNode = builder.functionExpression( |
| 294 Modifiers.EMPTY, | 276 Modifiers.EMPTY, |
| 295 'toString', | 277 'toString', |
| 296 builder.argumentList([]), | 278 builder.argumentList([]), |
| 297 builder.returnStatement( | 279 builder.returnStatement(builder.indexGet( |
| 298 builder.indexGet( | 280 builder.mapLiteral(mapEntries, isConst: true), |
| 299 builder.mapLiteral(mapEntries, isConst: true), | 281 builder.reference(builder.identifier('index'))))); |
| 300 builder.reference(builder.identifier('index'))) | |
| 301 ) | |
| 302 ); | |
| 303 | 282 |
| 304 EnumMethodElementX toString = new EnumMethodElementX('toString', | 283 EnumMethodElementX toString = new EnumMethodElementX( |
| 305 enumClass, Modifiers.EMPTY, toStringNode); | 284 'toString', enumClass, Modifiers.EMPTY, toStringNode); |
| 306 FunctionSignatureX toStringSignature = new FunctionSignatureX( | 285 FunctionSignatureX toStringSignature = |
| 307 type: new FunctionType(toString, stringType)); | 286 new FunctionSignatureX(type: new FunctionType(toString, stringType)); |
| 308 toString.functionSignature = toStringSignature; | 287 toString.functionSignature = toStringSignature; |
| 309 enumClass.addMember(toString, reporter); | 288 enumClass.addMember(toString, reporter); |
| 310 | 289 |
| 311 enumClass.enumValues = enumValues; | 290 enumClass.enumValues = enumValues; |
| 312 } | 291 } |
| 313 } | 292 } |
| OLD | NEW |