| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 /** | 5 /** |
| 6 * The [CompileTimeConstantHandler] keeps track of compile-time constants, | 6 * The [CompileTimeConstantHandler] keeps track of compile-time constants, |
| 7 * initializations of global and static fields, and default values of | 7 * initializations of global and static fields, and default values of |
| 8 * optional parameters. | 8 * optional parameters. |
| 9 */ | 9 */ |
| 10 class CompileTimeConstantHandler extends CompilerTask { | 10 class CompileTimeConstantHandler extends CompilerTask { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 && element.modifiers.isFinal(); | 89 && element.modifiers.isFinal(); |
| 90 }); | 90 }); |
| 91 } | 91 } |
| 92 | 92 |
| 93 StringBuffer writeJsCodeForVariable(StringBuffer buffer, | 93 StringBuffer writeJsCodeForVariable(StringBuffer buffer, |
| 94 VariableElement element) { | 94 VariableElement element) { |
| 95 var value = initialVariableValues[element]; | 95 var value = initialVariableValues[element]; |
| 96 if (value === null) { | 96 if (value === null) { |
| 97 buffer.add("(void 0)"); | 97 buffer.add("(void 0)"); |
| 98 } else if (value is num) { | 98 } else if (value is num) { |
| 99 buffer.add("($value)"); | 99 if (value.isNaN()) { |
| 100 buffer.add("(0/0)"); |
| 101 } else if (value == double.INFINITY) { |
| 102 buffer.add("(1/0)"); |
| 103 } else if (value == -double.INFINITY) { |
| 104 buffer.add("(-1/0)"); |
| 105 } else { |
| 106 buffer.add("($value)"); |
| 107 } |
| 100 } else if (value === true) { | 108 } else if (value === true) { |
| 101 buffer.add("true"); | 109 buffer.add("true"); |
| 102 } else if (value === false) { | 110 } else if (value === false) { |
| 103 buffer.add("false"); | 111 buffer.add("false"); |
| 104 } else if (value is DartString) { | 112 } else if (value is DartString) { |
| 105 buffer.add("'"); | 113 buffer.add("'"); |
| 106 writeEscapedString(value, buffer, (reason) { | 114 writeEscapedString(value, buffer, (reason) { |
| 107 compiler.cancel("failed to write escaped string: $value"); | 115 compiler.cancel("failed to write escaped string: $value"); |
| 108 }); | 116 }); |
| 109 buffer.add("'"); | 117 buffer.add("'"); |
| 110 } else { | 118 } else { |
| 111 // TODO(floitsch): support more values. | 119 // TODO(floitsch): support more values. |
| 112 compiler.unimplemented("CompileTimeConstantHandler" + | 120 compiler.unimplemented("CompileTimeConstantHandler" + |
| 113 "writeJsCodeForVariable", | 121 "writeJsCodeForVariable", |
| 114 node: element.parseNode(compiler)); | 122 element: element); |
| 115 } | 123 } |
| 116 return buffer; | 124 return buffer; |
| 117 } | 125 } |
| 118 | 126 |
| 119 /** | 127 /** |
| 120 * Write the contents of the quoted string to a [StringBuffer] in | 128 * Write the contents of the quoted string to a [StringBuffer] in |
| 121 * a form that is valid as JavaScript string literal content. | 129 * a form that is valid as JavaScript string literal content. |
| 122 * The string is assumed quoted by single quote characters. | 130 * The string is assumed quoted by single quote characters. |
| 123 */ | 131 */ |
| 124 static void writeEscapedString(DartString string, | 132 static void writeEscapedString(DartString string, |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 } | 197 } |
| 190 | 198 |
| 191 visitLiteral(Literal literal) { | 199 visitLiteral(Literal literal) { |
| 192 if (literal is LiteralString) { | 200 if (literal is LiteralString) { |
| 193 assert(literal.asLiteralString().isValidated()); | 201 assert(literal.asLiteralString().isValidated()); |
| 194 return literal.asLiteralString().dartString; | 202 return literal.asLiteralString().dartString; |
| 195 } | 203 } |
| 196 return literal.value; | 204 return literal.value; |
| 197 } | 205 } |
| 198 | 206 |
| 207 // TODO(floitsch): provide better error-messages. |
| 199 visitSend(Send send) { | 208 visitSend(Send send) { |
| 200 Element element = definitions[send]; | 209 Element element = definitions[send]; |
| 201 if (element !== null && element.kind == ElementKind.FIELD) { | 210 if (Elements.isStaticOrTopLevelField(element)) { |
| 202 if (element.isInstanceMember() || | 211 if (element.modifiers === null || |
| 203 element.modifiers === null || | |
| 204 !element.modifiers.isFinal()) { | 212 !element.modifiers.isFinal()) { |
| 205 error(element); | 213 error(send); |
| 206 } | 214 } |
| 207 return constantHandler.compileVariable(element); | 215 return constantHandler.compileVariable(element); |
| 216 } else if (send.isPrefix) { |
| 217 assert(send.isOperator); |
| 218 var receiverValue = evaluate(send.receiver); |
| 219 Operator op = send.selector; |
| 220 switch (op.source.stringValue) { |
| 221 case "-": |
| 222 if (receiverValue is !num) error(send); |
| 223 return -receiverValue; |
| 224 case "~": |
| 225 if (receiverValue is !int) error(send); |
| 226 return ~receiverValue; |
| 227 case "!": |
| 228 if (receiverValue is !bool) error(send); |
| 229 return !receiverValue; |
| 230 default: |
| 231 error(send); |
| 232 } |
| 233 } else if (send.isOperator && !send.isPostfix) { |
| 234 assert(send.argumentCount() == 1); |
| 235 var left = evaluate(send.receiver); |
| 236 var right = evaluate(send.argumentsNode.nodes.head); |
| 237 String op = send.selector.asOperator().source.stringValue; |
| 238 |
| 239 if (op == "==" || op == "===") { |
| 240 // We use == instead of === so that non-canonicalized DartStrings can |
| 241 // use their equality operator. |
| 242 return left == right; |
| 243 } else if (op == "!=" || op == "!==") { |
| 244 return left != right; |
| 245 } |
| 246 if (left is num && right is num) { |
| 247 switch (op) { |
| 248 case "+": return left + right; |
| 249 case "-": return left - right; |
| 250 case "*": return left * right; |
| 251 case "/": return left / right; |
| 252 case "~/": |
| 253 case "%": |
| 254 if (left is int && right is int && right == 0) { |
| 255 error(send); |
| 256 } |
| 257 return op == "~/" ? left ~/ right : left % right; |
| 258 case "<": return left < right; |
| 259 case "<=": return left <= right; |
| 260 case ">": return left > right; |
| 261 case ">=": return left >= right; |
| 262 } |
| 263 } |
| 264 if (left is int && right is int) { |
| 265 switch (op) { |
| 266 case "|": return left | right; |
| 267 case "&": return left & right; |
| 268 case "<<": |
| 269 // TODO(floitsch): find a better way to guard against shifts to the |
| 270 // left. |
| 271 if (right > 100) error(send); |
| 272 if (right < 0) error(send); |
| 273 return left << right; |
| 274 case ">>": |
| 275 if (right < 0) error(send); |
| 276 return left >> right; |
| 277 case "^": return left ^ right; |
| 278 } |
| 279 } |
| 280 if (left is DartString && right is DartString && op == "+") { |
| 281 return new ConsDartString(left, right); |
| 282 } |
| 208 } | 283 } |
| 209 return super.visitSend(send); | 284 return super.visitSend(send); |
| 210 } | 285 } |
| 211 | 286 |
| 212 error(Element element) { | 287 visitSendSet(SendSet node) { |
| 288 error(node); |
| 289 } |
| 290 |
| 291 error(Node node) { |
| 213 // TODO(floitsch): get the list of constants that are currently compiled | 292 // TODO(floitsch): get the list of constants that are currently compiled |
| 214 // and present some kind of stack-trace. | 293 // and present some kind of stack-trace. |
| 215 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; | 294 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; |
| 216 List arguments = [element.name]; | 295 compiler.reportError(node, new CompileTimeConstantError(kind, const [])); |
| 217 Node node = element.parseNode(compiler); | |
| 218 compiler.reportError(node, new CompileTimeConstantError(kind, arguments)); | |
| 219 } | 296 } |
| 220 } | 297 } |
| OLD | NEW |