001 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 002 // for details. All rights reserved. Use of this source code is governed by a 003 // BSD-style license that can be found in the LICENSE file. 004 005 package com.google.dart.compiler.backend.js.ast; 006 007 import gnu.trove.TDoubleObjectHashMap; 008 import gnu.trove.THashMap; 009 import gnu.trove.TIntObjectHashMap; 010 import org.jetbrains.annotations.NotNull; 011 012 import java.util.Map; 013 014 import static com.google.dart.compiler.backend.js.ast.JsNumberLiteral.JsDoubleLiteral; 015 import static com.google.dart.compiler.backend.js.ast.JsNumberLiteral.JsIntLiteral; 016 017 /** 018 * A JavaScript program. 019 */ 020 public final class JsProgram extends SourceInfoAwareJsNode { 021 @NotNull 022 private final JsEmpty emptyStatement; 023 @NotNull final JsExpression emptyExpression; 024 025 private JsProgramFragment[] fragments; 026 027 private final TDoubleObjectHashMap<JsDoubleLiteral> doubleLiteralMap = new TDoubleObjectHashMap<JsDoubleLiteral>(); 028 private final TIntObjectHashMap<JsIntLiteral> intLiteralMap = new TIntObjectHashMap<JsIntLiteral>(); 029 030 private final JsRootScope rootScope; 031 private final Map<String, JsStringLiteral> stringLiteralMap = new THashMap<String, JsStringLiteral>(); 032 private final JsObjectScope topScope; 033 034 public JsProgram(String unitId) { 035 rootScope = new JsRootScope(this); 036 topScope = new JsObjectScope(rootScope, "Global", unitId); 037 setFragmentCount(1); 038 039 emptyStatement = new JsEmpty(); 040 emptyExpression = new JsEmptyExpression(); 041 } 042 043 @NotNull 044 public JsEmpty getEmptyStatement() { 045 return emptyStatement; 046 } 047 048 @NotNull 049 public JsExpression getEmptyExpression() { 050 return emptyExpression; 051 } 052 053 public JsBlock getFragmentBlock(int fragment) { 054 if (fragment < 0 || fragment >= fragments.length) { 055 throw new IllegalArgumentException("Invalid fragment: " + fragment); 056 } 057 return fragments[fragment].getGlobalBlock(); 058 } 059 060 public JsBlock getGlobalBlock() { 061 return getFragmentBlock(0); 062 } 063 064 public JsNumberLiteral getNumberLiteral(double value) { 065 JsDoubleLiteral literal = doubleLiteralMap.get(value); 066 if (literal == null) { 067 literal = new JsDoubleLiteral(value); 068 doubleLiteralMap.put(value, literal); 069 } 070 071 return literal; 072 } 073 074 public JsNumberLiteral getNumberLiteral(int value) { 075 JsIntLiteral literal = intLiteralMap.get(value); 076 if (literal == null) { 077 literal = new JsIntLiteral(value); 078 intLiteralMap.put(value, literal); 079 } 080 081 return literal; 082 } 083 084 /** 085 * Gets the quasi-mythical root scope. This is not the same as the top scope; 086 * all unresolvable identifiers wind up here, because they are considered 087 * external to the program. 088 */ 089 public JsRootScope getRootScope() { 090 return rootScope; 091 } 092 093 /** 094 * Gets the top level scope. This is the scope of all the statements in the 095 * main program. 096 */ 097 public JsObjectScope getScope() { 098 return topScope; 099 } 100 101 /** 102 * Creates or retrieves a JsStringLiteral from an interned object pool. 103 */ 104 @NotNull 105 public JsStringLiteral getStringLiteral(String value) { 106 JsStringLiteral literal = stringLiteralMap.get(value); 107 if (literal == null) { 108 literal = new JsStringLiteral(value); 109 stringLiteralMap.put(value, literal); 110 } 111 return literal; 112 } 113 114 public void setFragmentCount(int fragments) { 115 this.fragments = new JsProgramFragment[fragments]; 116 for (int i = 0; i < fragments; i++) { 117 this.fragments[i] = new JsProgramFragment(); 118 } 119 } 120 121 @Override 122 public void accept(JsVisitor v) { 123 v.visitProgram(this); 124 } 125 126 @Override 127 public void acceptChildren(JsVisitor visitor) { 128 for (JsProgramFragment fragment : fragments) { 129 visitor.accept(fragment); 130 } 131 } 132 133 @Override 134 public void traverse(JsVisitorWithContext v, JsContext ctx) { 135 if (v.visit(this, ctx)) { 136 for (JsProgramFragment fragment : fragments) { 137 v.accept(fragment); 138 } 139 } 140 v.endVisit(this, ctx); 141 } 142 143 @NotNull 144 @Override 145 public JsProgram deepCopy() { 146 throw new UnsupportedOperationException(); 147 } 148 }