OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of js_ast; | 5 part of js_ast; |
6 | 6 |
7 abstract class NodeVisitor<T> implements TypeRefVisitor<T> { | 7 abstract class NodeVisitor<T> implements TypeRefVisitor<T> { |
8 T visitProgram(Program node); | 8 T visitProgram(Program node); |
9 | 9 |
10 T visitBlock(Block node); | 10 T visitBlock(Block node); |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 } | 304 } |
305 } | 305 } |
306 | 306 |
307 class Program extends Node { | 307 class Program extends Node { |
308 /// Script tag hash-bang, e.g. `#!/usr/bin/env node` | 308 /// Script tag hash-bang, e.g. `#!/usr/bin/env node` |
309 final String scriptTag; | 309 final String scriptTag; |
310 | 310 |
311 /// Top-level statements in the program. | 311 /// Top-level statements in the program. |
312 final List<ModuleItem> body; | 312 final List<ModuleItem> body; |
313 | 313 |
314 Program(this.body, {this.scriptTag}); | 314 /// The module's own name. |
| 315 /// |
| 316 /// This is not used in ES6, but is provided to allow module lowering. |
| 317 final String name; |
| 318 |
| 319 Program(this.body, {this.scriptTag, this.name}); |
315 | 320 |
316 accept(NodeVisitor visitor) => visitor.visitProgram(this); | 321 accept(NodeVisitor visitor) => visitor.visitProgram(this); |
317 void visitChildren(NodeVisitor visitor) { | 322 void visitChildren(NodeVisitor visitor) { |
318 for (ModuleItem statement in body) statement.accept(visitor); | 323 for (ModuleItem statement in body) statement.accept(visitor); |
319 } | 324 } |
320 Program _clone() => new Program(body); | 325 Program _clone() => new Program(body); |
321 } | 326 } |
322 | 327 |
323 abstract class Statement extends ModuleItem { | 328 abstract class Statement extends ModuleItem { |
324 Statement toStatement() => this; | 329 Statement toStatement() => this; |
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
734 // Code that uses JS must take care of operator precedences, and | 739 // Code that uses JS must take care of operator precedences, and |
735 // put parenthesis if needed. | 740 // put parenthesis if needed. |
736 int get precedenceLevel => PRIMARY; | 741 int get precedenceLevel => PRIMARY; |
737 } | 742 } |
738 | 743 |
739 /** | 744 /** |
740 * [VariableDeclarationList] is a subclass of [Expression] to simplify the | 745 * [VariableDeclarationList] is a subclass of [Expression] to simplify the |
741 * AST. | 746 * AST. |
742 */ | 747 */ |
743 class VariableDeclarationList extends Expression { | 748 class VariableDeclarationList extends Expression { |
744 /** The `var` or `let` keyword used for this variable declaration list. */ | 749 /** |
| 750 * The `var` or `let` or `const` keyword used for this variable declaration |
| 751 * list. |
| 752 */ |
745 final String keyword; | 753 final String keyword; |
746 final List<VariableInitialization> declarations; | 754 final List<VariableInitialization> declarations; |
747 | 755 |
748 VariableDeclarationList(this.keyword, this.declarations); | 756 VariableDeclarationList(this.keyword, this.declarations); |
749 | 757 |
750 accept(NodeVisitor visitor) => visitor.visitVariableDeclarationList(this); | 758 accept(NodeVisitor visitor) => visitor.visitVariableDeclarationList(this); |
751 | 759 |
752 void visitChildren(NodeVisitor visitor) { | 760 void visitChildren(NodeVisitor visitor) { |
753 for (VariableInitialization declaration in declarations) { | 761 for (VariableInitialization declaration in declarations) { |
754 declaration.accept(visitor); | 762 declaration.accept(visitor); |
(...skipping 971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1726 abstract class ModuleItem extends Node {} | 1734 abstract class ModuleItem extends Node {} |
1727 | 1735 |
1728 class ImportDeclaration extends ModuleItem { | 1736 class ImportDeclaration extends ModuleItem { |
1729 final Identifier defaultBinding; // Can be null. | 1737 final Identifier defaultBinding; // Can be null. |
1730 | 1738 |
1731 // Can be null, a single specifier of `* as name`, or a list. | 1739 // Can be null, a single specifier of `* as name`, or a list. |
1732 final List<NameSpecifier> namedImports; | 1740 final List<NameSpecifier> namedImports; |
1733 | 1741 |
1734 final LiteralString from; | 1742 final LiteralString from; |
1735 | 1743 |
1736 ImportDeclaration({this.defaultBinding, this.namedImports, this.from}); | 1744 ImportDeclaration({this.defaultBinding, this.namedImports, this.from}) { |
| 1745 assert(from != null); |
| 1746 } |
1737 | 1747 |
1738 /** The `import "name.js"` form of import */ | 1748 /** The `import "name.js"` form of import */ |
1739 ImportDeclaration.all(LiteralString module) : this(from: module); | 1749 ImportDeclaration.all(LiteralString module) : this(from: module); |
1740 | 1750 |
1741 /** If this import has `* as name` returns the name, otherwise null. */ | 1751 /** If this import has `* as name` returns the name, otherwise null. */ |
1742 String get importStarAs { | 1752 Identifier get importStarAs { |
1743 if (namedImports != null && namedImports.length == 1 && | 1753 if (namedImports != null && namedImports.length == 1 && |
1744 namedImports[0].name == '*') { | 1754 namedImports[0].isStar) { |
1745 return namedImports[0].asName; | 1755 return namedImports[0].asName; |
1746 } | 1756 } |
1747 return null; | 1757 return null; |
1748 } | 1758 } |
1749 | 1759 |
1750 accept(NodeVisitor visitor) => visitor.visitImportDeclaration(this); | 1760 accept(NodeVisitor visitor) => visitor.visitImportDeclaration(this); |
1751 void visitChildren(NodeVisitor visitor) { | 1761 void visitChildren(NodeVisitor visitor) { |
1752 if (namedImports != null) { | 1762 if (namedImports != null) { |
1753 for (NameSpecifier name in namedImports) name.accept(visitor); | 1763 for (NameSpecifier name in namedImports) name.accept(visitor); |
1754 } | 1764 } |
(...skipping 18 matching lines...) Expand all Loading... |
1773 | 1783 |
1774 ExportDeclaration(this.exported, {this.isDefault: false}) { | 1784 ExportDeclaration(this.exported, {this.isDefault: false}) { |
1775 assert(exported is ClassDeclaration || | 1785 assert(exported is ClassDeclaration || |
1776 exported is FunctionDeclaration || | 1786 exported is FunctionDeclaration || |
1777 isDefault | 1787 isDefault |
1778 ? exported is Expression | 1788 ? exported is Expression |
1779 : exported is VariableDeclarationList || | 1789 : exported is VariableDeclarationList || |
1780 exported is ExportClause); | 1790 exported is ExportClause); |
1781 } | 1791 } |
1782 | 1792 |
| 1793 /// Gets the list of names exported by this export declaration, or `null` |
| 1794 /// if this is an `export *`. |
| 1795 /// |
| 1796 /// This can be useful for lowering to other module formats. |
| 1797 List<Identifier> get exportedNames { |
| 1798 if (isDefault) return [new Identifier('default')]; |
| 1799 |
| 1800 var exported = this.exported; |
| 1801 if (exported is ClassDeclaration) return [exported.classExpr.name]; |
| 1802 if (exported is FunctionDeclaration) return [exported.name]; |
| 1803 if (exported is VariableDeclarationList) { |
| 1804 return exported.declarations.map((i) => i.declaration).toList(); |
| 1805 } |
| 1806 if (exported is ExportClause) { |
| 1807 if (exported.exportStar) return null; |
| 1808 return exported.exports.map((e) => e.name).toList(); |
| 1809 } |
| 1810 throw new StateError('invalid export declaration'); |
| 1811 } |
| 1812 |
1783 accept(NodeVisitor visitor) => visitor.visitExportDeclaration(this); | 1813 accept(NodeVisitor visitor) => visitor.visitExportDeclaration(this); |
1784 visitChildren(NodeVisitor visitor) => exported.accept(visitor); | 1814 visitChildren(NodeVisitor visitor) => exported.accept(visitor); |
1785 ExportDeclaration _clone() => | 1815 ExportDeclaration _clone() => |
1786 new ExportDeclaration(exported, isDefault: isDefault); | 1816 new ExportDeclaration(exported, isDefault: isDefault); |
1787 } | 1817 } |
1788 | 1818 |
1789 class ExportClause extends Node { | 1819 class ExportClause extends Node { |
1790 final List<NameSpecifier> exports; | 1820 final List<NameSpecifier> exports; |
1791 final LiteralString from; // Can be null. | 1821 final LiteralString from; // Can be null. |
1792 | 1822 |
1793 ExportClause(this.exports, {this.from}); | 1823 ExportClause(this.exports, {this.from}); |
1794 | 1824 |
1795 /** The `export * from 'name.js'` form. */ | 1825 /** The `export * from 'name.js'` form. */ |
1796 ExportClause.star(LiteralString from) | 1826 ExportClause.star(LiteralString from) |
1797 : this([new NameSpecifier('*')], from: from); | 1827 : this([new NameSpecifier.star()], from: from); |
1798 | 1828 |
1799 /** True if this is an `export *`. */ | 1829 /** True if this is an `export *`. */ |
1800 bool get exportStar => exports.length == 1 && exports[0].name == '*'; | 1830 bool get exportStar => exports.length == 1 && exports[0].isStar; |
1801 | 1831 |
1802 accept(NodeVisitor visitor) => visitor.visitExportClause(this); | 1832 accept(NodeVisitor visitor) => visitor.visitExportClause(this); |
1803 void visitChildren(NodeVisitor visitor) { | 1833 void visitChildren(NodeVisitor visitor) { |
1804 for (NameSpecifier name in exports) name.accept(visitor); | 1834 for (NameSpecifier name in exports) name.accept(visitor); |
1805 if (from != null) from.accept(visitor); | 1835 if (from != null) from.accept(visitor); |
1806 } | 1836 } |
1807 ExportClause _clone() => new ExportClause(exports, from: from); | 1837 ExportClause _clone() => new ExportClause(exports, from: from); |
1808 } | 1838 } |
1809 | 1839 |
1810 /** An import or export specifier. */ | 1840 /** An import or export specifier. */ |
1811 class NameSpecifier extends Node { | 1841 class NameSpecifier extends Node { |
1812 // TODO(jmesserly): should we wrap this in a node of some sort? | 1842 final Identifier name; |
1813 final String name; | 1843 final Identifier asName; // Can be null. |
1814 final String asName; // Can be null. | |
1815 | 1844 |
1816 NameSpecifier(this.name, {this.asName}); | 1845 NameSpecifier(this.name, {this.asName}); |
| 1846 NameSpecifier.star() : this(null); |
| 1847 |
| 1848 /** True if this is a `* as someName` specifier. */ |
| 1849 bool get isStar => name == null; |
1817 | 1850 |
1818 accept(NodeVisitor visitor) => visitor.visitNameSpecifier(this); | 1851 accept(NodeVisitor visitor) => visitor.visitNameSpecifier(this); |
1819 void visitChildren(NodeVisitor visitor) {} | 1852 void visitChildren(NodeVisitor visitor) {} |
1820 NameSpecifier _clone() => new NameSpecifier(name, asName: asName); | 1853 NameSpecifier _clone() => new NameSpecifier(name, asName: asName); |
1821 } | 1854 } |
1822 | 1855 |
1823 // TODO(jmesserly): should this be related to [Program]? | 1856 // TODO(jmesserly): should this be related to [Program]? |
1824 class Module extends Node { | 1857 class Module extends Node { |
1825 /// The module's name | 1858 /// The module's name |
1826 // TODO(jmesserly): this is not declared in ES6, but is known by the loader. | 1859 // TODO(jmesserly): this is not declared in ES6, but is known by the loader. |
1827 // We use this because some ES5 desugarings require it. | 1860 // We use this because some ES5 desugarings require it. |
1828 final String name; | 1861 final String name; |
1829 | 1862 |
1830 final List<ModuleItem> body; | 1863 final List<ModuleItem> body; |
1831 Module(this.body, {this.name}); | 1864 Module(this.body, {this.name}); |
1832 | 1865 |
1833 accept(NodeVisitor visitor) => visitor.visitModule(this); | 1866 accept(NodeVisitor visitor) => visitor.visitModule(this); |
1834 void visitChildren(NodeVisitor visitor) { | 1867 void visitChildren(NodeVisitor visitor) { |
1835 for (ModuleItem item in body) item.accept(visitor); | 1868 for (ModuleItem item in body) item.accept(visitor); |
1836 } | 1869 } |
1837 Module _clone() => new Module(body); | 1870 Module _clone() => new Module(body); |
1838 } | 1871 } |
OLD | NEW |