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 final JsExpression emptyExpression; 022 023 private JsProgramFragment[] fragments; 024 025 private final TDoubleObjectHashMap<JsDoubleLiteral> doubleLiteralMap = new TDoubleObjectHashMap<JsDoubleLiteral>(); 026 private final TIntObjectHashMap<JsIntLiteral> intLiteralMap = new TIntObjectHashMap<JsIntLiteral>(); 027 028 private final JsRootScope rootScope; 029 private final Map<String, JsStringLiteral> stringLiteralMap = new THashMap<String, JsStringLiteral>(); 030 private final JsObjectScope topScope; 031 032 public JsProgram(String unitId) { 033 rootScope = new JsRootScope(this); 034 topScope = new JsObjectScope(rootScope, "Global", unitId); 035 setFragmentCount(1); 036 037 emptyExpression = new JsEmptyExpression(); 038 } 039 040 @NotNull 041 public JsExpression getEmptyExpression() { 042 return emptyExpression; 043 } 044 045 public JsBlock getFragmentBlock(int fragment) { 046 if (fragment < 0 || fragment >= fragments.length) { 047 throw new IllegalArgumentException("Invalid fragment: " + fragment); 048 } 049 return fragments[fragment].getGlobalBlock(); 050 } 051 052 public JsBlock getGlobalBlock() { 053 return getFragmentBlock(0); 054 } 055 056 public JsNumberLiteral getNumberLiteral(double value) { 057 JsDoubleLiteral literal = doubleLiteralMap.get(value); 058 if (literal == null) { 059 literal = new JsDoubleLiteral(value); 060 doubleLiteralMap.put(value, literal); 061 } 062 063 return literal; 064 } 065 066 public JsNumberLiteral getNumberLiteral(int value) { 067 JsIntLiteral literal = intLiteralMap.get(value); 068 if (literal == null) { 069 literal = new JsIntLiteral(value); 070 intLiteralMap.put(value, literal); 071 } 072 073 return literal; 074 } 075 076 /** 077 * Gets the quasi-mythical root scope. This is not the same as the top scope; 078 * all unresolvable identifiers wind up here, because they are considered 079 * external to the program. 080 */ 081 public JsRootScope getRootScope() { 082 return rootScope; 083 } 084 085 /** 086 * Gets the top level scope. This is the scope of all the statements in the 087 * main program. 088 */ 089 public JsObjectScope getScope() { 090 return topScope; 091 } 092 093 /** 094 * Creates or retrieves a JsStringLiteral from an interned object pool. 095 */ 096 @NotNull 097 public JsStringLiteral getStringLiteral(String value) { 098 JsStringLiteral literal = stringLiteralMap.get(value); 099 if (literal == null) { 100 literal = new JsStringLiteral(value); 101 stringLiteralMap.put(value, literal); 102 } 103 return literal; 104 } 105 106 public void setFragmentCount(int fragments) { 107 this.fragments = new JsProgramFragment[fragments]; 108 for (int i = 0; i < fragments; i++) { 109 this.fragments[i] = new JsProgramFragment(); 110 } 111 } 112 113 @Override 114 public void accept(JsVisitor v) { 115 v.visitProgram(this); 116 } 117 118 @Override 119 public void acceptChildren(JsVisitor visitor) { 120 for (JsProgramFragment fragment : fragments) { 121 visitor.accept(fragment); 122 } 123 } 124 125 @Override 126 public void traverse(JsVisitorWithContext v, JsContext ctx) { 127 if (v.visit(this, ctx)) { 128 for (JsProgramFragment fragment : fragments) { 129 v.accept(fragment); 130 } 131 } 132 v.endVisit(this, ctx); 133 } 134 135 @NotNull 136 @Override 137 public JsProgram deepCopy() { 138 throw new UnsupportedOperationException(); 139 } 140 }