/*
 * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.example.debug.expr;

import com.sun.jdi.*;
import java.util.*;

abstract class LValue {

    // The JDI Value object for this LValue.  Once we have this Value,
    // we have to remember it since after we return the LValue object
    // to the ExpressionParser, it might decide that it needs
    // the 'toString' value for the LValue in which case it will
    // call getMassagedValue to get this toString value.  At that
    // point, we don't want to call JDI a 2nd time to get the Value
    // for the LValue.  This is especially wrong when the LValue
    // represents a member function.  We would end up calling it
    // a 2nd time.
    //
    // Unfortunately, there are several levels of calls to
    // get/set values in this file.  To minimize confusion,
    // jdiValue is set/tested at the lowest level - right
    // next to the actual calls to JDI methods to get/set the
    // value in the debuggee.
    protected Value jdiValue;

    abstract Value getValue() throws InvocationException,
                                     IncompatibleThreadStateException,
                                     InvalidTypeException,
                                     ClassNotLoadedException,
                                     ParseException;

    abstract void setValue0(Value value)
                   throws ParseException, InvalidTypeException,
                          ClassNotLoadedException;

    abstract void invokeWith(List<Value> arguments) throws ParseException;

    void setValue(Value value) throws ParseException {
        try {
            setValue0(value);
        } catch (InvalidTypeException exc) {
            throw new ParseException(
                "Attempt to set value of incorrect type" +
                exc);
        } catch (ClassNotLoadedException exc) {
            throw new ParseException(
                "Attempt to set value before " + exc.className() + " was loaded" +
                exc);
        }
    }

    void setValue(LValue lval) throws ParseException {
        setValue(lval.interiorGetValue());
    }

    LValue memberLValue(ExpressionParser.GetFrame frameGetter,
                        String fieldName) throws ParseException {
        try {
            return memberLValue(fieldName, frameGetter.get().thread());
        } catch (IncompatibleThreadStateException exc) {
            throw new ParseException("Thread not suspended");
        }
    }

    LValue memberLValue(String fieldName, ThreadReference thread) throws ParseException {

        Value val = interiorGetValue();
        if ((val instanceof ArrayReference) &&
            "length".equals(fieldName)){
            return new LValueArrayLength((ArrayReference)val);
        }
        return new LValueInstanceMember(val, fieldName, thread);
    }

    // Return the Value for this LValue that would be used to concatenate
    // to a String.  IE, if it is an Object, call toString in the debuggee.
    Value getMassagedValue(ExpressionParser.GetFrame frameGetter) throws ParseException {
        Value vv = interiorGetValue();

        // If vv is an ObjectReference, then we have to
        // do the implicit call to toString().
        if (vv instanceof ObjectReference &&
            !(vv instanceof StringReference) &&
            !(vv instanceof ArrayReference)) {
            StackFrame frame;
            try {
                frame = frameGetter.get();
            } catch (IncompatibleThreadStateException exc) {
                throw new ParseException("Thread not suspended");
            }

            ThreadReference thread = frame.thread();
            LValue toStringMember = memberLValue("toString", thread);
            toStringMember.invokeWith(new ArrayList<Value>());
            return toStringMember.interiorGetValue();
        }
        return vv;
    }

    Value interiorGetValue() throws ParseException {
        Value value;
        try {
            value = getValue();
        } catch (InvocationException e) {
            throw new ParseException("Unable to complete expression. Exception " +
                                     e.exception() + " thrown");
        } catch (IncompatibleThreadStateException itse) {
            throw new ParseException("Unable to complete expression. Thread " +
                                     "not suspended for method invoke");
        } catch (InvalidTypeException ite) {
            throw new ParseException("Unable to complete expression. Method " +
                                     "argument type mismatch");
        } catch (ClassNotLoadedException tnle) {
            throw new ParseException("Unable to complete expression. Method " +
                                     "argument type " + tnle.className() +
                                     " not yet loaded");
        }
        return value;
    }

    LValue arrayElementLValue(LValue lval) throws ParseException {
        Value indexValue = lval.interiorGetValue();
        int index;
        if ( (indexValue instanceof IntegerValue) ||
             (indexValue instanceof ShortValue) ||
             (indexValue instanceof ByteValue) ||
             (indexValue instanceof CharValue) ) {
            index = ((PrimitiveValue)indexValue).intValue();
        } else {
            throw new ParseException("Array index must be a integer type");
        }
        return new LValueArrayElement(interiorGetValue(), index);
    }

    public String toString() {
        try {
            return interiorGetValue().toString();
        } catch (ParseException e) {
            return "<Parse Exception>";
        }
    }

    static final int STATIC = 0;
    static final int INSTANCE = 1;

    static Field fieldByName(ReferenceType refType, String name, int kind) {
        /*
         * TO DO: Note that this currently fails to find superclass
         * or implemented interface fields. This is due to a temporary
         * limititation of RefType.fieldByName. Once that method is
         * fixed, superclass fields will be found.
         */
        Field field = refType.fieldByName(name);
        if (field != null) {
            boolean isStatic = field.isStatic();
            if (((kind == STATIC) && !isStatic) ||
                ((kind == INSTANCE) && isStatic)) {
                field = null;
            }
        }
