/** * 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(); } }
/** * Declare a variable in the local scope and set its initial value. Value may be null to indicate * that we would like the default value for the variable type. (e.g. 0 for integer types, null for * object types). An existing typed variable may only be set to the same type. If an untyped * variable of the same name exists it will be overridden with the new typed var. The set will * perform a Types.getAssignableForm() on the value if necessary. * * <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 * @param value If value is null, you'll get the default value for the type * @param modifiers may be null */ public void setTypedVariable(String name, Class type, Object value, Modifiers modifiers) throws UtilEvalError { // checkVariableModifiers( name, modifiers ); ensureVariables(); // Setting a typed variable is always a local operation. Variable existing = getVariableImpl(name, false /*recurse*/); // Null value is just a declaration // Note: we might want to keep any existing value here instead of reset /* // Moved to Variable if ( value == null ) value = Primitive.getDefaultValue( type ); */ // does the variable already exist? if (existing != null) { // Is it typed? if (existing.getType() != null) { // If it had a different type throw error. // This allows declaring the same var again, but not with // a different (even if assignable) type. if (existing.getType() != type) { throw new UtilEvalError( "Typed variable: " + name + " was previously declared with type: " + existing.getType()); } else { // else set it and return existing.setValue(value, Variable.DECLARATION); return; } } // Careful here: // else fall through to override and install the new typed version } // Add the new typed var variables.put(name, new Variable(name, type, value, modifiers)); }