| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2015, 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 library builtin_operator; | |
| 5 // This is shared by the CPS and Tree IRs. | |
| 6 // Both cps_ir_nodes and tree_ir_nodes import and re-export this file. | |
| 7 | |
| 8 import 'effects.dart'; | |
| 9 | |
| 10 /// An operator supported natively in the CPS and Tree IRs using the | |
| 11 /// `ApplyBuiltinOperator` instructions. | |
| 12 /// | |
| 13 /// These operators are pure in the sense that they cannot throw, diverge, | |
| 14 /// have observable side-effects, return new objects, nor depend on any | |
| 15 /// mutable state. | |
| 16 /// | |
| 17 /// Most operators place restrictions on the values that may be given as | |
| 18 /// argument; their behaviour is unspecified if those requirements are violated. | |
| 19 /// | |
| 20 /// In all cases, the word "null" refers to the Dart null object, corresponding | |
| 21 /// to both JS null and JS undefined. | |
| 22 /// | |
| 23 /// Some operators, notably [IsFloor] and [IsInteger], take "repeated" | |
| 24 /// arguments to reflect the number of times the given value is referenced | |
| 25 /// by the generated code. The tree IR needs to know the number of references | |
| 26 /// to safely propagate assignments. | |
| 27 enum BuiltinOperator { | |
| 28 /// The numeric binary operators must take two numbers as argument. | |
| 29 /// The bitwise operators coerce the result to an unsigned integer, but | |
| 30 /// otherwise these all behave like the corresponding JS operator. | |
| 31 NumAdd, | |
| 32 NumSubtract, | |
| 33 NumMultiply, | |
| 34 NumDivide, | |
| 35 NumAnd, | |
| 36 NumOr, | |
| 37 NumXor, | |
| 38 NumShl, | |
| 39 NumLt, | |
| 40 NumLe, | |
| 41 NumGt, | |
| 42 NumGe, | |
| 43 | |
| 44 /// NumShr behaves like JS '>>>' but is valid only when the left is in the | |
| 45 /// uint32 range and the right in the range [0, 31]. | |
| 46 NumShr, | |
| 47 | |
| 48 /// NumRemainder corresponds to JavaScript's `a % b`, and Dart's | |
| 49 /// `a.remainder(b)`, except at zero, since JavaScript `1 % 0` is `NaN`. | |
| 50 /// Dart's modulo (`%`) is the same as remainder only when if both arguments | |
| 51 /// are non-negative. | |
| 52 NumRemainder, | |
| 53 | |
| 54 /// Corresponds to `a ~/ b` when b is non-zero and the result fits in a signed | |
| 55 /// 32 bit value. | |
| 56 /// | |
| 57 /// This case can be compiled to `(a / b) | 0`. | |
| 58 NumTruncatingDivideToSigned32, | |
| 59 | |
| 60 /// Corresponds to JavaScript's negation, which converts 0 to -0.0. | |
| 61 NumNegate, | |
| 62 | |
| 63 /// Bit inversions, with coercion to uint32. | |
| 64 /// | |
| 65 /// Compiles to `(~x) >>> 0`. | |
| 66 NumBitNot, | |
| 67 | |
| 68 /// Concatenates any number of strings. | |
| 69 /// | |
| 70 /// Takes any number of arguments, and each argument must be a string. | |
| 71 /// | |
| 72 /// Returns the empty string if no arguments are given. | |
| 73 StringConcatenate, | |
| 74 | |
| 75 /// Corresponds to `a.charCodeAt(b)`. `a' must be a String. The index `b` must | |
| 76 /// be in range `0 <= b < a.length`. | |
| 77 /// TODO(sra): Consider replacing with a Primitive to allow lowering when 'a' | |
| 78 /// is nullable (i.e. throws). | |
| 79 CharCodeAt, | |
| 80 | |
| 81 /// Returns true if the two arguments are the same value, and that value is | |
| 82 /// not NaN, or if one argument is +0 and the other is -0. | |
| 83 /// | |
| 84 /// Compiled as a static method call. | |
| 85 Identical, | |
| 86 | |
| 87 /// Like [Identical], except at most one argument may be null. | |
| 88 /// | |
| 89 /// Compiles to `===`. | |
| 90 StrictEq, | |
| 91 | |
| 92 /// Negated version of [StrictEq]. Introduced by [LogicalRewriter] in Tree IR. | |
| 93 StrictNeq, | |
| 94 | |
| 95 /// Returns true if the two arguments are both null or are the same string, | |
| 96 /// boolean, or number, and that number is not NaN, or one argument is +0 | |
| 97 /// and the other is -0. | |
| 98 /// | |
| 99 /// One of the following must hold: | |
| 100 /// - At least one argument is null. | |
| 101 /// - Arguments are both strings, or both booleans, or both numbers. | |
| 102 /// | |
| 103 /// Compiles to `==`. | |
| 104 LooseEq, | |
| 105 | |
| 106 /// Negated version of [LooseEq]. Introduced by [LogicalRewriter] in Tree IR. | |
| 107 LooseNeq, | |
| 108 | |
| 109 /// Returns true if the argument is false, +0. -0, NaN, the empty string, | |
| 110 /// or null. | |
| 111 /// | |
| 112 /// Compiles to `!`. | |
| 113 IsFalsy, | |
| 114 | |
| 115 /// Returns true if the argument is a number. | |
| 116 /// | |
| 117 /// Compiles to `typeof x === 'number'` | |
| 118 IsNumber, | |
| 119 | |
| 120 /// Returns true if the argument is not a number. | |
| 121 /// | |
| 122 /// Compiles to `typeof x !== 'number'`. | |
| 123 IsNotNumber, | |
| 124 | |
| 125 /// Returns true if the argument is an integer, false if it is a double or | |
| 126 /// null, and unspecified if it is anything else. | |
| 127 /// | |
| 128 /// The argument must be repeated 2 times. | |
| 129 /// | |
| 130 /// Compiles to `Math.floor(x) === x` | |
| 131 IsFloor, | |
| 132 | |
| 133 /// Returns true if the argument is an integer. | |
| 134 /// | |
| 135 /// The argument must be repeated 3 times. | |
| 136 /// | |
| 137 /// Compiles to `typeof x === 'number' && Math.floor(x) === x` | |
| 138 IsInteger, | |
| 139 | |
| 140 /// Returns true if the argument is not an integer. | |
| 141 /// | |
| 142 /// The argument must be repeated 3 times. | |
| 143 /// | |
| 144 /// Compiles to `typeof x !== 'number' || Math.floor(x) !== x` | |
| 145 IsNotInteger, | |
| 146 | |
| 147 /// Returns true if `x` is an unsigned 32-bit integer. | |
| 148 /// | |
| 149 /// The argument must be repeated 2 times. | |
| 150 /// | |
| 151 /// Compiles to `x >>> 0 === x` | |
| 152 IsUnsigned32BitInteger, | |
| 153 | |
| 154 /// Returns false if `x` is an unsigned 32-bit integer. | |
| 155 /// | |
| 156 /// The argument must be repeated 2 times. | |
| 157 /// | |
| 158 /// Compiles to `x >>> 0 !== x` | |
| 159 IsNotUnsigned32BitInteger, | |
| 160 | |
| 161 /// Returns true if the argument is a fixed length Array. | |
| 162 /// | |
| 163 /// Uses one argument. | |
| 164 /// | |
| 165 /// Precondition: Argument is a JavaScript Array. | |
| 166 IsFixedLengthJSArray, | |
| 167 | |
| 168 // TODO(sra): Remove this and replace with IsFalsy(IsFixedLengthJSArray(x)). | |
| 169 IsExtendableJSArray, | |
| 170 | |
| 171 /// Returns true if the argument is an unmodifiable Array. | |
| 172 /// | |
| 173 /// Uses one argument. | |
| 174 /// | |
| 175 /// Precondition: Argument is a JavaScript Array. | |
| 176 IsUnmodifiableJSArray, | |
| 177 | |
| 178 // TODO(sra): Remove this and replace with IsFalsy(IsUnmodifiableArray(x)). | |
| 179 IsModifiableJSArray, | |
| 180 } | |
| 181 | |
| 182 /// A method supported natively in the CPS and Tree IRs using the | |
| 183 /// `ApplyBuiltinMethod` instructions. | |
| 184 /// | |
| 185 /// These methods all operate on a distinguished 'object' argument, and | |
| 186 /// take zero or more additional arguments. | |
| 187 /// | |
| 188 /// These methods may mutate and depend on the state of the object argument, | |
| 189 /// but may not depend on or mutate any other state. An exception is thrown | |
| 190 /// if the object is null, but otherwise they cannot throw or diverge. | |
| 191 enum BuiltinMethod { | |
| 192 /// Add an item to an array. | |
| 193 /// | |
| 194 /// Takes any number of arguments, each argument will be added to the | |
| 195 /// list on the order given (as per the JS `push` method). | |
| 196 /// | |
| 197 /// Compiles to `object.push(x1, ..., xN)`. | |
| 198 Push, | |
| 199 | |
| 200 /// Remove and return the last item from an array. | |
| 201 /// | |
| 202 /// Takes no arguments. | |
| 203 /// | |
| 204 /// Compiles to `object.pop()`. | |
| 205 Pop, | |
| 206 | |
| 207 /// Sets the length of the array. | |
| 208 /// | |
| 209 /// Compiles to `object.length = x1`. | |
| 210 SetLength, | |
| 211 } | |
| 212 | |
| 213 /// True for the built-in operators that may be used in a compound assignment. | |
| 214 bool isCompoundableOperator(BuiltinOperator operator) { | |
| 215 switch (operator) { | |
| 216 case BuiltinOperator.NumAdd: | |
| 217 case BuiltinOperator.NumSubtract: | |
| 218 case BuiltinOperator.NumMultiply: | |
| 219 case BuiltinOperator.NumDivide: | |
| 220 case BuiltinOperator.NumRemainder: | |
| 221 case BuiltinOperator.StringConcatenate: | |
| 222 return true; | |
| 223 default: | |
| 224 return false; | |
| 225 } | |
| 226 } | |
| 227 | |
| 228 int getEffectsOfBuiltinMethod(BuiltinMethod method) { | |
| 229 switch (method) { | |
| 230 case BuiltinMethod.Push: | |
| 231 return Effects.changesIndexableContent | Effects.changesIndexableLength; | |
| 232 case BuiltinMethod.Pop: | |
| 233 return Effects.dependsOnIndexableContent | | |
| 234 Effects.dependsOnIndexableLength | | |
| 235 Effects.changesIndexableLength; | |
| 236 case BuiltinMethod.SetLength: | |
| 237 return Effects.changesIndexableLength; | |
| 238 } | |
| 239 } | |
| OLD | NEW |