/***
        System.err.println("fieldByName: " + refType.name() + " " +
                                             name + " " +
                                             kind + " " +
                                             (field != null));
***/
        return field;
    }

    static List<Method> methodsByName(ReferenceType refType,
                                      String name, int kind) {
        List<Method> list = refType.methodsByName(name);
        Iterator<Method> iter = list.iterator();
        while (iter.hasNext()) {
            Method method = iter.next();
            boolean isStatic = method.isStatic();
            if (((kind == STATIC) && !isStatic) ||
                ((kind == INSTANCE) && isStatic)) {
                iter.remove();
            }
        }
        return list;
    }

    static List<String> primitiveTypeNames = new ArrayList<String>();
    static {
        primitiveTypeNames.add("boolean");
        primitiveTypeNames.add("byte");
        primitiveTypeNames.add("char");
        primitiveTypeNames.add("short");
        primitiveTypeNames.add("int");
        primitiveTypeNames.add("long");
        primitiveTypeNames.add("float");
        primitiveTypeNames.add("double");
    }


    static final int SAME = 0;
    static final int ASSIGNABLE = 1;
    static final int DIFFERENT = 2;
    /*
     * Return SAME, DIFFERENT or ASSIGNABLE.
     * SAME means each arg type is the same as type of the corr. arg.
     * ASSIGNABLE means that not all the pairs are the same, but
     * for those that aren't, at least the argType is assignable
     * from the type of the argument value.
     * DIFFERENT means that in at least one pair, the
     * argType is not assignable from the type of the argument value.
     * IE, one is an Apple and the other is an Orange.
     */
    static int argumentsMatch(List<Type> argTypes, List<Value> arguments) {
        if (argTypes.size() != arguments.size()) {
            return DIFFERENT;
        }

        Iterator<Type> typeIter = argTypes.iterator();
        Iterator<Value> valIter = arguments.iterator();
        int result = SAME;

        // If any pair aren't the same, change the
        // result to ASSIGNABLE.  If any pair aren't
        // assignable, return DIFFERENT
        while (typeIter.hasNext()) {
            Type argType = typeIter.next();
            Value value = valIter.next();
            if (value == null) {
                // Null values can be passed to any non-primitive argument
                if (primitiveTypeNames.contains(argType.name())) {
                    return DIFFERENT;
                }
                // Else, we will assume that a null value
                // exactly matches an object type.
            }
            if (!value.type().equals(argType)) {
                if (isAssignableTo(value.type(), argType)) {
                    result = ASSIGNABLE;
                } else {
                    return DIFFERENT;
                }
            }
        }
        return result;
    }


    // These is...AssignableTo methods are based on similar code in the JDI
    // implementations of ClassType, ArrayType, and InterfaceType

    static boolean isComponentAssignable(Type fromType, Type toType) {
        if (fromType instanceof PrimitiveType) {
            // Assignment of primitive arrays requires identical
            // component types.
            return fromType.equals(toType);
        }
        if (toType instanceof PrimitiveType) {
            return false;
        }
        // Assignment of object arrays requires availability
        // of widening conversion of component types
        return isAssignableTo(fromType, toType);
    }

    static boolean isArrayAssignableTo(ArrayType fromType, Type toType) {
        if (toType instanceof ArrayType) {
            try {
                Type toComponentType = ((ArrayType)toType).componentType();
                return isComponentAssignable(fromType.componentType(), toComponentType);
            } catch (ClassNotLoadedException e) {
                // One or both component types has not yet been
                // loaded => can't assign
                return false;
            }
        }
        if (toType instanceof InterfaceType) {
            // Only valid InterfaceType assignee is Cloneable
            return toType.name().equals("java.lang.Cloneable");
        }
        // Only valid ClassType assignee is Object
        return toType.name().equals("java.lang.Object");
    }

    static boolean isAssignableTo(Type fromType, Type toType) {
        if (fromType.equals(toType)) {
            return true;
        }

        // If one is boolean, so must be the other.
        if (fromType instanceof BooleanType) {
            if (toType instanceof BooleanType) {
                return true;
            }
            return false;
        }
        if (toType instanceof BooleanType) {
            return false;
        }

        // Other primitive types are intermixable only with each other.
        if (fromType instanceof PrimitiveType) {
            if (toType instanceof PrimitiveType) {
                return true;
            }
            return false;
        }
        if (toType instanceof PrimitiveType) {
            return false;
        }

        // neither one is primitive.
        if (fromType instanceof ArrayType) {
            return isArrayAssignableTo((ArrayType)fromType, toType);
        }
        List<InterfaceType> interfaces;
        if (fromType instanceof ClassType) {
            ClassType superclazz = ((ClassType)fromType).superclass();
            if ((superclazz != null) && isAssignableTo(superclazz, toType)) {
                return true;
            }
            interfaces = ((ClassType)fromType).interfaces();
        } else {
            // fromType must be an InterfaceType
            interfaces = ((InterfaceType)fromType).superinterfaces();
        }
        for (InterfaceType interfaze : interfaces) {
            if (isAssignableTo(interfaze, toType)) {
                return true;
            }
        }
        return false;
    }

    static Method resolveOverload(List<Method> overloads,
                                  List<Value> arguments)
                                       throws ParseException {

        // If there is only one method to call, we'll just choose
        // that without looking at the args.  If they aren't right
        // the invoke will return a better error message than we
        // could generate here.
        if (overloads.size() == 1) {
            return overloads.get(0);
        }

        // Resolving overloads is beyond the scope of this exercise.
        // So, we will look for a method that matches exactly the
        // types of the arguments.  If we can't find one, then
        // if there is exactly one method whose param types are assignable
        // from the arg types, we will use that.  Otherwise,
        // it is an error.  We won't guess which of multiple possible
        // methods to call. And, since casts aren't implemented,
        // the user can't use them to pick a particular overload to call.
        // IE, the user is out of luck in this case.
        Method retVal = null;
        int assignableCount = 0;
        for (Method mm : overloads) {
            List<Type> argTypes;
            try {
                argTypes = mm.argumentTypes();
            } catch (ClassNotLoadedException ee) {
                // This probably won't happen for the
                // method that we are really supposed to
                // call.
                continue;
            }
            int compare = argumentsMatch(argTypes, arguments);
            if (compare == SAME) {
                return mm;
            }
            if (compare == DIFFERENT) {
                continue;
            }
            // Else, it is assignable.  Remember it.
            retVal = mm;
            assignableCount++;
        }

        // At this point, we didn't find an exact match,
        // but we found one for which the args are assignable.
        //
        if (retVal != null) {
            if (assignableCount == 1) {
                return retVal;
            }
            throw new ParseException("Arguments match multiple methods");
        }
        throw new ParseException("Arguments match no method");
    }

    private static class LValueLocal extends LValue {
        final StackFrame frame;
        final LocalVariable var;

        LValueLocal(StackFrame frame, LocalVariable var) {
            this.frame = frame;
            this.var = var;
        }

        Value getValue() {
            if (jdiValue == null) {
                jdiValue = frame.getValue(var);
            }
            return jdiValue;
        }

        void setValue0(Value val) throws InvalidTypeException,
                                         ClassNotLoadedException {
            frame.setValue(var, val);
            jdiValue = val;
        }

        void invokeWith(List<Value> arguments) throws ParseException {
            throw new ParseException(var.name() + " is not a method");
        }
    }

    private static class LValueInstanceMember extends LValue {
        final ObjectReference obj;
        final ThreadReference thread;
        final Field matchingField;
        final List<Method> overloads;
        Method matchingMethod = null;
        List<Value> methodArguments = null;

        LValueInstanceMember(Value value,
                            String memberName,
                            ThreadReference thread) throws ParseException {
            if (!(value instanceof ObjectReference)) {
                throw new ParseException(
                       "Cannot access field of primitive type: " + value);
            }
            this.obj = (ObjectReference)value;
            this.thread = thread;
            ReferenceType refType = obj.referenceType();
            /*
             * Can't tell yet whether this LValue will be accessed as a
             * field or method, so we keep track of all the possibilities
             */
            matchingField = LValue.fieldByName(refType, memberName,
                                               LValue.INSTANCE);
            overloads = LValue.methodsByName(refType, memberName,
                                              LValue.INSTANCE);
            if ((matchingField == null) && overloads.size() == 0) {
                throw new ParseException("No instance field or method with the name "
                               + memberName + " in " + refType.name());
            }
        }

        Value getValue() throws InvocationException, InvalidTypeException,
                                ClassNotLoadedException, IncompatibleThreadStateException,
                                ParseException {
            if (jdiValue != null) {
                return jdiValue;
            }
            if (matchingMethod == null) {
                if (matchingField == null) {
                    throw new ParseException("No such field in " + obj.referenceType().name());
                }
                return jdiValue = obj.getValue(matchingField);
            } else {
                return jdiValue = obj.invokeMethod(thread, matchingMethod, methodArguments, 0);
            }
        }

        void setValue0(Value val) throws ParseException,
                                         InvalidTypeException,
                                        ClassNotLoadedException {
            if (matchingMethod != null) {
                throw new ParseException("Cannot assign to a method invocation");
            }
            obj.setValue(matchingField, val);
            jdiValue = val;
        }

        void invokeWith(List<Value> arguments) throws ParseException {
            if (matchingMethod != null) {
                throw new ParseException("Invalid consecutive invocations");
            }
            methodArguments = arguments;
            matchingMethod = LValue.resolveOverload(overloads, arguments);
        }
    }

    private static class LValueStaticMember extends LValue {
        final ReferenceType refType;
        final ThreadReference thread;
        final Field matchingField;
        final List<Method> overloads;
        Method matchingMethod = null;
        List<Value> methodArguments = null;

        LValueStaticMember(ReferenceType refType,
                          String memberName,
                          ThreadReference thread) throws ParseException {
            this.refType = refType;
            this.thread = thread;
            /*
             * Can't tell yet whether this LValue will be accessed as a
             * field or method, so we keep track of all the possibilities
             */
            matchingField = LValue.fieldByName(refType, memberName,
                                               LValue.STATIC);
            overloads = LValue.methodsByName(refType, memberName,
                                              LValue.STATIC);
            if ((matchingField == null) && overloads.size() == 0) {
                throw new ParseException("No static field or method with the name "
                               + memberName + " in " + refType.name());
            }
        }

        Value getValue() throws InvocationException, InvalidTypeException,
                                ClassNotLoadedException, IncompatibleThreadStateException,
                                ParseException {
            if (jdiValue != null) {
                return jdiValue;
            }
            if (matchingMethod == null) {
                return jdiValue = refType.getValue(matchingField);
            } else if (refType instanceof ClassType) {
                ClassType clazz = (ClassType)refType;
                return jdiValue = clazz.invokeMethod(thread, matchingMethod, methodArguments, 0);
            } else {
                throw new InvalidTypeException("Cannot invoke static method on " +
                                         refType.name());
            }
        }

        void setValue0(Value val)
                           throws ParseException, InvalidTypeException,
                                  ClassNotLoadedException {
            if (matchingMethod != null) {
                throw new ParseException("Cannot assign to a method invocation");
            }
            if (!(refType instanceof ClassType)) {
                throw new ParseException(
                       "Cannot set interface field: " + refType);
            }
            ((ClassType)refType).setValue(matchingField, val);
            jdiValue = val;
        }

        void invokeWith(List<Value> arguments) throws ParseException {
            if (matchingMethod != null) {
                throw new ParseException("Invalid consecutive invocations");
            }
            methodArguments = arguments;
            matchingMethod = LValue.resolveOverload(overloads, arguments);
        }
    }

    private static class LValueArrayLength extends LValue {
        /*
         * Since one can code "int myLen = myArray.length;",
         * one might expect that these JDI calls would get a Value
         * object for the length of an array in the debugee:
         *    Field xxx = ArrayType.fieldByName("length")
         *    Value lenVal= ArrayReference.getValue(xxx)
         *
         * However, this doesn't work because the array length isn't
         * really stored as a field, and can't be accessed as such
         * via JDI.  Instead, the arrayRef.length() method has to be
         * used.
         */
        final ArrayReference arrayRef;
        LValueArrayLength (ArrayReference value) {
            this.arrayRef = value;
        }

        Value getValue() {
            if (jdiValue == null) {
                jdiValue = arrayRef.virtualMachine().mirrorOf(arrayRef.length());
            }
            return jdiValue;
        }

        void setValue0(Value value) throws ParseException  {
            throw new ParseException("Cannot set constant: " + value);
        }

        void invokeWith(List<Value> arguments) throws ParseException {
            throw new ParseException("Array element is not a method");
        }
    }

    private static class LValueArrayElement extends LValue {
        final ArrayReference array;
        final int index;

        LValueArrayElement(Value value, int index) throws ParseException {
            if (!(value instanceof ArrayReference)) {
                throw new ParseException(
                       "Must be array type: " + value);
            }
            this.array = (ArrayReference)value;
            this.index = index;
        }

        Value getValue() {
            if (jdiValue == null) {
                jdiValue = array.getValue(index);
            }
            return jdiValue;
        }

        void setValue0(Value val) throws InvalidTypeException,
                                         ClassNotLoadedException  {
            array.setValue(index, val);
            jdiValue = val;
        }

        void invokeWith(List<Value> arguments) throws ParseException {
            throw new ParseException("Array element is not a method");
        }
    }

    private static class LValueConstant extends LValue {
        final Value value;

        LValueConstant(Value value) {
            this.value = value;
        }

        Value getValue() {
            if (jdiValue == null) {
                jdiValue = value;
            }
            return jdiValue;
        }

        void setValue0(Value val) throws ParseException {
            throw new ParseException("Cannot set constant: " + value);
        }

        void invokeWith(List<Value> arguments) throws ParseException {
            throw new ParseException("Constant is not a method");
        }
    }

    static LValue make(VirtualMachine vm, boolean val) {
        return new LValueConstant(vm.mirrorOf(val));
    }

    static LValue make(VirtualMachine vm, byte val) {
        return new LValueConstant(vm.mirrorOf(val));
    }

    static LValue make(VirtualMachine vm, char val) {
        return new LValueConstant(vm.mirrorOf(val));
    }

    static LValue make(VirtualMachine vm, short val) {
        return new LValueConstant(vm.mirrorOf(val));
    }

    static LValue make(VirtualMachine vm, int val) {
        return new LValueConstant(vm.mirrorOf(val));
    }

    static LValue make(VirtualMachine vm, long val) {
        return new LValueConstant(vm.mirrorOf(val));
    }

    static LValue make(VirtualMachine vm, float val) {
        return new LValueConstant(vm.mirrorOf(val));
    }

    static LValue make(VirtualMachine vm, double val) {
        return new LValueConstant(vm.mirrorOf(val));
    }

    static LValue make(VirtualMachine vm, String val) throws ParseException {
        return new LValueConstant(vm.mirrorOf(val));
    }

    static LValue makeBoolean(VirtualMachine vm, Token token) {
        return make(vm, token.image.charAt(0) == 't');
    }

    static LValue makeCharacter(VirtualMachine vm, Token token) {
        return make(vm, token.image.charAt(1));
    }

    static LValue makeFloat(VirtualMachine vm, Token token) {
        return make(vm, Float.valueOf(token.image).floatValue());
    }

    static LValue makeDouble(VirtualMachine vm, Token token) {
        return make(vm, Double.valueOf(token.image).doubleValue());
    }

    static LValue makeInteger(VirtualMachine vm, Token token) {
        return make(vm, Integer.parseInt(token.image));
    }

    static LValue makeShort(VirtualMachine vm, Token token) {
        return make(vm, Short.parseShort(token.image));
    }

    static LValue makeLong(VirtualMachine vm, Token token) {
        return make(vm, Long.parseLong(token.image));
    }

    static LValue makeByte(VirtualMachine vm, Token token) {
        return make(vm, Byte.parseByte(token.image));
    }

    static LValue makeString(VirtualMachine vm,
                             Token token) throws ParseException {
        int len = token.image.length();
        return make(vm, token.image.substring(1,len-1));
    }

    static LValue makeNull(VirtualMachine vm,
                           Token token) throws ParseException {
        return new LValueConstant(null);
    }

    static LValue makeThisObject(VirtualMachine vm,
                                 ExpressionParser.GetFrame frameGetter,
                                 Token token) throws ParseException {
        if (frameGetter == null) {
            throw new ParseException("No current thread");
        } else {
            try {
                StackFrame frame = frameGetter.get();
                ObjectReference thisObject = frame.thisObject();

                if (thisObject==null) {
                        throw new ParseException(
                            "No 'this'.  In native or static method");
                } else {
                        return new LValueConstant(thisObject);
                }
            } catch (IncompatibleThreadStateException exc) {
                throw new ParseException("Thread not suspended");
            }
        }
    }

    static LValue makeNewObject(VirtualMachine vm,
                                 ExpressionParser.GetFrame frameGetter,
                                String className, List<Value> arguments) throws ParseException {
        List<ReferenceType> classes = vm.classesByName(className);
        if (classes.size() == 0) {
            throw new ParseException("No class named: " + className);
        }

        if (classes.size() > 1) {
            throw new ParseException("More than one class named: " +
                                     className);
        }
        ReferenceType refType = classes.get(0);


        if (!(refType instanceof ClassType)) {
            throw new ParseException("Cannot create instance of interface " +
                                     className);
        }

        ClassType classType = (ClassType)refType;
        List<Method> methods = new ArrayList<Method>(classType.methods()); // writable
        Iterator<Method> iter = methods.iterator();
        while (iter.hasNext()) {
            Method method = iter.next();
            if (!method.isConstructor()) {
                iter.remove();
            }
        }
        Method constructor = LValue.resolveOverload(methods, arguments);

        ObjectReference newObject;
        try {
            ThreadReference thread = frameGetter.get().thread();
            newObject = classType.newInstance(thread, constructor, arguments, 0);
        } catch (InvocationException ie) {
            throw new ParseException("Exception in " + className + " constructor: " +
                                     ie.exception().referenceType().name());
        } catch (IncompatibleThreadStateException exc) {
            throw new ParseException("Thread not suspended");
        } catch (Exception e) {
            /*
             * TO DO: Better error handling
             */
            throw new ParseException("Unable to create " + className + " instance");
        }
        return new LValueConstant(newObject);
    }

    private static LValue nFields(LValue lval,
                                  StringTokenizer izer,
                                  ThreadReference thread)
                                          throws ParseException {
        if (!izer.hasMoreTokens()) {
            return lval;
        } else {
            return nFields(lval.memberLValue(izer.nextToken(), thread), izer, thread);
        }
    }

    static LValue makeName(VirtualMachine vm,
                           ExpressionParser.GetFrame frameGetter,
                           String name) throws ParseException {
        StringTokenizer izer = new StringTokenizer(name, ".");
        String first = izer.nextToken();
        // check local variables
        if (frameGetter != null) {
            try {
                StackFrame frame = frameGetter.get();
                ThreadReference thread = frame.thread();
                LocalVariable var;
                try {
                    var = frame.visibleVariableByName(first);
                } catch (AbsentInformationException e) {
                    var = null;
                }
                if (var != null) {
                    return nFields(new LValueLocal(frame, var), izer, thread);
                } else {
                    ObjectReference thisObject = frame.thisObject();
                    if (thisObject != null) {
                        // check if it is a field of 'this'
                        LValue thisLValue = new LValueConstant(thisObject);
                        LValue fv;
                        try {
                            fv = thisLValue.memberLValue(first, thread);
                        } catch (ParseException exc) {
                            fv = null;
                        }
                        if (fv != null) {
                            return nFields(fv, izer, thread);
                        }
                    }
                }
                // check for class name
                while (izer.hasMoreTokens()) {
                    List<ReferenceType> classes = vm.classesByName(first);
                    if (classes.size() > 0) {
                        if (classes.size() > 1) {
                            throw new ParseException("More than one class named: " +
                                                     first);
                        } else {
                            ReferenceType refType = classes.get(0);
                            LValue lval = new LValueStaticMember(refType,
                                                            izer.nextToken(), thread);
                            return nFields(lval, izer, thread);
                        }
                    }
                    first = first + '.' + izer.nextToken();
                }
            } catch (IncompatibleThreadStateException exc) {
                throw new ParseException("Thread not suspended");
            }
        }
        throw new ParseException("Name unknown: " + name);
    }

    static String stringValue(LValue lval, ExpressionParser.GetFrame frameGetter
                              ) throws ParseException {
        Value val = lval.getMassagedValue(frameGetter);
        if (val == null) {
            return "null";
        }
        if (val instanceof StringReference) {
            return ((StringReference)val).value();
        }
        return val.toString();  // is this correct in all cases?
    }

    static LValue booleanOperation(VirtualMachine vm, Token token,
                            LValue rightL,
                            LValue leftL) throws ParseException {
        String op = token.image;
        Value right = rightL.interiorGetValue();
        Value left = leftL.interiorGetValue();
        if ( !(right instanceof PrimitiveValue) ||
             !(left instanceof PrimitiveValue) ) {
            if (op.equals("==")) {
                return make(vm, right.equals(left));
            } else if (op.equals("!=")) {
                return make(vm, !right.equals(left));
            } else {
                throw new ParseException("Operands or '" + op +
                                     "' must be primitive");
            }
        }
        // can compare any numeric doubles
        double rr = ((PrimitiveValue)right).doubleValue();
        double ll = ((PrimitiveValue)left).doubleValue();
        boolean res;
        if (op.equals("<")) {
            res = rr < ll;
        } else if (op.equals(">")) {
            res = rr > ll;
        } else if (op.equals("<=")) {
            res = rr <= ll;
        } else if (op.equals(">=")) {
            res = rr >= ll;
        } else if (op.equals("==")) {
            res = rr == ll;
        } else if (op.equals("!=")) {
            res = rr != ll;
        } else {
            throw new ParseException("Unknown operation: " + op);
        }
        return make(vm, res);
    }

    static LValue operation(VirtualMachine vm, Token token,
                            LValue rightL, LValue leftL,
                            ExpressionParser.GetFrame frameGetter
                            ) throws ParseException {
        String op = token.image;
        Value right = rightL.interiorGetValue();
        Value left = leftL.interiorGetValue();
        if ((right instanceof StringReference) ||
                              (left instanceof StringReference)) {
            if (op.equals("+")) {
                // If one is an ObjectRef, we will need to invoke
                // toString on it, so we need the thread.
                return make(vm, stringValue(rightL, frameGetter) +
                            stringValue(leftL, frameGetter));
            }
        }
        if ((right instanceof ObjectReference) ||
                              (left instanceof ObjectReference)) {
            if (op.equals("==")) {
                return make(vm, right.equals(left));
            } else if (op.equals("!=")) {
                return make(vm, !right.equals(left));
            } else {
                throw new ParseException("Invalid operation '" +
                                         op + "' on an Object");
            }
        }
        if ((right instanceof BooleanValue) ||
                              (left instanceof BooleanValue)) {
            throw new ParseException("Invalid operation '" +
                                     op + "' on a Boolean");
        }
        // from here on, we know it is a integer kind of type
        PrimitiveValue primRight = (PrimitiveValue)right;
        PrimitiveValue primLeft = (PrimitiveValue)left;
        if ((primRight instanceof DoubleValue) ||
                              (primLeft instanceof DoubleValue)) {
            double rr = primRight.doubleValue();
            double ll = primLeft.doubleValue();
            double res;
            if (op.equals("+")) {
                res = rr + ll;
            } else if (op.equals("-")) {
                res = rr - ll;
            } else if (op.equals("*")) {
                res = rr * ll;
            } else if (op.equals("/")) {
                res = rr / ll;
            } else {
                throw new ParseException("Unknown operation: " + op);
            }
            return make(vm, res);
        }
        if ((primRight instanceof FloatValue) ||
                              (primLeft instanceof FloatValue)) {
            float rr = primRight.floatValue();
            float ll = primLeft.floatValue();
            float res;
            if (op.equals("+")) {
                res = rr + ll;
            } else if (op.equals("-")) {
                res = rr - ll;
            } else if (op.equals("*")) {
                res = rr * ll;
            } else if (op.equals("/")) {
                res = rr / ll;
            } else {
                throw new ParseException("Unknown operation: " + op);
            }
            return make(vm, res);
        }
        if ((primRight instanceof LongValue) ||
                              (primLeft instanceof LongValue)) {
            long rr = primRight.longValue();
            long ll = primLeft.longValue();
            long res;
            if (op.equals("+")) {
                res = rr + ll;
            } else if (op.equals("-")) {
                res = rr - ll;
            } else if (op.equals("*")) {
                res = rr * ll;
            } else if (op.equals("/")) {
                res = rr / ll;
            } else {
                throw new ParseException("Unknown operation: " + op);
            }
            return make(vm, res);
        } else {
            int rr = primRight.intValue();
            int ll = primLeft.intValue();
            int res;
            if (op.equals("+")) {
                res = rr + ll;
            } else if (op.equals("-")) {
                res = rr - ll;
            } else if (op.equals("*")) {
                res = rr * ll;
            } else if (op.equals("/")) {
                res = rr / ll;
            } else {
                throw new ParseException("Unknown operation: " + op);
            }
            return make(vm, res);
        }
    }
}
