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