/*****************************************************************************
* *
* This file is part of the BeanShell Java Scripting distribution. *
* Documentation and updates may be found at http://www.beanshell.org/ *
* *
* Sun Public License Notice: *
* *
* The contents of this file are subject to the Sun Public License Version *
* 1.0 (the "License"); you may not use this file except in compliance with *
* the License. A copy of the License is available at http://www.sun.com *
* *
* The Original Code is BeanShell. The Initial Developer of the Original *
* Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright *
* (C) 2000. All Rights Reserved. *
* *
* GNU Public License Notice: *
* *
* Alternatively, the contents of this file may be used under the terms of *
* the GNU Lesser General Public License (the "LGPL"), in which case the *
* provisions of LGPL are applicable instead of those above. If you wish to *
* allow use of your version of this file only under the terms of the LGPL *
* and not to allow others to use your version of this file under the SPL, *
* indicate your decision by deleting the provisions above and replace *
* them with the notice and other provisions required by the LGPL. If you *
* do not delete the provisions above, a recipient may use your version of *
* this file under either the SPL or the LGPL. *
* *
* Patrick Niemeyer (pat@pat.net) *
* Author of Learning Java, O'Reilly & Associates *
* http://www.pat.net/~pat/ *
* *
*****************************************************************************/
package bsh;
import java.lang.reflect.
Array;
class
BSHArrayInitializer extends
SimpleNode
{
BSHArrayInitializer(int
id) { super(
id); }
public
Object eval(
CallStack callstack,
Interpreter interpreter )
throws
EvalError
{
throw new
EvalError( "Array initializer has no base type.",
this,
callstack );
}
/**
Construct the array from the initializer syntax.
@param baseType the base class type of the array (no dimensionality)
@param dimensions the top number of dimensions of the array
e.g. 2 for a String [][];
*/
public
Object eval(
Class baseType, int
dimensions,
CallStack callstack,
Interpreter interpreter )
throws
EvalError
{
int
numInitializers =
jjtGetNumChildren();
// allocate the array to store the initializers
int []
dima = new int [
dimensions]; // description of the array
// The other dimensions default to zero and are assigned when
// the values are set.
dima[0] =
numInitializers;
Object initializers =
Array.
newInstance(
baseType,
dima );
// Evaluate the initializers
for (int
i = 0;
i <
numInitializers;
i++)
{
SimpleNode node = (
SimpleNode)
jjtGetChild(
i);
Object currentInitializer;
if (
node instanceof
BSHArrayInitializer ) {
if (
dimensions < 2 )
throw new
EvalError(
"Invalid Location for Intializer, position: "+
i,
this,
callstack );
currentInitializer =
((
BSHArrayInitializer)
node).
eval(
baseType,
dimensions-1,
callstack,
interpreter);
} else
currentInitializer =
node.
eval(
callstack,
interpreter);
if (
currentInitializer ==
Primitive.
VOID )
throw new
EvalError(
"Void in array initializer, position"+
i, this,
callstack );
// Determine if any conversion is necessary on the initializers.
//
// Quick test to see if conversions apply:
// If the dimensionality of the array is 1 then the elements of
// the initializer can be primitives or boxable types. If it is
// greater then the values must be array (object) types and there
// are currently no conversions that we do on those.
// If we have conversions on those in the future then we need to
// get the real base type here instead of the dimensionless one.
Object value =
currentInitializer;
if (
dimensions == 1 )
{
// We do a bsh cast here. strictJava should be able to affect
// the cast there when we tighten control
try {
value =
Types.
castObject(
currentInitializer,
baseType,
Types.
CAST );
} catch (
UtilEvalError e ) {
throw
e.
toEvalError(
"Error in array initializer", this,
callstack );
}
// unwrap any primitive, map voids to null, etc.
value =
Primitive.
unwrap(
value );
}
// store the value in the array
try {
Array.
set(
initializers,
i,
value);
} catch(
IllegalArgumentException e ) {
Interpreter.
debug("illegal arg"+
e);
throwTypeError(
baseType,
currentInitializer,
i,
callstack );
} catch(
ArrayStoreException e ) { // I think this can happen
Interpreter.
debug("arraystore"+
e);
throwTypeError(
baseType,
currentInitializer,
i,
callstack );
}
}
return
initializers;
}
private void
throwTypeError(
Class baseType,
Object initializer, int
argNum,
CallStack callstack )
throws
EvalError
{
String rhsType;
if (
initializer instanceof
Primitive)
rhsType =
((
Primitive)
initializer).
getType().
getName();
else
rhsType =
Reflect.
normalizeClassName(
initializer.
getClass());
throw new
EvalError ( "Incompatible type: " +
rhsType
+" in initializer of array type: "+
baseType
+" at position: "+
argNum, this,
callstack );
}
}