001: /*****************************************************************************
002: * *
003: * This file is part of the BeanShell Java Scripting distribution. *
004: * Documentation and updates may be found at http://www.beanshell.org/ *
005: * *
006: * Sun Public License Notice: *
007: * *
008: * The contents of this file are subject to the Sun Public License Version *
009: * 1.0 (the "License"); you may not use this file except in compliance with *
010: * the License. A copy of the License is available at http://www.sun.com *
011: * *
012: * The Original Code is BeanShell. The Initial Developer of the Original *
013: * Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright *
014: * (C) 2000. All Rights Reserved. *
015: * *
016: * GNU Public License Notice: *
017: * *
018: * Alternatively, the contents of this file may be used under the terms of *
019: * the GNU Lesser General Public License (the "LGPL"), in which case the *
020: * provisions of LGPL are applicable instead of those above. If you wish to *
021: * allow use of your version of this file only under the terms of the LGPL *
022: * and not to allow others to use your version of this file under the SPL, *
023: * indicate your decision by deleting the provisions above and replace *
024: * them with the notice and other provisions required by the LGPL. If you *
025: * do not delete the provisions above, a recipient may use your version of *
026: * this file under either the SPL or the LGPL. *
027: * *
028: * Patrick Niemeyer (pat@pat.net) *
029: * Author of Learning Java, O'Reilly & Associates *
030: * http://www.pat.net/~pat/ *
031: * *
032: *****************************************************************************/package bsh;
033:
034: class BSHBlock extends SimpleNode {
035: public boolean isSynchronized = false;
036: public boolean isStatic = false;
037:
038: BSHBlock(int id) {
039: super (id);
040: }
041:
042: public Object eval(CallStack callstack, Interpreter interpreter)
043: throws EvalError {
044: return eval(callstack, interpreter, false);
045: }
046:
047: /**
048: @param overrideNamespace if set to true the block will be executed
049: in the current namespace (not a subordinate one).
050: <p>
051: If true *no* new BlockNamespace will be swapped onto the stack and
052: the eval will happen in the current
053: top namespace. This is used by BshMethod, TryStatement, etc.
054: which must intialize the block first and also for those that perform
055: multiple passes in the same block.
056: */
057: public Object eval(CallStack callstack, Interpreter interpreter,
058: boolean overrideNamespace) throws EvalError {
059: Object syncValue = null;
060: if (isSynchronized) {
061: // First node is the expression on which to sync
062: SimpleNode exp = ((SimpleNode) jjtGetChild(0));
063: syncValue = exp.eval(callstack, interpreter);
064: }
065:
066: Object ret;
067: if (isSynchronized) // Do the actual synchronization
068: synchronized (syncValue) {
069: ret = evalBlock(callstack, interpreter,
070: overrideNamespace, null/*filter*/);
071: }
072: else
073: ret = evalBlock(callstack, interpreter, overrideNamespace,
074: null/*filter*/);
075:
076: return ret;
077: }
078:
079: Object evalBlock(CallStack callstack, Interpreter interpreter,
080: boolean overrideNamespace, NodeFilter nodeFilter)
081: throws EvalError {
082: Object ret = Primitive.VOID;
083: NameSpace enclosingNameSpace = null;
084: if (!overrideNamespace) {
085: enclosingNameSpace = callstack.top();
086: BlockNameSpace bodyNameSpace = new BlockNameSpace(
087: enclosingNameSpace);
088:
089: callstack.swap(bodyNameSpace);
090: }
091:
092: int startChild = isSynchronized ? 1 : 0;
093: int numChildren = jjtGetNumChildren();
094:
095: try {
096: /*
097: Evaluate block in two passes:
098: First do class declarations then do everything else.
099: */
100: for (int i = startChild; i < numChildren; i++) {
101: SimpleNode node = ((SimpleNode) jjtGetChild(i));
102:
103: if (nodeFilter != null && !nodeFilter.isVisible(node))
104: continue;
105:
106: if (node instanceof BSHClassDeclaration)
107: node.eval(callstack, interpreter);
108: }
109: for (int i = startChild; i < numChildren; i++) {
110: SimpleNode node = ((SimpleNode) jjtGetChild(i));
111: if (node instanceof BSHClassDeclaration)
112: continue;
113:
114: // filter nodes
115: if (nodeFilter != null && !nodeFilter.isVisible(node))
116: continue;
117:
118: ret = node.eval(callstack, interpreter);
119:
120: // statement or embedded block evaluated a return statement
121: if (ret instanceof ReturnControl)
122: break;
123: }
124: } finally {
125: // make sure we put the namespace back when we leave.
126: if (!overrideNamespace)
127: callstack.swap(enclosingNameSpace);
128: }
129: return ret;
130: }
131:
132: public interface NodeFilter {
133: public boolean isVisible(SimpleNode node);
134: }
135:
136: }
|