package ch.unibe.scg.regex;

import java.util.LinkedHashMap;
import java.util.Map;

interface Instruction {
  static class CopyInstruction implements Instruction {
    public static Instruction make(final int fromTag, final int fromPos, final int toTag,
        final int toPos) {
      return new CopyInstruction(fromTag, fromPos, toTag, toPos);
    }

    final int fromTag, fromPos, toTag, toPos;

    public CopyInstruction(final int fromTag, final int fromPos, final int toTag, final int toPos) {
      this.fromTag = fromTag;
      this.fromPos = fromPos;
      this.toTag = toTag;
      this.toPos = toPos;
    }

    @Override
    public void execute(Memory memory, int pos) {
      throw new RuntimeException("Not implemented");
    }

    @Override
    public String toString() {
      return "" + fromTag + "," + fromPos + " <- " + toTag + "," + toPos;
    }
  }

  /** Not threadsafe. */
  class InstructionMaker {
    public static InstructionMaker get() {
      return new InstructionMaker();
    }

    int id = -1;

    Map<Tag, Integer> tagIds = new LinkedHashMap<>();

    // TODO: Delete?
    int lookup(final Tag tag) {
      final Integer tagId = tagIds.get(tag);
      if (tagId != null) {
        return tagId;
      }
      final int ret = nextId();
      tagIds.put(tag, ret);
      return ret;
    }

    public int nextId() {
      return ++id;
    }

    public Instruction reorder(final int from, final int to) {
      return new ReorderInstruction(from, to);
    }

    public Instruction storePos(final int tag) {
      return SetInstruction.make(tag);
    }
  }

  static class ReorderInstruction implements Instruction {
    final int from, to;

    ReorderInstruction(int from, int to) {
      this.from = from;
      this.to = to;
    }

    @Override
    public void execute(Memory memory, int pos) {
      memory.copyTo(from, to);
    }

    @Override
    public String toString() {
      return String.valueOf(from) + "->" + to;
    }
  }

  static class SetInstruction implements Instruction {
    static SetInstruction make(final int tag) {
      return new SetInstruction(tag);
    }

    final int tag;

    public SetInstruction(final int tag) {
      this.tag = tag;
    }

    @Override
    public void execute(final Memory memory, final int pos) {
      memory.write(tag, pos);
    }

    @Override
    public String toString() {
      return "" + tag + "<- pos";
    }
  }

  public void execute(Memory memory, int pos);
}

@@ -1551,16 +1551,20 @@
  return 
+new 
 SetInstr
@@ -1573,13 +1573,8 @@
 tion
-.make
 (tag
@@ -2029,101 +2029,8 @@
 n %7B%0A
-    static SetInstruction make(final int tag) %7B%0A      return new SetInstruction(tag);%0A    %7D%0A%0A
     
@@ -2049,23 +2049,16 @@
 g;%0A%0A    
-public 
 SetInstr
@@ -2313,16 +2313,299 @@
  %7D%0A  %7D%0A%0A
+  static class CommitInstruction implements Instruction %7B%0A    final int memoryPos;%0A%0A    CommitInstruction(final int memoryPos) %7B%0A      this.memoryPos = memoryPos;%0A    %7D%0A%0A    @Override%0A    public void execute(Memory memory, int unusedPos) %7B%0A      memory.commit(memoryPos);%0A    %7D%0A  %7D%0A%0A
   public

Add CommitInstruction and refactoring away SetInstruction.make.