001 /*
002 $Id: Expression.java,v 1.4 2005/02/01 10:46:54 russel Exp $
003
004 Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
005
006 Redistribution and use of this software and associated documentation
007 ("Software"), with or without modification, are permitted provided
008 that the following conditions are met:
009
010 1. Redistributions of source code must retain copyright
011 statements and notices. Redistributions must also contain a
012 copy of this document.
013
014 2. Redistributions in binary form must reproduce the
015 above copyright notice, this list of conditions and the
016 following disclaimer in the documentation and/or other
017 materials provided with the distribution.
018
019 3. The name "groovy" must not be used to endorse or promote
020 products derived from this Software without prior written
021 permission of The Codehaus. For written permission,
022 please contact info@codehaus.org.
023
024 4. Products derived from this Software may not be called "groovy"
025 nor may "groovy" appear in their names without prior written
026 permission of The Codehaus. "groovy" is a registered
027 trademark of The Codehaus.
028
029 5. Due credit should be given to The Codehaus -
030 http://groovy.codehaus.org/
031
032 THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
033 ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
034 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
035 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
036 THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
037 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
038 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
039 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
040 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
041 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
042 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
043 OF THE POSSIBILITY OF SUCH DAMAGE.
044
045 */
046 package org.codehaus.groovy.ast.expr;
047
048 import java.util.ArrayList;
049 import java.util.Iterator;
050 import java.util.List;
051
052 import org.codehaus.groovy.ast.ASTNode;
053 import org.codehaus.groovy.classgen.AsmClassGenerator;
054 import groovy.lang.GroovyRuntimeException;
055
056 /**
057 * Represents a base class for expressions which evaluate as an object
058 *
059 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
060 * @version $Revision: 1.4 $
061 */
062 public abstract class Expression extends ASTNode {
063 protected boolean typeResolved = false;
064
065 public boolean isResolveFailed() {
066 return resolveFailed;
067 }
068
069 public void setResolveFailed(boolean resolveFailed) {
070 this.resolveFailed = resolveFailed;
071 }
072
073 public String getFailure() {
074 return failure;
075 }
076
077 public void setFailure(String failure) {
078 this.failure = failure;
079 }
080
081 String failure = "";
082 private boolean resolveFailed = false;
083
084 public Class getTypeClass() {
085 return typeClass;
086 }
087
088 public void setTypeClass(Class typeClass) {
089 if (typeClass != null) {
090 this.typeClass = typeClass;
091 type = typeClass.getName();
092 setTypeResolved(true);
093 }
094 }
095
096 public Class typeClass = null;
097
098 public String getType() {
099 if (type != null){
100 return type;
101 } else {
102 Class cls = getTypeClass();
103 return cls != null? cls.getName() : null;//"java.lang.Object";
104 }
105 }
106
107 /**
108 * true if the datatype can be changed, false otherwise.
109 * @return
110 */
111 public boolean isDynamic() {
112 return true;
113 }
114
115 protected String type = null;
116 /**
117 * Return a copy of the expression calling the transformer on any nested expressions
118 * @param transformer
119 * @return
120 */
121 public abstract Expression transformExpression(ExpressionTransformer transformer);
122
123 /**
124 * Transforms the list of expressions
125 * @return a new list of transformed expressions
126 */
127 protected List transformExpressions(List expressions, ExpressionTransformer transformer) {
128 List list = new ArrayList(expressions.size());
129 for (Iterator iter = expressions.iterator(); iter.hasNext(); ) {
130 list.add(transformer.transform((Expression) iter.next()));
131 }
132 return list;
133 }
134
135 public void setType(String name) {
136 if (name == null)
137 throw new GroovyRuntimeException("cannot set null on type");
138 // handle primitives first
139 if (name.equals("int")) {
140 setTypeClass(Integer.TYPE);
141 return;
142 }
143 else if (name.equals("long")) {
144 setTypeClass(Long.TYPE);
145 return;
146 }
147 else if (name.equals("short")) {
148 setTypeClass(Short.TYPE);
149 return;
150 }
151 else if (name.equals("float")) {
152 setTypeClass(Float.TYPE);
153 return;
154 }
155 else if (name.equals("double")) {
156 setTypeClass(Double.TYPE);
157 return;
158 }
159 else if (name.equals("byte")) {
160 setTypeClass(Byte.TYPE);
161 return;
162 }
163 else if (name.equals("char")) {
164 setTypeClass(Character.TYPE);
165 return;
166 }
167 else if (name.equals("boolean")) {
168 setTypeClass(Boolean.TYPE);
169 return;
170 }
171
172 if (name.endsWith("[]")) {
173 String prefix = "[";
174 name = name.substring(0, name.length() - 2);
175
176 if (name.equals("int")) {
177 type = prefix + "I";
178 }
179 else if (name.equals("long")) {
180 type = prefix + "J";
181 }
182 else if (name.equals("short")) {
183 type = prefix + "S";
184 }
185 else if (name.equals("float")) {
186 type = prefix + "F";
187 }
188 else if (name.equals("double")) {
189 type = prefix + "D";
190 }
191 else if (name.equals("byte")) {
192 type = prefix + "B";
193 }
194 else if (name.equals("char")) {
195 type = prefix + "C";
196 }
197 else if (name.equals("boolean")) {
198 type = prefix + "Z";
199 } else {
200 type = prefix + "L" + name + ";";
201 }
202 }
203 else {
204 type = name;
205 }
206 if (type == null) {
207 System.out.println("Expression.setType(): null");
208 System.out.println("name = " + name);
209 }
210 try {
211 this.setTypeClass(Class.forName(type, false, this.getClass().getClassLoader()));
212 } catch (Throwable e) {
213 this.typeResolved = false;
214 }
215 }
216
217 public boolean isTypeResolved() {
218 return typeResolved;
219 }
220
221 public void setTypeResolved(boolean b) {
222 this.typeResolved = b;
223 this.resolveFailed = false;
224 }
225
226 public void resolve(AsmClassGenerator cg) {
227 if (shouldContinue()) {
228 resolveType(cg);
229 }
230 }
231
232 protected abstract void resolveType(AsmClassGenerator resolver);
233
234 protected boolean shouldContinue() {
235 return !isResolveFailed() && !isTypeResolved();
236 }
237
238 }