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 }