Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(619)

Unified Diff: lib/src/compiler/code_generator.dart

Issue 1924413002: Fix modulo and bitwise operators. (Closed) Base URL: https://github.com/dart-lang/dev_compiler@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | test/browser/language_tests.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/compiler/code_generator.dart
diff --git a/lib/src/compiler/code_generator.dart b/lib/src/compiler/code_generator.dart
index d6e8a5d91e68e0603021bd950b6397c45b103203..0e8ca488fe735ca17aa02da8e1939fb728254698 100644
--- a/lib/src/compiler/code_generator.dart
+++ b/lib/src/compiler/code_generator.dart
@@ -2810,21 +2810,61 @@ class CodeGenerator extends GeneralizingAstVisitor
// these values are assumed to be non-null (determined by the checker)
// TODO(jmesserly): it would be nice to just inline the method from core,
// instead of special cases here.
- if (op.type == TokenType.TILDE_SLASH) {
- // `a ~/ b` is equivalent to `(a / b).truncate()`
- var div = AstBuilder.binaryExpression(left, '/', right)
- ..staticType = node.staticType;
- return _emitSend(div, 'truncate', []);
- } else {
- // TODO(vsm): When do Dart ops not map to JS?
- code = '# $op #';
+ JS.Expression binary(String code) {
+ return js.call(code, [notNull(left), notNull(right)]);
+ }
+
+ JS.Expression bitwise(String code) {
+ return _coerceBitOperationResultToUnsigned(node, binary(code));
+ }
+
+ switch (op.type) {
+ case TokenType.TILDE_SLASH:
+ // `a ~/ b` is equivalent to `(a / b).truncate()`
+ var div = AstBuilder.binaryExpression(left, '/', right)
+ ..staticType = node.staticType;
+ return _emitSend(div, 'truncate', []);
+
+ case TokenType.PERCENT:
+ // TODO(sra): We can generate `a % b + 0` if both are non-negative
+ // (the `+ 0` is to coerce -0.0 to 0).
+ return _emitSend(left, op.lexeme, [right]);
+
+ case TokenType.AMPERSAND:
+ return bitwise('# & #');
+
+ case TokenType.BAR:
+ return bitwise('# | #');
+
+ case TokenType.CARET:
+ return bitwise('# ^ #');
+
+ case TokenType.GT_GT:
+ // TODO(sra): Detect when JS shift does the right thing.
+ return _emitSend(left, op.lexeme, [right]);
+
+ case TokenType.LT_LT:
+ // TODO(sra): Detect when JS shift does the right thing.
+ return _emitSend(left, op.lexeme, [right]);
+
+ default:
+ // TODO(vsm): When do Dart ops not map to JS?
+ return binary('# $op #');
}
- return js.call(code, [notNull(left), notNull(right)]);
}
return _emitSend(left, op.lexeme, [right]);
}
+ /// Bit operations are coerced to values on [0, 2^32). The coercion changes
+ /// the interpretation of the 32-bit value from signed to unsigned. Most
+ /// JavaScript operations interpret their operands as signed and generate
+ /// signed results.
+ JS.Expression _coerceBitOperationResultToUnsigned(
+ Expression node, JS.Expression operation) {
+ return js.call('# >>> 0', operation);
+ }
+
/// If the type [t] is [int] or [double], or a type parameter
/// bounded by [int], [double] or [num] returns [num].
/// Otherwise returns [t].
@@ -3001,9 +3041,17 @@ class CodeGenerator extends GeneralizingAstVisitor
var dispatchType = getStaticType(expr);
if (unaryOperationIsPrimitive(dispatchType)) {
+ if (op.lexeme == '~') {
+ if (_isNumberInJS(dispatchType)) {
+ JS.Expression jsExpr = js.call('~#', notNull(expr));
+ return _coerceBitOperationResultToUnsigned(node, jsExpr);
+ }
+ return _emitSend(expr, op.lexeme[0], []);
+ }
if (!isNullable(expr)) {
return js.call('$op#', _visit(expr));
- } else if (op.lexeme == '++' || op.lexeme == '--') {
+ }
+ if (op.lexeme == '++' || op.lexeme == '--') {
// We need a null check, so the increment must be expanded out.
var vars = <JS.MetaLetVariable, JS.Expression>{};
var x = _bindLeftHandSide(vars, expr, context: expr);
@@ -3014,9 +3062,8 @@ class CodeGenerator extends GeneralizingAstVisitor
..staticType = getStaticType(expr);
return new JS.MetaLet(vars, [_emitSet(x, increment)]);
- } else {
- return js.call('$op#', notNull(expr));
}
+ return js.call('$op#', notNull(expr));
}
if (op.lexeme == '++' || op.lexeme == '--') {
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | test/browser/language_tests.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698