001: /*
002: * Copyright (c) 1998-2008 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: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.quercus.program;
031:
032: import com.caucho.quercus.Location;
033: import com.caucho.quercus.env.Env;
034: import com.caucho.quercus.env.ObjectValue;
035: import com.caucho.quercus.env.QuercusClass;
036: import com.caucho.quercus.env.Value;
037: import com.caucho.quercus.expr.Expr;
038: import com.caucho.util.L10N;
039:
040: /**
041: * Represents a function
042: */
043: abstract public class AbstractFunction {
044: private static final L10N L = new L10N(AbstractFunction.class);
045:
046: private static final Arg[] NULL_ARGS = new Arg[0];
047: private static final Value[] NULL_ARG_VALUES = new Value[0];
048:
049: private final Location _location;
050:
051: private boolean _isGlobal = true;
052: private boolean _isFinal = false;
053:
054: protected Visibility _visibility = Visibility.PUBLIC;
055: protected String _declaringClassName;
056:
057: public AbstractFunction() {
058: // XXX:
059: _location = Location.UNKNOWN;
060: }
061:
062: public AbstractFunction(Location location) {
063: _location = location;
064: }
065:
066: public String getName() {
067: return "unknown";
068: }
069:
070: /*
071: * Returns the name of the implementing class.
072: */
073: public String getDeclaringClassName() {
074: return _declaringClassName;
075: }
076:
077: public void setDeclaringClassName(String name) {
078: _declaringClassName = name;
079: }
080:
081: /*
082: * Returns the implementing class.
083: */
084: public ClassDef getDeclaringClass() {
085: return null;
086: }
087:
088: /**
089: * Returns true for a global function.
090: */
091: public final boolean isGlobal() {
092: return _isGlobal;
093: }
094:
095: /**
096: * Returns true for an abstract function.
097: */
098: public boolean isAbstract() {
099: return false;
100: }
101:
102: /*
103: * Returns true for a static function.
104: */
105: public boolean isStatic() {
106: return false;
107: }
108:
109: /*
110: * Returns true for a final function.
111: */
112: public final boolean isFinal() {
113: return _isFinal;
114: }
115:
116: public final void setFinal(boolean isFinal) {
117: _isFinal = isFinal;
118: }
119:
120: /*
121: * Returns true for a protected function.
122: */
123: public final boolean isPublic() {
124: return _visibility == Visibility.PUBLIC;
125: }
126:
127: /*
128: * Returns true for a protected function.
129: */
130: public final boolean isProtected() {
131: return _visibility == Visibility.PROTECTED;
132: }
133:
134: /*
135: * Returns true for a private function.
136: */
137: public final boolean isPrivate() {
138: return _visibility == Visibility.PRIVATE;
139: }
140:
141: public final void setVisibility(Visibility v) {
142: _visibility = v;
143: }
144:
145: public final Location getLocation() {
146: return _location;
147: }
148:
149: /**
150: * Returns true for a global function.
151: */
152: public final void setGlobal(boolean isGlobal) {
153: _isGlobal = isGlobal;
154: }
155:
156: /**
157: * Returns true for a boolean function.
158: */
159: public boolean isBoolean() {
160: return false;
161: }
162:
163: /**
164: * Returns true for a string function.
165: */
166: public boolean isString() {
167: return false;
168: }
169:
170: /**
171: * Returns true for a long function.
172: */
173: public boolean isLong() {
174: return false;
175: }
176:
177: /**
178: * Returns true for a double function.
179: */
180: public boolean isDouble() {
181: return false;
182: }
183:
184: /**
185: * Returns true if the function uses variable args.
186: */
187: public boolean isCallUsesVariableArgs() {
188: return false;
189: }
190:
191: /**
192: * Returns true if the function uses/modifies the local symbol table
193: */
194: public boolean isCallUsesSymbolTable() {
195: return false;
196: }
197:
198: /**
199: * True for a returns reference.
200: */
201: public boolean isReturnsReference() {
202: return true;
203: }
204:
205: /**
206: * Returns the args.
207: */
208: public Arg[] getArgs() {
209: return NULL_ARGS;
210: }
211:
212: /**
213: * Binds the user's arguments to the actual arguments.
214: *
215: * @param args the user's arguments
216: * @return the user arguments augmented by any defaults
217: */
218: public Value[] evalArguments(Env env, Expr fun, Expr[] args) {
219: Value[] values = new Value[args.length];
220:
221: for (int i = 0; i < args.length; i++)
222: values[i] = args[i].evalArg(env);
223:
224: return values;
225: }
226:
227: /**
228: * Evaluates the function.
229: */
230: abstract public Value call(Env env, Value[] args);
231:
232: /**
233: * Evaluates the function, returning a reference.
234: */
235: public Value callRef(Env env, Value[] args) {
236: return call(env, args);
237: }
238:
239: /**
240: * Evaluates the function, returning a copy
241: */
242: public Value callCopy(Env env, Value[] args) {
243: return call(env, args).copyReturn();
244: }
245:
246: /**
247: * Evaluates the function as a method call.
248: */
249: public Value callMethod(Env env, Value obj, Value[] args) {
250: Value oldThis = env.getThis();
251:
252: try {
253: if (obj != null) {
254: env.setThis(obj);
255:
256: /*
257: if (isPublic()) {
258: }
259: else if (isProtected()) {
260: if (oldThis != null
261: && oldThis.isA(getDeclaringClassName())) {
262: }
263: else {
264: errorProtectedAccess(env, oldThis);
265: }
266: }
267: else {
268: //private
269:
270: if (oldThis != null
271: && getDeclaringClassName().equals(oldThis.getClassName())) {
272: }
273: else {
274: errorPrivateAccess(env, oldThis);
275: }
276: }
277: */
278: }
279:
280: return call(env, args);
281: } finally {
282: env.setThis(oldThis);
283: }
284: }
285:
286: protected Value errorProtectedAccess(Env env, Value oldThis) {
287: return env
288: .error(L
289: .l(
290: "Cannot call protected method {0}::{1}() from '{2}' context",
291: getDeclaringClassName(), getName(),
292: oldThis != null ? oldThis
293: .getClassName() : null));
294: }
295:
296: protected Value errorPrivateAccess(Env env, Value oldThis) {
297: return env
298: .error(L
299: .l(
300: "Cannot call private method {0}::{1}() from '{2}' context",
301: getDeclaringClassName(), getName(),
302: oldThis != null ? oldThis
303: .getClassName() : null));
304: }
305:
306: /**
307: * Evaluates the function as a method call, returning a reference.
308: */
309: public Value callMethodRef(Env env, Value obj, Value[] args) {
310: Value oldThis = env.getThis();
311:
312: try {
313: env.setThis(obj);
314:
315: return callRef(env, args);
316: } finally {
317: env.setThis(oldThis);
318: }
319: }
320:
321: /**
322: * Evaluates the function.
323: */
324: public Value call(Env env) {
325: return call(env, NULL_ARG_VALUES);
326: }
327:
328: /**
329: * Evaluates the function with an argument .
330: */
331: public Value call(Env env, Value a1) {
332: return call(env, new Value[] { a1 });
333: }
334:
335: /**
336: * Evaluates the function with arguments
337: */
338: public Value call(Env env, Value a1, Value a2) {
339: return call(env, new Value[] { a1, a2 });
340: }
341:
342: /**
343: * Evaluates the function with arguments
344: */
345: public Value call(Env env, Value a1, Value a2, Value a3) {
346: return call(env, new Value[] { a1, a2, a3 });
347: }
348:
349: /**
350: * Evaluates the function with arguments
351: */
352: public Value call(Env env, Value a1, Value a2, Value a3, Value a4) {
353: return call(env, new Value[] { a1, a2, a3, a4 });
354: }
355:
356: /**
357: * Evaluates the function with arguments
358: */
359: public Value call(Env env, Value a1, Value a2, Value a3, Value a4,
360: Value a5) {
361: return call(env, new Value[] { a1, a2, a3, a4, a5 });
362: }
363:
364: /**
365: * Evaluates the function.
366: */
367: public Value call(Env env, Expr[] exprs) {
368: Value[] argValues = new Value[exprs.length];
369: Arg[] args = getArgs();
370:
371: for (int i = 0; i < exprs.length; i++) {
372: // quercus/0d19
373: if (i < args.length && args[i].isReference())
374: argValues[i] = exprs[i].evalArg(env);
375: else
376: argValues[i] = exprs[i].eval(env);
377: }
378:
379: return call(env, argValues);
380: }
381:
382: /**
383: * Evaluates the function.
384: */
385: public Value callCopy(Env env, Expr[] exprs) {
386: return call(env, exprs).copy();
387: }
388:
389: /**
390: * Evaluates the function.
391: */
392: public Value callRef(Env env) {
393: return callRef(env, NULL_ARG_VALUES);
394: }
395:
396: /**
397: * Evaluates the function with an argument .
398: */
399: public Value callRef(Env env, Value a1) {
400: return callRef(env, new Value[] { a1 });
401: }
402:
403: /**
404: * Evaluates the function with arguments
405: */
406: public Value callRef(Env env, Value a1, Value a2) {
407: return callRef(env, new Value[] { a1, a2 });
408: }
409:
410: /**
411: * Evaluates the function with arguments
412: */
413: public Value callRef(Env env, Value a1, Value a2, Value a3) {
414: return callRef(env, new Value[] { a1, a2, a3 });
415: }
416:
417: /**
418: * Evaluates the function with arguments
419: */
420: public Value callRef(Env env, Value a1, Value a2, Value a3, Value a4) {
421: return callRef(env, new Value[] { a1, a2, a3, a4 });
422: }
423:
424: /**
425: * Evaluates the function with arguments
426: */
427: public Value callRef(Env env, Value a1, Value a2, Value a3,
428: Value a4, Value a5) {
429: return callRef(env, new Value[] { a1, a2, a3, a4, a5 });
430: }
431:
432: /**
433: * Evaluates the function.
434: */
435: public Value callRef(Env env, Expr[] exprs) {
436: Value[] argValues = new Value[exprs.length];
437: Arg[] args = getArgs();
438:
439: for (int i = 0; i < exprs.length; i++) {
440: // quercus/0d19
441: if (i < args.length && args[i].isReference())
442: argValues[i] = exprs[i].evalArg(env);
443: else
444: argValues[i] = exprs[i].eval(env);
445: }
446:
447: return callRef(env, argValues);
448: }
449:
450: /**
451: * Evaluates the function as a method call.
452: */
453: public Value callMethod(Env env, Value obj) {
454: return callMethod(env, obj, NULL_ARG_VALUES);
455: }
456:
457: /**
458: * Evaluates the function as a method call.
459: */
460: public Value callMethod(Env env, Value obj, Value a1) {
461: return callMethod(env, obj, new Value[] { a1 });
462: }
463:
464: /**
465: * Evaluates the function as a method call.
466: */
467: public Value callMethod(Env env, Value obj, Value a1, Value a2) {
468: return callMethod(env, obj, new Value[] { a1, a2 });
469: }
470:
471: /**
472: * Evaluates the function as a method call.
473: */
474: public Value callMethod(Env env, Value obj, Value a1, Value a2,
475: Value a3) {
476: return callMethod(env, obj, new Value[] { a1, a2, a3 });
477: }
478:
479: /**
480: * Evaluates the function as a method call.
481: */
482: public Value callMethod(Env env, Value obj, Value a1, Value a2,
483: Value a3, Value a4) {
484: return callMethod(env, obj, new Value[] { a1, a2, a3, a4 });
485: }
486:
487: /**
488: * Evaluates the function as a method call.
489: */
490: public Value callMethod(Env env, Value obj, Value a1, Value a2,
491: Value a3, Value a4, Value a5) {
492: return callMethod(env, obj, new Value[] { a1, a2, a3, a4, a5 });
493: }
494:
495: /**
496: * Evaluates the function.
497: */
498: public Value callMethod(Env env, Value obj, Expr[] exprs) {
499: Value[] argValues = new Value[exprs.length];
500: Arg[] args = getArgs();
501:
502: for (int i = 0; i < exprs.length; i++) {
503: if (i < args.length && args[i].isReference()) {
504: argValues[i] = exprs[i].evalArg(env);
505: } else
506: argValues[i] = exprs[i].eval(env);
507: }
508:
509: return callMethod(env, obj, argValues);
510: }
511:
512: /**
513: * Evaluates the function as a method call.
514: */
515: public Value callMethodRef(Env env, Value obj) {
516: return callMethodRef(env, obj, NULL_ARG_VALUES);
517: }
518:
519: /**
520: * Evaluates the function as a method call.
521: */
522: public Value callMethodRef(Env env, Value obj, Value a1) {
523: return callMethodRef(env, obj, new Value[] { a1 });
524: }
525:
526: /**
527: * Evaluates the function as a method call.
528: */
529: public Value callMethodRef(Env env, Value obj, Value a1, Value a2) {
530: return callMethodRef(env, obj, new Value[] { a1, a2 });
531: }
532:
533: /**
534: * Evaluates the function as a method call.
535: */
536: public Value callMethodRef(Env env, Value obj, Value a1, Value a2,
537: Value a3) {
538: return callMethodRef(env, obj, new Value[] { a1, a2, a3 });
539: }
540:
541: /**
542: * Evaluates the function as a method call.
543: */
544: public Value callMethodRef(Env env, Value obj, Value a1, Value a2,
545: Value a3, Value a4) {
546: return callMethodRef(env, obj, new Value[] { a1, a2, a3, a4 });
547: }
548:
549: /**
550: * Evaluates the function as a method call.
551: */
552: public Value callMethodRef(Env env, Value obj, Value a1, Value a2,
553: Value a3, Value a4, Value a5) {
554: return callMethodRef(env, obj,
555: new Value[] { a1, a2, a3, a4, a5 });
556: }
557:
558: /**
559: * Evaluates the function.
560: */
561: public Value callMethodRef(Env env, Value obj, Expr[] exprs) {
562: Value[] argValues = new Value[exprs.length];
563: Arg[] args = getArgs();
564:
565: for (int i = 0; i < exprs.length; i++) {
566: if (i < args.length && args[i].isReference())
567: argValues[i] = exprs[i].evalArg(env);
568: else
569: argValues[i] = exprs[i].eval(env);
570: }
571:
572: return callMethodRef(env, obj, argValues);
573: }
574: }
|