PageRenderTime 68ms CodeModel.GetById 30ms app.highlight 7ms RepoModel.GetById 20ms app.codeStats 0ms

/jEdit/tags/jedit-4-3-pre5/bsh/BlockNameSpace.java

#
Java | 192 lines | 54 code | 14 blank | 124 comment | 3 complexity | 1fb014a806b8853f3e4b547c12a383ac MD5 | raw file
  1/*****************************************************************************
  2 *                                                                           *
  3 *  This file is part of the BeanShell Java Scripting distribution.          *
  4 *  Documentation and updates may be found at http://www.beanshell.org/      *
  5 *                                                                           *
  6 *  Sun Public License Notice:                                               *
  7 *                                                                           *
  8 *  The contents of this file are subject to the Sun Public License Version  *
  9 *  1.0 (the "License"); you may not use this file except in compliance with *
 10 *  the License. A copy of the License is available at http://www.sun.com    * 
 11 *                                                                           *
 12 *  The Original Code is BeanShell. The Initial Developer of the Original    *
 13 *  Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright     *
 14 *  (C) 2000.  All Rights Reserved.                                          *
 15 *                                                                           *
 16 *  GNU Public License Notice:                                               *
 17 *                                                                           *
 18 *  Alternatively, the contents of this file may be used under the terms of  *
 19 *  the GNU Lesser General Public License (the "LGPL"), in which case the    *
 20 *  provisions of LGPL are applicable instead of those above. If you wish to *
 21 *  allow use of your version of this file only under the  terms of the LGPL *
 22 *  and not to allow others to use your version of this file under the SPL,  *
 23 *  indicate your decision by deleting the provisions above and replace      *
 24 *  them with the notice and other provisions required by the LGPL.  If you  *
 25 *  do not delete the provisions above, a recipient may use your version of  *
 26 *  this file under either the SPL or the LGPL.                              *
 27 *                                                                           *
 28 *  Patrick Niemeyer (pat@pat.net)                                           *
 29 *  Author of Learning Java, O'Reilly & Associates                           *
 30 *  http://www.pat.net/~pat/                                                 *
 31 *                                                                           *
 32 *****************************************************************************/
 33
 34package	bsh;
 35
 36/**
 37    A specialized namespace	for Blocks (e.g. the body of a "for" statement).
 38	The Block acts like a child namespace but only for typed variables 
 39	declared within it (block local scope) or untyped variables explicitly set 
 40	in it via setBlockVariable().  Otherwise variable assignment 
 41	(including untyped variable usage) acts like it is part of the containing
 42	block.  
 43	<p>
 44*/
 45/*
 46	Note: This class essentially just delegates most of its methods to its
 47	parent.  The setVariable() indirection is very small.  We could probably
 48	fold this functionality back into the base NameSpace as a special case.
 49	But this has changed a few times so I'd like to leave this abstraction for
 50	now.
 51*/
 52class BlockNameSpace extends NameSpace 
 53{
 54    public BlockNameSpace( NameSpace parent ) 
 55		throws EvalError
 56	{
 57		super( parent, parent.getName()+ "/BlockNameSpace" );
 58    }
 59
 60	/**
 61		Override the standard namespace behavior to make assignments
 62		happen in our parent (enclosing) namespace, unless the variable has
 63		already been assigned here via a typed declaration or through
 64		the special setBlockVariable() (used for untyped args in try/catch).
 65		<p>
 66		i.e. only allow typed var declaration to happen in this namespace.
 67		Typed vars are handled in the ordinary way local scope.  All untyped
 68		assignments are delegated to the enclosing context.
 69	*/
 70	/*
 71		Note: it may see like with the new 1.3 scoping this test could be
 72		removed, but it cannot.  When recurse is false we still need to set the
 73		variable in our parent, not here.
 74	*/
 75    public void	setVariable( 
 76		String name, Object value, boolean strictJava, boolean recurse ) 
 77		throws UtilEvalError 
 78	{
 79		if ( weHaveVar( name ) ) 
 80			// set the var here in the block namespace
 81			super.setVariable( name, value, strictJava, false );
 82		else
 83			// set the var in the enclosing (parent) namespace
 84			getParent().setVariable( name, value, strictJava, recurse );
 85    }
 86
 87	/**
 88		Set an untyped variable in the block namespace.
 89		The BlockNameSpace would normally delegate this set to the parent.
 90		Typed variables are naturally set locally.
 91		This is used in try/catch block argument. 
 92	*/
 93    public void	setBlockVariable( String name, Object value ) 
 94		throws UtilEvalError 
 95	{
 96		super.setVariable( name, value, false/*strict?*/, false );
 97	}
 98
 99	/**
100		We have the variable: either it was declared here with a type, giving
101		it block local scope or an untyped var was explicitly set here via
102		setBlockVariable().
103	*/
104	private boolean weHaveVar( String name ) 
105	{
106		// super.variables.containsKey( name ) not any faster, I checked
107		try {
108			return super.getVariableImpl( name, false ) != null;
109		} catch ( UtilEvalError e ) { return false; }
110	}
111
112/**
113		Get the actual BlockNameSpace 'this' reference.
114		<p/>
115		Normally a 'this' reference to a BlockNameSpace (e.g. if () { } )
116		resolves to the parent namespace (e.g. the namespace containing the
117		"if" statement).  However when code inside the BlockNameSpace needs to
118		resolve things relative to 'this' we must use the actual block's 'this'
119		reference.  Name.java is smart enough to handle this using
120		getBlockThis().
121		@see #getThis( Interpreter )
122    This getBlockThis( Interpreter declaringInterpreter ) 
123	{
124		return super.getThis( declaringInterpreter );
125	}
126*/
127
128	//
129	// Begin methods which simply delegate to our parent (enclosing scope) 
130	//
131
132	/**
133		This method recurses to find the nearest non-BlockNameSpace parent.
134
135	public NameSpace getParent() 
136	{
137		NameSpace parent = super.getParent();
138		if ( parent instanceof BlockNameSpace )
139			return parent.getParent();
140		else
141			return parent;
142	}
143*/
144	/** do we need this? */
145	private NameSpace getNonBlockParent() 
146	{
147		NameSpace parent = super.getParent();
148		if ( parent instanceof BlockNameSpace )
149			return ((BlockNameSpace)parent).getNonBlockParent();
150		else
151			return parent;
152	}
153
154	/**
155		Get a 'this' reference is our parent's 'this' for the object closure.
156		e.g. Normally a 'this' reference to a BlockNameSpace (e.g. if () { } )
157		resolves to the parent namespace (e.g. the namespace containing the
158		"if" statement). 
159		@see #getBlockThis( Interpreter )
160	*/
161    This getThis( Interpreter declaringInterpreter ) {
162		return getNonBlockParent().getThis( declaringInterpreter );
163	}
164
165	/**
166		super is our parent's super
167	*/
168    public This getSuper( Interpreter declaringInterpreter ) {
169		return getNonBlockParent().getSuper( declaringInterpreter );
170	}
171
172	/**
173		delegate import to our parent
174	*/
175    public void	importClass(String name) {
176		getParent().importClass( name );
177	}
178
179	/**
180		delegate import to our parent
181	*/
182    public void	importPackage(String name) {
183		getParent().importPackage( name );
184	}
185
186    public void	setMethod(String name, BshMethod method) 
187		throws UtilEvalError
188	{
189		getParent().setMethod( name, method );
190	}
191}
192