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

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

Issue 1993023003: Better boolean conversion tests. (Closed) Base URL: https://github.com/dart-lang/dev_compiler@master
Patch Set: Created 4 years, 7 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') | tool/input_sdk/private/ddc_runtime/operations.dart » ('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 8a97a278c6114a34e3a048de9a9dd36cedc82799..9f551c7b9cb338febf22a170989001a6dc5dd23c 100644
--- a/lib/src/compiler/code_generator.dart
+++ b/lib/src/compiler/code_generator.dart
@@ -456,44 +456,28 @@ class CodeGenerator extends GeneralizingAstVisitor
}
@override
- visitAsExpression(AsExpression node) =>
- _emitCast(node.expression, to: node.type.type);
-
- /// Emits a cast and/or a null check (i.e. a cast to a non-null type).
- JS.Expression _emitCast(Expression fromExpr,
- {DartType to, bool checkNull: false}) {
- var jsFrom = _visit(fromExpr);
+ visitAsExpression(AsExpression node) {
+ Expression fromExpr = node.expression;
var from = getStaticType(fromExpr);
+ var to = node.type.type;
- JS.Expression maybeCheckNull(JS.Expression jsExpr) {
- if (checkNull && isNullable(fromExpr)) {
- return js.call('dart.notNull(#)', jsExpr);
- }
- return jsExpr;
- }
+ var jsFrom = _visit(fromExpr);
// Skip the cast if it's not needed.
- if (to == null || rules.isSubtypeOf(from, to)) {
- return maybeCheckNull(jsFrom);
- }
+ if (rules.isSubtypeOf(from, to)) return jsFrom;
// All Dart number types map to a JS double.
if (_isNumberInJS(from) && _isNumberInJS(to)) {
// Make sure to check when converting to int.
if (from != types.intType && to == types.intType) {
- // TODO(jmesserly): fuse this with notNull check.
Jennifer Messerly 2016/05/19 17:45:38 Why remove this TODO? We still want to be smarter
sra1 2016/05/19 18:57:56 I'll add it back.
- return maybeCheckNull(js.call('dart.asInt(#)', [jsFrom]));
+ return js.call('dart.asInt(#)', jsFrom);
}
// A no-op in JavaScript.
- return maybeCheckNull(jsFrom);
- }
-
- if (to == types.boolType && checkNull) {
- return js.call('dart.test(#)', _visit(fromExpr));
+ return jsFrom;
}
- return maybeCheckNull(js.call('dart.as(#, #)', [jsFrom, _emitType(to)]));
+ return js.call('dart.as(#, #)', [jsFrom, _emitType(to)]);
}
@override
@@ -3128,10 +3112,9 @@ class CodeGenerator extends GeneralizingAstVisitor
JS.Expression notNull(Expression expr) {
if (expr == null) return null;
- if (expr is AsExpression) {
- return _emitCast(expr.expression, to: expr.type.type, checkNull: true);
- }
- return _emitCast(expr, checkNull: true);
+ var jsExpr = _visit(expr);
+ if (!isNullable(expr)) return jsExpr;
+ return js.call('dart.notNull(#)', jsExpr);
}
@override
@@ -3839,7 +3822,7 @@ class CodeGenerator extends GeneralizingAstVisitor
@override
visitConditionalExpression(ConditionalExpression node) {
return js.call('# ? # : #', [
- notNull(node.condition),
+ _visitTest(node.condition),
_visit(node.thenExpression),
_visit(node.elseExpression)
]);
@@ -3881,8 +3864,8 @@ class CodeGenerator extends GeneralizingAstVisitor
@override
JS.If visitIfStatement(IfStatement node) {
- return new JS.If(notNull(node.condition), _visitScope(node.thenStatement),
- _visitScope(node.elseStatement));
+ return new JS.If(_visitTest(node.condition),
+ _visitScope(node.thenStatement), _visitScope(node.elseStatement));
}
@override
@@ -3891,18 +3874,18 @@ class CodeGenerator extends GeneralizingAstVisitor
if (init == null) init = _visit(node.variables);
var update = _visitListToBinary(node.updaters, ',');
if (update != null) update = update.toVoidExpression();
- return new JS.For(
- init, notNull(node.condition), update, _visitScope(node.body));
+ var condition = node.condition == null ? null : _visitTest(node.condition);
+ return new JS.For(init, condition, update, _visitScope(node.body));
}
@override
JS.While visitWhileStatement(WhileStatement node) {
- return new JS.While(notNull(node.condition), _visitScope(node.body));
+ return new JS.While(_visitTest(node.condition), _visitScope(node.body));
}
@override
JS.Do visitDoStatement(DoStatement node) {
- return new JS.Do(_visitScope(node.body), notNull(node.condition));
+ return new JS.Do(_visitScope(node.body), _visitTest(node.condition));
}
@override
@@ -4239,6 +4222,39 @@ class CodeGenerator extends GeneralizingAstVisitor
_visitList(nodes) as List<JS.Expression>, operator);
}
+ /// Generates an expression for a boolean conversion context (if, while, &&,
+ /// etc.), where conversions and null checks are implemented via `dart.test`
+ /// to give a more helpful message.
+ // TODO(sra): When nullablility is available earlier, it would be cleaner to
+ // build an input AST where the boolean conversion is a single AST node.
+ JS.Expression _visitTest(Expression node) {
+ JS.Expression finish(JS.Expression result) {
+ return annotate(result, node);
+ }
+ if (node is PrefixExpression && node.operator.lexeme == '!') {
+ return finish(js.call('!#', _visitTest(node.operand)));
+ }
+ if (node is BinaryExpression) {
+ JS.Expression shortCircuit(String code) {
+ return finish(js.call(code,
+ [_visitTest(node.leftOperand), _visitTest(node.rightOperand)]));
+ }
+ var op = node.operator.type.lexeme;
+ if (op == '&&') return shortCircuit('# && #');
+ if (op == '||') return shortCircuit('# || #');
+ }
+ // Offset 0 from start of file is syntactically impossible for normal code.
+ // TODO(sra): Find a better way to recognize reified coercion, since we
+ // can't set the isSynthetic attribute.
Jennifer Messerly 2016/05/19 17:45:38 FYI -- we can send a patch to Analyzer if we need
sra1 2016/05/19 18:57:56 Acknowledged.
+ if (node is AsExpression && node.asOperator.offset == 0) {
+ assert(node.staticType == types.boolType);
+ return js.call('dart.test(#)', _visit(node.expression));
+ }
+ JS.Expression result = _visit(node);
+ if (isNullable(node)) result = js.call('dart.test(#)', result);
+ return result;
+ }
+
/// Like [_emitMemberName], but for declaration sites.
///
/// Unlike call sites, we always have an element available, so we can use it
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | tool/input_sdk/private/ddc_runtime/operations.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698