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

Side by Side 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: 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 unified diff | Download patch
« lib/runtime/dart_runtime.js ('K') | « lib/runtime/dart_runtime.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 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 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 library ddc.src.codegen.js_codegen; 5 library ddc.src.codegen.js_codegen;
6 6
7 import 'dart:io' show Directory, File; 7 import 'dart:io' show Directory, File;
8 8
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 } else { 670 } else {
671 result = new JS.VariableUse(name); 671 result = new JS.VariableUse(name);
672 } 672 }
673 673
674 if (typeArgs != null) { 674 if (typeArgs != null) {
675 result = js.call('#(#)', [result, typeArgs]); 675 result = js.call('#(#)', [result, typeArgs]);
676 } 676 }
677 return result; 677 return result;
678 } 678 }
679 679
680 JS.Node _generateDPutIfDynamic(
681 Expression target, SimpleIdentifier id, Expression rhs) {
682 if (rules.isDynamicTarget(target)) {
683 return js.call('dart.dput(#, #, #)', [
684 target.accept(this),
685 js.string(id.name, "'"),
686 rhs.accept(this)
687 ]);
688 } else {
689 return null;
690 }
691 }
692
680 @override 693 @override
681 JS.Node visitAssignmentExpression(AssignmentExpression node) { 694 JS.Node visitAssignmentExpression(AssignmentExpression node) {
682 var lhs = node.leftHandSide; 695 var lhs = node.leftHandSide;
683 var rhs = node.rightHandSide; 696 var rhs = node.rightHandSide;
697 return _generateAssignment(lhs, rhs, node.parent);
698 }
699
700 JS.Node _generateAssignment(Expression lhs, Expression rhs,
Jennifer Messerly 2015/02/26 20:53:16 I've been using the "_emit" prefix. For better or
vsm 2015/03/03 21:06:12 Done.
701 [AstNode parent]) {
684 if (lhs is IndexExpression) { 702 if (lhs is IndexExpression) {
685 String code; 703 String code;
686 var target = _getTarget(lhs); 704 var target = _getTarget(lhs);
687 if (rules.isDynamicTarget(target)) { 705 if (rules.isDynamicTarget(target)) {
688 code = 'dart.dsetindex(#, #, #)'; 706 code = 'dart.dsetindex(#, #, #)';
689 } else { 707 } else {
690 code = '#.set(#, #)'; 708 code = '#.set(#, #)';
691 } 709 }
692 return js.call(code, [ 710 return js.call(code, [
693 target.accept(this), 711 target.accept(this),
694 lhs.index.accept(this), 712 lhs.index.accept(this),
695 rhs.accept(this) 713 rhs.accept(this)
696 ]); 714 ]);
697 } 715 }
698 716
699 if (lhs is PropertyAccess) { 717 if (lhs is PropertyAccess) {
700 var target = _getTarget(lhs); 718 var result =
701 if (rules.isDynamicTarget(target)) { 719 _generateDPutIfDynamic(_getTarget(lhs), lhs.propertyName, rhs);
702 return js.call('dart.dput(#, #, #)', [ 720 if (result != null) return result;
703 target.accept(this), 721 } else if (lhs is PrefixedIdentifier) {
Jennifer Messerly 2015/02/26 20:53:16 how does a prefixed identifier end up as a dynamic
vsm 2015/03/03 21:06:12 In sunflower, notes.textContent shows up as a Pref
704 js.string(lhs.propertyName.name, "'"), 722 // TODO(vsm): Is this the right code if the prefix is a library?
705 rhs.accept(this) 723 var result = _generateDPutIfDynamic(lhs.prefix, lhs.identifier, rhs);
706 ]); 724 if (result != null) return result;
707 }
708 } 725 }
709 726
710 if (node.parent is ExpressionStatement && 727 if (parent is ExpressionStatement &&
711 rhs is CascadeExpression && 728 rhs is CascadeExpression &&
712 _isStateless(lhs, rhs)) { 729 _isStateless(lhs, rhs)) {
713 // Special case: cascade assignment to a variable in a statement. 730 // Special case: cascade assignment to a variable in a statement.
714 // We can reuse the variable to desugar it: 731 // We can reuse the variable to desugar it:
715 // result = []..length = length; 732 // result = []..length = length;
716 // becomes: 733 // becomes:
717 // result = []; 734 // result = [];
718 // result.length = length; 735 // result.length = length;
719 var savedCascadeTemp = _cascadeTarget; 736 var savedCascadeTemp = _cascadeTarget;
720 _cascadeTarget = lhs; 737 _cascadeTarget = lhs;
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
1086 } else { 1103 } else {
1087 // Generic static-dispatch, user-defined operator code path. 1104 // Generic static-dispatch, user-defined operator code path.
1088 return js.call( 1105 return js.call(
1089 '#.#(#)', [left.accept(this), opString, right.accept(this)]); 1106 '#.#(#)', [left.accept(this), opString, right.accept(this)]);
1090 } 1107 }
1091 } 1108 }
1092 } 1109 }
1093 1110
1094 bool _isNull(Expression expr) => expr is NullLiteral; 1111 bool _isNull(Expression expr) => expr is NullLiteral;
1095 1112
1113 JS.Expression _generateIncrement(Token op, Expression expr, bool prefix) {
1114 // TODO(vsm): Should we generate a runtime helper for this?
Jennifer Messerly 2015/02/26 20:53:16 yeah, for now i think that's the pattern. this loo
vsm 2015/03/03 21:06:12 Note - there is a free expression in the closure,
1115 var tmp = '_';
1116 var applied = prefix ? '$tmp$op' : '$op$tmp';
1117 var id =
1118 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, tmp, 0));
1119 id.staticElement = new LocalVariableElementImpl.forNode(id);
1120 id.staticType = expr.staticType;
1121 var assignment = _generateAssignment(expr, id);
1122 return js.call('''
1123 (function () {
1124 var $tmp = #;
1125 if (typeof($tmp) != 'number') throw 'number expected';
1126 var result = $applied;
1127 #;
1128 return result;
1129 })()
1130 ''', [expr.accept(this), assignment]);
1131 }
1132
1096 @override 1133 @override
1097 JS.Expression visitPostfixExpression(PostfixExpression node) { 1134 JS.Expression visitPostfixExpression(PostfixExpression node) {
1098 var op = node.operator; 1135 var op = node.operator;
1099 var expr = node.operand; 1136 var expr = node.operand;
1100 1137
1101 var dispatchType = rules.getStaticType(expr); 1138 var dispatchType = rules.getStaticType(expr);
1102 if (unaryOperationIsPrimitive(dispatchType)) { 1139 if (unaryOperationIsPrimitive(dispatchType)) {
1103 // TODO(vsm): When do Dart ops not map to JS? 1140 // TODO(vsm): When do Dart ops not map to JS?
1104 return js.call('#$op', notNull(expr)); 1141 return js.call('#$op', notNull(expr));
1105 } else { 1142 } else {
1106 // TODO(vsm): Figure out operator calling convention / dispatch. 1143 assert(op.lexeme == '++' || op.lexeme == '--');
1107 return visitExpression(node); 1144 return _generateIncrement(op, expr, false);
Jennifer Messerly 2015/02/26 20:53:17 nit: use named arg `prefix: false`
vsm 2015/03/03 21:06:12 Done.
1108 } 1145 }
1109 } 1146 }
1110 1147
1111 @override 1148 @override
1112 JS.Expression visitPrefixExpression(PrefixExpression node) { 1149 JS.Expression visitPrefixExpression(PrefixExpression node) {
1113 var op = node.operator; 1150 var op = node.operator;
1114 var expr = node.operand; 1151 var expr = node.operand;
1115 1152
1116 var dispatchType = rules.getStaticType(expr); 1153 var dispatchType = rules.getStaticType(expr);
1117 if (unaryOperationIsPrimitive(dispatchType)) { 1154 if (unaryOperationIsPrimitive(dispatchType)) {
1118 // TODO(vsm): When do Dart ops not map to JS? 1155 // TODO(vsm): When do Dart ops not map to JS?
1119 return js.call('$op#', notNull(expr)); 1156 return js.call('$op#', notNull(expr));
1120 } else { 1157 } else {
1121 // TODO(vsm): Figure out operator calling convention / dispatch. 1158 if (op.lexeme == '++' || op.lexeme == '--') {
1122 return visitExpression(node); 1159 return _generateIncrement(op, expr, true);
1160 }
1123 } 1161 }
1162 // TODO(vsm): Expand out.
1163 return visitExpression(node);
vsm 2015/02/26 00:34:00 Should this just be: x['-']() ? Or similar? T
Jennifer Messerly 2015/02/26 20:53:17 IMO, name should be "unary-" unless we find a good
1124 } 1164 }
1125 1165
1126 // Cascades can contain [IndexExpression], [MethodInvocation] and 1166 // Cascades can contain [IndexExpression], [MethodInvocation] and
1127 // [PropertyAccess]. The code generation for those is handled in their 1167 // [PropertyAccess]. The code generation for those is handled in their
1128 // respective visit methods. 1168 // respective visit methods.
1129 @override 1169 @override
1130 JS.Node visitCascadeExpression(CascadeExpression node) { 1170 JS.Node visitCascadeExpression(CascadeExpression node) {
1131 var savedCascadeTemp = _cascadeTarget; 1171 var savedCascadeTemp = _cascadeTarget;
1132 1172
1133 var parent = node.parent; 1173 var parent = node.parent;
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after
1705 /// Choose a canonical name from the library element. 1745 /// Choose a canonical name from the library element.
1706 /// This never uses the library's name (the identifier in the `library` 1746 /// This never uses the library's name (the identifier in the `library`
1707 /// declaration) as it doesn't have any meaningful rules enforced. 1747 /// declaration) as it doesn't have any meaningful rules enforced.
1708 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library); 1748 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library);
1709 1749
1710 /// Path to file that will be generated for [info]. 1750 /// Path to file that will be generated for [info].
1711 // TODO(jmesserly): library directory should be relative to its package 1751 // TODO(jmesserly): library directory should be relative to its package
1712 // root. For example, "package:dev_compiler/src/codegen/js_codegen.dart" would b e: 1752 // root. For example, "package:dev_compiler/src/codegen/js_codegen.dart" would b e:
1713 // "ddc/src/codegen/js_codegen.js" under the output directory. 1753 // "ddc/src/codegen/js_codegen.js" under the output directory.
1714 String jsOutputPath(LibraryInfo info) => '${info.name}/${info.name}.js'; 1754 String jsOutputPath(LibraryInfo info) => '${info.name}/${info.name}.js';
OLDNEW
« lib/runtime/dart_runtime.js ('K') | « lib/runtime/dart_runtime.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698