001: /*****************************************************************************
002: * *
003: * This file is part of the BeanShell Java Scripting distribution. *
004: * Documentation and updates may be found at http://www.beanshell.org/ *
005: * *
006: * Sun Public License Notice: *
007: * *
008: * The contents of this file are subject to the Sun Public License Version *
009: * 1.0 (the "License"); you may not use this file except in compliance with *
010: * the License. A copy of the License is available at http://www.sun.com *
011: * *
012: * The Original Code is BeanShell. The Initial Developer of the Original *
013: * Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright *
014: * (C) 2000. All Rights Reserved. *
015: * *
016: * GNU Public License Notice: *
017: * *
018: * Alternatively, the contents of this file may be used under the terms of *
019: * the GNU Lesser General Public License (the "LGPL"), in which case the *
020: * provisions of LGPL are applicable instead of those above. If you wish to *
021: * allow use of your version of this file only under the terms of the LGPL *
022: * and not to allow others to use your version of this file under the SPL, *
023: * indicate your decision by deleting the provisions above and replace *
024: * them with the notice and other provisions required by the LGPL. If you *
025: * do not delete the provisions above, a recipient may use your version of *
026: * this file under either the SPL or the LGPL. *
027: * *
028: * Patrick Niemeyer (pat@pat.net) *
029: * Author of Learning Java, O'Reilly & Associates *
030: * http://www.pat.net/~pat/ *
031: * *
032: *****************************************************************************/package bsh;
033:
034: import java.lang.reflect.Array;
035:
036: class BSHArrayInitializer extends SimpleNode {
037: BSHArrayInitializer(int id) {
038: super (id);
039: }
040:
041: public Object eval(CallStack callstack, Interpreter interpreter)
042: throws EvalError {
043: throw new EvalError("Array initializer has no base type.",
044: this , callstack);
045: }
046:
047: /**
048: Construct the array from the initializer syntax.
049:
050: @param baseType the base class type of the array (no dimensionality)
051: @param dimensions the top number of dimensions of the array
052: e.g. 2 for a String [][];
053: */
054: public Object eval(Class baseType, int dimensions,
055: CallStack callstack, Interpreter interpreter)
056: throws EvalError {
057: int numInitializers = jjtGetNumChildren();
058:
059: // allocate the array to store the initializers
060: int[] dima = new int[dimensions]; // description of the array
061: // The other dimensions default to zero and are assigned when
062: // the values are set.
063: dima[0] = numInitializers;
064: Object initializers = Array.newInstance(baseType, dima);
065:
066: // Evaluate the initializers
067: for (int i = 0; i < numInitializers; i++) {
068: SimpleNode node = (SimpleNode) jjtGetChild(i);
069: Object currentInitializer;
070: if (node instanceof BSHArrayInitializer) {
071: if (dimensions < 2)
072: throw new EvalError(
073: "Invalid Location for Intializer, position: "
074: + i, this , callstack);
075: currentInitializer = ((BSHArrayInitializer) node).eval(
076: baseType, dimensions - 1, callstack,
077: interpreter);
078: } else
079: currentInitializer = node.eval(callstack, interpreter);
080:
081: if (currentInitializer == Primitive.VOID)
082: throw new EvalError(
083: "Void in array initializer, position" + i,
084: this , callstack);
085:
086: // Determine if any conversion is necessary on the initializers.
087: //
088: // Quick test to see if conversions apply:
089: // If the dimensionality of the array is 1 then the elements of
090: // the initializer can be primitives or boxable types. If it is
091: // greater then the values must be array (object) types and there
092: // are currently no conversions that we do on those.
093: // If we have conversions on those in the future then we need to
094: // get the real base type here instead of the dimensionless one.
095: Object value = currentInitializer;
096: if (dimensions == 1) {
097: // We do a bsh cast here. strictJava should be able to affect
098: // the cast there when we tighten control
099: try {
100: value = Types.castObject(currentInitializer,
101: baseType, Types.CAST);
102: } catch (UtilEvalError e) {
103: throw e.toEvalError("Error in array initializer",
104: this , callstack);
105: }
106: // unwrap any primitive, map voids to null, etc.
107: value = Primitive.unwrap(value);
108: }
109:
110: // store the value in the array
111: try {
112: Array.set(initializers, i, value);
113: } catch (IllegalArgumentException e) {
114: Interpreter.debug("illegal arg" + e);
115: throwTypeError(baseType, currentInitializer, i,
116: callstack);
117: } catch (ArrayStoreException e) { // I think this can happen
118: Interpreter.debug("arraystore" + e);
119: throwTypeError(baseType, currentInitializer, i,
120: callstack);
121: }
122: }
123:
124: return initializers;
125: }
126:
127: private void throwTypeError(Class baseType, Object initializer,
128: int argNum, CallStack callstack) throws EvalError {
129: String rhsType;
130: if (initializer instanceof Primitive)
131: rhsType = ((Primitive) initializer).getType().getName();
132: else
133: rhsType = Reflect
134: .normalizeClassName(initializer.getClass());
135:
136: throw new EvalError("Incompatible type: " + rhsType
137: + " in initializer of array type: " + baseType
138: + " at position: " + argNum, this, callstack);
139: }
140:
141: }
|