PageRenderTime 57ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

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

#
Java | 184 lines | 108 code | 31 blank | 45 comment | 29 complexity | 6bb3e186784b6250efc76b759bd77da5 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. class BSHAssignment extends SimpleNode implements ParserConstants
  35. {
  36. public int operator;
  37. BSHAssignment(int id) { super(id); }
  38. public Object eval(
  39. CallStack callstack, Interpreter interpreter)
  40. throws EvalError
  41. {
  42. BSHPrimaryExpression lhsNode =
  43. (BSHPrimaryExpression)jjtGetChild(0);
  44. if ( lhsNode == null )
  45. throw new InterpreterError( "Error, null LHSnode" );
  46. boolean strictJava = interpreter.getStrictJava();
  47. LHS lhs = lhsNode.toLHS( callstack, interpreter);
  48. if ( lhs == null )
  49. throw new InterpreterError( "Error, null LHS" );
  50. // For operator-assign operations save the lhs value before evaluating
  51. // the rhs. This is correct Java behavior for postfix operations
  52. // e.g. i=1; i+=i++; // should be 2 not 3
  53. Object lhsValue = null;
  54. if ( operator != ASSIGN ) // assign doesn't need the pre-value
  55. try {
  56. lhsValue = lhs.getValue();
  57. } catch ( UtilEvalError e ) {
  58. throw e.toEvalError( this, callstack );
  59. }
  60. SimpleNode rhsNode = (SimpleNode)jjtGetChild(1);
  61. Object rhs;
  62. // implement "blocks" foo = { };
  63. // if ( rhsNode instanceof BSHBlock )
  64. // rsh =
  65. // else
  66. rhs = rhsNode.eval(callstack, interpreter);
  67. if ( rhs == Primitive.VOID )
  68. throw new EvalError("Void assignment.", this, callstack );
  69. try {
  70. switch(operator)
  71. {
  72. case ASSIGN:
  73. return lhs.assign( rhs, strictJava );
  74. case PLUSASSIGN:
  75. return lhs.assign(
  76. operation(lhsValue, rhs, PLUS), strictJava );
  77. case MINUSASSIGN:
  78. return lhs.assign(
  79. operation(lhsValue, rhs, MINUS), strictJava );
  80. case STARASSIGN:
  81. return lhs.assign(
  82. operation(lhsValue, rhs, STAR), strictJava );
  83. case SLASHASSIGN:
  84. return lhs.assign(
  85. operation(lhsValue, rhs, SLASH), strictJava );
  86. case ANDASSIGN:
  87. case ANDASSIGNX:
  88. return lhs.assign(
  89. operation(lhsValue, rhs, BIT_AND), strictJava );
  90. case ORASSIGN:
  91. case ORASSIGNX:
  92. return lhs.assign(
  93. operation(lhsValue, rhs, BIT_OR), strictJava );
  94. case XORASSIGN:
  95. return lhs.assign(
  96. operation(lhsValue, rhs, XOR), strictJava );
  97. case MODASSIGN:
  98. return lhs.assign(
  99. operation(lhsValue, rhs, MOD), strictJava );
  100. case LSHIFTASSIGN:
  101. case LSHIFTASSIGNX:
  102. return lhs.assign(
  103. operation(lhsValue, rhs, LSHIFT), strictJava );
  104. case RSIGNEDSHIFTASSIGN:
  105. case RSIGNEDSHIFTASSIGNX:
  106. return lhs.assign(
  107. operation(lhsValue, rhs, RSIGNEDSHIFT ), strictJava );
  108. case RUNSIGNEDSHIFTASSIGN:
  109. case RUNSIGNEDSHIFTASSIGNX:
  110. return lhs.assign(
  111. operation(lhsValue, rhs, RUNSIGNEDSHIFT),
  112. strictJava );
  113. default:
  114. throw new InterpreterError(
  115. "unimplemented operator in assignment BSH");
  116. }
  117. } catch ( UtilEvalError e ) {
  118. throw e.toEvalError( this, callstack );
  119. }
  120. }
  121. private Object operation( Object lhs, Object rhs, int kind )
  122. throws UtilEvalError
  123. {
  124. /*
  125. Implement String += value;
  126. According to the JLS, value may be anything.
  127. In BeanShell, we'll disallow VOID (undefined) values.
  128. (or should we map them to the empty string?)
  129. */
  130. if ( lhs instanceof String && rhs != Primitive.VOID ) {
  131. if ( kind != PLUS )
  132. throw new UtilEvalError(
  133. "Use of non + operator with String LHS" );
  134. return (String)lhs + rhs;
  135. }
  136. if ( lhs instanceof Primitive || rhs instanceof Primitive )
  137. if(lhs == Primitive.VOID || rhs == Primitive.VOID)
  138. throw new UtilEvalError(
  139. "Illegal use of undefined object or 'void' literal" );
  140. else if ( lhs == Primitive.NULL || rhs == Primitive.NULL )
  141. throw new UtilEvalError(
  142. "Illegal use of null object or 'null' literal" );
  143. if( (lhs instanceof Boolean || lhs instanceof Character ||
  144. lhs instanceof Number || lhs instanceof Primitive) &&
  145. (rhs instanceof Boolean || rhs instanceof Character ||
  146. rhs instanceof Number || rhs instanceof Primitive) )
  147. {
  148. return Primitive.binaryOperation(lhs, rhs, kind);
  149. }
  150. throw new UtilEvalError("Non primitive value in operator: " +
  151. lhs.getClass() + " " + tokenImage[kind] + " " + rhs.getClass() );
  152. }
  153. }