//#include "Unix.h"
#include "stdafx.h"   //MS Windows
#include "Strawberry.h"

void assert(DWORD iii, DWORD where)
{
  DWORD i, j, k, t, p, q, m, n, m1, m2, k2, k3, ff_pointer2, Func, OBSEG, clause_flag=1;

    t=Program[iii];
    ProgTail[iii]=M1;
        if (t>=TT_START && Chfil_c[t-=TT_START]==1)
        {
          if (Ufil_c1[t]==Definition[DF_DptMi] || Ufil_c1[t]==Definition[DF_DptMiMi])// clause
          {
            if (Ufil_c1[t]==Definition[DF_DptMiMi]) // look at yourself
              ProgTail[iii]=iii;
            if ((i=Ufil_c2[t])>=TT_START && Chfil_c[i-=TT_START]==2 && (k=Ufil_c1[i])>=TT_START
               && Chfil_c[k-=TT_START]==1 && (k2=Ufil_c2[k])>=TT_START && Chfil_c[k2-=TT_START]==2)
            {
              if (Ufil_c1[k]==Definition[DF_BUILT_IN])
              {
                if (Ufil_c2[k2]!=TT_LIST) // Temp
                {
                  MitiText("Error: ", &cf_red);
                  MitiText("Bad definition of built_in predicate");
e4:               error++;
                  if (iii<program_br1)
                    sprintf(string2, " in the ADD file before clause %d.\r\n", iii);
                  else
                    sprintf(string2, " before clause %d.\r\n", iii-program_br2);
                  MitiText(string2);
                  return;  
                }
                Func=2;
                if ((k2=Ufil_c1[k2])>=TT_START && Chfil_c[k2-TT_START]==1) // long
                {
                  if (ff_pointer>FUNC_F && correct_F_field())
                  {
                    MitiText("Small memory for functions.");
                    goto e4;
                  }
                  k3=Ufil_c1[k2-TT_START];
                  if (!(Pointers[k3]&OBSEG1))
                  {
                    put_in_f(ff_pointer+2, k3, 2, OBSEG1);
                    ff_pointer++;   // Max Arguments
                    k3=M1;
                    if (ProgTail[iii]==iii)
                      F_field[ff_pointer++]=iii;
                    else
                      F_field[ff_pointer++]=HALF | iii;
#if TR
                    F_field[ff_pointer-1]|=TP_TEMP_FLAG;
#endif
                  }
e8:               ff_pointer2=ff_pointer;
                  if ((k=Ufil_c2[i])>=TT_START && Ufil_c1[k-TT_START]==TT_VAR && Prog_Obj[iii]!=M1
                                           && Ufil_c2[k-TT_START]==TT_LIST)
                  {
                    Atoms[iii]=0;
                    Program[iii]=HALF | NewObj[Prog_Obj[iii]]; // number, HALF is flag
                    clause_flag=3;
                  }
                  else
                  {
                    if (k3==M1)
                      F_field[ff_pointer-1]&=HALFM;
                    Program[iii]=i+TT_START;
                    clause_flag=2;
                  }
                  while ((k2=Ufil_c2[k2-TT_START])!=TT_LIST)
                  {
                    if (k2<TT_START || Chfil_c[k2-TT_START]==1)
                      k=k2;
                    else
                      k=Ufil_c1[k2-TT_START];
                    if (k==TT_VAR)
                      F_field[ff_pointer++]=TP_CALK;
                    else
                    {
                      F_field[ff_pointer]=0;
                      while (k>=TT_START && Chfil_c[k-=TT_START]==1)
                      {
                        i=Ufil_c1[k];
                        if (i==Definition[DF_VAR])
                          F_field[ff_pointer]|=TP_VAR;
                        else if (i==Definition[DF_TERM])
                          F_field[ff_pointer]|=TP_TERM;
                        else if (i==Definition[DF_STR])
                          F_field[ff_pointer]|=TP_STR;
                        else if (i==Definition[DF_INT])
                          F_field[ff_pointer]|=TP_INT;
                        else if (i==Definition[DF_FLOAT])
                          F_field[ff_pointer]|=TP_FLOAT;
                        else if (i==Definition[DF_OBJ])
                          F_field[ff_pointer]|=TP_OBJ;
                        else if (i==Definition[DF_LIST])
                          F_field[ff_pointer]|=TP_LIST;
                        else if (i==Definition[DF_NUM])
                          F_field[ff_pointer]|=TP_INT | TP_FLOAT;
                        else if (i==Definition[DF_NOCALK])
                        {
                          F_field[ff_pointer]=0;
                          goto e10;
                        }
                        else if (i==Definition[DF_IO])
                        {
                          if (F_field[ff_pointer])
                            F_field[ff_pointer]|=TP_IO | TP_VAR;
                          else
                            F_field[ff_pointer]=TP_IO | TP_CALK;
                          goto e10;
                        }
                        else if (i==Definition[DF_METHOD])
                        {
                          if (F_field[ff_pointer])
                            goto e4; // error
                          F_field[ff_pointer]=9*TP_SET;  // 8+1
e10:                      if ((k=Ufil_c2[k])<TT_START || Chfil_c[k-=TT_START]!=2 || Ufil_c2[k]!=TT_LIST)
                            goto e4; // error
                          k=Ufil_c1[k];
                          break;
                        }
                        else
                          goto e4; // error
                        if ((k=Ufil_c2[k])<TT_START || Chfil_c[k-=TT_START]!=2 || Ufil_c2[k]!=TT_LIST)
                          goto e4; // error
                        k=Ufil_c1[k];
                      }
                      if (k!=TT_VAR)
                        goto e4; // error
                      ff_pointer++;
                    }
                    if (k2<TT_START || Chfil_c[k2-TT_START]==1)
                    {
                      F_field[ff_pointer-1]|=TP_TAPA;
                      if (k3==M1)
                      {
                        F_field[ff_pointer2-2]=ff_pointer-ff_pointer2;
                        return;
                      }
                      else
                        goto e7;
                    }
                  }
                  F_field[ff_pointer++]=TP_TAPA|TP_REAL_TAPA;   // Tapa
                  if (k3==M1)
                    F_field[ff_pointer2-2]=ff_pointer-ff_pointer2-1;
                  else
                  {
e7:                 k=D_field[(Pointers[k3]&MASKA3)+Func];
                    if (F_field[k-2]!=ff_pointer-ff_pointer2-1)
                    {
e5:                   MitiText("Error: ", &cf_red);
                      MitiText("Cannot define with diferent arguments");
                      goto e4;
                    }
                    for (i=0; i<ff_pointer-ff_pointer2; i++)
                      if((F_field[ff_pointer2+i]&(M1^MASKA_TP))!=(F_field[k+i]&(M1^MASKA_TP)))
                        goto e5;
                    ff_pointer=ff_pointer2;
                    F_field[k-1]&=HALFM;
                    for(k=F_field[k-1]& (M1^(HALF | TP_TEMP_FLAG | OBSEG1 | OBSEG2));
                           ProgTail[k]!=M1; k=ProgTail[k])
                      if (ProgTail[k]==k)
                      {
                        MitiText("Error: ", &cf_red);
                        MitiText("Unreachable clause (after :--)");
                        goto e4;
                      }
                    ProgTail[k]=iii;
                    if (k<iii-1)
                    {   // redefine
                        warn_br++;
                      len=0;
                      write_p(k3, 4, 0);
                      if (iii<program_br1)
                        MitiText("Warning 8: ", &cf_green);
                      else if (k<program_br2)
                        MitiText("Warning 6: ", &cf_green);
                      else
                        MitiText("Warning 7: ", &cf_green);
                      if (Func==2)
                        MitiText("The built-in predicate ");
                      else
                        MitiText("The function ");
                      MitiText(string2, &cf_black);
                      MitiText("(...)", &cf_black);
                      if (iii<program_br1)
                        sprintf(string2, " has an interrupted definition in clause %d in the ADD file.\r\n", iii);
                      else if (k<program_br2)
                        sprintf(string2, " is defined in the ADD file.\r\n", iii-program_br2);
                      else
                        sprintf(string2, " has an interrupted definition in clause %d.\r\n", iii-program_br2);
                      MitiText(string2);
                    }
                  }
                  if (clause_flag==3)
                    return;
                  goto e3;
                }
                else // short
                {
                  OBSEG=OBSEG2;
e9:               Func++;
                  if (Pointers[k2]&OBSEG)
                  {
                    k=D_field[(Pointers[k2]&MASKA3)+Func]&=HALFM;
                    for( ; ProgTail[k]!=M1; k=ProgTail[k])
                      if (ProgTail[k]==k)
                      {
                        MitiText("Error: ", &cf_red);
                        MitiText("Unreachable clause (after :--)");
                        goto e4;
                      }
                    ProgTail[k]=iii;
                    if (k<iii-1)
                    {   // redefine
                        warn_br++;
                      len=0;
                      write_p(k2, 4, 0);
                      if (iii<program_br1)
                        MitiText("Warning 8: ", &cf_green);
                      else if (k<program_br2)
                        MitiText("Warning 6: ", &cf_green);
                      else
                        MitiText("Warning 7: ", &cf_green);
                      if (Func==3)  
                        MitiText("The built-in atom ");
                      else
                        MitiText("The constant ");
                      MitiText(string2, &cf_black);
                      if (iii<program_br1)
                        sprintf(string2, " has an interrupted definition in clause %d in the ADD file.\r\n", iii);
                      else if (k<program_br2)
                        sprintf(string2, " is defined in the ADD file.\r\n", iii-program_br2);
                      else
                        sprintf(string2, " has an interrupted definition in clause %d.\r\n", iii-program_br2);
                      MitiText(string2);
                    }
                  }
                  else if (ProgTail[iii]==iii)
                    put_in_f(iii, k2, Func, OBSEG);
                  else
                    put_in_f(HALF | iii, k2, Func, OBSEG);
                  if ((k=Ufil_c2[i])>=TT_START && Ufil_c1[k-TT_START]==TT_VAR && Prog_Obj[iii]!=M1
                                           && Ufil_c2[k-TT_START]==TT_LIST)
                  {
                    Atoms[iii]=0;
                    Program[iii]=HALF | NewObj[Prog_Obj[iii]]; // number, HALF is flag
                    return;
                  }
                  else
                  {
                    D_field[(Pointers[k2]&MASKA3)+Func]&=HALFM;
                    Program[iii]=i+TT_START;
                    clause_flag=2;
                    goto e3;
                  }
                }
              }
              else if (Ufil_c1[k]==Definition[DF_IS])
              {
                if ((k2=Ufil_c2[k3=k2])<TT_START || Ufil_c2[k2-=TT_START]!=TT_LIST) // Temp
                {
                  MitiText("Error: ", &cf_red);
                  MitiText("Bad definition of function");
                  goto e4;
                }
                // k3 return
                Func=4;
                if ((k2=Ufil_c1[k2])>=TT_START && Chfil_c[k2-TT_START]==1) // f(X,Y, ...)
                {
                  if (ff_pointer>FUNC_F && correct_F_field())
                    goto e4;
                  k3=Ufil_c1[k2-TT_START];
                  if (!(Pointers[k3]&OBSEG3))
                  {
                    put_in_f(ff_pointer+2, k3, 4, OBSEG3);
                    ff_pointer++;   // Max Arguments
                    k3=M1;
                    if (ProgTail[iii]==iii)
                      F_field[ff_pointer++]=iii;
                    else
                      F_field[ff_pointer++]=HALF | iii;
#if TR
                    F_field[ff_pointer-1]|=TP_TEMP_FLAG | OBSEG2;
#endif
                  }
                  goto e8;
                }
                else // constant
                {
                  OBSEG=OBSEG4;
                  goto e9;
                }
              }
              //else if (Ufil_c1[k]==Definition[DF_MES_FUNC])
              //  return;
            }
            Program[iii]=Ufil_c2[t];
            goto e3;
          }
          else if (Ufil_c1[t]==Definition[DF_VpMi]) // goal
            goto e3;
        }
    Atoms[iii]=1;  // aksiom
    i=Prog_fild[p_fild_br]=Program[iii];
    Program[iii]=t=p_fild_br;
    if ((p_fild_br+=2)>PROGRAM_F && correct_PROG_F() )
      MitiText("Small p_fild_br\r\n");
    k=clause_flag=0;
    goto S8;

e3:              // klause
    Atoms[iii]=0;
    i=Program[iii];
    Program[iii]=t=p_fild_br;
    if (i<TT_START)
    {
S6:   error++;
      if (iii<program_br1)
        sprintf(string2, "You have a mistake in the ADD file on clause %d.\r\n", iii);
      else
        sprintf(string2, "You have a mistake at clause %d.\r\n", iii-program_br2);
      MitiText(string2);
      return;
    }
    for (; i!=TT_LIST; i=Ufil_c2[i-TT_START])
    {
      if (i<TT_START || (Chfil_c[i-TT_START]!=2 && Atoms[iii]))
        goto S6;
      Atoms[iii]++;
      Prog_fild[p_fild_br]=i;
      if ((p_fild_br+=2)>PROGRAM_F && correct_PROG_F() )
        MitiText("Small p_fild_br\r\n");
    }
    for (k=0; k<Atoms[iii]; k++)          /* k atoms */
    {
      i=Ufil_c1[Prog_fild[t+2*k]-TT_START];
S8:   if (i>=MEMORY_c256)
        j=Chfil_v[i-MEMORY_c256];
      else if (i==TT_VAR)
        j=1;
      else
        j=0;
      Prog_fild[t+2*k+1]=p_fild_br;
      for (p=0; p<j; p++)                /* j variables */
      {
        for (m=p, m1=M1, n=k; n>0; )
        {
          q=Prog_fild[t+2*(--n)];
          if (Ufil_vs[q-MEMORY_c256]!=M1)
          {
            m=Substi[Ufil_vs[q-MEMORY_c256]+m];
            if (Ufil_c1[q-TT_START]==TT_VAR)
            {
              if (m<1)
                goto S7;
            }
            else if (m<Chfil_v[Ufil_c1[q-TT_START]-MEMORY_c256])
            {
S7:           m1=n;
              m2=m;
            }
          }
          else if (Ufil_c1[q-TT_START]>=MEMORY_c256)
            m+=Chfil_v[Ufil_c1[q-TT_START]-MEMORY_c256];
          else if (Ufil_c1[q-TT_START]==TT_VAR)
            m++;
        }
        if (m1!=M1)
        {
          Prog_fild[p_fild_br]=p;
          Prog_fild[p_fild_br+1]=(m1?(HALF|(Atoms[iii]-m1)):HALF);
          Prog_fild[p_fild_br+2]=m2;
          if ((p_fild_br+=3)>PROGRAM_F && correct_PROG_F() )
            MitiText("Small p_fild_br\r\n");
        }
        else if (Prog_Obj[iii]!=M1)
        {
          for(i=Prog_Obj[iii]; NewObj1[i] && NewObj2[i]<m; i++);
          if(NewObj1[i] && NewObj2[i]==m)
          {
            Prog_fild[p_fild_br]=p;
            Prog_fild[p_fild_br+1]=NewObj1[i]+TT_ADD;
            Prog_fild[p_fild_br+2]=NewObj[i];
            if ((p_fild_br+=3)>PROGRAM_F && correct_PROG_F() )
              MitiText("Small p_fild_br\r\n");
          }  
        }
      }
      if (Prog_fild[t+2*k+1]!=p_fild_br)
      {
        Prog_fild[t+2*k+1]|=HALF;
        Prog_fild[p_fild_br++]=M1;
      }
      else
        Prog_fild[t+2*k+1]=j;
    }
    if (clause_flag)  
    {
      Prog_fild[t]=Ufil_c1[Prog_fild[t]-TT_START];
      if (clause_flag==2)  
        Prog_fild[Program[iii]+1]|=QUARTER;
    }
    for (n=Atoms[iii]/2; n; n--)
    {
      m1=Ufil_c1[Prog_fild[t+2*n]-TT_START];
      m2=Prog_fild[t+2*n+1];
      Prog_fild[t+2*n]=Ufil_c1[Prog_fild[t+2*(Atoms[iii]-n)]-TT_START];
      Prog_fild[t+2*n+1]=Prog_fild[t+2*(Atoms[iii]-n)+1];
      Prog_fild[t+2*(Atoms[iii]-n)]=m1;
      Prog_fild[t+2*(Atoms[iii]-n)+1]=m2;
    }
    Atoms[iii]--;
}
