From 78bb71f837ef2677e1ac541370dd19e6637741ec Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 8 Jan 2015 16:43:37 -0800 Subject: [PATCH] Optimizing forEachChild function to not create closures --- src/compiler/parser.ts | 307 +++++++++++++++++++++-------------------- 1 file changed, 156 insertions(+), 151 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 00cd54b94eb..87f4c20c97d 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -12,43 +12,48 @@ module ts { return new (getNodeConstructor(kind))(); } + function child(cbNode: (node: Node) => T, node: Node): T { + return node ? cbNode(node) : void 0; + } + + function children1(cbNodes: (nodes: Node[]) => T, nodes: Node[]) { + return nodes ? cbNodes(nodes) : void 0; + } + + function children2(cbNode: (node: Node) => T, nodes: Node[]) { + if (nodes) { + for (var i = 0, len = nodes.length; i < len; i++) { + var result = cbNode(nodes[i]) + if (result) { + return result; + } + } + } + } + // Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes // stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, // embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns // a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. export function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodes?: (nodes: Node[]) => T): T { - function child(node: Node): T { - if (node) { - return cbNode(node); - } - } - function children(nodes: Node[]) { - if (nodes) { - if (cbNodes) { - return cbNodes(nodes); - } - - for (var i = 0, len = nodes.length; i < len; i++) { - var result = cbNode(nodes[i]) - if (result) { - return result; - } - } - - return undefined; - } - } if (!node) { return; } + if (cbNodes) { + var children = children1; + } + else { + cbNodes = cbNode; + children = children2; + } switch (node.kind) { case SyntaxKind.QualifiedName: - return child((node).left) || - child((node).right); + return child(cbNode, (node).left) || + child(cbNode, (node).right); case SyntaxKind.TypeParameter: - return child((node).name) || - child((node).constraint) || - child((node).expression); + return child(cbNode, (node).name) || + child(cbNode, (node).constraint) || + child(cbNode, (node).expression); case SyntaxKind.Parameter: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: @@ -56,22 +61,22 @@ module ts { case SyntaxKind.ShorthandPropertyAssignment: case SyntaxKind.VariableDeclaration: case SyntaxKind.BindingElement: - return children(node.modifiers) || - child((node).propertyName) || - child((node).dotDotDotToken) || - child((node).name) || - child((node).questionToken) || - child((node).type) || - child((node).initializer); + return children(cbNodes, node.modifiers) || + child(cbNode, (node).propertyName) || + child(cbNode, (node).dotDotDotToken) || + child(cbNode, (node).name) || + child(cbNode, (node).questionToken) || + child(cbNode, (node).type) || + child(cbNode, (node).initializer); case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: case SyntaxKind.CallSignature: case SyntaxKind.ConstructSignature: case SyntaxKind.IndexSignature: - return children(node.modifiers) || - children((node).typeParameters) || - children((node).parameters) || - child((node).type); + return children(cbNodes, node.modifiers) || + children(cbNodes, (node).typeParameters) || + children(cbNodes, (node).parameters) || + child(cbNode, (node).type); case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: case SyntaxKind.Constructor: @@ -80,182 +85,182 @@ module ts { case SyntaxKind.FunctionExpression: case SyntaxKind.FunctionDeclaration: case SyntaxKind.ArrowFunction: - return children(node.modifiers) || - child((node).asteriskToken) || - child((node).name) || - child((node).questionToken) || - children((node).typeParameters) || - children((node).parameters) || - child((node).type) || - child((node).body); + return children(cbNodes, node.modifiers) || + child(cbNode, (node).asteriskToken) || + child(cbNode, (node).name) || + child(cbNode, (node).questionToken) || + children(cbNodes, (node).typeParameters) || + children(cbNodes, (node).parameters) || + child(cbNode, (node).type) || + child(cbNode, (node).body); case SyntaxKind.TypeReference: - return child((node).typeName) || - children((node).typeArguments); + return child(cbNode, (node).typeName) || + children(cbNodes, (node).typeArguments); case SyntaxKind.TypeQuery: - return child((node).exprName); + return child(cbNode, (node).exprName); case SyntaxKind.TypeLiteral: - return children((node).members); + return children(cbNodes, (node).members); case SyntaxKind.ArrayType: - return child((node).elementType); + return child(cbNode, (node).elementType); case SyntaxKind.TupleType: - return children((node).elementTypes); + return children(cbNodes, (node).elementTypes); case SyntaxKind.UnionType: - return children((node).types); + return children(cbNodes, (node).types); case SyntaxKind.ParenthesizedType: - return child((node).type); + return child(cbNode, (node).type); case SyntaxKind.ObjectBindingPattern: case SyntaxKind.ArrayBindingPattern: - return children((node).elements); + return children(cbNodes, (node).elements); case SyntaxKind.ArrayLiteralExpression: - return children((node).elements); + return children(cbNodes, (node).elements); case SyntaxKind.ObjectLiteralExpression: - return children((node).properties); + return children(cbNodes, (node).properties); case SyntaxKind.PropertyAccessExpression: - return child((node).expression) || - child((node).name); + return child(cbNode, (node).expression) || + child(cbNode, (node).name); case SyntaxKind.ElementAccessExpression: - return child((node).expression) || - child((node).argumentExpression); + return child(cbNode, (node).expression) || + child(cbNode, (node).argumentExpression); case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: - return child((node).expression) || - children((node).typeArguments) || - children((node).arguments); + return child(cbNode, (node).expression) || + children(cbNodes, (node).typeArguments) || + children(cbNodes, (node).arguments); case SyntaxKind.TaggedTemplateExpression: - return child((node).tag) || - child((node).template); + return child(cbNode, (node).tag) || + child(cbNode, (node).template); case SyntaxKind.TypeAssertionExpression: - return child((node).type) || - child((node).expression); + return child(cbNode, (node).type) || + child(cbNode, (node).expression); case SyntaxKind.ParenthesizedExpression: - return child((node).expression); + return child(cbNode, (node).expression); case SyntaxKind.DeleteExpression: - return child((node).expression); + return child(cbNode, (node).expression); case SyntaxKind.TypeOfExpression: - return child((node).expression); + return child(cbNode, (node).expression); case SyntaxKind.VoidExpression: - return child((node).expression); + return child(cbNode, (node).expression); case SyntaxKind.PrefixUnaryExpression: - return child((node).operand); + return child(cbNode, (node).operand); case SyntaxKind.YieldExpression: - return child((node).asteriskToken) || - child((node).expression); + return child(cbNode, (node).asteriskToken) || + child(cbNode, (node).expression); case SyntaxKind.PostfixUnaryExpression: - return child((node).operand); + return child(cbNode, (node).operand); case SyntaxKind.BinaryExpression: - return child((node).left) || - child((node).right); + return child(cbNode, (node).left) || + child(cbNode, (node).right); case SyntaxKind.ConditionalExpression: - return child((node).condition) || - child((node).whenTrue) || - child((node).whenFalse); + return child(cbNode, (node).condition) || + child(cbNode, (node).whenTrue) || + child(cbNode, (node).whenFalse); case SyntaxKind.SpreadElementExpression: - return child((node).expression); + return child(cbNode, (node).expression); case SyntaxKind.Block: case SyntaxKind.ModuleBlock: - return children((node).statements); + return children(cbNodes, (node).statements); case SyntaxKind.SourceFile: - return children((node).statements) || - child((node).endOfFileToken); + return children(cbNodes, (node).statements) || + child(cbNode, (node).endOfFileToken); case SyntaxKind.VariableStatement: - return children(node.modifiers) || - child((node).declarationList); + return children(cbNodes, node.modifiers) || + child(cbNode, (node).declarationList); case SyntaxKind.VariableDeclarationList: - return children((node).declarations); + return children(cbNodes, (node).declarations); case SyntaxKind.ExpressionStatement: - return child((node).expression); + return child(cbNode, (node).expression); case SyntaxKind.IfStatement: - return child((node).expression) || - child((node).thenStatement) || - child((node).elseStatement); + return child(cbNode, (node).expression) || + child(cbNode, (node).thenStatement) || + child(cbNode, (node).elseStatement); case SyntaxKind.DoStatement: - return child((node).statement) || - child((node).expression); + return child(cbNode, (node).statement) || + child(cbNode, (node).expression); case SyntaxKind.WhileStatement: - return child((node).expression) || - child((node).statement); + return child(cbNode, (node).expression) || + child(cbNode, (node).statement); case SyntaxKind.ForStatement: - return child((node).initializer) || - child((node).condition) || - child((node).iterator) || - child((node).statement); + return child(cbNode, (node).initializer) || + child(cbNode, (node).condition) || + child(cbNode, (node).iterator) || + child(cbNode, (node).statement); case SyntaxKind.ForInStatement: - return child((node).initializer) || - child((node).expression) || - child((node).statement); + return child(cbNode, (node).initializer) || + child(cbNode, (node).expression) || + child(cbNode, (node).statement); case SyntaxKind.ContinueStatement: case SyntaxKind.BreakStatement: - return child((node).label); + return child(cbNode, (node).label); case SyntaxKind.ReturnStatement: - return child((node).expression); + return child(cbNode, (node).expression); case SyntaxKind.WithStatement: - return child((node).expression) || - child((node).statement); + return child(cbNode, (node).expression) || + child(cbNode, (node).statement); case SyntaxKind.SwitchStatement: - return child((node).expression) || - children((node).clauses); + return child(cbNode, (node).expression) || + children(cbNodes, (node).clauses); case SyntaxKind.CaseClause: - return child((node).expression) || - children((node).statements); + return child(cbNode, (node).expression) || + children(cbNodes, (node).statements); case SyntaxKind.DefaultClause: - return children((node).statements); + return children(cbNodes, (node).statements); case SyntaxKind.LabeledStatement: - return child((node).label) || - child((node).statement); + return child(cbNode, (node).label) || + child(cbNode, (node).statement); case SyntaxKind.ThrowStatement: - return child((node).expression); + return child(cbNode, (node).expression); case SyntaxKind.TryStatement: - return child((node).tryBlock) || - child((node).catchClause) || - child((node).finallyBlock); + return child(cbNode, (node).tryBlock) || + child(cbNode, (node).catchClause) || + child(cbNode, (node).finallyBlock); case SyntaxKind.CatchClause: - return child((node).name) || - child((node).type) || - child((node).block); + return child(cbNode, (node).name) || + child(cbNode, (node).type) || + child(cbNode, (node).block); case SyntaxKind.ClassDeclaration: - return children(node.modifiers) || - child((node).name) || - children((node).typeParameters) || - children((node).heritageClauses) || - children((node).members); + return children(cbNodes, node.modifiers) || + child(cbNode, (node).name) || + children(cbNodes, (node).typeParameters) || + children(cbNodes, (node).heritageClauses) || + children(cbNodes, (node).members); case SyntaxKind.InterfaceDeclaration: - return children(node.modifiers) || - child((node).name) || - children((node).typeParameters) || - children((node).heritageClauses) || - children((node).members); + return children(cbNodes, node.modifiers) || + child(cbNode, (node).name) || + children(cbNodes, (node).typeParameters) || + children(cbNodes, (node).heritageClauses) || + children(cbNodes, (node).members); case SyntaxKind.TypeAliasDeclaration: - return children(node.modifiers) || - child((node).name) || - child((node).type); + return children(cbNodes, node.modifiers) || + child(cbNode, (node).name) || + child(cbNode, (node).type); case SyntaxKind.EnumDeclaration: - return children(node.modifiers) || - child((node).name) || - children((node).members); + return children(cbNodes, node.modifiers) || + child(cbNode, (node).name) || + children(cbNodes, (node).members); case SyntaxKind.EnumMember: - return child((node).name) || - child((node).initializer); + return child(cbNode, (node).name) || + child(cbNode, (node).initializer); case SyntaxKind.ModuleDeclaration: - return children(node.modifiers) || - child((node).name) || - child((node).body); + return children(cbNodes, node.modifiers) || + child(cbNode, (node).name) || + child(cbNode, (node).body); case SyntaxKind.ImportDeclaration: - return children(node.modifiers) || - child((node).name) || - child((node).moduleReference); + return children(cbNodes, node.modifiers) || + child(cbNode, (node).name) || + child(cbNode, (node).moduleReference); case SyntaxKind.ExportAssignment: - return children(node.modifiers) || - child((node).exportName); + return children(cbNodes, node.modifiers) || + child(cbNode, (node).exportName); case SyntaxKind.TemplateExpression: - return child((node).head) || children((node).templateSpans); + return child(cbNode, (node).head) || children(cbNodes, (node).templateSpans); case SyntaxKind.TemplateSpan: - return child((node).expression) || child((node).literal); + return child(cbNode, (node).expression) || child(cbNode, (node).literal); case SyntaxKind.ComputedPropertyName: - return child((node).expression); + return child(cbNode, (node).expression); case SyntaxKind.HeritageClause: - return children((node).types); + return children(cbNodes, (node).types); case SyntaxKind.ExternalModuleReference: - return child((node).expression); + return child(cbNode, (node).expression); } }