// File: /workspace/github_cpp_makefile_star2_O1/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 0x2e80
movq %rax, %r15
movq (%rax), %rdi
testq %rdi, %rdi
je 0x291c
callq 0x35ec
testb %al, %al
je 0x2931
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 0x3616
testb %al, %al
jne 0x2922
movq 0x10(%r15), %rdi
callq 0x35ec
testb %al, %al
je 0x2b5e
movq 0x8(%r15), %rax
movq 0x8(%rax), %rdi
callq 0x35ec
testb %al, %al
je 0x2b5e
movq (%rbx), %rax
decl 0x10(%rax)
movq 0x10(%r15), %rax
movq 0x18(%rax), %r15
incl 0x8(%r15)
movl $0x20, %edi
callq 0x20f0
movq %rax, %r12
movl 0xc(%r15), %edx
movq %rax, %rdi
movq %r15, %rsi
callq 0x35e0
movq 0x10(%r14), %rdi
callq 0x35ec
testb %al, %al
jne 0x29b0
movq 0x10(%r14), %rsi
movq %rbx, %rdi
callq 0x2f8e
movq 0x8(%r14), %rax
movq 0x8(%rax), %rdi
callq 0x35ec
testb %al, %al
jne 0x29cd
movq 0x8(%r14), %rsi
movq %rbx, %rdi
callq 0x2f8e
movq 0x10(%r14), %rdi
movq %r12, %rsi
callq 0x362c
movq 0x8(%r14), %rax
movq 0x8(%rax), %rsi
movq %r12, %rdi
callq 0x362c
movq 0x10(%r12), %rdi
callq 0x35ec
testb %al, %al
jne 0x2a04
movq 0x10(%r12), %rsi
movq %rbx, %rdi
callq 0x28ec
movq 0x8(%r12), %rdi
callq 0x35ec
testb %al, %al
jne 0x2a1d
movq %rbx, %rdi
movq %r12, %rsi
callq 0x28ec
movq 0x8(%r14), %rdi
testq %rdi, %rdi
je 0x2a30
movl $0x20, %esi
callq 0x2100
movl $0x20, %esi
movq %r14, %rdi
callq 0x2100
movq (%r15), %rax
movq 0x8(%rax), %r14
movq %r14, %rdi
callq 0x35ec
testb %al, %al
jne 0x2922
movl (%r14), %ecx
movq (%rbx), %rax
cmpl 0x20(%rax), %ecx
jl 0x2b4a
movq 0x18(%r14), %rcx
movl 0x8(%rcx), %edx
leal -0x1(%rdx), %esi
movl %esi, 0x8(%rcx)
cmpl $0x2, %edx
jg 0x2b4a
decl 0x18(%rax)
decl 0x10(%rax)
movq 0x10(%r14), %rdi
callq 0x35ec
testb %al, %al
jne 0x2a98
movq 0x10(%r14), %rsi
movq %rbx, %rdi
callq 0x2f8e
movq 0x8(%r14), %rdi
callq 0x35ec
testb %al, %al
jne 0x2ab0
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2f8e
movq 0x10(%r14), %rdi
movq 0x18(%r14), %rax
movq (%rax), %rax
movq 0x8(%rax), %rsi
callq 0x362c
movq 0x8(%r14), %rsi
movq 0x18(%r14), %rax
movq (%rax), %rax
movq 0x10(%rax), %rdi
callq 0x362c
movq 0x8(%r14), %rdi
callq 0x35ec
testb %al, %al
jne 0x2af5
movq 0x8(%r14), %rax
movq 0x10(%rax), %rsi
movq %rbx, %rdi
callq 0x28ec
movq 0x10(%r14), %rdi
callq 0x35ec
testb %al, %al
jne 0x2b0e
movq 0x10(%r14), %rsi
movq %rbx, %rdi
callq 0x28ec
movq 0x8(%r14), %r15
movq 0x18(%r14), %rax
movq (%rax), %rdi
testq %rdi, %rdi
je 0x2b28
movl $0x20, %esi
callq 0x2100
movq 0x18(%r14), %rdi
testq %rdi, %rdi
je 0x2b3b
movl $0x18, %esi
callq 0x2100
movl $0x20, %esi
movq %r14, %rdi
callq 0x2100
jmp 0x2b4e
movq 0x8(%r14), %r15
movq %r15, %rdi
callq 0x35ec
movq %r15, %r14
jmp 0x2a4c
movq %r15, -0x40(%rbp)
movq (%rbx), %r12
incl 0x18(%r12)
movl 0x1c(%r12), %r13d
leal 0x1(%r13), %eax
movl %eax, 0x1c(%r12)
movl $0x18, %edi
callq 0x20f0
movq %rax, %r15
movq %rax, %rdi
movl %r13d, %esi
movq %r12, %rdx
callq 0x3188
movl $0x2, 0x8(%r15)
movl $0x20, %edi
callq 0x20f0
movq %rax, %r12
movq %rax, %rdi
movq %r15, %rsi
movl %r13d, %edx
callq 0x35e0
movl $0x20, %edi
callq 0x20f0
movq %rax, -0x30(%rbp)
movq %rax, %rdi
movq %r15, -0x38(%rbp)
movq %r15, %rsi
movl %r13d, %edx
callq 0x35e0
movq 0x10(%r14), %rdi
callq 0x35ec
testb %al, %al
jne 0x2bef
movq 0x10(%r14), %rsi
movq %rbx, %rdi
callq 0x2f8e
movq 0x8(%r14), %rax
movq 0x8(%rax), %rdi
callq 0x35ec
testb %al, %al
movq -0x38(%rbp), %r15
movq -0x30(%rbp), %r13
jne 0x2c14
movq 0x8(%r14), %rsi
movq %rbx, %rdi
callq 0x2f8e
movq 0x10(%r14), %rdi
movq %r12, %rsi
callq 0x362c
movq 0x8(%r14), %rax
movq 0x8(%rax), %rsi
movq %r12, %rdi
callq 0x362c
movq 0x10(%r12), %rdi
callq 0x35ec
testb %al, %al
jne 0x2c4b
movq 0x10(%r12), %rsi
movq %rbx, %rdi
callq 0x2854
movq 0x8(%r12), %rdi
callq 0x35ec
testb %al, %al
jne 0x2c64
movq %rbx, %rdi
movq %r12, %rsi
callq 0x2854
movq -0x40(%rbp), %r12
movq 0x10(%r12), %rdi
callq 0x35ec
testb %al, %al
jne 0x2c83
movq 0x10(%r12), %rsi
movq %rbx, %rdi
callq 0x2f8e
movq 0x8(%r12), %rax
movq 0x8(%rax), %rdi
callq 0x35ec
testb %al, %al
jne 0x2ca2
movq 0x8(%r12), %rsi
movq %rbx, %rdi
callq 0x2f8e
movq 0x10(%r12), %rdi
movq %r13, %rsi
callq 0x362c
movq 0x8(%r12), %rax
movq 0x8(%rax), %rsi
movq %r13, %rdi
callq 0x362c
movq 0x10(%r13), %rdi
callq 0x35ec
testb %al, %al
jne 0x2cd9
movq 0x10(%r13), %rsi
movq %rbx, %rdi
callq 0x2854
movq 0x8(%r13), %rdi
callq 0x35ec
testb %al, %al
jne 0x2cf1
movq %rbx, %rdi
movq %r13, %rsi
callq 0x2854
movq (%r15), %rdi
movq %r12, %rsi
callq 0x362c
movq 0x8(%r12), %rdi
movq (%r15), %rsi
callq 0x362c
movq 0x8(%r14), %rdi
testq %rdi, %rdi
je 0x2d1c
movl $0x20, %esi
callq 0x2100
movl $0x20, %esi
movq %r14, %rdi
callq 0x2100
movq (%r15), %rax
movq 0x8(%rax), %r14
movq %r14, %rdi
callq 0x35ec
testb %al, %al
jne 0x2922
movl (%r14), %ecx
movq (%rbx), %rax
cmpl 0x20(%rax), %ecx
jl 0x2e36
movq 0x18(%r14), %rcx
movl 0x8(%rcx), %edx
leal -0x1(%rdx), %esi
movl %esi, 0x8(%rcx)
cmpl $0x2, %edx
jg 0x2e36
decl 0x10(%rax)
decl 0x18(%rax)
movq 0x10(%r14), %rdi
callq 0x35ec
testb %al, %al
jne 0x2d84
movq 0x10(%r14), %rsi
movq %rbx, %rdi
callq 0x2f8e
movq 0x8(%r14), %rdi
callq 0x35ec
testb %al, %al
jne 0x2d9c
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2f8e
movq 0x10(%r14), %rdi
movq 0x18(%r14), %rax
movq (%rax), %rax
movq 0x8(%rax), %rsi
callq 0x362c
movq 0x8(%r14), %rsi
movq 0x18(%r14), %rax
movq (%rax), %rax
movq 0x10(%rax), %rdi
callq 0x362c
movq 0x8(%r14), %rdi
callq 0x35ec
testb %al, %al
jne 0x2de1
movq 0x8(%r14), %rax
movq 0x10(%rax), %rsi
movq %rbx, %rdi
callq 0x28ec
movq 0x10(%r14), %rdi
callq 0x35ec
testb %al, %al
jne 0x2dfa
movq 0x10(%r14), %rsi
movq %rbx, %rdi
callq 0x28ec
movq 0x8(%r14), %r15
movq 0x18(%r14), %rax
movq (%rax), %rdi
testq %rdi, %rdi
je 0x2e14
movl $0x20, %esi
callq 0x2100
movq 0x18(%r14), %rdi
testq %rdi, %rdi
je 0x2e27
movl $0x18, %esi
callq 0x2100
movl $0x20, %esi
movq %r14, %rdi
callq 0x2100
jmp 0x2e3a
movq 0x8(%r14), %r15
movq %r15, %rdi
callq 0x35ec
movq %r15, %r14
jmp 0x2d38
jmp 0x2e5a
movq %rax, %rbx
movl $0x20, %esi
movq -0x30(%rbp), %rdi
jmp 0x2e72
movq %rax, %rbx
movl $0x20, %esi
movq %r12, %rdi
jmp 0x2e72
movq %rax, %rbx
movl $0x18, %esi
movq %r15, %rdi
callq 0x2100
movq %rbx, %rdi
callq 0x21a0
nop