/** * Return the Element which corresponds to the given variable name. It will first check local * variables and then the parent context. This method will return null if the variable doesn't * exist or the argument is null. Note that this will clone the final value, if it originated from * a global variable. * * @param name name of the variable to lookup * @param lookupOnly flag indicating if only a lookup should be done * @param terms values for dereferencing the given variable * @return Element value of the associated dereferenced variable */ public Element dereferenceVariable(String name, boolean lookupOnly, Term[] terms) throws InvalidTermException { boolean duplicate = false; Element result = localVariables.get(name); // If the result is null, then try to look up a global variable. if (result == null) { duplicate = true; result = getGlobalVariable(name); } // Now actually dereference the given variable. The caller must deal // with any invalid term exceptions or evaluation exceptions. We just // pass those on. if (result != null) { if (!(result instanceof Undef)) { // FIXME: Determine if the result needs to be protected. result = result.rget(terms, 0, false, lookupOnly); } else { // Trying to dereference an undefined value. Therefore, the // value does not exist; return null to caller. result = null; } } // FIXME: This is inefficient and should be avoided. However, one must // ensure that global variables are protected against changes. // To ensure that global variables are not inadvertently modified via // copies in local variables, duplicate the result. Do this only AFTER // the dereference to limit the amount of potentially unnecessary // cloning. if (duplicate && result != null) { result = result.duplicate(); } return result; }