jdk/src/share/classes/com/sun/tools/example/debug/expr/LValue.java
author nloodin
Tue, 26 Apr 2011 12:49:34 +0200
changeset 9520 99d378796e54
parent 5506 202f599c92aa
child 10292 ed7db6a12c2a
permissions -rw-r--r--
7029383: Refresh of non-client demos Reviewed-by: mchung, ohair
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
     2
 * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package com.sun.tools.example.debug.expr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import com.sun.jdi.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.util.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
abstract class LValue {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
    // The JDI Value object for this LValue.  Once we have this Value,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
    // we have to remember it since after we return the LValue object
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
    // to the ExpressionParser, it might decide that it needs
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
    // the 'toString' value for the LValue in which case it will
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
    // call getMassagedValue to get this toString value.  At that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
    // point, we don't want to call JDI a 2nd time to get the Value
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
    // for the LValue.  This is especially wrong when the LValue
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
    // represents a member function.  We would end up calling it
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
    // a 2nd time.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
    //
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
    // Unfortunately, there are several levels of calls to
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
    // get/set values in this file.  To minimize confusion,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
    // jdiValue is set/tested at the lowest level - right
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
    // next to the actual calls to JDI methods to get/set the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
    // value in the debuggee.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
    protected Value jdiValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
    abstract Value getValue() throws InvocationException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
                                     IncompatibleThreadStateException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
                                     InvalidTypeException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
                                     ClassNotLoadedException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
                                     ParseException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
    abstract void setValue0(Value value)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
                   throws ParseException, InvalidTypeException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
                          ClassNotLoadedException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
    abstract void invokeWith(List<Value> arguments) throws ParseException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
    void setValue(Value value) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
            setValue0(value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
        } catch (InvalidTypeException exc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
            throw new ParseException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
                "Attempt to set value of incorrect type" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
                exc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
        } catch (ClassNotLoadedException exc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
            throw new ParseException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
                "Attempt to set value before " + exc.className() + " was loaded" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
                exc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
    void setValue(LValue lval) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
        setValue(lval.interiorGetValue());
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    LValue memberLValue(ExpressionParser.GetFrame frameGetter,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
                        String fieldName) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
            return memberLValue(fieldName, frameGetter.get().thread());
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
        } catch (IncompatibleThreadStateException exc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
            throw new ParseException("Thread not suspended");
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
    LValue memberLValue(String fieldName, ThreadReference thread) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
        Value val = interiorGetValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
        if ((val instanceof ArrayReference) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
            "length".equals(fieldName)){
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
            return new LValueArrayLength((ArrayReference)val);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
        return new LValueInstanceMember(val, fieldName, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
    // Return the Value for this LValue that would be used to concatenate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
    // to a String.  IE, if it is an Object, call toString in the debuggee.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    Value getMassagedValue(ExpressionParser.GetFrame frameGetter) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
        Value vv = interiorGetValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
        // If vv is an ObjectReference, then we have to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
        // do the implicit call to toString().
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
        if (vv instanceof ObjectReference &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
            !(vv instanceof StringReference) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
            !(vv instanceof ArrayReference)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
            StackFrame frame;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
                frame = frameGetter.get();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
            } catch (IncompatibleThreadStateException exc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
                throw new ParseException("Thread not suspended");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
            ThreadReference thread = frame.thread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
            LValue toStringMember = memberLValue("toString", thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
            toStringMember.invokeWith(new ArrayList<Value>());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
            return toStringMember.interiorGetValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
        return vv;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
    Value interiorGetValue() throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
        Value value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
            value = getValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
        } catch (InvocationException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
            throw new ParseException("Unable to complete expression. Exception " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
                                     e.exception() + " thrown");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
        } catch (IncompatibleThreadStateException itse) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
            throw new ParseException("Unable to complete expression. Thread " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
                                     "not suspended for method invoke");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
        } catch (InvalidTypeException ite) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
            throw new ParseException("Unable to complete expression. Method " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
                                     "argument type mismatch");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
        } catch (ClassNotLoadedException tnle) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
            throw new ParseException("Unable to complete expression. Method " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
                                     "argument type " + tnle.className() +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
                                     " not yet loaded");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
        return value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
    LValue arrayElementLValue(LValue lval) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
        Value indexValue = lval.interiorGetValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
        int index;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
        if ( (indexValue instanceof IntegerValue) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
             (indexValue instanceof ShortValue) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
             (indexValue instanceof ByteValue) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
             (indexValue instanceof CharValue) ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
            index = ((PrimitiveValue)indexValue).intValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
            throw new ParseException("Array index must be a integer type");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
        return new LValueArrayElement(interiorGetValue(), index);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   159
   @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
    public String toString() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
            return interiorGetValue().toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
        } catch (ParseException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
            return "<Parse Exception>";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
    static final int STATIC = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
    static final int INSTANCE = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
    static Field fieldByName(ReferenceType refType, String name, int kind) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
         * TO DO: Note that this currently fails to find superclass
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
         * or implemented interface fields. This is due to a temporary
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
         * limititation of RefType.fieldByName. Once that method is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
         * fixed, superclass fields will be found.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
        Field field = refType.fieldByName(name);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
        if (field != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
            boolean isStatic = field.isStatic();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
            if (((kind == STATIC) && !isStatic) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
                ((kind == INSTANCE) && isStatic)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
                field = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
/***
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
        System.err.println("fieldByName: " + refType.name() + " " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
                                             name + " " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
                                             kind + " " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
                                             (field != null));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
***/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        return field;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   195
    static List<Method> methodsByName(ReferenceType refType,
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   196
                                      String name, int kind) {
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   197
        List<Method> list = refType.methodsByName(name);
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   198
        Iterator<Method> iter = list.iterator();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
        while (iter.hasNext()) {
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   200
            Method method = iter.next();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
            boolean isStatic = method.isStatic();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
            if (((kind == STATIC) && !isStatic) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
                ((kind == INSTANCE) && isStatic)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
                iter.remove();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
        return list;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
    static List<String> primitiveTypeNames = new ArrayList<String>();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
    static {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
        primitiveTypeNames.add("boolean");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
        primitiveTypeNames.add("byte");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
        primitiveTypeNames.add("char");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
        primitiveTypeNames.add("short");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
        primitiveTypeNames.add("int");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
        primitiveTypeNames.add("long");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
        primitiveTypeNames.add("float");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
        primitiveTypeNames.add("double");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
    static final int SAME = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
    static final int ASSIGNABLE = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
    static final int DIFFERENT = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
     * Return SAME, DIFFERENT or ASSIGNABLE.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
     * SAME means each arg type is the same as type of the corr. arg.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
     * ASSIGNABLE means that not all the pairs are the same, but
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
     * for those that aren't, at least the argType is assignable
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
     * from the type of the argument value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
     * DIFFERENT means that in at least one pair, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
     * argType is not assignable from the type of the argument value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
     * IE, one is an Apple and the other is an Orange.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
     */
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   236
    static int argumentsMatch(List<Type> argTypes, List<Value> arguments) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
        if (argTypes.size() != arguments.size()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
            return DIFFERENT;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   241
        Iterator<Type> typeIter = argTypes.iterator();
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   242
        Iterator<Value> valIter = arguments.iterator();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
        int result = SAME;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
        // If any pair aren't the same, change the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
        // result to ASSIGNABLE.  If any pair aren't
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
        // assignable, return DIFFERENT
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
        while (typeIter.hasNext()) {
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   249
            Type argType = typeIter.next();
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   250
            Value value = valIter.next();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
            if (value == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
                // Null values can be passed to any non-primitive argument
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
                if (primitiveTypeNames.contains(argType.name())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
                    return DIFFERENT;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
                // Else, we will assume that a null value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
                // exactly matches an object type.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
            if (!value.type().equals(argType)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
                if (isAssignableTo(value.type(), argType)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
                    result = ASSIGNABLE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
                    return DIFFERENT;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
        return result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
    // These is...AssignableTo methods are based on similar code in the JDI
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
    // implementations of ClassType, ArrayType, and InterfaceType
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
    static boolean isComponentAssignable(Type fromType, Type toType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
        if (fromType instanceof PrimitiveType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
            // Assignment of primitive arrays requires identical
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
            // component types.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
            return fromType.equals(toType);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
        if (toType instanceof PrimitiveType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
        // Assignment of object arrays requires availability
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
        // of widening conversion of component types
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
        return isAssignableTo(fromType, toType);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
    static boolean isArrayAssignableTo(ArrayType fromType, Type toType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
        if (toType instanceof ArrayType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
                Type toComponentType = ((ArrayType)toType).componentType();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
                return isComponentAssignable(fromType.componentType(), toComponentType);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
            } catch (ClassNotLoadedException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
                // One or both component types has not yet been
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
                // loaded => can't assign
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
        if (toType instanceof InterfaceType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
            // Only valid InterfaceType assignee is Cloneable
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
            return toType.name().equals("java.lang.Cloneable");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
        // Only valid ClassType assignee is Object
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
        return toType.name().equals("java.lang.Object");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
    static boolean isAssignableTo(Type fromType, Type toType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
        if (fromType.equals(toType)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
            return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
        // If one is boolean, so must be the other.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
        if (fromType instanceof BooleanType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
            if (toType instanceof BooleanType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
                return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
        if (toType instanceof BooleanType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
        // Other primitive types are intermixable only with each other.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
        if (fromType instanceof PrimitiveType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
            if (toType instanceof PrimitiveType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
                return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
        if (toType instanceof PrimitiveType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
        // neither one is primitive.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
        if (fromType instanceof ArrayType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
            return isArrayAssignableTo((ArrayType)fromType, toType);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
        }
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   338
        List<InterfaceType> interfaces;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
        if (fromType instanceof ClassType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
            ClassType superclazz = ((ClassType)fromType).superclass();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
            if ((superclazz != null) && isAssignableTo(superclazz, toType)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
                return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
            interfaces = ((ClassType)fromType).interfaces();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
            // fromType must be an InterfaceType
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
            interfaces = ((InterfaceType)fromType).superinterfaces();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
        }
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   349
        for (InterfaceType interfaze : interfaces) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
            if (isAssignableTo(interfaze, toType)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
                return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   357
    static Method resolveOverload(List<Method> overloads,
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   358
                                  List<Value> arguments)
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
                                       throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
        // If there is only one method to call, we'll just choose
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
        // that without looking at the args.  If they aren't right
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
        // the invoke will return a better error message than we
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
        // could generate here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
        if (overloads.size() == 1) {
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   366
            return overloads.get(0);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
        // Resolving overloads is beyond the scope of this exercise.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
        // So, we will look for a method that matches exactly the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
        // types of the arguments.  If we can't find one, then
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
        // if there is exactly one method whose param types are assignable
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
        // from the arg types, we will use that.  Otherwise,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
        // it is an error.  We won't guess which of multiple possible
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
        // methods to call. And, since casts aren't implemented,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
        // the user can't use them to pick a particular overload to call.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
        // IE, the user is out of luck in this case.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
        Method retVal = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
        int assignableCount = 0;
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   380
        for (Method mm : overloads) {
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   381
            List<Type> argTypes;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
                argTypes = mm.argumentTypes();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
            } catch (ClassNotLoadedException ee) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
                // This probably won't happen for the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
                // method that we are really supposed to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
                // call.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
                continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
            int compare = argumentsMatch(argTypes, arguments);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
            if (compare == SAME) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
                return mm;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
            if (compare == DIFFERENT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
                continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
            // Else, it is assignable.  Remember it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
            retVal = mm;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
            assignableCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
        // At this point, we didn't find an exact match,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
        // but we found one for which the args are assignable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
        if (retVal != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
            if (assignableCount == 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
                return retVal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
            throw new ParseException("Arguments match multiple methods");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
        throw new ParseException("Arguments match no method");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
    private static class LValueLocal extends LValue {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
        final StackFrame frame;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
        final LocalVariable var;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
        LValueLocal(StackFrame frame, LocalVariable var) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
            this.frame = frame;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
            this.var = var;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   423
      @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
        Value getValue() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
            if (jdiValue == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
                jdiValue = frame.getValue(var);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
            return jdiValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   431
      @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
        void setValue0(Value val) throws InvalidTypeException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
                                         ClassNotLoadedException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
            frame.setValue(var, val);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
            jdiValue = val;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   438
      @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
        void invokeWith(List<Value> arguments) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
            throw new ParseException(var.name() + " is not a method");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
    private static class LValueInstanceMember extends LValue {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
        final ObjectReference obj;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
        final ThreadReference thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
        final Field matchingField;
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   448
        final List<Method> overloads;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
        Method matchingMethod = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
        List<Value> methodArguments = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
        LValueInstanceMember(Value value,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
                            String memberName,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
                            ThreadReference thread) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
            if (!(value instanceof ObjectReference)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
                throw new ParseException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
                       "Cannot access field of primitive type: " + value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
            this.obj = (ObjectReference)value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
            this.thread = thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
            ReferenceType refType = obj.referenceType();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
             * Can't tell yet whether this LValue will be accessed as a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
             * field or method, so we keep track of all the possibilities
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
            matchingField = LValue.fieldByName(refType, memberName,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
                                               LValue.INSTANCE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
            overloads = LValue.methodsByName(refType, memberName,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
                                              LValue.INSTANCE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
            if ((matchingField == null) && overloads.size() == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
                throw new ParseException("No instance field or method with the name "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
                               + memberName + " in " + refType.name());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   476
      @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
        Value getValue() throws InvocationException, InvalidTypeException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
                                ClassNotLoadedException, IncompatibleThreadStateException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
                                ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
            if (jdiValue != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
                return jdiValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
            if (matchingMethod == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
                if (matchingField == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
                    throw new ParseException("No such field in " + obj.referenceType().name());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
                return jdiValue = obj.getValue(matchingField);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
                return jdiValue = obj.invokeMethod(thread, matchingMethod, methodArguments, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   493
        @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
        void setValue0(Value val) throws ParseException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
                                         InvalidTypeException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
                                        ClassNotLoadedException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
            if (matchingMethod != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
                throw new ParseException("Cannot assign to a method invocation");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
            obj.setValue(matchingField, val);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
            jdiValue = val;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   504
        @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
        void invokeWith(List<Value> arguments) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
            if (matchingMethod != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
                throw new ParseException("Invalid consecutive invocations");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
            methodArguments = arguments;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
            matchingMethod = LValue.resolveOverload(overloads, arguments);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
    private static class LValueStaticMember extends LValue {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
        final ReferenceType refType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
        final ThreadReference thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
        final Field matchingField;
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   518
        final List<Method> overloads;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
        Method matchingMethod = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
        List<Value> methodArguments = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
        LValueStaticMember(ReferenceType refType,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
                          String memberName,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
                          ThreadReference thread) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
            this.refType = refType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
            this.thread = thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
             * Can't tell yet whether this LValue will be accessed as a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
             * field or method, so we keep track of all the possibilities
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
            matchingField = LValue.fieldByName(refType, memberName,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
                                               LValue.STATIC);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
            overloads = LValue.methodsByName(refType, memberName,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
                                              LValue.STATIC);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
            if ((matchingField == null) && overloads.size() == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
                throw new ParseException("No static field or method with the name "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
                               + memberName + " in " + refType.name());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   541
        @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
        Value getValue() throws InvocationException, InvalidTypeException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
                                ClassNotLoadedException, IncompatibleThreadStateException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
                                ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
            if (jdiValue != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
                return jdiValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
            if (matchingMethod == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
                return jdiValue = refType.getValue(matchingField);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
            } else if (refType instanceof ClassType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
                ClassType clazz = (ClassType)refType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
                return jdiValue = clazz.invokeMethod(thread, matchingMethod, methodArguments, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
                throw new InvalidTypeException("Cannot invoke static method on " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
                                         refType.name());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   559
        @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
        void setValue0(Value val)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
                           throws ParseException, InvalidTypeException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
                                  ClassNotLoadedException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
            if (matchingMethod != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
                throw new ParseException("Cannot assign to a method invocation");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
            if (!(refType instanceof ClassType)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
                throw new ParseException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
                       "Cannot set interface field: " + refType);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
            ((ClassType)refType).setValue(matchingField, val);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
            jdiValue = val;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   574
        @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
        void invokeWith(List<Value> arguments) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
            if (matchingMethod != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
                throw new ParseException("Invalid consecutive invocations");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
            methodArguments = arguments;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
            matchingMethod = LValue.resolveOverload(overloads, arguments);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
    private static class LValueArrayLength extends LValue {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
         * Since one can code "int myLen = myArray.length;",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
         * one might expect that these JDI calls would get a Value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
         * object for the length of an array in the debugee:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
         *    Field xxx = ArrayType.fieldByName("length")
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
         *    Value lenVal= ArrayReference.getValue(xxx)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
         * However, this doesn't work because the array length isn't
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
         * really stored as a field, and can't be accessed as such
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
         * via JDI.  Instead, the arrayRef.length() method has to be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
         * used.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
        final ArrayReference arrayRef;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
        LValueArrayLength (ArrayReference value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
            this.arrayRef = value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   602
        @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
        Value getValue() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
            if (jdiValue == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
                jdiValue = arrayRef.virtualMachine().mirrorOf(arrayRef.length());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
            return jdiValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   610
        @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
        void setValue0(Value value) throws ParseException  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
            throw new ParseException("Cannot set constant: " + value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   615
        @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
        void invokeWith(List<Value> arguments) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
            throw new ParseException("Array element is not a method");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
    private static class LValueArrayElement extends LValue {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
        final ArrayReference array;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
        final int index;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
        LValueArrayElement(Value value, int index) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
            if (!(value instanceof ArrayReference)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
                throw new ParseException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
                       "Must be array type: " + value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
            this.array = (ArrayReference)value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
            this.index = index;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   634
        @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
        Value getValue() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
            if (jdiValue == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
                jdiValue = array.getValue(index);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
            return jdiValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   642
        @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
        void setValue0(Value val) throws InvalidTypeException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
                                         ClassNotLoadedException  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
            array.setValue(index, val);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
            jdiValue = val;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   649
        @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
        void invokeWith(List<Value> arguments) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
            throw new ParseException("Array element is not a method");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
    private static class LValueConstant extends LValue {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
        final Value value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
        LValueConstant(Value value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
            this.value = value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   662
        @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
        Value getValue() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
            if (jdiValue == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
                jdiValue = value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
            return jdiValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   670
        @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
        void setValue0(Value val) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
            throw new ParseException("Cannot set constant: " + value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   675
        @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
        void invokeWith(List<Value> arguments) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
            throw new ParseException("Constant is not a method");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
    static LValue make(VirtualMachine vm, boolean val) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
        return new LValueConstant(vm.mirrorOf(val));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
    static LValue make(VirtualMachine vm, byte val) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
        return new LValueConstant(vm.mirrorOf(val));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
    static LValue make(VirtualMachine vm, char val) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
        return new LValueConstant(vm.mirrorOf(val));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
    static LValue make(VirtualMachine vm, short val) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
        return new LValueConstant(vm.mirrorOf(val));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
    static LValue make(VirtualMachine vm, int val) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
        return new LValueConstant(vm.mirrorOf(val));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
    static LValue make(VirtualMachine vm, long val) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
        return new LValueConstant(vm.mirrorOf(val));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
    static LValue make(VirtualMachine vm, float val) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
        return new LValueConstant(vm.mirrorOf(val));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
    static LValue make(VirtualMachine vm, double val) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
        return new LValueConstant(vm.mirrorOf(val));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
    static LValue make(VirtualMachine vm, String val) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
        return new LValueConstant(vm.mirrorOf(val));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
    static LValue makeBoolean(VirtualMachine vm, Token token) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
        return make(vm, token.image.charAt(0) == 't');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
    static LValue makeCharacter(VirtualMachine vm, Token token) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
        return make(vm, token.image.charAt(1));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
    static LValue makeFloat(VirtualMachine vm, Token token) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
        return make(vm, Float.valueOf(token.image).floatValue());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
    static LValue makeDouble(VirtualMachine vm, Token token) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
        return make(vm, Double.valueOf(token.image).doubleValue());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
    static LValue makeInteger(VirtualMachine vm, Token token) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
        return make(vm, Integer.parseInt(token.image));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
    static LValue makeShort(VirtualMachine vm, Token token) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
        return make(vm, Short.parseShort(token.image));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
    static LValue makeLong(VirtualMachine vm, Token token) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
        return make(vm, Long.parseLong(token.image));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
    static LValue makeByte(VirtualMachine vm, Token token) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
        return make(vm, Byte.parseByte(token.image));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
    static LValue makeString(VirtualMachine vm,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
                             Token token) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
        int len = token.image.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
        return make(vm, token.image.substring(1,len-1));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
    static LValue makeNull(VirtualMachine vm,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
                           Token token) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
        return new LValueConstant(null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
    static LValue makeThisObject(VirtualMachine vm,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
                                 ExpressionParser.GetFrame frameGetter,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
                                 Token token) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
        if (frameGetter == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
            throw new ParseException("No current thread");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
                StackFrame frame = frameGetter.get();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
                ObjectReference thisObject = frame.thisObject();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
                if (thisObject==null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
                        throw new ParseException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
                            "No 'this'.  In native or static method");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
                        return new LValueConstant(thisObject);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
            } catch (IncompatibleThreadStateException exc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
                throw new ParseException("Thread not suspended");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
    static LValue makeNewObject(VirtualMachine vm,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
                                 ExpressionParser.GetFrame frameGetter,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
                                String className, List<Value> arguments) throws ParseException {
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   785
        List<ReferenceType> classes = vm.classesByName(className);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
        if (classes.size() == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
            throw new ParseException("No class named: " + className);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
        if (classes.size() > 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
            throw new ParseException("More than one class named: " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
                                     className);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
        }
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   794
        ReferenceType refType = classes.get(0);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
        if (!(refType instanceof ClassType)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
            throw new ParseException("Cannot create instance of interface " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
                                     className);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
        ClassType classType = (ClassType)refType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
        List<Method> methods = new ArrayList<Method>(classType.methods()); // writable
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   804
        Iterator<Method> iter = methods.iterator();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
        while (iter.hasNext()) {
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   806
            Method method = iter.next();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
            if (!method.isConstructor()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
                iter.remove();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
        Method constructor = LValue.resolveOverload(methods, arguments);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
        ObjectReference newObject;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
            ThreadReference thread = frameGetter.get().thread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
            newObject = classType.newInstance(thread, constructor, arguments, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
        } catch (InvocationException ie) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
            throw new ParseException("Exception in " + className + " constructor: " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
                                     ie.exception().referenceType().name());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
        } catch (IncompatibleThreadStateException exc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
            throw new ParseException("Thread not suspended");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
        } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
             * TO DO: Better error handling
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
            throw new ParseException("Unable to create " + className + " instance");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
        return new LValueConstant(newObject);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
    private static LValue nFields(LValue lval,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
                                  StringTokenizer izer,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
                                  ThreadReference thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
                                          throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
        if (!izer.hasMoreTokens()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
            return lval;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
            return nFields(lval.memberLValue(izer.nextToken(), thread), izer, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
    static LValue makeName(VirtualMachine vm,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
                           ExpressionParser.GetFrame frameGetter,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
                           String name) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
        StringTokenizer izer = new StringTokenizer(name, ".");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
        String first = izer.nextToken();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
        // check local variables
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
        if (frameGetter != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
                StackFrame frame = frameGetter.get();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
                ThreadReference thread = frame.thread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
                LocalVariable var;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
                    var = frame.visibleVariableByName(first);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
                } catch (AbsentInformationException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
                    var = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
                if (var != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
                    return nFields(new LValueLocal(frame, var), izer, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
                    ObjectReference thisObject = frame.thisObject();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
                    if (thisObject != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
                        // check if it is a field of 'this'
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
                        LValue thisLValue = new LValueConstant(thisObject);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
                        LValue fv;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
                        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
                            fv = thisLValue.memberLValue(first, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
                        } catch (ParseException exc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
                            fv = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
                        if (fv != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
                            return nFields(fv, izer, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
                // check for class name
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
                while (izer.hasMoreTokens()) {
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   878
                    List<ReferenceType> classes = vm.classesByName(first);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
                    if (classes.size() > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
                        if (classes.size() > 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
                            throw new ParseException("More than one class named: " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
                                                     first);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
                        } else {
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   884
                            ReferenceType refType = classes.get(0);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
                            LValue lval = new LValueStaticMember(refType,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
                                                            izer.nextToken(), thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
                            return nFields(lval, izer, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
                    first = first + '.' + izer.nextToken();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
            } catch (IncompatibleThreadStateException exc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
                throw new ParseException("Thread not suspended");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
        throw new ParseException("Name unknown: " + name);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
    static String stringValue(LValue lval, ExpressionParser.GetFrame frameGetter
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
                              ) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
        Value val = lval.getMassagedValue(frameGetter);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
        if (val == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
            return "null";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
        if (val instanceof StringReference) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
            return ((StringReference)val).value();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
        return val.toString();  // is this correct in all cases?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
    static LValue booleanOperation(VirtualMachine vm, Token token,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
                            LValue rightL,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
                            LValue leftL) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
        String op = token.image;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
        Value right = rightL.interiorGetValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
        Value left = leftL.interiorGetValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
        if ( !(right instanceof PrimitiveValue) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
             !(left instanceof PrimitiveValue) ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
            if (op.equals("==")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
                return make(vm, right.equals(left));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
            } else if (op.equals("!=")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
                return make(vm, !right.equals(left));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
                throw new ParseException("Operands or '" + op +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
                                     "' must be primitive");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
        // can compare any numeric doubles
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
        double rr = ((PrimitiveValue)right).doubleValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
        double ll = ((PrimitiveValue)left).doubleValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
        boolean res;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
        if (op.equals("<")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
            res = rr < ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
        } else if (op.equals(">")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
            res = rr > ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
        } else if (op.equals("<=")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
            res = rr <= ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
        } else if (op.equals(">=")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
            res = rr >= ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
        } else if (op.equals("==")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
            res = rr == ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
        } else if (op.equals("!=")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
            res = rr != ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
            throw new ParseException("Unknown operation: " + op);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
        return make(vm, res);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
    static LValue operation(VirtualMachine vm, Token token,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
                            LValue rightL, LValue leftL,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
                            ExpressionParser.GetFrame frameGetter
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
                            ) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
        String op = token.image;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
        Value right = rightL.interiorGetValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
        Value left = leftL.interiorGetValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
        if ((right instanceof StringReference) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
                              (left instanceof StringReference)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
            if (op.equals("+")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
                // If one is an ObjectRef, we will need to invoke
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
                // toString on it, so we need the thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
                return make(vm, stringValue(rightL, frameGetter) +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
                            stringValue(leftL, frameGetter));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
        if ((right instanceof ObjectReference) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
                              (left instanceof ObjectReference)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
            if (op.equals("==")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
                return make(vm, right.equals(left));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
            } else if (op.equals("!=")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
                return make(vm, !right.equals(left));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
                throw new ParseException("Invalid operation '" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
                                         op + "' on an Object");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
        if ((right instanceof BooleanValue) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
                              (left instanceof BooleanValue)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
            throw new ParseException("Invalid operation '" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   980
                                     op + "' on a Boolean");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   981
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
        // from here on, we know it is a integer kind of type
90ce3da70b43 Initial load
duke
parents:
diff changeset
   983
        PrimitiveValue primRight = (PrimitiveValue)right;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   984
        PrimitiveValue primLeft = (PrimitiveValue)left;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   985
        if ((primRight instanceof DoubleValue) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   986
                              (primLeft instanceof DoubleValue)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   987
            double rr = primRight.doubleValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   988
            double ll = primLeft.doubleValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   989
            double res;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
            if (op.equals("+")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
                res = rr + ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   992
            } else if (op.equals("-")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
                res = rr - ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
            } else if (op.equals("*")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   995
                res = rr * ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
            } else if (op.equals("/")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
                res = rr / ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   999
                throw new ParseException("Unknown operation: " + op);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1000
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1001
            return make(vm, res);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1002
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1003
        if ((primRight instanceof FloatValue) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1004
                              (primLeft instanceof FloatValue)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1005
            float rr = primRight.floatValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1006
            float ll = primLeft.floatValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1007
            float res;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1008
            if (op.equals("+")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1009
                res = rr + ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1010
            } else if (op.equals("-")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1011
                res = rr - ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1012
            } else if (op.equals("*")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1013
                res = rr * ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1014
            } else if (op.equals("/")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1015
                res = rr / ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1016
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1017
                throw new ParseException("Unknown operation: " + op);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1018
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1019
            return make(vm, res);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1020
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1021
        if ((primRight instanceof LongValue) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1022
                              (primLeft instanceof LongValue)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1023
            long rr = primRight.longValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1024
            long ll = primLeft.longValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1025
            long res;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1026
            if (op.equals("+")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1027
                res = rr + ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1028
            } else if (op.equals("-")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1029
                res = rr - ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1030
            } else if (op.equals("*")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1031
                res = rr * ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1032
            } else if (op.equals("/")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1033
                res = rr / ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1034
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1035
                throw new ParseException("Unknown operation: " + op);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1036
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1037
            return make(vm, res);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1038
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1039
            int rr = primRight.intValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1040
            int ll = primLeft.intValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1041
            int res;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1042
            if (op.equals("+")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1043
                res = rr + ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1044
            } else if (op.equals("-")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1045
                res = rr - ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1046
            } else if (op.equals("*")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1047
                res = rr * ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1048
            } else if (op.equals("/")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1049
                res = rr / ll;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1050
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1051
                throw new ParseException("Unknown operation: " + op);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1053
            return make(vm, res);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1054
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1055
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1056
}