コード例 #1
0
 public LHS toLHS(CallStack callstack, Interpreter interpreter) throws EvalError {
   try {
     return getName(callstack.top()).toLHS(callstack, interpreter);
   } catch (UtilEvalError e) {
     throw e.toEvalError(this, callstack);
   }
 }
コード例 #2
0
ファイル: NameSpace.java プロジェクト: svn2github/BeanShell2
  /**
   * Set the value of a the variable 'name' through this namespace. The variable may be an existing
   * or non-existing variable. It may live in this namespace or in a parent namespace if recurse is
   * true.
   *
   * <p>Note: This method is not public and does *not* know about LOCALSCOPING. Its caller methods
   * must set recurse intelligently in all situations (perhaps based on LOCALSCOPING).
   *
   * <p>Note: this method is primarily intended for use internally. If you use this method outside
   * of the bsh package and wish to set variables with primitive values you will have to wrap them
   * using bsh.Primitive.
   *
   * @see bsh.Primitive
   *     <p>Setting a new variable (which didn't exist before) or removing a variable causes a
   *     namespace change.
   * @param strictJava specifies whether strict java rules are applied.
   * @param recurse determines whether we will search for the variable in our parent's scope before
   *     assigning locally.
   */
  void setVariable(String name, Object value, boolean strictJava, boolean recurse)
      throws UtilEvalError {
    ensureVariables();

    // primitives should have been wrapped
    if (value == null) throw new InterpreterError("null variable value");

    // Locate the variable definition if it exists.
    Variable existing = getVariableImpl(name, recurse);

    // Found an existing variable here (or above if recurse allowed)
    if (existing != null) {
      try {
        existing.setValue(value, Variable.ASSIGNMENT);
      } catch (UtilEvalError e) {
        throw new UtilEvalError("Variable assignment: " + name + ": " + e.getMessage());
      }
    } else
    // No previous variable definition found here (or above if recurse)
    {
      if (strictJava)
        throw new UtilEvalError("(Strict Java mode) Assignment to undeclared variable: " + name);

      // If recurse, set global untyped var, else set it here.
      // NameSpace varScope = recurse ? getGlobal() : this;
      // This modification makes default allocation local
      NameSpace varScope = this;

      varScope.variables.put(name, new Variable(name, value, null /*modifiers*/));

      // nameSpaceChanged() on new variable addition
      nameSpaceChanged();
    }
  }
コード例 #3
0
 Object toObject(CallStack callstack, Interpreter interpreter, boolean forceClass)
     throws EvalError {
   try {
     return getName(callstack.top()).toObject(callstack, interpreter, forceClass);
   } catch (UtilEvalError e) {
     throw e.toEvalError(this, callstack);
   }
 }
コード例 #4
0
 public Class toClass(CallStack callstack, Interpreter interpreter) throws EvalError {
   try {
     return getName(callstack.top()).toClass();
   } catch (ClassNotFoundException e) {
     throw new EvalError(e.getMessage(), this, callstack);
   } catch (UtilEvalError e2) {
     // ClassPathException is a type of UtilEvalError
     throw e2.toEvalError(this, callstack);
   }
 }
