OLD | NEW |
(Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 library dart2js.resolution.enum_creator; |
| 6 |
| 7 import '../dart_types.dart'; |
| 8 import '../dart2jslib.dart'; |
| 9 import '../elements/elements.dart'; |
| 10 import '../elements/modelx.dart'; |
| 11 import '../scanner/scannerlib.dart'; |
| 12 import '../tree/tree.dart'; |
| 13 import '../util/util.dart'; |
| 14 |
| 15 // TODO(johnniwinther): Merge functionality with the `TreePrinter`. |
| 16 class AstBuilder { |
| 17 final Token position; |
| 18 |
| 19 AstBuilder(this.position); |
| 20 |
| 21 int get charOffset => position.charOffset; |
| 22 |
| 23 final Modifiers finalModifiers = |
| 24 new Modifiers.withFlags(null, Modifiers.FLAG_FINAL); |
| 25 final Modifiers constModifiers = |
| 26 new Modifiers.withFlags(null, Modifiers.FLAG_CONST); |
| 27 final Modifiers staticConstModifiers = |
| 28 new Modifiers.withFlags(null, |
| 29 Modifiers.FLAG_STATIC | Modifiers.FLAG_CONST); |
| 30 |
| 31 Token keywordToken(String text) { |
| 32 return new KeywordToken(Keyword.keywords[text], position.charOffset); |
| 33 } |
| 34 |
| 35 Token stringToken(String text) { |
| 36 return new StringToken.fromString(IDENTIFIER_INFO, text, charOffset); |
| 37 } |
| 38 |
| 39 Token symbolToken(PrecedenceInfo info) { |
| 40 return new SymbolToken(info, charOffset); |
| 41 } |
| 42 |
| 43 Identifier identifier(String text) { |
| 44 Keyword keyword = Keyword.keywords[text]; |
| 45 Token token; |
| 46 if (keyword != null) { |
| 47 token = new KeywordToken(Keyword.keywords[text], charOffset); |
| 48 } else { |
| 49 token = stringToken(text); |
| 50 } |
| 51 return new Identifier(token); |
| 52 } |
| 53 |
| 54 Link linkedList(List elements) { |
| 55 LinkBuilder builder = new LinkBuilder(); |
| 56 elements.forEach((e) => builder.addLast(e)); |
| 57 return builder.toLink(); |
| 58 } |
| 59 |
| 60 NodeList argumentList(List<Node> nodes) { |
| 61 return new NodeList(symbolToken(OPEN_PAREN_INFO), |
| 62 linkedList(nodes), |
| 63 symbolToken(CLOSE_PAREN_INFO), |
| 64 ','); |
| 65 } |
| 66 |
| 67 Return returnStatement(Expression expression) { |
| 68 return new Return( |
| 69 keywordToken('return'), |
| 70 symbolToken(SEMICOLON_INFO), |
| 71 expression); |
| 72 } |
| 73 |
| 74 FunctionExpression functionExpression(Modifiers modifiers, |
| 75 String name, |
| 76 NodeList argumentList, |
| 77 Statement body, |
| 78 [TypeAnnotation returnType]) { |
| 79 return new FunctionExpression( |
| 80 identifier(name), |
| 81 argumentList, |
| 82 body, |
| 83 returnType, |
| 84 modifiers, |
| 85 null, // Initializer. |
| 86 null, // get/set. |
| 87 null // Async modifier. |
| 88 ); |
| 89 } |
| 90 |
| 91 EmptyStatement emptyStatement() { |
| 92 return new EmptyStatement(symbolToken(COMMA_INFO)); |
| 93 } |
| 94 |
| 95 LiteralInt literalInt(int value) { |
| 96 return new LiteralInt(stringToken('$value'), null); |
| 97 } |
| 98 |
| 99 LiteralString literalString(String text, |
| 100 {String prefix: '"', |
| 101 String suffix: '"'}) { |
| 102 return new LiteralString(stringToken('$prefix$text$suffix'), |
| 103 new DartString.literal(text)); |
| 104 } |
| 105 |
| 106 LiteralList listLiteral(List<Node> elements, {bool isConst: false}) { |
| 107 return new LiteralList( |
| 108 null, |
| 109 new NodeList(symbolToken(OPEN_SQUARE_BRACKET_INFO), |
| 110 linkedList(elements), |
| 111 symbolToken(CLOSE_SQUARE_BRACKET_INFO), |
| 112 ','), |
| 113 isConst ? keywordToken('const') : null); |
| 114 } |
| 115 |
| 116 Node createDefinition(Identifier name, Expression initializer) { |
| 117 if (initializer == null) return name; |
| 118 return new SendSet(null, name, new Operator(symbolToken(EQ_INFO)), |
| 119 new NodeList.singleton(initializer)); |
| 120 } |
| 121 |
| 122 VariableDefinitions initializingFormal(String fieldName) { |
| 123 return new VariableDefinitions.forParameter( |
| 124 new NodeList.empty(), |
| 125 null, |
| 126 Modifiers.EMPTY, |
| 127 new NodeList.singleton( |
| 128 new Send(identifier('this'), identifier(fieldName)))); |
| 129 } |
| 130 |
| 131 NewExpression newExpression(String typeName, |
| 132 NodeList arguments, |
| 133 {bool isConst: false}) { |
| 134 return new NewExpression(keywordToken(isConst ? 'const' : 'new'), |
| 135 new Send(null, identifier(typeName), arguments)); |
| 136 } |
| 137 |
| 138 } |
| 139 |
| 140 class EnumCreator { |
| 141 final Compiler compiler; |
| 142 final EnumClassElementX enumClass; |
| 143 |
| 144 EnumCreator(this.compiler, this.enumClass); |
| 145 |
| 146 void createMembers() { |
| 147 Enum node = enumClass.node; |
| 148 InterfaceType enumType = enumClass.thisType; |
| 149 AstBuilder builder = new AstBuilder(enumClass.position); |
| 150 |
| 151 InterfaceType intType = compiler.intClass.computeType(compiler); |
| 152 InterfaceType stringType = compiler.stringClass.computeType(compiler); |
| 153 |
| 154 EnumFieldElementX addInstanceMember(String name, InterfaceType type) { |
| 155 Identifier identifier = builder.identifier(name); |
| 156 VariableList variableList = new VariableList(builder.finalModifiers); |
| 157 variableList.type = type; |
| 158 EnumFieldElementX variable = new EnumFieldElementX( |
| 159 identifier, enumClass, variableList, identifier); |
| 160 enumClass.addMember(variable, compiler); |
| 161 return variable; |
| 162 } |
| 163 |
| 164 EnumFieldElementX indexVariable = addInstanceMember('index', intType); |
| 165 EnumFieldElementX nameVariable = addInstanceMember('_name', stringType); |
| 166 |
| 167 VariableDefinitions indexDefinition = builder.initializingFormal('index'); |
| 168 VariableDefinitions nameDefinition = builder.initializingFormal('_name'); |
| 169 |
| 170 FunctionExpression constructorNode = builder.functionExpression( |
| 171 builder.constModifiers, |
| 172 enumClass.name, |
| 173 builder.argumentList([indexDefinition, nameDefinition]), |
| 174 builder.emptyStatement()); |
| 175 |
| 176 EnumConstructorElementX constructor = new EnumConstructorElementX( |
| 177 enumClass, |
| 178 builder.constModifiers, |
| 179 constructorNode); |
| 180 |
| 181 EnumFormalElementX indexFormal = new EnumFormalElementX( |
| 182 constructor, |
| 183 indexDefinition, |
| 184 builder.identifier('index'), |
| 185 indexVariable); |
| 186 |
| 187 EnumFormalElementX nameFormal = new EnumFormalElementX( |
| 188 constructor, |
| 189 nameDefinition, |
| 190 builder.identifier('_name'), |
| 191 nameVariable); |
| 192 |
| 193 FunctionSignatureX constructorSignature = new FunctionSignatureX( |
| 194 requiredParameters: builder.linkedList([indexFormal, nameFormal]), |
| 195 requiredParameterCount: 2, |
| 196 type: new FunctionType(constructor, const VoidType(), |
| 197 <DartType>[intType, stringType])); |
| 198 constructor.functionSignatureCache = constructorSignature; |
| 199 enumClass.addMember(constructor, compiler); |
| 200 |
| 201 VariableList variableList = new VariableList(builder.staticConstModifiers); |
| 202 variableList.type = enumType; |
| 203 int index = 0; |
| 204 List<Node> valueReferences = <Node>[]; |
| 205 for (Link<Node> link = node.names.nodes; |
| 206 !link.isEmpty; |
| 207 link = link.tail) { |
| 208 Identifier name = link.head; |
| 209 AstBuilder valueBuilder = new AstBuilder(name.token); |
| 210 valueReferences.add(new Send(null, name)); |
| 211 |
| 212 Expression initializer = valueBuilder.newExpression( |
| 213 enumClass.name, |
| 214 valueBuilder.argumentList([ |
| 215 valueBuilder.literalInt(index), |
| 216 valueBuilder.literalString('${name.source}') |
| 217 ]), |
| 218 isConst: true); |
| 219 SendSet definition = valueBuilder.createDefinition(name, initializer); |
| 220 |
| 221 EnumFieldElementX field = new EnumFieldElementX( |
| 222 name, enumClass, variableList, definition, initializer); |
| 223 enumClass.addMember(field, compiler); |
| 224 index++; |
| 225 } |
| 226 |
| 227 VariableList valuesVariableList = |
| 228 new VariableList(builder.staticConstModifiers); |
| 229 InterfaceType listType = compiler.listClass.computeType(compiler); |
| 230 valuesVariableList.type = listType.createInstantiation([enumType]); |
| 231 |
| 232 Identifier valuesIdentifier = builder.identifier('values'); |
| 233 // TODO(johnniwinther): Add type argument. |
| 234 Expression initializer = builder.listLiteral( |
| 235 valueReferences, isConst: true); |
| 236 |
| 237 Node definition = builder.createDefinition(valuesIdentifier, initializer); |
| 238 |
| 239 EnumFieldElementX valuesVariable = new EnumFieldElementX( |
| 240 valuesIdentifier, enumClass, valuesVariableList, |
| 241 definition, initializer); |
| 242 |
| 243 enumClass.addMember(valuesVariable, compiler); |
| 244 |
| 245 // TODO(johnniwinther): Support return type. Note `String` might be prefixed |
| 246 // or not imported within the current library. |
| 247 FunctionExpression toStringNode = builder.functionExpression( |
| 248 Modifiers.EMPTY, |
| 249 'toString', |
| 250 builder.argumentList([]), |
| 251 builder.returnStatement( |
| 252 new StringInterpolation( |
| 253 builder.literalString('${enumClass.name}.', suffix: ''), |
| 254 new NodeList.singleton(new StringInterpolationPart( |
| 255 new Send(null, builder.identifier('_name')), |
| 256 builder.literalString('', prefix: ''))) |
| 257 )) |
| 258 ); |
| 259 |
| 260 EnumMethodElementX toString = new EnumMethodElementX('toString', |
| 261 enumClass, Modifiers.EMPTY, toStringNode); |
| 262 FunctionSignatureX toStringSignature = new FunctionSignatureX( |
| 263 type: new FunctionType(toString, stringType)); |
| 264 toString.functionSignatureCache = toStringSignature; |
| 265 enumClass.addMember(toString, compiler); |
| 266 } |
| 267 } |
OLD | NEW |