0001: /*
0002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
0003: *
0004: * This file is part of Resin(R) Open Source
0005: *
0006: * Each copy or derived work must preserve the copyright notice and this
0007: * notice unmodified.
0008: *
0009: * Resin Open Source is free software; you can redistribute it and/or modify
0010: * it under the terms of the GNU General Public License as published by
0011: * the Free Software Foundation; either version 2 of the License, or
0012: * (at your option) any later version.
0013: *
0014: * Resin Open Source is distributed in the hope that it will be useful,
0015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0017: * of NON-INFRINGEMENT. See the GNU General Public License for more
0018: * details.
0019: *
0020: * You should have received a copy of the GNU General Public License
0021: * along with Resin Open Source; if not, write to the
0022: *
0023: * Free Software Foundation, Inc.
0024: * 59 Temple Place, Suite 330
0025: * Boston, MA 02111-1307 USA
0026: *
0027: * @author Scott Ferguson
0028: */
0029:
0030: package com.caucho.quercus.env;
0031:
0032: import com.caucho.quercus.Location;
0033: import com.caucho.quercus.QuercusException;
0034: import com.caucho.quercus.QuercusRuntimeException;
0035: import com.caucho.quercus.expr.Expr;
0036: import com.caucho.quercus.program.AbstractFunction;
0037: import com.caucho.util.L10N;
0038: import com.caucho.vfs.WriteStream;
0039:
0040: import java.io.IOException;
0041: import java.io.InputStream;
0042: import java.io.PrintWriter;
0043: import java.math.BigDecimal;
0044: import java.math.BigInteger;
0045: import java.net.MalformedURLException;
0046: import java.net.URL;
0047: import java.util.*;
0048:
0049: /**
0050: * Represents a PHP expression value.
0051: */
0052: abstract public class Value implements java.io.Serializable {
0053: protected static final L10N L = new L10N(Value.class);
0054:
0055: public static final StringValue SCALAR_V = new StringBuilderValue(
0056: "scalar");
0057:
0058: public static final Value[] NULL_VALUE_ARRAY = new Value[0];
0059: public static final Value[] NULL_ARGS = new Value[0];
0060:
0061: //
0062: // Properties
0063: //
0064:
0065: /**
0066: * Returns the value's class name.
0067: */
0068: public String getClassName() {
0069: return getType();
0070: }
0071:
0072: //
0073: // Predicates and Relations
0074: //
0075:
0076: /**
0077: * Returns true for an implementation of a class
0078: */
0079: public boolean isA(String name) {
0080: return false;
0081: }
0082:
0083: /**
0084: * Checks if 'this' is a valid protected call for 'className'
0085: */
0086: public void checkProtected(Env env, String className) {
0087: }
0088:
0089: /**
0090: * Checks if 'this' is a valid private call for 'className'
0091: */
0092: public void checkPrivate(Env env, String className) {
0093: }
0094:
0095: /**
0096: * Returns the ValueType.
0097: */
0098: public ValueType getValueType() {
0099: return ValueType.VALUE;
0100: }
0101:
0102: /**
0103: * Returns true for an array.
0104: */
0105: public boolean isArray() {
0106: return false;
0107: }
0108:
0109: /**
0110: * Returns true for a double-value.
0111: */
0112: public boolean isDoubleConvertible() {
0113: return false;
0114: }
0115:
0116: /**
0117: * Returns true for a long-value.
0118: */
0119: public boolean isLongConvertible() {
0120: return false;
0121: }
0122:
0123: /**
0124: * Returns true for a null.
0125: */
0126: public boolean isNull() {
0127: return false;
0128: }
0129:
0130: /**
0131: * Returns true for a number.
0132: */
0133: public boolean isNumberConvertible() {
0134: return isLongConvertible() || isDoubleConvertible();
0135: }
0136:
0137: /**
0138: * Matches is_numeric
0139: */
0140: public boolean isNumeric() {
0141: return false;
0142: }
0143:
0144: /**
0145: * Returns true for an object.
0146: */
0147: public boolean isObject() {
0148: return false;
0149: }
0150:
0151: /**
0152: * Returns true for a StringValue.
0153: */
0154: public boolean isString() {
0155: return false;
0156: }
0157:
0158: /**
0159: * Returns true for a BinaryValue.
0160: */
0161: public boolean isBinary() {
0162: return false;
0163: }
0164:
0165: /**
0166: * Returns true for a UnicodeValue.
0167: */
0168: public boolean isUnicode() {
0169: return false;
0170: }
0171:
0172: /**
0173: * Returns true for a BooleanValue
0174: */
0175: public boolean isBoolean() {
0176: return false;
0177: }
0178:
0179: /**
0180: * Returns true for a DefaultValue
0181: */
0182: public boolean isDefault() {
0183: return false;
0184: }
0185:
0186: /**
0187: * Returns true if the value is set.
0188: */
0189: public boolean isset() {
0190: return true;
0191: }
0192:
0193: /**
0194: * Returns true if the value is empty
0195: */
0196: public boolean isEmpty() {
0197: return false;
0198: }
0199:
0200: /**
0201: * Returns true if there are more elements.
0202: */
0203: public boolean hasCurrent() {
0204: return false;
0205: }
0206:
0207: /**
0208: * Returns true for equality
0209: */
0210: public Value eqValue(Value rValue) {
0211: return eq(rValue) ? BooleanValue.TRUE : BooleanValue.FALSE;
0212: }
0213:
0214: /**
0215: * Returns true for equality
0216: */
0217: public boolean eq(Value rValue) {
0218: if (rValue instanceof BooleanValue)
0219: return toBoolean() == rValue.toBoolean();
0220: else if (isLongConvertible() && rValue.isLongConvertible())
0221: return toLong() == rValue.toLong();
0222: else if (isNumberConvertible() || rValue.isNumberConvertible())
0223: return toDouble() == rValue.toDouble();
0224: else
0225: return toString().equals(rValue.toString());
0226: }
0227:
0228: /**
0229: * Returns true for equality
0230: */
0231: public boolean eql(Value rValue) {
0232: return this == rValue.toValue();
0233: }
0234:
0235: /**
0236: * Returns a negative/positive integer if this Value is
0237: * lessthan/greaterthan rValue.
0238: */
0239: public int cmp(Value rValue) {
0240: // This is tricky: implemented according to Table 15-5 of
0241: // http://us2.php.net/manual/en/language.operators.comparison.php
0242:
0243: Value lVal = toValue();
0244: Value rVal = rValue.toValue();
0245:
0246: if (lVal instanceof StringValue && rVal instanceof NullValue)
0247: return ((StringValue) lVal).cmpString(StringValue.EMPTY);
0248:
0249: if (lVal instanceof NullValue && rVal instanceof StringValue)
0250: return StringValue.EMPTY.cmpString((StringValue) rVal);
0251:
0252: if (lVal instanceof StringValue && rVal instanceof StringValue)
0253: return ((StringValue) lVal).cmpString((StringValue) rVal);
0254:
0255: if (lVal instanceof NullValue || lVal instanceof BooleanValue
0256: || rVal instanceof NullValue
0257: || rVal instanceof BooleanValue) {
0258: boolean lBool = toBoolean();
0259: boolean rBool = rValue.toBoolean();
0260: if (!lBool && rBool)
0261: return -1;
0262: if (lBool && !rBool)
0263: return 1;
0264: return 0;
0265: }
0266:
0267: if (lVal.isObject() && rVal.isObject())
0268: return ((ObjectValue) lVal).cmpObject((ObjectValue) rVal);
0269:
0270: if ((lVal instanceof StringValue || lVal instanceof NumberValue || lVal instanceof ResourceValue)
0271: && (rVal instanceof StringValue
0272: || rVal instanceof NumberValue || rVal instanceof ResourceValue))
0273: return NumberValue.compareNum(lVal, rVal);
0274:
0275: if (lVal instanceof ArrayValue)
0276: return 1;
0277: if (rVal instanceof ArrayValue)
0278: return -1;
0279: if (lVal instanceof ObjectValue)
0280: return 1;
0281: if (rVal instanceof ObjectValue)
0282: return -1;
0283:
0284: // XXX: proper default case?
0285: throw new RuntimeException("values are incomparable: " + lVal
0286: + " <=> " + rVal);
0287: }
0288:
0289: /**
0290: * Returns true for less than
0291: */
0292: public boolean lt(Value rValue) {
0293: return cmp(rValue) < 0;
0294: }
0295:
0296: /**
0297: * Returns true for less than or equal to
0298: */
0299: public boolean leq(Value rValue) {
0300: return cmp(rValue) <= 0;
0301: }
0302:
0303: /**
0304: * Returns true for greater than
0305: */
0306: public boolean gt(Value rValue) {
0307: return cmp(rValue) > 0;
0308: }
0309:
0310: /**
0311: * Returns true for greater than or equal to
0312: */
0313: public boolean geq(Value rValue) {
0314: return cmp(rValue) >= 0;
0315: }
0316:
0317: //
0318: // Conversions
0319: //
0320:
0321: /**
0322: * Converts to a boolean.
0323: */
0324: public boolean toBoolean() {
0325: return true;
0326: }
0327:
0328: /**
0329: * Converts to a long.
0330: */
0331: public long toLong() {
0332: return toBoolean() ? 1 : 0;
0333: }
0334:
0335: /**
0336: * Converts to an int
0337: */
0338: public int toInt() {
0339: return (int) toLong();
0340: }
0341:
0342: /**
0343: * Converts to a double.
0344: */
0345: public double toDouble() {
0346: return 0;
0347: }
0348:
0349: /**
0350: * Converts to a char
0351: */
0352: public char toChar() {
0353: String s = toString();
0354:
0355: if (s == null || s.length() < 1)
0356: return 0;
0357: else
0358: return s.charAt(0);
0359: }
0360:
0361: /**
0362: * Converts to a string.
0363: *
0364: * @param env
0365: */
0366: public StringValue toString(Env env) {
0367: return toStringValue();
0368: }
0369:
0370: /**
0371: * Converts to an array.
0372: */
0373: public Value toArray() {
0374: return new ArrayValueImpl().append(this );
0375: }
0376:
0377: /**
0378: * Converts to an array if null.
0379: */
0380: public Value toAutoArray() {
0381: return this ;
0382: }
0383:
0384: /**
0385: * Casts to an array.
0386: */
0387: public ArrayValue toArrayValue(Env env) {
0388: env.warning(L.l("'{0}' ({1}) is not assignable to ArrayValue",
0389: this , getType()));
0390:
0391: return null;
0392: }
0393:
0394: /**
0395: * Converts to an object if null.
0396: */
0397: public Value toAutoObject(Env env) {
0398: return this ;
0399: }
0400:
0401: /**
0402: * Converts to an object.
0403: */
0404: public Value toObject(Env env) {
0405: ObjectValue obj = env.createObject();
0406:
0407: obj.putField(env, env.createString("scalar"), this );
0408:
0409: return obj;
0410: }
0411:
0412: /**
0413: * Converts to a java object.
0414: */
0415: public Object toJavaObject() {
0416: return null;
0417: }
0418:
0419: /**
0420: * Converts to a java object.
0421: */
0422: public Object toJavaObject(Env env, Class type) {
0423: env.warning(L.l("Can't convert {0} to Java {1}", getClass()
0424: .getName(), type.getName()));
0425:
0426: return null;
0427: }
0428:
0429: /**
0430: * Converts to a java object.
0431: */
0432: public Object toJavaObjectNotNull(Env env, Class type) {
0433: env.warning(L.l("Can't convert {0} to Java {1}", getClass()
0434: .getName(), type.getName()));
0435:
0436: return null;
0437: }
0438:
0439: /**
0440: * Converts to a java boolean object.
0441: */
0442: public Boolean toJavaBoolean() {
0443: return toBoolean() ? Boolean.TRUE : Boolean.FALSE;
0444: }
0445:
0446: /**
0447: * Converts to a java byte object.
0448: */
0449: public Byte toJavaByte() {
0450: return new Byte((byte) toLong());
0451: }
0452:
0453: /**
0454: * Converts to a java short object.
0455: */
0456: public Short toJavaShort() {
0457: return new Short((short) toLong());
0458: }
0459:
0460: /**
0461: * Converts to a java Integer object.
0462: */
0463: public Integer toJavaInteger() {
0464: return new Integer((int) toLong());
0465: }
0466:
0467: /**
0468: * Converts to a java Long object.
0469: */
0470: public Long toJavaLong() {
0471: return new Long((int) toLong());
0472: }
0473:
0474: /**
0475: * Converts to a java Float object.
0476: */
0477: public Float toJavaFloat() {
0478: return new Float((float) toDouble());
0479: }
0480:
0481: /**
0482: * Converts to a java Double object.
0483: */
0484: public Double toJavaDouble() {
0485: return new Double(toDouble());
0486: }
0487:
0488: /**
0489: * Converts to a java Character object.
0490: */
0491: public Character toJavaCharacter() {
0492: return new Character(toChar());
0493: }
0494:
0495: /**
0496: * Converts to a java String object.
0497: */
0498: public String toJavaString() {
0499: return toString();
0500: }
0501:
0502: /**
0503: * Converts to a java Collection object.
0504: */
0505: public Collection toJavaCollection(Env env, Class type) {
0506: env.warning(L.l("Can't convert {0} to Java {1}", getClass()
0507: .getName(), type.getName()));
0508:
0509: return null;
0510: }
0511:
0512: /**
0513: * Converts to a java List object.
0514: */
0515: public List toJavaList(Env env, Class type) {
0516: env.warning(L.l("Can't convert {0} to Java {1}", getClass()
0517: .getName(), type.getName()));
0518:
0519: return null;
0520: }
0521:
0522: /**
0523: * Converts to a java Map object.
0524: */
0525: public Map toJavaMap(Env env, Class type) {
0526: env.warning(L.l("Can't convert {0} to Java {1}", getClass()
0527: .getName(), type.getName()));
0528:
0529: return null;
0530: }
0531:
0532: /**
0533: * Converts to a Java Calendar.
0534: */
0535: public Calendar toJavaCalendar() {
0536: Calendar cal = Calendar.getInstance();
0537:
0538: cal.setTimeInMillis(toLong());
0539:
0540: return cal;
0541: }
0542:
0543: /**
0544: * Converts to a Java Date.
0545: */
0546: public Date toJavaDate() {
0547: return new Date(toLong());
0548: }
0549:
0550: /**
0551: * Converts to a Java URL.
0552: */
0553: public URL toJavaURL(Env env) {
0554: try {
0555: return new URL(toString());
0556: } catch (MalformedURLException e) {
0557: env.warning(L.l(e.getMessage()));
0558: return null;
0559: }
0560: }
0561:
0562: /**
0563: * Converts to a Java BigDecimal.
0564: */
0565: public BigDecimal toBigDecimal() {
0566: return new BigDecimal(toString());
0567: }
0568:
0569: /**
0570: * Converts to a Java BigInteger.
0571: */
0572: public BigInteger toBigInteger() {
0573: return new BigInteger(toString());
0574: }
0575:
0576: /**
0577: * Converts to an exception.
0578: */
0579: public QuercusException toException(Env env, String file, int line) {
0580: putField(env, env.createString("file"), env.createString(file));
0581: putField(env, env.createString("line"), LongValue.create(line));
0582:
0583: return new QuercusLanguageException(this );
0584: }
0585:
0586: /**
0587: * Converts to a raw value.
0588: */
0589: public Value toValue() {
0590: return this ;
0591: }
0592:
0593: /**
0594: * Converts to a key.
0595: */
0596: public Value toKey() {
0597: throw new QuercusRuntimeException(L.l("{0} is not a valid key",
0598: this ));
0599: }
0600:
0601: /**
0602: * Convert to a ref.
0603: */
0604: public Value toRef() {
0605: return this ;
0606: }
0607:
0608: /**
0609: * Convert to a function argument value, e.g. for
0610: *
0611: * function foo($a)
0612: *
0613: * where $a is never assigned or modified
0614: */
0615: public Value toArgValueReadOnly() {
0616: return this ;
0617: }
0618:
0619: /**
0620: * Convert to a function argument value, e.g. for
0621: *
0622: * function foo($a)
0623: *
0624: * where $a is never assigned, but might be modified, e.g. $a[3] = 9
0625: */
0626: public Value toArgValue() {
0627: return this ;
0628: }
0629:
0630: /**
0631: * Convert to a function argument reference value, e.g. for
0632: *
0633: * function foo(&$a)
0634: *
0635: * where $a is never assigned in the function
0636: */
0637: public Value toRefValue() {
0638: return this ;
0639: }
0640:
0641: /**
0642: * Convert to a function argument value, e.g. for
0643: *
0644: * function foo($a)
0645: *
0646: * where $a is used as a variable in the function
0647: */
0648: public Var toVar() {
0649: return new Var(toArgValue());
0650: }
0651:
0652: /**
0653: * Convert to a function argument reference value, e.g. for
0654: *
0655: * function foo(&$a)
0656: *
0657: * where $a is used as a variable in the function
0658: */
0659: public Var toRefVar() {
0660: return new Var(this );
0661: }
0662:
0663: /**
0664: * Converts to a StringValue.
0665: */
0666: public StringValue toStringValue() {
0667: return Env.getInstance().createString(toString());
0668: }
0669:
0670: /**
0671: * Converts to a UnicodeValue.
0672: */
0673: public StringValue toUnicodeValue() {
0674: return toUnicodeValue(Env.getInstance());
0675: }
0676:
0677: /**
0678: * Converts to a UnicodeValue.
0679: */
0680: public StringValue toUnicodeValue(Env env) {
0681: return env.createString(toString());
0682: }
0683:
0684: /**
0685: * Converts to a BinaryValue.
0686: */
0687: public StringValue toBinaryValue() {
0688: return toBinaryValue(Env.getInstance());
0689: }
0690:
0691: /**
0692: * Converts to a BinaryValue.
0693: */
0694: public StringValue toBinaryValue(Env env) {
0695: StringValue bb = env.createBinaryBuilder();
0696:
0697: bb.append(this );
0698:
0699: return bb;
0700:
0701: /*
0702: try {
0703: int length = 0;
0704: while (true) {
0705: bb.ensureCapacity(bb.getLength() + 256);
0706:
0707: int sublen = is.read(bb.getBuffer(),
0708: bb.getOffset(),
0709: bb.getLength() - bb.getOffset());
0710:
0711: if (sublen <= 0)
0712: return bb;
0713: else {
0714: length += sublen;
0715: bb.setOffset(length);
0716: }
0717: }
0718: } catch (IOException e) {
0719: throw new QuercusException(e);
0720: }
0721: */
0722: }
0723:
0724: /**
0725: * Returns a byteArrayInputStream for the value.
0726: * See TempBufferStringValue for how this can be overriden
0727: *
0728: * @return InputStream
0729: */
0730: public InputStream toInputStream() {
0731: return new StringInputStream(toString());
0732: }
0733:
0734: /**
0735: * Converts to a string builder
0736: */
0737: public StringValue toStringBuilder() {
0738: // XXX: should be illegal?
0739: return new UnicodeBuilderValue(toString(), 32);
0740: }
0741:
0742: /**
0743: * Converts to a string builder
0744: */
0745: public StringValue toStringBuilder(Env env) {
0746: return env.createUnicodeBuilder().appendUnicode(this );
0747: }
0748:
0749: /**
0750: * Converts to a long vaule
0751: */
0752: public LongValue toLongValue() {
0753: return new LongValue(toLong());
0754: }
0755:
0756: /**
0757: * Converts to a double vaule
0758: */
0759: public DoubleValue toDoubleValue() {
0760: return new DoubleValue(toDouble());
0761: }
0762:
0763: //
0764: // Operations
0765: //
0766:
0767: /**
0768: * Append to a string builder.
0769: */
0770: public StringValue appendTo(UnicodeBuilderValue sb) {
0771: return sb.append(toString());
0772: }
0773:
0774: /**
0775: * Append to a binary builder.
0776: */
0777: public StringValue appendTo(StringBuilderValue sb) {
0778: return sb.append(toString());
0779: }
0780:
0781: /**
0782: * Append to a binary builder.
0783: */
0784: public StringValue appendTo(BinaryBuilderValue sb) {
0785: return sb.appendBytes(toString());
0786: }
0787:
0788: /**
0789: * Append to a binary builder.
0790: */
0791: public StringValue appendTo(LargeStringBuilderValue sb) {
0792: return sb.append(toString());
0793: }
0794:
0795: /**
0796: * Copy for assignment.
0797: */
0798: public Value copy() {
0799: return this ;
0800: }
0801:
0802: /**
0803: * Copy as an array item
0804: */
0805: public Value copyArrayItem() {
0806: return copy();
0807: }
0808:
0809: /**
0810: * Copy as a return value
0811: */
0812: public Value copyReturn() {
0813: // php/3a5d
0814:
0815: return this ;
0816: }
0817:
0818: /**
0819: * Copy for serialization
0820: */
0821: public final Value copy(Env env) {
0822: return copy(env, new IdentityHashMap<Value, Value>());
0823: }
0824:
0825: /**
0826: * Copy for serialization
0827: */
0828: public Value copy(Env env, IdentityHashMap<Value, Value> map) {
0829: return this ;
0830: }
0831:
0832: /**
0833: * Copy for serialization
0834: */
0835: public Value copyTree(Env env) {
0836: return this ;
0837: }
0838:
0839: /**
0840: * Clone for the clone keyword
0841: */
0842: public Value clone() {
0843: return this ;
0844: }
0845:
0846: /**
0847: * Returns the type.
0848: */
0849: public String getType() {
0850: return "value";
0851: }
0852:
0853: /**
0854: * Returns the current key
0855: */
0856: public Value key() {
0857: return NullValue.NULL;
0858: }
0859:
0860: /**
0861: * Returns the current value
0862: */
0863: public Value current() {
0864: return NullValue.NULL;
0865: }
0866:
0867: /**
0868: * Returns the current value
0869: */
0870: public Value next() {
0871: return BooleanValue.FALSE;
0872: }
0873:
0874: /**
0875: * Finds the method name.
0876: */
0877: public AbstractFunction findFunction(String methodName) {
0878: return null;
0879: }
0880:
0881: //
0882: // Methods from hash parameters
0883: //
0884:
0885: /**
0886: * Evaluates a method.
0887: */
0888: public Value callMethod(Env env, int hash, char[] name,
0889: int nameLen, Expr[] args) {
0890: Value[] value = new Value[args.length];
0891:
0892: for (int i = 0; i < args.length; i++) {
0893: value[i] = args[i].eval(env);
0894: }
0895:
0896: return callMethod(env, hash, name, nameLen, value);
0897: }
0898:
0899: /**
0900: * Evaluates a method.
0901: */
0902: public Value callMethod(Env env, int hash, char[] name,
0903: int nameLen, Value[] args) {
0904: switch (args.length) {
0905: case 0:
0906: return callMethod(env, hash, name, nameLen);
0907:
0908: case 1:
0909: return callMethod(env, hash, name, nameLen, args[0]);
0910:
0911: case 2:
0912: return callMethod(env, hash, name, nameLen, args[0],
0913: args[1]);
0914:
0915: case 3:
0916: return callMethod(env, hash, name, nameLen, args[0],
0917: args[1], args[2]);
0918:
0919: case 4:
0920: return callMethod(env, hash, name, nameLen, args[0],
0921: args[1], args[2], args[3]);
0922:
0923: case 5:
0924: return callMethod(env, hash, name, nameLen, args[0],
0925: args[1], args[2], args[3], args[4]);
0926:
0927: default:
0928: return errorNoMethod(env, name, nameLen);
0929: }
0930: }
0931:
0932: /**
0933: * Evaluates a method with 0 args.
0934: */
0935: public Value callMethod(Env env, int hash, char[] name, int nameLen) {
0936: return errorNoMethod(env, name, nameLen);
0937: }
0938:
0939: /**
0940: * Evaluates a method with 1 arg.
0941: */
0942: public Value callMethod(Env env, int hash, char[] name,
0943: int nameLen, Value a0) {
0944: return errorNoMethod(env, name, nameLen);
0945: }
0946:
0947: /**
0948: * Evaluates a method with 1 arg.
0949: */
0950: public Value callMethod(Env env, int hash, char[] name,
0951: int nameLen, Value a0, Value a1) {
0952: return errorNoMethod(env, name, nameLen);
0953: }
0954:
0955: /**
0956: * Evaluates a method with 3 args.
0957: */
0958: public Value callMethod(Env env, int hash, char[] name,
0959: int nameLen, Value a0, Value a1, Value a2) {
0960: return errorNoMethod(env, name, nameLen);
0961: }
0962:
0963: /**
0964: * Evaluates a method with 4 args.
0965: */
0966: public Value callMethod(Env env, int hash, char[] name,
0967: int nameLen, Value a0, Value a1, Value a2, Value a3) {
0968: return errorNoMethod(env, name, nameLen);
0969: }
0970:
0971: /**
0972: * Evaluates a method with 5 args.
0973: */
0974: public Value callMethod(Env env, int hash, char[] name,
0975: int nameLen, Value a0, Value a1, Value a2, Value a3,
0976: Value a5) {
0977: return errorNoMethod(env, name, nameLen);
0978: }
0979:
0980: /**
0981: * Evaluates a method.
0982: */
0983: public Value callMethodRef(Env env, int hash, char[] name,
0984: int nameLen, Expr[] args) {
0985: Value[] value = new Value[args.length];
0986:
0987: for (int i = 0; i < args.length; i++) {
0988: value[i] = args[i].eval(env);
0989: }
0990:
0991: return callMethodRef(env, hash, name, nameLen, value);
0992: }
0993:
0994: /**
0995: * Evaluates a method.
0996: */
0997: public Value callMethodRef(Env env, int hash, char[] name,
0998: int nameLen, Value[] args) {
0999: switch (args.length) {
1000: case 0:
1001: return callMethodRef(env, hash, name, nameLen);
1002:
1003: case 1:
1004: return callMethodRef(env, hash, name, nameLen, args[0]);
1005:
1006: case 2:
1007: return callMethodRef(env, hash, name, nameLen, args[0],
1008: args[1]);
1009:
1010: case 3:
1011: return callMethodRef(env, hash, name, nameLen, args[0],
1012: args[1], args[2]);
1013:
1014: case 4:
1015: return callMethodRef(env, hash, name, nameLen, args[0],
1016: args[1], args[2], args[3]);
1017:
1018: case 5:
1019: return callMethodRef(env, hash, name, nameLen, args[0],
1020: args[1], args[2], args[3], args[4]);
1021:
1022: default:
1023: return errorNoMethod(env, name, nameLen);
1024: }
1025: }
1026:
1027: /**
1028: * Evaluates a method with 0 args.
1029: */
1030: public Value callMethodRef(Env env, int hash, char[] name,
1031: int nameLen) {
1032: return errorNoMethod(env, name, nameLen);
1033: }
1034:
1035: /**
1036: * Evaluates a method with 1 arg.
1037: */
1038: public Value callMethodRef(Env env, int hash, char[] name,
1039: int nameLen, Value a0) {
1040: return errorNoMethod(env, name, nameLen);
1041: }
1042:
1043: /**
1044: * Evaluates a method with 1 arg.
1045: */
1046: public Value callMethodRef(Env env, int hash, char[] name,
1047: int nameLen, Value a0, Value a1) {
1048: return errorNoMethod(env, name, nameLen);
1049: }
1050:
1051: /**
1052: * Evaluates a method with 3 args.
1053: */
1054: public Value callMethodRef(Env env, int hash, char[] name,
1055: int nameLen, Value a0, Value a1, Value a2) {
1056: return errorNoMethod(env, name, nameLen);
1057: }
1058:
1059: /**
1060: * Evaluates a method with 4 args.
1061: */
1062: public Value callMethodRef(Env env, int hash, char[] name,
1063: int nameLen, Value a0, Value a1, Value a2, Value a3) {
1064: return errorNoMethod(env, name, nameLen);
1065: }
1066:
1067: /**
1068: * Evaluates a method with 5 args.
1069: */
1070: public Value callMethodRef(Env env, int hash, char[] name,
1071: int nameLen, Value a0, Value a1, Value a2, Value a3,
1072: Value a5) {
1073: return errorNoMethod(env, name, nameLen);
1074: }
1075:
1076: //
1077: // Methods from StringValue
1078: //
1079:
1080: /**
1081: * Evaluates a method.
1082: */
1083: public Value callMethod(Env env, StringValue nameValue, Expr[] args) {
1084: Value[] value = new Value[args.length];
1085:
1086: for (int i = 0; i < args.length; i++) {
1087: value[i] = args[i].eval(env);
1088: }
1089:
1090: char[] name = nameValue.getRawCharArray();
1091: int nameLen = nameValue.length();
1092: int hash = MethodMap.hash(name, nameLen);
1093:
1094: return callMethod(env, hash, name, nameLen, value);
1095: }
1096:
1097: /**
1098: * Evaluates a method.
1099: */
1100: public Value callMethod(Env env, StringValue nameValue, Value[] args) {
1101: char[] name = nameValue.getRawCharArray();
1102: int nameLen = nameValue.length();
1103: int hash = MethodMap.hash(name, nameLen);
1104:
1105: switch (args.length) {
1106: case 0:
1107: return callMethod(env, hash, name, nameLen);
1108:
1109: case 1:
1110: return callMethod(env, hash, name, nameLen, args[0]);
1111:
1112: case 2:
1113: return callMethod(env, hash, name, nameLen, args[0],
1114: args[1]);
1115:
1116: case 3:
1117: return callMethod(env, hash, name, nameLen, args[0],
1118: args[1], args[2]);
1119:
1120: case 4:
1121: return callMethod(env, hash, name, nameLen, args[0],
1122: args[1], args[2], args[3]);
1123:
1124: case 5:
1125: return callMethod(env, hash, name, nameLen, args[0],
1126: args[1], args[2], args[3], args[4]);
1127:
1128: default:
1129: return errorNoMethod(env, name, nameLen);
1130: }
1131: }
1132:
1133: /**
1134: * Evaluates a method with 0 args.
1135: */
1136: public Value callMethod(Env env, StringValue nameValue) {
1137: char[] name = nameValue.getRawCharArray();
1138: int nameLen = nameValue.length();
1139: int hash = MethodMap.hash(name, nameLen);
1140:
1141: return callMethod(env, hash, name, nameLen);
1142: }
1143:
1144: /**
1145: * Evaluates a method with 1 arg.
1146: */
1147: public Value callMethod(Env env, StringValue nameValue, Value a0) {
1148: char[] name = nameValue.getRawCharArray();
1149: int nameLen = nameValue.length();
1150: int hash = MethodMap.hash(name, nameLen);
1151:
1152: return callMethod(env, hash, name, nameLen, a0);
1153: }
1154:
1155: /**
1156: * Evaluates a method with 1 arg.
1157: */
1158: public Value callMethod(Env env, StringValue nameValue, Value a0,
1159: Value a1) {
1160: char[] name = nameValue.getRawCharArray();
1161: int nameLen = nameValue.length();
1162: int hash = MethodMap.hash(name, nameLen);
1163:
1164: return callMethod(env, hash, name, nameLen, a0, a1);
1165: }
1166:
1167: /**
1168: * Evaluates a method with 3 args.
1169: */
1170: public Value callMethod(Env env, StringValue nameValue, Value a0,
1171: Value a1, Value a2) {
1172: char[] name = nameValue.getRawCharArray();
1173: int nameLen = nameValue.length();
1174: int hash = MethodMap.hash(name, nameLen);
1175:
1176: return callMethod(env, hash, name, nameLen, a0, a1, a2);
1177: }
1178:
1179: /**
1180: * Evaluates a method with 4 args.
1181: */
1182: public Value callMethod(Env env, StringValue nameValue, Value a0,
1183: Value a1, Value a2, Value a3) {
1184: char[] name = nameValue.getRawCharArray();
1185: int nameLen = nameValue.length();
1186: int hash = MethodMap.hash(name, nameLen);
1187:
1188: return callMethod(env, hash, name, nameLen, a0, a1, a2, a3);
1189: }
1190:
1191: /**
1192: * Evaluates a method with 5 args.
1193: */
1194: public Value callMethod(Env env, StringValue nameValue, Value a0,
1195: Value a1, Value a2, Value a3, Value a4) {
1196: char[] name = nameValue.getRawCharArray();
1197: int nameLen = nameValue.length();
1198: int hash = MethodMap.hash(name, nameLen);
1199:
1200: return callMethod(env, hash, name, nameLen, a0, a1, a2, a3, a4);
1201: }
1202:
1203: /**
1204: * Evaluates a method.
1205: */
1206: public Value callMethodRef(Env env, StringValue nameValue,
1207: Expr[] args) {
1208: Value[] value = new Value[args.length];
1209:
1210: for (int i = 0; i < args.length; i++) {
1211: value[i] = args[i].eval(env);
1212: }
1213:
1214: char[] name = nameValue.getRawCharArray();
1215: int nameLen = nameValue.length();
1216: int hash = MethodMap.hash(name, nameLen);
1217:
1218: return callMethodRef(env, hash, name, nameLen, value);
1219: }
1220:
1221: /**
1222: * Evaluates a method.
1223: */
1224: public Value callMethodRef(Env env, StringValue nameValue,
1225: Value[] args) {
1226: char[] name = nameValue.getRawCharArray();
1227: int nameLen = nameValue.length();
1228: int hash = MethodMap.hash(name, nameLen);
1229:
1230: switch (args.length) {
1231: case 0:
1232: return callMethodRef(env, hash, name, nameLen);
1233:
1234: case 1:
1235: return callMethodRef(env, hash, name, nameLen, args[0]);
1236:
1237: case 2:
1238: return callMethodRef(env, hash, name, nameLen, args[0],
1239: args[1]);
1240:
1241: case 3:
1242: return callMethodRef(env, hash, name, nameLen, args[0],
1243: args[1], args[2]);
1244:
1245: case 4:
1246: return callMethodRef(env, hash, name, nameLen, args[0],
1247: args[1], args[2], args[3]);
1248:
1249: case 5:
1250: return callMethodRef(env, hash, name, nameLen, args[0],
1251: args[1], args[2], args[3], args[4]);
1252:
1253: default:
1254: return errorNoMethod(env, name, nameLen);
1255: }
1256: }
1257:
1258: /**
1259: * Evaluates a method with 0 args.
1260: */
1261: public Value callMethodRef(Env env, StringValue nameValue) {
1262: char[] name = nameValue.getRawCharArray();
1263: int nameLen = nameValue.length();
1264: int hash = MethodMap.hash(name, nameLen);
1265:
1266: return callMethodRef(env, hash, name, nameLen);
1267: }
1268:
1269: /**
1270: * Evaluates a method with 1 arg.
1271: */
1272: public Value callMethodRef(Env env, StringValue nameValue, Value a0) {
1273: char[] name = nameValue.getRawCharArray();
1274: int nameLen = nameValue.length();
1275: int hash = MethodMap.hash(name, nameLen);
1276:
1277: return callMethodRef(env, hash, name, nameLen, a0);
1278: }
1279:
1280: /**
1281: * Evaluates a method with 2 args.
1282: */
1283: public Value callMethodRef(Env env, StringValue nameValue,
1284: Value a0, Value a1) {
1285: char[] name = nameValue.getRawCharArray();
1286: int nameLen = nameValue.length();
1287: int hash = MethodMap.hash(name, nameLen);
1288:
1289: return callMethodRef(env, hash, name, nameLen, a0, a1);
1290: }
1291:
1292: /**
1293: * Evaluates a method with 3 args.
1294: */
1295: public Value callMethodRef(Env env, StringValue nameValue,
1296: Value a0, Value a1, Value a2) {
1297: char[] name = nameValue.getRawCharArray();
1298: int nameLen = nameValue.length();
1299: int hash = MethodMap.hash(name, nameLen);
1300:
1301: return callMethodRef(env, hash, name, nameLen, a0, a1, a2);
1302: }
1303:
1304: /**
1305: * Evaluates a method with 4 args.
1306: */
1307: public Value callMethodRef(Env env, StringValue nameValue,
1308: Value a0, Value a1, Value a2, Value a3) {
1309: char[] name = nameValue.getRawCharArray();
1310: int nameLen = nameValue.length();
1311: int hash = MethodMap.hash(name, nameLen);
1312:
1313: return callMethodRef(env, hash, name, nameLen, a0, a1, a2, a3);
1314: }
1315:
1316: /**
1317: * Evaluates a method with 5 args.
1318: */
1319: public Value callMethodRef(Env env, StringValue nameValue,
1320: Value a0, Value a1, Value a2, Value a3, Value a4) {
1321: char[] name = nameValue.getRawCharArray();
1322: int nameLen = nameValue.length();
1323: int hash = MethodMap.hash(name, nameLen);
1324:
1325: return callMethodRef(env, hash, name, nameLen, a0, a1, a2, a3,
1326: a4);
1327: }
1328:
1329: /**
1330: * Evaluates a method.
1331: */
1332: public Value callClassMethod(Env env, AbstractFunction fun,
1333: Value[] args) {
1334: return NullValue.NULL;
1335: }
1336:
1337: private Value errorNoMethod(Env env, char[] name, int nameLen) {
1338: String methodName = new String(name, 0, nameLen);
1339:
1340: if (isNull())
1341: return env
1342: .error(L
1343: .l(
1344: "Method call '{0}' is not allowed for a null value.",
1345: methodName));
1346: else
1347: return env.error(L.l("'{0}' is an unknown method of {1}.",
1348: methodName, toDebugString()));
1349: }
1350:
1351: //
1352: // Arithmetic operations
1353: //
1354:
1355: /**
1356: * Negates the value.
1357: */
1358: public Value neg() {
1359: return new LongValue(-toLong());
1360: }
1361:
1362: /**
1363: * Negates the value.
1364: */
1365: public Value pos() {
1366: return new LongValue(toLong());
1367: }
1368:
1369: /**
1370: * Adds to the following value.
1371: */
1372: public Value add(Value rValue) {
1373: if (getValueType().isLongAdd()
1374: && rValue.getValueType().isLongAdd())
1375: return LongValue.create(toLong() + rValue.toLong());
1376:
1377: return DoubleValue.create(toDouble() + rValue.toDouble());
1378: }
1379:
1380: /**
1381: * Multiplies to the following value.
1382: */
1383: public Value add(long lLong) {
1384: return new DoubleValue(lLong + toDouble());
1385: }
1386:
1387: /**
1388: * Pre-increment the following value.
1389: */
1390: public Value preincr(int incr) {
1391: long lValue = toLong();
1392:
1393: return new LongValue(lValue + incr);
1394: }
1395:
1396: /**
1397: * Post-increment the following value.
1398: */
1399: public Value postincr(int incr) {
1400: long lValue = toLong();
1401:
1402: return new LongValue(lValue + incr);
1403: }
1404:
1405: /**
1406: * Subtracts to the following value.
1407: */
1408: public Value sub(Value rValue) {
1409: if (getValueType().isLongAdd()
1410: && rValue.getValueType().isLongAdd())
1411: return LongValue.create(toLong() - rValue.toLong());
1412:
1413: return DoubleValue.create(toDouble() - rValue.toDouble());
1414: }
1415:
1416: /**
1417: * Subtracts
1418: */
1419: public Value sub(long rLong) {
1420: return new DoubleValue(toDouble() - rLong);
1421: }
1422:
1423: /**
1424: * Substracts from the previous value.
1425: */
1426: public Value sub_rev(long lLong) {
1427: if (getValueType().isLongAdd())
1428: return LongValue.create(lLong - toLong());
1429: else
1430: return new DoubleValue(lLong - toDouble());
1431: }
1432:
1433: /**
1434: * Multiplies to the following value.
1435: */
1436: public Value mul(Value rValue) {
1437: if (getValueType().isLongAdd()
1438: && rValue.getValueType().isLongAdd())
1439: return LongValue.create(toLong() * rValue.toLong());
1440: else
1441: return new DoubleValue(toDouble() * rValue.toDouble());
1442: }
1443:
1444: /**
1445: * Multiplies to the following value.
1446: */
1447: public Value mul(long r) {
1448: if (isDoubleConvertible())
1449: return new DoubleValue(toDouble() * r);
1450: else
1451: return LongValue.create(toLong() * r);
1452: }
1453:
1454: /**
1455: * Divides the following value.
1456: */
1457: public Value div(Value rValue) {
1458: if (getValueType().isLongAdd()
1459: && rValue.getValueType().isLongAdd()) {
1460: long l = toLong();
1461: long r = rValue.toLong();
1462:
1463: if (l % r == 0)
1464: return LongValue.create(l / r);
1465: else
1466: return new DoubleValue(toDouble() / rValue.toDouble());
1467: } else
1468: return new DoubleValue(toDouble() / rValue.toDouble());
1469: }
1470:
1471: /**
1472: * Multiplies to the following value.
1473: */
1474: public Value div(long r) {
1475: long l = toLong();
1476:
1477: if (l % r == 0)
1478: return LongValue.create(l / r);
1479: else
1480: return new DoubleValue(toDouble() / r);
1481: }
1482:
1483: /**
1484: * modulo the following value.
1485: */
1486: public Value mod(Value rValue) {
1487: double lDouble = toDouble();
1488: double rDouble = rValue.toDouble();
1489:
1490: return LongValue.create((long) lDouble % rDouble);
1491: }
1492:
1493: /**
1494: * Shifts left by the value.
1495: */
1496: public Value lshift(Value rValue) {
1497: long lLong = toLong();
1498: long rLong = rValue.toLong();
1499:
1500: return new LongValue(lLong << rLong);
1501: }
1502:
1503: /**
1504: * Shifts right by the value.
1505: */
1506: public Value rshift(Value rValue) {
1507: long lLong = toLong();
1508: long rLong = rValue.toLong();
1509:
1510: return new LongValue(lLong >> rLong);
1511: }
1512:
1513: /*
1514: * Binary And.
1515: */
1516: public Value bitAnd(Value rValue) {
1517: return LongValue.create(toLong() & rValue.toLong());
1518: }
1519:
1520: /*
1521: * Binary or.
1522: */
1523: public Value bitOr(Value rValue) {
1524: return LongValue.create(toLong() | rValue.toLong());
1525: }
1526:
1527: /*
1528: * Binary xor.
1529: */
1530: public Value bitXor(Value rValue) {
1531: return LongValue.create(toLong() ^ rValue.toLong());
1532: }
1533:
1534: /**
1535: * Returns the next array index based on this value.
1536: */
1537: public long nextIndex(long oldIndex) {
1538: return oldIndex;
1539: }
1540:
1541: //
1542: // string functions
1543: //
1544:
1545: /**
1546: * Returns the length as a string.
1547: */
1548: public int length() {
1549: return toStringValue().length();
1550: }
1551:
1552: //
1553: // Array functions
1554: //
1555:
1556: /**
1557: * Returns the array size.
1558: */
1559: public int getSize() {
1560: return 1;
1561: }
1562:
1563: /**
1564: * Returns the count, as returned by the global php count() function
1565: */
1566: public int getCount(Env env) {
1567: return 1;
1568: }
1569:
1570: /**
1571: * Returns the count, as returned by the global php count() function
1572: */
1573: public int getCountRecursive(Env env) {
1574: return getCount(env);
1575: }
1576:
1577: /**
1578: * Returns an iterator for the key => value pairs.
1579: */
1580: public Iterator<Map.Entry<Value, Value>> getIterator(Env env) {
1581: Set<Map.Entry<Value, Value>> emptySet = Collections.emptySet();
1582:
1583: return emptySet.iterator();
1584: }
1585:
1586: /**
1587: * Returns an iterator for the field keys.
1588: * The default implementation uses the Iterator returned
1589: * by {@link #getIterator(Env)}; derived classes may override and
1590: * provide a more efficient implementation.
1591: */
1592: public Iterator<Value> getKeyIterator(Env env) {
1593: final Iterator<Map.Entry<Value, Value>> iter = getIterator(env);
1594:
1595: return new Iterator<Value>() {
1596: public boolean hasNext() {
1597: return iter.hasNext();
1598: }
1599:
1600: public Value next() {
1601: return iter.next().getKey();
1602: }
1603:
1604: public void remove() {
1605: iter.remove();
1606: }
1607: };
1608: }
1609:
1610: /**
1611: * Returns the field keys.
1612: */
1613: public Value[] getKeyArray(Env env) {
1614: return NULL_VALUE_ARRAY;
1615: }
1616:
1617: /**
1618: * Returns the field values.
1619: */
1620: public Value[] getValueArray(Env env) {
1621: return NULL_VALUE_ARRAY;
1622: }
1623:
1624: /**
1625: * Returns an iterator for the field values.
1626: * The default implementation uses the Iterator returned
1627: * by {@link #getIterator(Env)}; derived classes may override and
1628: * provide a more efficient implementation.
1629: */
1630: public Iterator<Value> getValueIterator(Env env) {
1631: final Iterator<Map.Entry<Value, Value>> iter = getIterator(env);
1632:
1633: return new Iterator<Value>() {
1634: public boolean hasNext() {
1635: return iter.hasNext();
1636: }
1637:
1638: public Value next() {
1639: return iter.next().getValue();
1640: }
1641:
1642: public void remove() {
1643: iter.remove();
1644: }
1645: };
1646: }
1647:
1648: //
1649: // Object field references
1650: //
1651:
1652: /**
1653: * Returns the field value
1654: */
1655: public Value getField(Env env, StringValue name) {
1656: return NullValue.NULL;
1657: }
1658:
1659: /**
1660: * Returns the field ref.
1661: */
1662: public Value getFieldRef(Env env, StringValue name) {
1663: return getField(env, name);
1664: }
1665:
1666: /**
1667: * Returns the field used as a method argument
1668: */
1669: public Value getFieldArg(Env env, StringValue name) {
1670: return getFieldRef(env, name);
1671: }
1672:
1673: /**
1674: * Returns the field ref for an argument.
1675: */
1676: public Value getFieldArgRef(Env env, StringValue name) {
1677: return getFieldRef(env, name);
1678: }
1679:
1680: /**
1681: * Returns the value for a field, creating an object if the field
1682: * is unset.
1683: */
1684: public Value getFieldObject(Env env, StringValue name) {
1685: Value v = getField(env, name);
1686:
1687: if (!v.isset()) {
1688: v = env.createObject();
1689:
1690: putField(env, name, v);
1691: }
1692:
1693: return v;
1694: }
1695:
1696: /**
1697: * Returns the value for a field, creating an object if the field
1698: * is unset.
1699: */
1700: public Value getFieldArray(Env env, StringValue name) {
1701: Value v = getField(env, name);
1702:
1703: Value array = v.toAutoArray();
1704:
1705: if (v == array)
1706: return v;
1707: else {
1708: putField(env, name, array);
1709:
1710: return array;
1711: }
1712: }
1713:
1714: /**
1715: * Returns the field ref.
1716: */
1717: public Value putField(Env env, StringValue name, Value object) {
1718: return NullValue.NULL;
1719: }
1720:
1721: /**
1722: * Returns true if the field is set
1723: */
1724: public boolean issetField(StringValue name) {
1725: return false;
1726: }
1727:
1728: /**
1729: * Removes the field ref.
1730: */
1731: public void unsetField(StringValue name) {
1732: }
1733:
1734: /**
1735: * Returns the field value
1736: */
1737: public Value getThisField(Env env, StringValue name) {
1738: return getField(env, name);
1739: }
1740:
1741: /**
1742: * Returns the field ref.
1743: */
1744: public Value getThisFieldRef(Env env, StringValue name) {
1745: return getThisField(env, name);
1746: }
1747:
1748: /**
1749: * Returns the field used as a method argument
1750: */
1751: public Value getThisFieldArg(Env env, StringValue name) {
1752: return getThisFieldRef(env, name);
1753: }
1754:
1755: /**
1756: * Returns the field ref for an argument.
1757: */
1758: public Value getThisFieldArgRef(Env env, StringValue name) {
1759: return getThisFieldRef(env, name);
1760: }
1761:
1762: /**
1763: * Returns the value for a field, creating an object if the field
1764: * is unset.
1765: */
1766: public Value getThisFieldObject(Env env, StringValue name) {
1767: Value v = getThisField(env, name);
1768:
1769: if (!v.isset()) {
1770: v = env.createObject();
1771:
1772: putThisField(env, name, v);
1773: }
1774:
1775: return v;
1776: }
1777:
1778: /**
1779: * Returns the value for a field, creating an object if the field
1780: * is unset.
1781: */
1782: public Value getThisFieldArray(Env env, StringValue name) {
1783: Value v = getField(env, name);
1784:
1785: Value array = v.toAutoArray();
1786:
1787: if (v == array)
1788: return v;
1789: else {
1790: putField(env, name, array);
1791:
1792: return array;
1793: }
1794: }
1795:
1796: /**
1797: * Returns the field ref.
1798: */
1799: public Value putThisField(Env env, StringValue name, Value object) {
1800: return putField(env, name, object);
1801: }
1802:
1803: /**
1804: * Returns true if the field is set
1805: */
1806: public boolean issetThisField(StringValue name) {
1807: return issetField(name);
1808: }
1809:
1810: /**
1811: * Removes the field ref.
1812: */
1813: public void unsetThisField(StringValue name) {
1814: unsetField(name);
1815: }
1816:
1817: //
1818: // field convenience
1819: //
1820: public Value putField(Env env, String name, Value value) {
1821: return putThisField(env, env.createString(name), value);
1822: }
1823:
1824: /**
1825: * Returns the array ref.
1826: */
1827: public Value get(Value index) {
1828: return UnsetValue.UNSET;
1829: }
1830:
1831: /**
1832: * Returns a reference to the array value.
1833: */
1834: public Value getRef(Value index) {
1835: return get(index);
1836: }
1837:
1838: /**
1839: * Returns the array ref as a function argument.
1840: */
1841: public Value getArg(Value index) {
1842: return get(index);
1843: }
1844:
1845: /**
1846: * Returns the array value, copying on write if necessary.
1847: */
1848: public Value getDirty(Value index) {
1849: return get(index);
1850: }
1851:
1852: /**
1853: * Returns the value for a field, creating an array if the field
1854: * is unset.
1855: */
1856: public Value getArray() {
1857: return this ;
1858: }
1859:
1860: /**
1861: * Returns the value for a field, creating an array if the field
1862: * is unset.
1863: */
1864: public Value getArray(Value index) {
1865: return NullValue.NULL;
1866: }
1867:
1868: /**
1869: * Returns the value for the variable, creating an object if the var
1870: * is unset.
1871: */
1872: public Value getObject(Env env) {
1873: return NullValue.NULL;
1874: }
1875:
1876: /**
1877: * Returns the value for a field, creating an object if the field
1878: * is unset.
1879: */
1880: public Value getObject(Env env, Value index) {
1881: return NullValue.NULL;
1882: }
1883:
1884: /**
1885: * Sets the value ref.
1886: */
1887: public Value set(Value value) {
1888: return value;
1889: }
1890:
1891: /**
1892: * Sets the array ref.
1893: */
1894: public Value put(Value index, Value value) {
1895: return value;
1896: }
1897:
1898: /**
1899: * Appends an array value
1900: */
1901: public Value put(Value value) {
1902: return value;
1903: }
1904:
1905: /**
1906: * Sets the array ref.
1907: */
1908: public Value putRef() {
1909: return NullValue.NULL;
1910: }
1911:
1912: /**
1913: * Appends the array
1914: */
1915: public Value putArray() {
1916: ArrayValue value = new ArrayValueImpl();
1917:
1918: put(value);
1919:
1920: return value;
1921: }
1922:
1923: /**
1924: * Appends a new object
1925: */
1926: public Value putObject(Env env) {
1927: Value value = env.createObject();
1928:
1929: put(value);
1930:
1931: return value;
1932: }
1933:
1934: /**
1935: * Return true if the array value is set
1936: */
1937: public boolean isset(Value index) {
1938: return false;
1939: }
1940:
1941: /**
1942: * Return unset the value.
1943: */
1944: public Value remove(Value index) {
1945: return UnsetValue.UNSET;
1946: }
1947:
1948: /**
1949: * Takes the values of this array, unmarshalls them to objects of type
1950: * <i>elementType</i>, and puts them in a java array.
1951: */
1952: public Object valuesToArray(Env env, Class elementType) {
1953: env.error(L.l("Can't assign {0} with type {1} to {2}[]", this ,
1954: this .getClass(), elementType));
1955: return null;
1956: }
1957:
1958: /**
1959: * Returns the character at the named index.
1960: */
1961: public Value charValueAt(long index) {
1962: return NullValue.NULL;
1963: }
1964:
1965: /**
1966: * Sets the character at the named index.
1967: */
1968: public Value setCharValueAt(long index, String value) {
1969: return NullValue.NULL;
1970: }
1971:
1972: /**
1973: * Prints the value.
1974: * @param env
1975: */
1976: public void print(Env env) {
1977: env.print(toString(env));
1978: }
1979:
1980: /**
1981: * Prints the value.
1982: * @param env
1983: */
1984: public void print(Env env, WriteStream out) {
1985: try {
1986: out.print(toString(env));
1987: } catch (IOException e) {
1988: throw new QuercusRuntimeException(e);
1989: }
1990: }
1991:
1992: /**
1993: * Serializes the value.
1994: */
1995: public void serialize(StringBuilder sb) {
1996: throw new UnsupportedOperationException(getClass().getName());
1997: }
1998:
1999: /**
2000: * Exports the value.
2001: */
2002: public void varExport(StringBuilder sb) {
2003: throw new UnsupportedOperationException(getClass().getName());
2004: }
2005:
2006: //
2007: // Java generator code
2008: //
2009:
2010: /**
2011: * Generates code to recreate the expression.
2012: *
2013: * @param out the writer to the Java source code.
2014: */
2015: public void generate(PrintWriter out) throws IOException {
2016: }
2017:
2018: protected void printJavaString(PrintWriter out, StringValue s) {
2019: if (s == null) {
2020: out.print("");
2021: return;
2022: }
2023:
2024: int len = s.length();
2025: for (int i = 0; i < len; i++) {
2026: char ch = s.charAt(i);
2027:
2028: switch (ch) {
2029: case '\r':
2030: out.print("\\r");
2031: break;
2032: case '\n':
2033: out.print("\\n");
2034: break;
2035: case '\"':
2036: out.print("\\\"");
2037: break;
2038: case '\'':
2039: out.print("\\\'");
2040: break;
2041: case '\\':
2042: out.print("\\\\");
2043: break;
2044: default:
2045: out.print(ch);
2046: break;
2047: }
2048: }
2049: }
2050:
2051: public String toInternString() {
2052: return toString().intern();
2053: }
2054:
2055: public String toDebugString() {
2056: return toString();
2057: }
2058:
2059: final public void varDump(Env env, WriteStream out, int depth,
2060: IdentityHashMap<Value, String> valueSet) throws IOException {
2061: if (valueSet.get(this ) != null) {
2062: out.print("#recursion#");
2063: return;
2064: }
2065:
2066: valueSet.put(this , "printing");
2067:
2068: try {
2069: varDumpImpl(env, out, depth, valueSet);
2070: } finally {
2071: valueSet.remove(this );
2072: }
2073: }
2074:
2075: protected void varDumpImpl(Env env, WriteStream out, int depth,
2076: IdentityHashMap<Value, String> valueSet) throws IOException {
2077: out.print("resource(" + toString() + ")");
2078: }
2079:
2080: final public void printR(Env env, WriteStream out, int depth,
2081: IdentityHashMap<Value, String> valueSet) throws IOException {
2082: if (valueSet.get(this ) != null) {
2083: out.print("#recursion#");
2084: return;
2085: }
2086:
2087: valueSet.put(this , "printing");
2088:
2089: try {
2090: printRImpl(env, out, depth, valueSet);
2091: } finally {
2092: valueSet.remove(this );
2093: }
2094: }
2095:
2096: protected void printRImpl(Env env, WriteStream out, int depth,
2097: IdentityHashMap<Value, String> valueSet) throws IOException {
2098: out.print(toString());
2099: }
2100:
2101: protected void printDepth(WriteStream out, int depth)
2102: throws IOException {
2103: for (int i = 0; i < depth; i++)
2104: out.print(' ');
2105: }
2106: }
|