PageRenderTime 39ms CodeModel.GetById 13ms RepoModel.GetById 0ms 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
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  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. package bsh;
  34. /**
  35. A specialized namespace for Blocks (e.g. the body of a "for" statement).
  36. The Block acts like a child namespace but only for typed variables
  37. declared within it (block local scope) or untyped variables explicitly set
  38. in it via setBlockVariable(). Otherwise variable assignment
  39. (including untyped variable usage) acts like it is part of the containing
  40. block.
  41. <p>
  42. */
  43. /*
  44. Note: This class essentially just delegates most of its methods to its
  45. parent. The setVariable() indirection is very small. We could probably
  46. fold this functionality back into the base NameSpace as a special case.
  47. But this has changed a few times so I'd like to leave this abstraction for
  48. now.
  49. */
  50. class BlockNameSpace extends NameSpace
  51. {
  52. public BlockNameSpace( NameSpace parent )
  53. throws EvalError
  54. {
  55. super( parent, parent.getName()+ "/BlockNameSpace" );
  56. }
  57. /**
  58. Override the standard namespace behavior to make assignments
  59. happen in our parent (enclosing) namespace, unless the variable has
  60. already been assigned here via a typed declaration or through
  61. the special setBlockVariable() (used for untyped args in try/catch).
  62. <p>
  63. i.e. only allow typed var declaration to happen in this namespace.
  64. Typed vars are handled in the ordinary way local scope. All untyped
  65. assignments are delegated to the enclosing context.
  66. */
  67. /*
  68. Note: it may see like with the new 1.3 scoping this test could be
  69. removed, but it cannot. When recurse is false we still need to set the
  70. variable in our parent, not here.
  71. */
  72. public void setVariable(
  73. String name, Object value, boolean strictJava, boolean recurse )
  74. throws UtilEvalError
  75. {
  76. if ( weHaveVar( name ) )
  77. // set the var here in the block namespace
  78. super.setVariable( name, value, strictJava, false );
  79. else
  80. // set the var in the enclosing (parent) namespace
  81. getParent().setVariable( name, value, strictJava, recurse );
  82. }
  83. /**
  84. Set an untyped variable in the block namespace.
  85. The BlockNameSpace would normally delegate this set to the parent.
  86. Typed variables are naturally set locally.
  87. This is used in try/catch block argument.
  88. */
  89. public void setBlockVariable( String name, Object value )
  90. throws UtilEvalError
  91. {
  92. super.setVariable( name, value, false/*strict?*/, false );
  93. }
  94. /**
  95. We have the variable: either it was declared here with a type, giving
  96. it block local scope or an untyped var was explicitly set here via
  97. setBlockVariable().
  98. */
  99. private boolean weHaveVar( String name )
  100. {
  101. // super.variables.containsKey( name ) not any faster, I checked
  102. try {
  103. return super.getVariableImpl( name, false ) != null;
  104. } catch ( UtilEvalError e ) { return false; }
  105. }
  106. /**
  107. Get the actual BlockNameSpace 'this' reference.
  108. <p/>
  109. Normally a 'this' reference to a BlockNameSpace (e.g. if () { } )
  110. resolves to the parent namespace (e.g. the namespace containing the
  111. "if" statement). However when code inside the BlockNameSpace needs to
  112. resolve things relative to 'this' we must use the actual block's 'this'
  113. reference. Name.java is smart enough to handle this using
  114. getBlockThis().
  115. @see #getThis( Interpreter )
  116. This getBlockThis( Interpreter declaringInterpreter )
  117. {
  118. return super.getThis( declaringInterpreter );
  119. }
  120. */
  121. //
  122. // Begin methods which simply delegate to our parent (enclosing scope)
  123. //
  124. /**
  125. This method recurses to find the nearest non-BlockNameSpace parent.
  126. public NameSpace getParent()
  127. {
  128. NameSpace parent = super.getParent();
  129. if ( parent instanceof BlockNameSpace )
  130. return parent.getParent();
  131. else
  132. return parent;
  133. }
  134. */
  135. /** do we need this? */
  136. private NameSpace getNonBlockParent()
  137. {
  138. NameSpace parent = super.getParent();
  139. if ( parent instanceof BlockNameSpace )
  140. return ((BlockNameSpace)parent).getNonBlockParent();
  141. else
  142. return parent;
  143. }
  144. /**
  145. Get a 'this' reference is our parent's 'this' for the object closure.
  146. e.g. Normally a 'this' reference to a BlockNameSpace (e.g. if () { } )
  147. resolves to the parent namespace (e.g. the namespace containing the
  148. "if" statement).
  149. @see #getBlockThis( Interpreter )
  150. */
  151. This getThis( Interpreter declaringInterpreter ) {
  152. return getNonBlockParent().getThis( declaringInterpreter );
  153. }
  154. /**
  155. super is our parent's super
  156. */
  157. public This getSuper( Interpreter declaringInterpreter ) {
  158. return getNonBlockParent().getSuper( declaringInterpreter );
  159. }
  160. /**
  161. delegate import to our parent
  162. */
  163. public void importClass(String name) {
  164. getParent().importClass( name );
  165. }
  166. /**
  167. delegate import to our parent
  168. */
  169. public void importPackage(String name) {
  170. getParent().importPackage( name );
  171. }
  172. public void setMethod(String name, BshMethod method)
  173. throws UtilEvalError
  174. {
  175. getParent().setMethod( name, method );
  176. }
  177. }