/*
 * Copyright (c) 1998, 2011, 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.
 */

/*
 * This source code is provided to illustrate the usage of a given feature
 * or technique and has been deliberately simplified. Additional steps
 * required for a production-quality application, such as security checks,
 * input validation and proper error handling, might not be present in
 * this sample code.
 */


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);
    }

   @Override
    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;
        }

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

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

      @Override
        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());
            }
        }

      @Override
        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);
            }
        }

        @Override
        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;
        }

        @Override
        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());
            }
        }

        @Override
        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());
            }
        }

        @Override
        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;
        }

        @Override
        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;
        }

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

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

        @Override
        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;
        }

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

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

        @Override
        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;
        }

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

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

        @Override
        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);
        }
    }
}
