// File: /workspace/github_cpp_makefile_star2_O2/elarielcl[P]ArielsSequitur/Dictionary.cpp
// Function: Dictionary::putUnique(Node*)
void Dictionary::putUnique(Node* node) {
  Node** insertAt = this->get(node);
  if ((*insertAt) == NULL || (*insertAt) ->isGuard()){ // is there a better way?
    *insertAt = node;
    this->a++;
  }
  else {
    Node* m = *insertAt;
    if (m->digramOverlap(node)) return;

    if (m->prev->isGuard() && m->next->next->isGuard()) {

      this->grammar->grammarSize--;

      Rule* existentRule = m->prev->rule;
      existentRule->usage++;

      //Create one new node
      Node* one = new Node(existentRule, existentRule->symbol);

      // remove existent digrams in the index
      if (!node->prev->isGuard())
        this->remove(node->prev);
      if (!node->next->next->isGuard())
        this->remove(node->next);

      //Insert one
      node->prev->connect(one);
      one->connect(node->next->next);

      // put new digrams in the index
      if (!one->prev->isGuard())
        this->putUnique(one->prev);
      if (!one->next->isGuard())
        this->putUnique(one);

        //DELETING
        delete node->next;
        delete node;
        //DELETING

        // delete deprecatedOcurrences
        Node* dOcc = existentRule->guard->next; //deprecatedOccurrence
        while (!dOcc->isGuard()) {
          if(dOcc->symbol>=this->grammar->M) {
            dOcc->rule->usage--;
            if (dOcc->rule->usage <= 1) {
              this->grammar->numberOfRules--;
              this->grammar->grammarSize--;

              // remove existent digrams in the index
              if (!dOcc->prev->isGuard())
                this->remove(dOcc->prev);
              if (!dOcc->next->isGuard())
                this->remove(dOcc);

              // restructure pointers
              dOcc->prev->connect(dOcc->rule->guard->next);
              dOcc->rule->guard->prev->connect(dOcc->next);

              // put new digrams in the index
              if (!dOcc->next->isGuard())
                this->putUnique(dOcc->next->prev);
              if (!dOcc->prev->isGuard())
                this->putUnique(dOcc->prev);

              Node* next = dOcc->next;

              //DELETING
              delete dOcc->rule->guard;
              delete dOcc->rule;
              delete dOcc;
              //DELETING
              dOcc = next;
            }else dOcc = dOcc->next;
          }else dOcc = dOcc->next;
      }
    }else {
      this->grammar->numberOfRules++;
      int ruleName = (this->grammar->nextRuleName ++); // Another idea?
      Rule* newRule = new Rule(ruleName, this->grammar);
      newRule->usage = 2;

      //Create two new nodes
      Node* one = new Node(newRule, ruleName);
      Node* two = new Node(newRule, ruleName);

      // remove existent digrams in the index
      if (!node->prev->isGuard())
        this->remove(node->prev);
      if (!node->next->next->isGuard())
        this->remove(node->next);

      //Insert one
      node->prev->connect(one);
      one->connect(node->next->next);

      //Here put in the index the new digram (case not before)
      if (!one->prev->isGuard())
        this->put(one->prev); //Not recursive
      if (!one->next->isGuard())
        this->put(one); //Not recursive

      // remove existent digrams in the index
      if (!m->prev->isGuard())
        this->remove(m->prev);
      if (!m->next->next->isGuard())
        this->remove(m->next);

      //Insert two
      m->prev->connect(two);
      two->connect(m->next->next);

      //Here put in the index the new digrams (case not before)
      if (!two->prev->isGuard())
        this->put(two->prev); //Not recursive
      if (!two->next->isGuard())
        this->put(two); //Not recursive

      //Put the symbols in the new rule
      newRule->guard->connect(m);
      m->next->connect(newRule->guard);

      //DELETING
      delete node->next;
      delete node;
      //DELETING

      // delete deprecatedOcurrences
      Node* dOcc = newRule->guard->next; //deprecatedOccurrence
      while (!dOcc->isGuard()) {
        if(dOcc->symbol>=this->grammar->M) {
          dOcc->rule->usage--;
          if (dOcc->rule->usage <= 1) {
            this->grammar->grammarSize--;
            this->grammar->numberOfRules--;

            // remove existent digrams in the index
            if (!dOcc->prev->isGuard())
              this->remove(dOcc->prev);
            if (!dOcc->next->isGuard())
              this->remove(dOcc);

            // restructure pointers
            dOcc->prev->connect(dOcc->rule->guard->next);
            dOcc->rule->guard->prev->connect(dOcc->next);

            // put new digrams in the index
            if (!dOcc->next->isGuard())
              this->putUnique(dOcc->next->prev);
            if (!dOcc->prev->isGuard())
              this->putUnique(dOcc->prev);

            Node* next = dOcc->next;

            //DELETING
            delete dOcc->rule->guard;
            delete dOcc->rule;
            delete dOcc;
            //DELETING
            dOcc = next;
          }else dOcc = dOcc->next;
        }else dOcc = dOcc->next;
      }
    }
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rsi, %r14
movq %rdi, %rbx
callq 0x1d92
movq %rax, %r15
movq (%rax), %rdi
testq %rdi, %rdi
je 0x1842
callq 0x2418
testb %al, %al
je 0x1857
movq %r14, (%r15)
incl 0x14(%rbx)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq (%r15), %r15
movq %r15, %rdi
movq %r14, %rsi
callq 0x2442
testb %al, %al
jne 0x1848
movq 0x10(%r15), %rdi
callq 0x2418
testb %al, %al
je 0x1a7d
movq 0x8(%r15), %rax
movq 0x8(%rax), %rdi
callq 0x2418
testb %al, %al
je 0x1a7d
movq (%rbx), %rax
decl 0x10(%rax)
movq 0x10(%r15), %rax
movq 0x18(%rax), %r12
incl 0x8(%r12)
pushq $0x20
popq %rdi
callq 0x10e0
movq %rax, %r15
movl 0xc(%r12), %edx
movq %rax, %rdi
movq %r12, %rsi
callq 0x240c
movq 0x10(%r14), %rdi
callq 0x2418
testb %al, %al
jne 0x18d6
movq 0x10(%r14), %rsi
movq %rbx, %rdi
callq 0x1e6a
movq 0x8(%r14), %rax
movq 0x8(%rax), %rdi
callq 0x2418
testb %al, %al
jne 0x18f3
movq 0x8(%r14), %rsi
movq %rbx, %rdi
callq 0x1e6a
movq 0x10(%r14), %rdi
movq %r15, %rsi
callq 0x2458
movq 0x8(%r14), %rax
movq 0x8(%rax), %rsi
movq %r15, %rdi
callq 0x2458
movq 0x10(%r15), %rdi
callq 0x2418
testb %al, %al
jne 0x1928
movq 0x10(%r15), %rsi
movq %rbx, %rdi
callq 0x1812
movq 0x8(%r15), %rdi
callq 0x2418
testb %al, %al
jne 0x1940
movq %rbx, %rdi
movq %r15, %rsi
callq 0x1812
movq 0x8(%r14), %rdi
pushq $0x20
popq %r15
movq %r15, %rsi
callq 0x10f0
movq %r14, %rdi
movq %r15, %rsi
callq 0x10f0
movq (%r12), %rax
movq 0x8(%rax), %r12
pushq $0x18
popq %r14
movq %r12, %rdi
callq 0x2418
testb %al, %al
jne 0x1848
movl (%r12), %ecx
movq (%rbx), %rax
cmpl 0x20(%rax), %ecx
jl 0x1a73
movq 0x18(%r12), %rcx
movl 0x8(%rcx), %edx
leal -0x1(%rdx), %esi
movl %esi, 0x8(%rcx)
cmpl $0x2, %edx
jg 0x1a73
decl 0x18(%rax)
decl 0x10(%rax)
movq 0x10(%r12), %rdi
callq 0x2418
testb %al, %al
jne 0x19bf
movq 0x10(%r12), %rsi
movq %rbx, %rdi
callq 0x1e6a
movq 0x8(%r12), %rdi
callq 0x2418
testb %al, %al
jne 0x19d8
movq %rbx, %rdi
movq %r12, %rsi
callq 0x1e6a
movq 0x10(%r12), %rdi
movq 0x18(%r12), %rax
movq (%rax), %rax
movq 0x8(%rax), %rsi
callq 0x2458
movq 0x8(%r12), %rsi
movq 0x18(%r12), %rax
movq (%rax), %rax
movq 0x10(%rax), %rdi
callq 0x2458
movq 0x8(%r12), %rdi
callq 0x2418
testb %al, %al
jne 0x1a23
movq 0x8(%r12), %rax
movq 0x10(%rax), %rsi
movq %rbx, %rdi
callq 0x1812
movq 0x10(%r12), %rdi
callq 0x2418
testb %al, %al
jne 0x1a3e
movq 0x10(%r12), %rsi
movq %rbx, %rdi
callq 0x1812
movq 0x8(%r12), %r13
movq 0x18(%r12), %rax
movq (%rax), %rdi
movq %r15, %rsi
callq 0x10f0
movq 0x18(%r12), %rdi
movq %r14, %rsi
callq 0x10f0
movq %r12, %rdi
movq %r15, %rsi
callq 0x10f0
movq %r13, %r12
jmp 0x1967
movq 0x8(%r12), %r12
jmp 0x1967
movq %r15, -0x40(%rbp)
movq (%rbx), %r12
incl 0x18(%r12)
movl 0x1c(%r12), %r13d
leal 0x1(%r13), %eax
movl %eax, 0x1c(%r12)
pushq $0x18
popq %rdi
callq 0x10e0
movq %rax, %r15
movq %rax, %rdi
movl %r13d, %esi
movq %r12, %rdx
callq 0x1fe0
movl $0x2, 0x8(%r15)
pushq $0x20
popq %rdi
callq 0x10e0
movq %rax, %r12
movq %rax, %rdi
movq %r15, %rsi
movl %r13d, %edx
callq 0x240c
pushq $0x20
popq %rdi
callq 0x10e0
movq %rax, -0x30(%rbp)
movq %rax, %rdi
movq %r15, -0x38(%rbp)
movq %r15, %rsi
movl %r13d, %edx
callq 0x240c
movq 0x10(%r14), %rdi
callq 0x2418
testb %al, %al
movq -0x40(%rbp), %r15
jne 0x1b0c
movq 0x10(%r14), %rsi
movq %rbx, %rdi
callq 0x1e6a
movq 0x8(%r14), %rax
movq 0x8(%rax), %rdi
callq 0x2418
testb %al, %al
movq -0x38(%rbp), %r13
jne 0x1b2d
movq 0x8(%r14), %rsi
movq %rbx, %rdi
callq 0x1e6a
movq 0x10(%r14), %rdi
movq %r12, %rsi
callq 0x2458
movq 0x8(%r14), %rax
movq 0x8(%rax), %rsi
movq %r12, %rdi
callq 0x2458
movq 0x10(%r12), %rdi
callq 0x2418
testb %al, %al
jne 0x1b64
movq 0x10(%r12), %rsi
movq %rbx, %rdi
callq 0x179a
movq 0x8(%r12), %rdi
callq 0x2418
testb %al, %al
jne 0x1b7d
movq %rbx, %rdi
movq %r12, %rsi
callq 0x179a
movq 0x10(%r15), %rdi
callq 0x2418
testb %al, %al
jne 0x1b96
movq 0x10(%r15), %rsi
movq %rbx, %rdi
callq 0x1e6a
movq 0x8(%r15), %rax
movq 0x8(%rax), %rdi
callq 0x2418
testb %al, %al
movq -0x30(%rbp), %r12
jne 0x1bb7
movq 0x8(%r15), %rsi
movq %rbx, %rdi
callq 0x1e6a
movq 0x10(%r15), %rdi
movq %r12, %rsi
callq 0x2458
movq 0x8(%r15), %rax
movq 0x8(%rax), %rsi
movq %r12, %rdi
callq 0x2458
movq 0x10(%r12), %rdi
callq 0x2418
testb %al, %al
jne 0x1bee
movq 0x10(%r12), %rsi
movq %rbx, %rdi
callq 0x179a
movq 0x8(%r12), %rdi
callq 0x2418
testb %al, %al
jne 0x1c07
movq %rbx, %rdi
movq %r12, %rsi
callq 0x179a
movq (%r13), %rdi
movq %r15, %rsi
callq 0x2458
movq 0x8(%r15), %rdi
movq (%r13), %rsi
callq 0x2458
movq 0x8(%r14), %rdi
pushq $0x20
popq %r15
movq %r15, %rsi
callq 0x10f0
movq %r14, %rdi
movq %r15, %rsi
callq 0x10f0
movq (%r13), %rax
movq 0x8(%rax), %r12
pushq $0x18
popq %r14
movq %r12, %rdi
callq 0x2418
testb %al, %al
jne 0x1848
movl (%r12), %ecx
movq (%rbx), %rax
cmpl 0x20(%rax), %ecx
jl 0x1d53
movq 0x18(%r12), %rcx
movl 0x8(%rcx), %edx
leal -0x1(%rdx), %esi
movl %esi, 0x8(%rcx)
cmpl $0x2, %edx
jg 0x1d53
decl 0x10(%rax)
decl 0x18(%rax)
movq 0x10(%r12), %rdi
callq 0x2418
testb %al, %al
jne 0x1c9f
movq 0x10(%r12), %rsi
movq %rbx, %rdi
callq 0x1e6a
movq 0x8(%r12), %rdi
callq 0x2418
testb %al, %al
jne 0x1cb8
movq %rbx, %rdi
movq %r12, %rsi
callq 0x1e6a
movq 0x10(%r12), %rdi
movq 0x18(%r12), %rax
movq (%rax), %rax
movq 0x8(%rax), %rsi
callq 0x2458
movq 0x8(%r12), %rsi
movq 0x18(%r12), %rax
movq (%rax), %rax
movq 0x10(%rax), %rdi
callq 0x2458
movq 0x8(%r12), %rdi
callq 0x2418
testb %al, %al
jne 0x1d03
movq 0x8(%r12), %rax
movq 0x10(%rax), %rsi
movq %rbx, %rdi
callq 0x1812
movq 0x10(%r12), %rdi
callq 0x2418
testb %al, %al
jne 0x1d1e
movq 0x10(%r12), %rsi
movq %rbx, %rdi
callq 0x1812
movq 0x8(%r12), %r13
movq 0x18(%r12), %rax
movq (%rax), %rdi
movq %r15, %rsi
callq 0x10f0
movq 0x18(%r12), %rdi
movq %r14, %rsi
callq 0x10f0
movq %r12, %rdi
movq %r15, %rsi
callq 0x10f0
movq %r13, %r12
jmp 0x1c47
movq 0x8(%r12), %r12
jmp 0x1c47
movq %rax, %rbx
pushq $0x20
jmp 0x1d80
movq %rax, %rbx
pushq $0x20
popq %rsi
movq -0x30(%rbp), %rdi
jmp 0x1d84
movq %rax, %rbx
pushq $0x20
popq %rsi
movq %r12, %rdi
jmp 0x1d84
movq %rax, %rbx
pushq $0x18
popq %rsi
movq %r15, %rdi
callq 0x10f0
movq %rbx, %rdi
callq 0x1190
nop