package bsh.interpreter;
import bsh.*;
import bsh.ast.BSHAssignment;
import bsh.ast.SimpleNode;
/**
* This file is a part of ZOOLA - an extensible BeanShell implementation.
* Zoola is based on original BeanShell code created by Pat Niemeyer.
* <p/>
* Original BeanShell code is Copyright (C) 2000 Pat Niemeyer <pat@pat.net>.
* <p/>
* New portions are Copyright 2012 Rafal Lewczuk <rafal.lewczuk@jitlogic.com>
* <p/>
* This is free software. You can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
* <p/>
* This software is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
* <p/>
* You should have received a copy of the GNU Lesser General Public License
* along with ZOOLA. If not, see <http://www.gnu.org/licenses/>.
*/
public class BshInterpreterUtil {
public static boolean evaluateCondition(
SimpleNode condExp, BshEvaluatingVisitor visitor)
throws EvalError
{
CallStack callstack = visitor.getCallstack();
Interpreter interpreter = visitor.getInterpreter();
Object obj = condExp.accept(visitor);
if(obj instanceof Primitive) {
if ( obj == Primitive.VOID )
throw new EvalError("Condition evaluates to void type",
condExp, callstack );
obj = ((Primitive)obj).getValue();
}
if(obj instanceof Boolean)
return ((Boolean)obj).booleanValue();
else
throw new EvalError(
"Condition must evaluate to a Boolean or boolean.",
condExp, callstack );
}
/**
*/
public static int getIndexAux(
Object obj, BshEvaluatingVisitor visitor,
SimpleNode callerInfo )
throws EvalError
{
if ( !obj.getClass().isArray() )
throw new EvalError("Not an array", callerInfo, visitor.getCallstack() );
int index;
try {
Object indexVal =
((SimpleNode)callerInfo.jjtGetChild(0)).accept(visitor);
if ( !(indexVal instanceof Primitive) )
indexVal = Types.castObject(
indexVal, Integer.TYPE, Types.ASSIGNMENT);
index = ((Primitive)indexVal).intValue();
} catch( UtilEvalError e ) {
Interpreter.debug("doIndex: "+e);
throw e.toEvalError(
"Arrays may only be indexed by integer types.",
callerInfo, visitor.getCallstack() );
}
return index;
}
public static Object operation(BSHAssignment node, Object lhs, Object rhs, int kind )
throws UtilEvalError
{
/*
Implement String += value;
According to the JLS, value may be anything.
In BeanShell, we'll disallow VOID (undefined) values.
(or should we map them to the empty string?)
*/
if ( lhs instanceof String && rhs != Primitive.VOID ) {
if ( kind != ParserConstants.PLUS )
throw new UtilEvalError(
"Use of non + operator with String LHS" );
return (String)lhs + rhs;
}
if ( lhs instanceof Primitive || rhs instanceof Primitive )
if(lhs == Primitive.VOID || rhs == Primitive.VOID)
throw new UtilEvalError(
"Illegal use of undefined object or 'void' literal" );
else if ( lhs == Primitive.NULL || rhs == Primitive.NULL )
throw new UtilEvalError(
"Illegal use of null object or 'null' literal" );
if( (lhs instanceof Boolean || lhs instanceof Character ||
lhs instanceof Number || lhs instanceof Primitive) &&
(rhs instanceof Boolean || rhs instanceof Character ||
rhs instanceof Number || rhs instanceof Primitive) )
{
return Primitive.binaryOperation(lhs, rhs, kind);
}
throw new UtilEvalError("Non primitive value in operator: " +
lhs.getClass() + " " + node.tokenImage[kind] + " " + rhs.getClass() );
}
public static String getTypeDescriptor( Class clas )
{
if ( clas == Boolean.TYPE ) return "Z";
if ( clas == Character.TYPE ) return "C";
if ( clas == Byte.TYPE ) return "B";
if ( clas == Short.TYPE ) return "S";
if ( clas == Integer.TYPE ) return "I";
if ( clas == Long.TYPE ) return "J";
if ( clas == Float.TYPE ) return "F";
if ( clas == Double.TYPE ) return "D";
if ( clas == Void.TYPE ) return "V";
// Is getName() ok? test with 1.1
String name = clas.getName().replace('.','/');
if ( name.startsWith("[") || name.endsWith(";") )
return name;
else
return "L"+ name.replace('.','/') +";";
}
}