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 org.gjt.sp.jedit.bsh;
033:
034: class BSHMethodDeclaration extends SimpleNode {
035: public String name;
036:
037: // Begin Child node structure evaluated by insureNodesParsed
038:
039: BSHReturnType returnTypeNode;
040: BSHFormalParameters paramsNode;
041: BSHBlock blockNode;
042: // index of the first throws clause child node
043: int firstThrowsClause;
044:
045: // End Child node structure evaluated by insureNodesParsed
046:
047: public Modifiers modifiers;
048:
049: // Unsafe caching of type here.
050: Class returnType; // null (none), Void.TYPE, or a Class
051: int numThrows = 0;
052:
053: BSHMethodDeclaration(int id) {
054: super (id);
055: }
056:
057: /**
058: Set the returnTypeNode, paramsNode, and blockNode based on child
059: node structure. No evaluation is done here.
060: */
061: synchronized void insureNodesParsed() {
062: if (paramsNode != null) // there is always a paramsNode
063: return;
064:
065: Object firstNode = jjtGetChild(0);
066: firstThrowsClause = 1;
067: if (firstNode instanceof BSHReturnType) {
068: returnTypeNode = (BSHReturnType) firstNode;
069: paramsNode = (BSHFormalParameters) jjtGetChild(1);
070: if (jjtGetNumChildren() > 2 + numThrows)
071: blockNode = (BSHBlock) jjtGetChild(2 + numThrows); // skip throws
072: ++firstThrowsClause;
073: } else {
074: paramsNode = (BSHFormalParameters) jjtGetChild(0);
075: blockNode = (BSHBlock) jjtGetChild(1 + numThrows); // skip throws
076: }
077: }
078:
079: /**
080: Evaluate the return type node.
081: @return the type or null indicating loosely typed return
082: */
083: Class evalReturnType(CallStack callstack, Interpreter interpreter)
084: throws EvalError {
085: insureNodesParsed();
086: if (returnTypeNode != null)
087: return returnTypeNode
088: .evalReturnType(callstack, interpreter);
089: else
090: return null;
091: }
092:
093: String getReturnTypeDescriptor(CallStack callstack,
094: Interpreter interpreter, String defaultPackage) {
095: insureNodesParsed();
096: if (returnTypeNode == null)
097: return null;
098: else
099: return returnTypeNode.getTypeDescriptor(callstack,
100: interpreter, defaultPackage);
101: }
102:
103: BSHReturnType getReturnTypeNode() {
104: insureNodesParsed();
105: return returnTypeNode;
106: }
107:
108: /**
109: Evaluate the declaration of the method. That is, determine the
110: structure of the method and install it into the caller's namespace.
111: */
112: public Object eval(CallStack callstack, Interpreter interpreter)
113: throws EvalError {
114: returnType = evalReturnType(callstack, interpreter);
115: evalNodes(callstack, interpreter);
116:
117: // Install an *instance* of this method in the namespace.
118: // See notes in BshMethod
119:
120: // This is not good...
121: // need a way to update eval without re-installing...
122: // so that we can re-eval params, etc. when classloader changes
123: // look into this
124:
125: NameSpace namespace = callstack.top();
126: BshMethod bshMethod = new BshMethod(this , namespace, modifiers);
127: try {
128: namespace.setMethod(name, bshMethod);
129: } catch (UtilEvalError e) {
130: throw e.toEvalError(this , callstack);
131: }
132:
133: return Primitive.VOID;
134: }
135:
136: private void evalNodes(CallStack callstack, Interpreter interpreter)
137: throws EvalError {
138: insureNodesParsed();
139:
140: // validate that the throws names are class names
141: for (int i = firstThrowsClause; i < numThrows
142: + firstThrowsClause; i++)
143: ((BSHAmbiguousName) jjtGetChild(i)).toClass(callstack,
144: interpreter);
145:
146: paramsNode.eval(callstack, interpreter);
147:
148: // if strictJava mode, check for loose parameters and return type
149: if (interpreter.getStrictJava()) {
150: for (int i = 0; i < paramsNode.paramTypes.length; i++)
151: if (paramsNode.paramTypes[i] == null)
152: // Warning: Null callstack here. Don't think we need
153: // a stack trace to indicate how we sourced the method.
154: throw new EvalError(
155: "(Strict Java Mode) Undeclared argument type, parameter: "
156: + paramsNode.getParamNames()[i]
157: + " in method: " + name, this , null);
158:
159: if (returnType == null)
160: // Warning: Null callstack here. Don't think we need
161: // a stack trace to indicate how we sourced the method.
162: throw new EvalError(
163: "(Strict Java Mode) Undeclared return type for method: "
164: + name, this , null);
165: }
166: }
167:
168: public String toString() {
169: return "MethodDeclaration: " + name;
170: }
171: }
|