anchor.diff:  
     Instruction(this.implementation, this.tokens, [this.immediateValue]);
   
  -  String toString() => implementation.format(argument);
  +  String toString() => implementation.immediateArgumentSize == 0
  +      ? implementation.name
  +      : '${implementation.name} $argument';
   }
   
   /// Implements a machine instruction that can be executed by a [VM].
   ///
  -/// Instructions are instantiated as const objects because we need several
  -/// different versions of some instructions. For example, we need integer
  -/// addition for 8, 16, 32 and 64 bit words.
  -abstract class InstructionTemplate {
  -  const InstructionTemplate();
  +/// Instructions are instantiated as objects because we need several different
  +/// versions of some of them. For example, we need integer addition for 8, 16,
  +/// 32 and 64 bit words.
  +abstract class InstructionImplementation {
  +  /// A verbose mnemonic for this instruction.
  +  String get name;
  +
  +  /// This number of bytes immediately following this instruction are passed to
  +  /// [execute] as `immediateArgument`.
  +  int get immediateArgumentSize => 0;
  +
  +  const InstructionImplementation();
   
     /// Execute this instruction on `vm`.
     void execute(VM vm, num immediateArgument);
  -
  -  /// Return a human-readable name for this instruction type.
  -  String format(int immediateArgument);
  -}
  -
  -/// Pushes the immediate argument on the stack.
  -class PushInstruction extends InstructionTemplate {
  +}
  +
  +/// Superclass for implementations that are overloaded with a single type. This
  +/// includes all overloaded implementations except [TypeConversionInstruction].
  +abstract class OverloadedImplementation extends InstructionImplementation {
  +  /// Some implementations (for example [AddInstruction]) don't distinct between
  +  /// signed and unsigned integers. This method generates a string similar to
  +  /// [NumberType#toString], but leaves out the sign prefix for integers.
  +  static String _unifyIntegerNames(NumberType t) => t.memoryInterpretation ==
  +      NumberType.float ? t.toString() : 'int${t.sizeInBits}';
  +
     /// Size of the value that is pushed to the stack.
     final NumberType valueType;
   
  -  const PushInstruction(this.valueType);
  +  String get name => format(valueType);
  +
  +  const OverloadedImplementation(this.valueType);
  +
  +  /// Return a mnemonic for the given overloaded type. This is used by
  +  /// [InstructionSet#resolveForType].
  +  ///
  +  /// _This method should be static, but static methods are not part and a class
  +  /// interface and difficult to call dynamically._
  +  String format(NumberType t);
  +}
  +
  +/// Pushes the immediate argument on the stack.
  +class PushInstruction extends OverloadedImplementation {
  +  int get immediateArgumentSize => valueType.sizeInBytes;
  +
  +  const PushInstruction(NumberType valueType) : super(valueType);
   
     void execute(VM vm, num value) {
       vm.pushStack(valueType, value);
     }
   
  -  String format(int value) => 'loadc<${valueType.sizeInBytes}> $value';
  +  String format(NumberType t) => 'loadc<${t.sizeInBits}>';
   }
   
   /// Reduces the stack by _n_ bytes, encoded as immediate argument.
  -class PopInstruction extends InstructionTemplate {
  +class PopInstruction extends InstructionImplementation {
  +  String get name => 'pop';
  +
     const PopInstruction();
   
     void execute(VM vm, int numberOfBytes) {
       vm.stackPointer += numberOfBytes;
     }
  -
  -  String format(int value) => 'pop $value';
   }
   
   /// Increases the stack by _n_ bytes, encoded as immediate argument.
  -class StackAllocateInstruction extends InstructionTemplate {
  +class StackAllocateInstruction extends InstructionImplementation {
  +  String get name => 'alloc';
  +
  +  int get immediateArgumentSize => addressSize.sizeInBytes;
  +
     const StackAllocateInstruction();
   
     void execute(VM vm, int numberOfBytes) {
       vm.stackPointer -= numberOfBytes;
     }
  -
  -  String format(int value) => 'alloc $value';
   }
   
   /// Loads _n_ bytes from _address_ to the stack, where _n_ is encoded as
   /// immediate argument in the instruction, and _address_ is read from the stack.
  -class FetchInstruction extends InstructionTemplate {
  +class FetchInstruction extends InstructionImplementation {
  +  String get name => 'loada';
  +
  +  int get immediateArgumentSize => addressSize.sizeInBytes;
  +
     const FetchInstruction();
   
     void execute(VM vm, num numberOfBytes) {
  
positive.code: ///
  /// Points the frame pointer to the top of the stack (and therefore on the
  /// return address).
  class CallInstruction extends InstructionTemplate {
    const CallInstruction();
  
    void execute(VM vm, int offset) {
  
negative.code:       address += chunk.size;
      }
    }
  }
  
  /// Stores _n_ bytes at _address_ on the stack, where _n_ is encoded as
  /// immediate argument in the instruction, and _address_ is read from the stack.
  class StoreInstruction extends InstructionImplementation {
    String get name => 'store';
  
    int get immediateArgumentSize => addressSize.sizeInBytes;
  
    const StoreInstruction();
  
    void execute(VM vm, num numberOfBytes) {
  