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

Unified Diff: lib/src/codegen/js_codegen.dart

Issue 961513002: Flesh out dynamic invocation code (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: Fix ++ and -- Created 5 years, 10 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/src/codegen/ast_builder.dart ('k') | test/codegen/expect/dart/_interceptors.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/codegen/js_codegen.dart
diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart
index cadeb9090c0f1e429e6bb906ea58913be5bbd7f2..a09350c6529ee25448ee18862a5afddd905b7e55 100644
--- a/lib/src/codegen/js_codegen.dart
+++ b/lib/src/codegen/js_codegen.dart
@@ -18,6 +18,8 @@ import 'package:source_maps/source_maps.dart' show SourceMapSpan;
import 'package:source_span/source_span.dart' show SourceLocation;
import 'package:path/path.dart' as path;
+import 'package:dev_compiler/src/codegen/ast_builder.dart' show AstBuilder;
+
// TODO(jmesserly): import from its own package
import 'package:dev_compiler/src/js/js_ast.dart' as JS;
import 'package:dev_compiler/src/js/js_ast.dart' show js;
@@ -698,10 +700,27 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
return result;
}
+ JS.Node _emitDPutIfDynamic(
+ Expression target, SimpleIdentifier id, Expression rhs) {
+ if (rules.isDynamicTarget(target)) {
+ return js.call('dart.dput(#, #, #)', [
+ _visit(target),
+ js.string(id.name, "'"),
+ _visit(rhs)
+ ]);
+ } else {
+ return null;
+ }
+ }
+
@override
JS.Node visitAssignmentExpression(AssignmentExpression node) {
var lhs = node.leftHandSide;
var rhs = node.rightHandSide;
+ return _emitAssignment(lhs, rhs, node.parent);
+ }
+
+ JS.Node _emitAssignment(Expression lhs, Expression rhs, [AstNode parent]) {
if (lhs is IndexExpression) {
String code;
var target = _getTarget(lhs);
@@ -714,17 +733,15 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
}
if (lhs is PropertyAccess) {
- var target = _getTarget(lhs);
- if (rules.isDynamicTarget(target)) {
- return js.call('dart.dput(#, #, #)', [
- _visit(target),
- js.string(lhs.propertyName.name, "'"),
- _visit(rhs)
- ]);
- }
+ var result = _emitDPutIfDynamic(_getTarget(lhs), lhs.propertyName, rhs);
+ if (result != null) return result;
+ } else if (lhs is PrefixedIdentifier) {
+ // TODO(vsm): Is this the right code if the prefix is a library?
Jennifer Messerly 2015/03/04 16:03:51 ah, I think the PrefixedIdentifier branch makes se
+ var result = _emitDPutIfDynamic(lhs.prefix, lhs.identifier, rhs);
+ if (result != null) return result;
}
- if (node.parent is ExpressionStatement &&
+ if (parent is ExpressionStatement &&
rhs is CascadeExpression &&
_isStateless(lhs, rhs)) {
// Special case: cascade assignment to a variable in a statement.
@@ -1169,6 +1186,38 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
bool _isNull(Expression expr) => expr is NullLiteral;
+ JS.Expression _emitIncrement(Token op, Expression expr, {bool prefix}) {
+ assert(prefix != null);
+
+ // TODO(vsm): Avoid collisions.
+ var tmp1 = '_t1';
Jennifer Messerly 2015/03/04 16:03:51 so far we've been using `$` for compiler generated
vsm 2015/03/04 17:55:30 Done.
+ var tmp2 = '_t2';
+
+ // Read
+ var read = _visit(expr);
+
+ // Increment
+ var one = AstBuilder.integerLiteral(1);
+ var binary = AstBuilder.binaryExpression(expr, op.lexeme[0], one);
Jennifer Messerly 2015/03/04 16:03:51 hmmm. Should this be `id` instead of `expr` as the
vsm 2015/03/04 17:55:30 good catch! fixed.
+ var increment = _visit(binary);
Jennifer Messerly 2015/03/04 16:03:51 this could be directly `visitBinaryExpression` sin
vsm 2015/03/04 17:55:30 This ends up being a little complicated. I'm feed
+
+ // Write
+ var id =
+ new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, tmp1, 0));
Jennifer Messerly 2015/03/04 16:03:51 maybe a TODO: I think we had to do something simil
vsm 2015/03/04 17:55:30 I factored this out a bit.
+ id.staticElement = new LocalVariableElementImpl.forNode(id);
+ id.staticType = expr.staticType;
+ var write = _emitAssignment(expr, id);
+
+ return js.call('''
+(function () {
Jennifer Messerly 2015/03/04 16:03:51 I think you want an `=>` function here. Otherwise
+ var $tmp1 = #;
Jennifer Messerly 2015/03/04 16:03:51 one warning I got from Stephen was to make sure to
+ var $tmp2 = #;
+ #;
+ return ${prefix ? tmp2 : tmp1};
Jennifer Messerly 2015/03/04 16:03:51 hmmm, I wonder if we can do better for prefix and
vsm 2015/03/04 17:55:30 Nice idea! I will try this. In the postfix, dyna
+})()
+''', [read, increment, write]);
+ }
+
@override
JS.Expression visitPostfixExpression(PostfixExpression node) {
var op = node.operator;
@@ -1179,8 +1228,9 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
// TODO(vsm): When do Dart ops not map to JS?
return js.call('#$op', notNull(expr));
} else {
- // TODO(vsm): Figure out operator calling convention / dispatch.
- return visitExpression(node);
+ assert(op.lexeme == '++' || op.lexeme == '--');
+ var result = _emitIncrement(op, expr, prefix: false);
+ return (result != null) ? result : visitExpression(node);
}
}
@@ -1194,8 +1244,24 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
// TODO(vsm): When do Dart ops not map to JS?
return js.call('$op#', notNull(expr));
} else {
- // TODO(vsm): Figure out operator calling convention / dispatch.
- return visitExpression(node);
+ // Increment or decrement must be numerical
+ if (op.lexeme == '++' || op.lexeme == '--') {
+ var result = _emitIncrement(op, expr, prefix: true);
+ return (result != null) ? result : visitExpression(node);
+ }
+ }
+ // TODO(vsm): Statically invoke the operator if the type is known.
+ // Fall back to dynamic dispatch.
+ var opString = _jsMemberName(op.lexeme, unary: true);
+ if (rules.isDynamicTarget(expr)) {
+ // dynamic dispatch
+ return js.call('dart.dunary(#, #)', [opString, _visit(expr)]);
+ } else if (_isJSBuiltinType(dispatchType)) {
+ return js.call(
+ '#.#(#)', [_emitTypeName(dispatchType), opString, _visit(expr)]);
+ } else {
+ // Generic static-dispatch, user-defined operator code path.
+ return js.call('#.#()', [_visit(expr), opString]);
}
}
« no previous file with comments | « lib/src/codegen/ast_builder.dart ('k') | test/codegen/expect/dart/_interceptors.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698