コード例 #5
0
  /**
   * 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;
  }
コード例 #6
0
  public Object eval(CallStack callstack, Interpreter interpreter) throws EvalError {
    Object lhs = ((SimpleNode) jjtGetChild(0)).eval(callstack, interpreter);

    /*
    	Doing instanceof?  Next node is a type.
    */
    if (kind == INSTANCEOF) {
      // null object ref is not instance of any type
      if (lhs == Primitive.NULL) return new Primitive(false);

      Class rhs = ((BSHType) jjtGetChild(1)).getType(callstack, interpreter);
      /*
      	// primitive (number or void) cannot be tested for instanceof
                if (lhs instanceof Primitive)
      		throw new EvalError("Cannot be instance of primitive type." );
      */
      /*
      	Primitive (number or void) is not normally an instanceof
      	anything.  But for internal use we'll test true for the
      	bsh.Primitive class.
      	i.e. (5 instanceof bsh.Primitive) will be true
      */
      if (lhs instanceof Primitive)
        if (rhs == lib.bsh.Primitive.class) return new Primitive(true);
        else return new Primitive(false);

      // General case - performe the instanceof based on assignability
      boolean ret = Types.isJavaBaseAssignable(rhs, lhs.getClass());
      return new Primitive(ret);
    }

    // The following two boolean checks were tacked on.
    // This could probably be smoothed out.

    /*
    	Look ahead and short circuit evaluation of the rhs if:
    		we're a boolean AND and the lhs is false.
    */
    if (kind == BOOL_AND || kind == BOOL_ANDX) {
      Object obj = lhs;
      if (isPrimitiveValue(lhs)) obj = ((Primitive) lhs).getValue();
      if (obj instanceof Boolean && (((Boolean) obj).booleanValue() == false))
        return new Primitive(false);
    }
    /*
    	Look ahead and short circuit evaluation of the rhs if:
    		we're a boolean AND and the lhs is false.
    */
    if (kind == BOOL_OR || kind == BOOL_ORX) {
      Object obj = lhs;
      if (isPrimitiveValue(lhs)) obj = ((Primitive) lhs).getValue();
      if (obj instanceof Boolean && (((Boolean) obj).booleanValue() == true))
        return new Primitive(true);
    }

    // end stuff that was tacked on for boolean short-circuiting.

    /*
    	Are both the lhs and rhs either wrappers or primitive values?
    	do binary op
    */
    boolean isLhsWrapper = isWrapper(lhs);
    Object rhs = ((SimpleNode) jjtGetChild(1)).eval(callstack, interpreter);
    boolean isRhsWrapper = isWrapper(rhs);
    if ((isLhsWrapper || isPrimitiveValue(lhs)) && (isRhsWrapper || isPrimitiveValue(rhs))) {
      // Special case for EQ on two wrapper objects
      if ((isLhsWrapper && isRhsWrapper && kind == EQ)) {
        /*
        	Don't auto-unwrap wrappers (preserve identity semantics)
        	FALL THROUGH TO OBJECT OPERATIONS BELOW.
        */
      } else
        try {
          return Primitive.binaryOperation(lhs, rhs, kind);
        } catch (UtilEvalError e) {
          throw e.toEvalError(this, callstack);
        }
    }
    /*
    Doing the following makes it hard to use untyped vars...
    e.g. if ( arg == null ) ...what if arg is a primitive?
    The answer is that we should test only if the var is typed...?
    need to get that info here...

    	else
    	{
    	// Do we have a mixture of primitive values and non-primitives ?
    	// (primitiveValue = not null, not void)

    	int primCount = 0;
    	if ( isPrimitiveValue( lhs ) )
    		++primCount;
    	if ( isPrimitiveValue( rhs ) )
    		++primCount;

    	if ( primCount > 1 )
    		// both primitive types, should have been handled above
    		throw new InterpreterError("should not be here");
    	else
    	if ( primCount == 1 )
    		// mixture of one and the other
    		throw new EvalError("Operator: '" + tokenImage[kind]
    			+"' inappropriate for object / primitive combination.",
    			this, callstack );

    	// else fall through to handle both non-primitive types

    	// end check for primitive and non-primitive mix
    	}
    */

    /*
    	Treat lhs and rhs as arbitrary objects and do the operation.
    	(including NULL and VOID represented by their Primitive types)
    */
    // System.out.println("binary op arbitrary obj: {"+lhs+"}, {"+rhs+"}");
    switch (kind) {
      case EQ:
        return new Primitive((lhs == rhs));

      case NE:
        return new Primitive((lhs != rhs));

      case PLUS:
        if (lhs instanceof String || rhs instanceof String) return lhs.toString() + rhs.toString();

        // FALL THROUGH TO DEFAULT CASE!!!

      default:
        if (lhs instanceof Primitive || rhs instanceof Primitive)
          if (lhs == Primitive.VOID || rhs == Primitive.VOID)
            throw new EvalError(
                "illegal use of undefined variable, class, or 'void' literal", this, callstack);
          else if (lhs == Primitive.NULL || rhs == Primitive.NULL)
            throw new EvalError("illegal use of null value or 'null' literal", this, callstack);

        throw new EvalError(
            "Operator: '" + tokenImage[kind] + "' inappropriate for objects", this, callstack);
    }
  }
コード例 #7
0
 public Object eval(CallStack callstack, Interpreter interpreter) throws EvalError {
   Class elementType = null;
   SimpleNode expression;
   SimpleNode statement = null;
   NameSpace enclosingNameSpace = callstack.top();
   SimpleNode firstNode = ((SimpleNode) jjtGetChild(0));
   int nodeCount = jjtGetNumChildren();
   if (firstNode instanceof BSHType) {
     elementType = ((BSHType) firstNode).getType(callstack, interpreter);
     expression = ((SimpleNode) jjtGetChild(1));
     if (nodeCount > 2) {
       statement = ((SimpleNode) jjtGetChild(2));
     }
   } else {
     expression = firstNode;
     if (nodeCount > 1) {
       statement = ((SimpleNode) jjtGetChild(1));
     }
   }
   BlockNameSpace eachNameSpace = new BlockNameSpace(enclosingNameSpace);
   callstack.swap(eachNameSpace);
   final Object iteratee = expression.eval(callstack, interpreter);
   if (iteratee == Primitive.NULL) {
     throw new EvalError(
         "The collection, array, map, iterator, or "
             + "enumeration portion of a for statement cannot be null.",
         this,
         callstack);
   }
   CollectionManager cm = CollectionManager.getCollectionManager();
   if (!cm.isBshIterable(iteratee)) {
     throw new EvalError("Can't iterate over type: " + iteratee.getClass(), this, callstack);
   }
   BshIterator iterator = cm.getBshIterator(iteratee);
   Object returnControl = Primitive.VOID;
   while (iterator.hasNext()) {
     try {
       Object value = iterator.next();
       if (value == null) {
         value = Primitive.NULL;
       }
       if (elementType != null) {
         eachNameSpace.setTypedVariable(
             varName /*name*/, elementType /*type*/, value /*value*/, new Modifiers() /*none*/);
       } else {
         eachNameSpace.setVariable(varName, value, false);
       }
     } catch (UtilEvalError e) {
       throw e.toEvalError("for loop iterator variable:" + varName, this, callstack);
     }
     boolean breakout = false; // switch eats a multi-level break here?
     if (statement != null) {
       // not empty statement
       Object ret = statement.eval(callstack, interpreter);
       if (ret instanceof ReturnControl) {
         switch (((ReturnControl) ret).kind) {
           case RETURN:
             returnControl = ret;
             breakout = true;
             break;
           case CONTINUE:
             break;
           case BREAK:
             breakout = true;
             break;
         }
       }
     }
     if (breakout) {
       break;
     }
   }
   callstack.swap(enclosingNameSpace);
   return returnControl;
 }