001: /*
002: * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.es.parser;
030:
031: import com.caucho.es.ESException;
032: import com.caucho.es.ESId;
033: import com.caucho.es.wrapper.ESMethodDescriptor;
034:
035: import java.io.IOException;
036: import java.util.ArrayList;
037:
038: /**
039: * Represents a method call. Both Java calls and JavaScript calls are
040: * handled here.
041: */
042: class CallExpr extends Expr {
043: protected Expr term;
044: private Expr field;
045: private boolean isNew;
046: protected boolean isTop;
047: protected ArrayList args = new ArrayList();
048:
049: protected TypeExpr typeExpr;
050: protected boolean isCalculated;
051:
052: // The Java method if we can determine direct Java call.
053: protected ESMethodDescriptor method;
054:
055: CallExpr(Block block, Expr term, Expr field, boolean isNew)
056: throws ESException {
057: super (block);
058:
059: this .term = term;
060: this .field = field;
061: this .isNew = isNew;
062:
063: if (term != null)
064: term.setUsed();
065: if (field != null)
066: field.setUsed();
067:
068: if (term == null
069: || !(term.getTypeExpr() instanceof JavaTypeExpr))
070: block.function.setCall();
071: }
072:
073: void exprStatement(Function fun) throws ESException {
074: isTop = true;
075: noValue = true;
076:
077: fun.addExpr(this );
078: }
079:
080: /**
081: * Returns the javascript type for the expression
082: *
083: * @return a javascript type.
084: */
085: int getType() {
086: calculateType();
087:
088: return type;
089: }
090:
091: /**
092: * Returns the type expression of the call.
093: *
094: * @return a type expression.
095: */
096: Expr getTypeExpr() {
097: calculateType();
098:
099: return typeExpr;
100: }
101:
102: /**
103: * Calculate the return type of the expression.
104: */
105: private void calculateType() {
106: boolean isStatic = false;
107:
108: if (isCalculated)
109: return;
110:
111: isCalculated = true;
112:
113: Class javaClass = term.getJavaClass();
114: if (term instanceof JavaClassExpr) {
115: isStatic = true;
116: javaClass = ((JavaClassExpr) term).getJavaClass();
117: }
118:
119: if (javaClass == null || field == null
120: || !(field instanceof LiteralExpr)
121: || term.getType() != TYPE_JAVA && !isStatic) {
122: return;
123: }
124:
125: LiteralExpr lit = (LiteralExpr) field;
126: String name = lit.getLiteral().toString();
127:
128: method = JavaMethod.bestMethod(javaClass, name, isStatic, args);
129:
130: // exception if can't find method
131: if (method != null) {
132: Class returnType = method.getReturnType();
133:
134: if (returnType.equals(void.class))
135: type = TYPE_VOID;
136: else if (returnType.equals(int.class))
137: type = TYPE_INTEGER;
138: else if (returnType.equals(double.class))
139: type = TYPE_NUMBER;
140: else if (returnType.equals(boolean.class))
141: type = TYPE_BOOLEAN;
142: else {
143: type = TYPE_JAVA;
144: this .javaType = returnType;
145: }
146:
147: typeExpr = new JavaTypeExpr(block, returnType);
148: }
149: }
150:
151: void printBooleanImpl() throws IOException {
152: printJavaImpl();
153: }
154:
155: void printInt32Impl() throws IOException {
156: printJavaImpl();
157: }
158:
159: void printNumImpl() throws IOException {
160: printJavaImpl();
161: }
162:
163: /**
164: * Generates code for the call, producing a JavaScript result.
165: */
166: void printImpl() throws IOException {
167: if (term instanceof IdExpr && field == null
168: && !((IdExpr) term).isJavaLocal()) {
169: ESId id = ((IdExpr) term).getId();
170:
171: field = new LiteralExpr(block, id);
172: term = null;
173: }
174:
175: if (term != null) {
176: if (isNew)
177: cl.print("_call.doNew(");
178: else
179: cl.print("_call.call(");
180:
181: term.print();
182:
183: if (field != null) {
184: cl.print(", ");
185: field.printStr();
186: }
187: } else if (function.isGlobalScope() && withDepth == 0) {
188: if (isNew)
189: cl.print("_call.doNew(_env.global, ");
190: else
191: cl.print("_call.call(_env.global, ");
192:
193: field.printStr();
194: } else {
195: if (isNew)
196: cl.print("_call.newScope(");
197: else
198: cl.print("_call.callScope(");
199:
200: field.printStr();
201: }
202:
203: int argCount = function.cl.getCallDepth();
204:
205: cl.print(", " + argCount);
206:
207: for (int i = 0; i < args.size() && i < 3; i++) {
208: Expr expr = (Expr) args.get(i);
209: cl.print(", ");
210: function.cl.pushCall();
211: expr.print();
212: }
213: if (args.size() >= 3)
214: cl.print(", 3");
215: for (int i = 3; i < args.size(); i++) {
216: Expr expr = (Expr) args.get(i);
217: cl.print("+ _call.arg(" + (i + argCount) + ", ");
218: function.cl.pushCall();
219: expr.print();
220: cl.print(")");
221: }
222: function.cl.popCall(args.size());
223: cl.print(")");
224: if (isTop)
225: cl.println(";");
226: }
227:
228: void printStringImpl() throws IOException {
229: if (String.class.equals(getJavaClass()))
230: printJavaImpl();
231: else {
232: cl.print("String.valueOf(");
233: printJavaImpl();
234: cl.print(")");
235: }
236: }
237:
238: /**
239: * Generates code for the call, producing a Java result.
240: */
241: void printJavaImpl() throws IOException {
242: if (method.isStaticVirtual()) {
243: cl.print(method.getMethodClassName());
244: } else {
245: if (term instanceof JavaClassExpr)
246: cl.print(method.getMethodClassName());
247: else {
248: term.printJava();
249: }
250: }
251:
252: cl.print('.');
253: cl.print(method.getName());
254: cl.print("(");
255:
256: boolean isFirst = true;
257: if (method.isStaticVirtual()) {
258: cl.print("(");
259: printJavaClass(method.getDeclaringClass());
260: cl.print(")");
261: isFirst = false;
262: term.printJava();
263: }
264:
265: Class[] params = null;
266: if (method != null)
267: params = method.getParameterTypes();
268:
269: for (int i = 0; i < args.size(); i++) {
270: Expr expr = (Expr) args.get(i);
271:
272: if (!isFirst)
273: cl.print(", ");
274: isFirst = false;
275:
276: if (params == null)
277: expr.printJava();
278: else if (params[i].equals(String.class)) {
279: expr.printJavaString();
280: } else if (!params[i].isPrimitive()) {
281: cl.print("(");
282: printJavaClass(params[i]);
283: cl.print(")");
284:
285: expr.printJava();
286: } else if (params[i].equals(int.class))
287: expr.printInt32();
288: else if (params[i].equals(long.class))
289: expr.printInt64();
290: else if (params[i].equals(boolean.class))
291: expr.printBoolean();
292: else if (params[i].equals(double.class))
293: expr.printNum();
294: else
295: expr.printJava();
296: }
297: cl.print(")");
298: if (isTop)
299: cl.println(";");
300: }
301:
302: /**
303: * adds a new call parameter
304: */
305: void addCallParam(Expr param) {
306: param.setUsed();
307: args.add(param);
308: }
309: }
|