anchor.diff:    DoubleValue(this.value);
   }
   
  -class BoolValue extends Value {
  +class BoolValue extends LiteralValue {
     final bool value;
   
     const BoolValue(this.value);
   }
   
  -class NullValue extends Value {
  +class NullValue extends LiteralValue {
     Object get value => null;
   
     const NullValue();
  
positive.code:     return env.assign(node.variable, eval(node.value, env));
    }
  
    Value visitStaticInvocation(StaticInvocation node, env) {
      if ('print' == node.name.toString()) {
        // Special evaluation of print.
  
negative.code:     return _classes[classRef];
    }
  
    ClassDeclaration._internal(Class currentClass) {
      if (currentClass.superclass != null) {
        superclass = new ClassDeclaration(currentClass.superclass.reference);
      }
  
      _populateInstanceFields(currentClass);
  
      // Populate implicit setters and getters.
      for (int i = 0; i < instanceFields.length; i++) {
        Field f = instanceFields[i];
        assert(f.hasImplicitGetter);
        getters[f.name] = (Value receiver) => receiver.fields[i];
        if (f.hasImplicitSetter) {
          setters[f.name] =
              (Value receiver, Value value) => receiver.fields[i] = value;
        }
      }
      // TODO: Populate methods.
    }
  
    Getter lookupGetter(Name name) {
      Getter getter = getters[name];
      if (getter != null) return getter;
      if (superclass != null) return superclass.lookupGetter(name);
      return (Value receiver) => notImplemented(obj: name);
    }
  
    Setter lookupSetter(Name name) {
      Setter setter = setters[name];
      if (setter != null) return setter;
      if (superclass != null) return lookupSetter(name);
      return (Value receiver, Value value) => notImplemented(obj: name);
    }
  
    Value getProperty(ObjectValue object, Member member) {
      if (member is Field) {
        int index = instanceFields.indexOf(member);
        // TODO: throw NoSuchMethodError instead.
        if (index < 0) return notImplemented(m: 'NoSuchMethod: ${member}');
        return object.fields[index];
      }
      return notImplemented(obj: member);
    }
  
    Value setProperty(ObjectValue object, Member member, Value value) {
      if (member is Field) {
        int index = instanceFields.indexOf(member);
        // TODO: throw NoSuchMethodError instead.
        if (index < 0) return notImplemented(m: 'NoSuchMethod: ${member}');
        object.fields[index] = value;
        return Value.nullInstance;
      }
      return notImplemented(obj: member);
    }
  
    // Populates with the instance fields of the current class and all its
    // superclasses recursively.
    _populateInstanceFields(Class class_) {
      for (Field f in class_.fields) {
        if (f.isInstanceMember) {
          instanceFields.add(f);
        }
      }
  
      if (class_.superclass != null) {
        _populateInstanceFields(class_.superclass);
      }
    }
  }
  
  abstract class Value {
    ClassDeclaration get classDeclaration;
    List<Value> get fields;
    Object get value;
  
    static final NullValue nullInstance = const NullValue();
  