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