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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js/builder.dart

Issue 671513013: dart2js: Accept named holes in js-templates. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 // Utilities for building JS ASTs at runtime. Contains a builder class 5 // Utilities for building JS ASTs at runtime. Contains a builder class
6 // and a parser that parses part of the language. 6 // and a parser that parses part of the language.
7 7
8 part of js; 8 part of js;
9 9
10 10
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 * 201 *
202 * See the MiniJsParser class. 202 * See the MiniJsParser class.
203 * 203 *
204 * [arguments] can be a single [Node] (e.g. an [Expression] or [Statement]) or 204 * [arguments] can be a single [Node] (e.g. an [Expression] or [Statement]) or
205 * a list of [Node]s, which will be interpolated into the source at the '#' 205 * a list of [Node]s, which will be interpolated into the source at the '#'
206 * signs. 206 * signs.
207 */ 207 */
208 Expression call(String source, [var arguments]) { 208 Expression call(String source, [var arguments]) {
209 Template template = _findExpressionTemplate(source); 209 Template template = _findExpressionTemplate(source);
210 if (arguments == null) return template.instantiate([]); 210 if (arguments == null) return template.instantiate([]);
211 return template.instantiate(arguments is List ? arguments : [arguments]); 211 // We allow a single argument to be given directly.
212 if (arguments is! List && arguments is! Map) arguments = [arguments];
213 return template.instantiate(arguments);
212 } 214 }
213 215
214 /** 216 /**
215 * Parses a JavaScript Statement, otherwise just like [call]. 217 * Parses a JavaScript Statement, otherwise just like [call].
216 */ 218 */
217 Statement statement(String source, [var arguments]) { 219 Statement statement(String source, [var arguments]) {
218 Template template = _findStatementTemplate(source); 220 Template template = _findStatementTemplate(source);
219 if (arguments == null) return template.instantiate([]); 221 if (arguments == null) return template.instantiate([]);
220 return template.instantiate(arguments is List ? arguments : [arguments]); 222 // We allow a single argument to be given directly.
223 if (arguments is! List && arguments is! Map) arguments = [arguments];
224 return template.instantiate(arguments);
221 } 225 }
222 226
223 /** 227 /**
224 * Parses JavaScript written in the `JS` foreign instruction. 228 * Parses JavaScript written in the `JS` foreign instruction.
225 * 229 *
226 * The [source] must be a JavaScript expression or a JavaScript throw 230 * The [source] must be a JavaScript expression or a JavaScript throw
227 * statement. 231 * statement.
228 */ 232 */
229 Template parseForeignJS(String source) { 233 Template parseForeignJS(String source) {
230 // TODO(sra): Parse with extra validation to forbid `#` interpolation in 234 // TODO(sra): Parse with extra validation to forbid `#` interpolation in
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 position = 0 { 399 position = 0 {
396 getToken(); 400 getToken();
397 } 401 }
398 402
399 int lastCategory = NONE; 403 int lastCategory = NONE;
400 String lastToken = null; 404 String lastToken = null;
401 int lastPosition = 0; 405 int lastPosition = 0;
402 int position = 0; 406 int position = 0;
403 bool skippedNewline = false; // skipped newline in last getToken? 407 bool skippedNewline = false; // skipped newline in last getToken?
404 final String src; 408 final String src;
409
410 /// Whether the template uses named or positional holes.
411 ///
412 /// Initially set to `null`, and updated when the first hole is encountered.
413 bool hasNamedHoles;
405 final List<InterpolatedNode> interpolatedValues = <InterpolatedNode>[]; 414 final List<InterpolatedNode> interpolatedValues = <InterpolatedNode>[];
406 415
407 static const NONE = -1; 416 static const NONE = -1;
408 static const ALPHA = 0; 417 static const ALPHA = 0;
409 static const NUMERIC = 1; 418 static const NUMERIC = 1;
410 static const STRING = 2; 419 static const STRING = 2;
411 static const SYMBOL = 3; 420 static const SYMBOL = 3;
412 static const ASSIGNMENT = 4; 421 static const ASSIGNMENT = 4;
413 static const DOT = 5; 422 static const DOT = 5;
414 static const LPAREN = 6; 423 static const LPAREN = 6;
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 getToken(); 666 getToken();
658 return true; 667 return true;
659 } 668 }
660 return false; 669 return false;
661 } 670 }
662 671
663 void error(message) { 672 void error(message) {
664 throw new MiniJsParserError(this, message); 673 throw new MiniJsParserError(this, message);
665 } 674 }
666 675
676 /// Returns either the name for the hole, or its integer position.
677 parseHash() {
678 String holeName = lastToken;
679 if (acceptCategory(ALPHA)) {
680 // Named hole. Example: 'function #funName() { ... }'
681 if (hasNamedHoles == false) {
682 error('Holes must all be positional or named. $holeName');
683 }
684 hasNamedHoles = true;
685 return holeName;
686 } else if (acceptCategory(LBRACE)) {
687 // Named guarded hole. Example: 'function #{funName}() { ... }'
688 String holeName = lastToken;
689 if (!acceptCategory(ALPHA)) {
690 error('Named hole does not contain alpha-characters.');
691 }
692 if (!acceptCategory(RBRACE)) {
693 error('Named hole is not correctly terminated with `}`');
694 }
695 if (hasNamedHoles == false) {
696 error('Holes must all be positional or named. $holeName');
697 }
698 hasNamedHoles = true;
699 return holeName;
700 } else {
701 if (hasNamedHoles == true) {
702 error('Holes must all be positional or named. $holeName');
703 }
704 hasNamedHoles = false;
705 int position = interpolatedValues.length;
706 return position;
707 }
708 }
709
667 Expression parsePrimary() { 710 Expression parsePrimary() {
668 String last = lastToken; 711 String last = lastToken;
669 if (acceptCategory(ALPHA)) { 712 if (acceptCategory(ALPHA)) {
670 if (last == "true") { 713 if (last == "true") {
671 return new LiteralBool(true); 714 return new LiteralBool(true);
672 } else if (last == "false") { 715 } else if (last == "false") {
673 return new LiteralBool(false); 716 return new LiteralBool(false);
674 } else if (last == "null") { 717 } else if (last == "null") {
675 return new LiteralNull(); 718 return new LiteralNull();
676 } else if (last == "function") { 719 } else if (last == "function") {
(...skipping 21 matching lines...) Expand all
698 } 741 }
699 return new ArrayInitializer(values.length, values); 742 return new ArrayInitializer(values.length, values);
700 } else if (last != null && last.startsWith("/")) { 743 } else if (last != null && last.startsWith("/")) {
701 String regexp = getDelimited(lastPosition); 744 String regexp = getDelimited(lastPosition);
702 getToken(); 745 getToken();
703 String flags = lastToken; 746 String flags = lastToken;
704 if (!acceptCategory(ALPHA)) flags = ""; 747 if (!acceptCategory(ALPHA)) flags = "";
705 Expression expression = new RegExpLiteral(regexp + flags); 748 Expression expression = new RegExpLiteral(regexp + flags);
706 return expression; 749 return expression;
707 } else if (acceptCategory(HASH)) { 750 } else if (acceptCategory(HASH)) {
708 InterpolatedExpression expression = 751 var name = parseHash();
709 new InterpolatedExpression(interpolatedValues.length); 752 InterpolatedExpression expression = new InterpolatedExpression(name);
710 interpolatedValues.add(expression); 753 interpolatedValues.add(expression);
711 return expression; 754 return expression;
712 } else { 755 } else {
713 error("Expected primary expression"); 756 error("Expected primary expression");
714 return null; 757 return null;
715 } 758 }
716 } 759 }
717 760
718 Expression parseFunctionExpression() { 761 Expression parseFunctionExpression() {
719 String last = lastToken; 762 String last = lastToken;
720 if (acceptCategory(ALPHA)) { 763 if (acceptCategory(ALPHA)) {
721 String functionName = last; 764 String functionName = last;
722 return new NamedFunction(new VariableDeclaration(functionName), 765 return new NamedFunction(new VariableDeclaration(functionName),
723 parseFun()); 766 parseFun());
724 } 767 }
725 return parseFun(); 768 return parseFun();
726 } 769 }
727 770
728 Expression parseFun() { 771 Expression parseFun() {
729 List<Parameter> params = <Parameter>[]; 772 List<Parameter> params = <Parameter>[];
730 773
731 expectCategory(LPAREN); 774 expectCategory(LPAREN);
732 if (!acceptCategory(RPAREN)) { 775 if (!acceptCategory(RPAREN)) {
733 for (;;) { 776 for (;;) {
734 if (acceptCategory(HASH)) { 777 if (acceptCategory(HASH)) {
735 InterpolatedParameter parameter = 778 var name = parseHash();
736 new InterpolatedParameter(interpolatedValues.length); 779 InterpolatedParameter parameter = new InterpolatedParameter(name);
737 interpolatedValues.add(parameter); 780 interpolatedValues.add(parameter);
738 params.add(parameter); 781 params.add(parameter);
739 } else { 782 } else {
740 String argumentName = lastToken; 783 String argumentName = lastToken;
741 expectCategory(ALPHA); 784 expectCategory(ALPHA);
742 params.add(new Parameter(argumentName)); 785 params.add(new Parameter(argumentName));
743 } 786 }
744 if (acceptCategory(COMMA)) continue; 787 if (acceptCategory(COMMA)) continue;
745 expectCategory(RPAREN); 788 expectCategory(RPAREN);
746 break; 789 break;
(...skipping 12 matching lines...) Expand all
759 // Limited subset: keys are identifiers, no 'get' or 'set' properties. 802 // Limited subset: keys are identifiers, no 'get' or 'set' properties.
760 Literal propertyName; 803 Literal propertyName;
761 String identifier = lastToken; 804 String identifier = lastToken;
762 if (acceptCategory(ALPHA)) { 805 if (acceptCategory(ALPHA)) {
763 propertyName = new LiteralString('"$identifier"'); 806 propertyName = new LiteralString('"$identifier"');
764 } else if (acceptCategory(STRING)) { 807 } else if (acceptCategory(STRING)) {
765 propertyName = new LiteralString(identifier); 808 propertyName = new LiteralString(identifier);
766 } else if (acceptCategory(SYMBOL)) { // e.g. void 809 } else if (acceptCategory(SYMBOL)) { // e.g. void
767 propertyName = new LiteralString('"$identifier"'); 810 propertyName = new LiteralString('"$identifier"');
768 } else if (acceptCategory(HASH)) { 811 } else if (acceptCategory(HASH)) {
812 var name = parseHash();
769 InterpolatedLiteral interpolatedLiteral = 813 InterpolatedLiteral interpolatedLiteral =
770 new InterpolatedLiteral(interpolatedValues.length); 814 new InterpolatedLiteral(name);
771 interpolatedValues.add(interpolatedLiteral); 815 interpolatedValues.add(interpolatedLiteral);
772 propertyName = interpolatedLiteral; 816 propertyName = interpolatedLiteral;
773 } else { 817 } else {
774 error('Expected property name'); 818 error('Expected property name');
775 } 819 }
776 expectCategory(COLON); 820 expectCategory(COLON);
777 Expression value = parseAssignment(); 821 Expression value = parseAssignment();
778 properties.add(new Property(propertyName, value)); 822 properties.add(new Property(propertyName, value));
779 if (acceptCategory(RBRACE)) break; 823 if (acceptCategory(RBRACE)) break;
780 expectCategory(COMMA); 824 expectCategory(COMMA);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
826 // JS allows new without (), but we don't. 870 // JS allows new without (), but we don't.
827 if (constructor) error("Parentheses are required for new"); 871 if (constructor) error("Parentheses are required for new");
828 break; 872 break;
829 } 873 }
830 } 874 }
831 return receiver; 875 return receiver;
832 } 876 }
833 877
834 Expression getDotRhs(Expression receiver) { 878 Expression getDotRhs(Expression receiver) {
835 if (acceptCategory(HASH)) { 879 if (acceptCategory(HASH)) {
836 InterpolatedSelector property = 880 var name = parseHash();
837 new InterpolatedSelector(interpolatedValues.length); 881 InterpolatedSelector property = new InterpolatedSelector(name);
838 interpolatedValues.add(property); 882 interpolatedValues.add(property);
839 return new PropertyAccess(receiver, property); 883 return new PropertyAccess(receiver, property);
840 } 884 }
841 String identifier = lastToken; 885 String identifier = lastToken;
842 // In ES5 keywords like delete and continue are allowed as property 886 // In ES5 keywords like delete and continue are allowed as property
843 // names, and the IndexedDB API uses that, so we need to allow it here. 887 // names, and the IndexedDB API uses that, so we need to allow it here.
844 if (acceptCategory(SYMBOL)) { 888 if (acceptCategory(SYMBOL)) {
845 if (!OPERATORS_THAT_LOOK_LIKE_IDENTIFIERS.contains(identifier)) { 889 if (!OPERATORS_THAT_LOOK_LIKE_IDENTIFIERS.contains(identifier)) {
846 error("Expected alphanumeric identifier"); 890 error("Expected alphanumeric identifier");
847 } 891 }
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
1190 Catch parseCatch() { 1234 Catch parseCatch() {
1191 expectCategory(LPAREN); 1235 expectCategory(LPAREN);
1192 String identifier = lastToken; 1236 String identifier = lastToken;
1193 expectCategory(ALPHA); 1237 expectCategory(ALPHA);
1194 expectCategory(RPAREN); 1238 expectCategory(RPAREN);
1195 expectCategory(LBRACE); 1239 expectCategory(LBRACE);
1196 Block body = parseBlock(); 1240 Block body = parseBlock();
1197 return new Catch(new VariableDeclaration(identifier), body); 1241 return new Catch(new VariableDeclaration(identifier), body);
1198 } 1242 }
1199 } 1243 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698