Talk:ABCDXYZ

From Esolang
Jump to navigation Jump to search

Link to implementation?

--YamTokTpaFa (talk) 03:35, 1 September 2019 (UTC)

I may as well just copy and paste it here. The following program is public domain by ais523, originally written in 2006.

/* ABCDXYZ to BackFlip compiler. By Alex Smith. */
/* The ABCDXYZ language was inspired when working on BackFlip; it is
 * designed to be compilable into BackFlip and therefore has the same
 * restrictions (no I/O, reversible, limited memory). These restrictions
 * are enforced by banning recursion; a version in which recursion is legal
 * would be more general. The operations used are those used by the first
 * (hopefully) practical BackFlip data-storage function discovered.
 * 
 * An ABCDXYZ program consists of a set of objects, each of which has
 * a value (which can only be A, B, C, or D) and a function. Objects can
 * affect each other using three commands (X, Y, and Z). All objects start
 * initialized to A.
 *
 * If an object's value is | X does       | Y does       | Z does
 *                       A | Value := B   | Value := B   | Value := A
 *                       B | Value := C,  | Value := C   | Value := D
 *                         | run function |              |
 *                       C | Value := D   | Value := D,  | Value := B
 *                         |              | run function |
 *                       D | Value := A   | Value := A   | Value := C
 *
 * The syntax of a program is
 *
 * <object>:
 * <command><object> <command><object> <command><object>, etc.
 *
 * <object> is a number, <command> is X, Y, or Z. Newline and space are
 * interchangeable as separators, and any number of them can be used.
 *
 * This version also accepts ", followed by a character, as a command.
 * Using this will quote the character into the BackFlip output; the
 * program will exit if it continues straight, or continue with the next
 * command if it rebounds. This can be used to access BackFlip extensions.
 * 
 * Object 0's function is run when the program starts; there is no way to
 * modify object 0's value (it cannot be used as the operand of a command).
 * Objects must be given in numerical order, and consecutive numbers must
 * be used. This implementation does not enforce this, but will give
 * incorrect answers if it isn't true, or possibly dump core.
 *
 * This implementation insists that the input file is seekable (so, don't
 * use /dev/stdin or /dev/tty, but most files should be fine).
 *
 * This implementation limits object numbers to half the range of an int,
 * without checking, and doesn't do error checking on the input program.
 * (It is likely to dump core or produce incorrect results if the input
 * program is incorrect).
 *
 * This implementation assumes that char is smaller than int, which is true
 * on most systems.
 *
 * The compiled output appears on stdout.
 */

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#if UCHAR_MAX > INT_MAX
#error int must be strictly larger than char for this program to work.
#endif

int numobjects = 0;

int objrefhi(int ref, int obj)
{
  if(ref<-numobjects) return 0;
  if(ref>numobjects) ref-=numobjects;
  if(ref<0) ref*=-1;
  return ref<obj;
}

int main(int argc, char** argv)
{
  int totalcmdcount = 0;
  FILE* in;
  int c,i,j,k,l;
  if(argc != 2)
  {
    fprintf(stderr,"Usage: abcdxyz [input file]\n");
    fprintf(stderr,"Output goes to stdout, which should be redirected if\n");
    fprintf(stderr,"you want to save the output.\n");
    return (argc!=1)*EXIT_FAILURE;
  }
  in = fopen(argv[1],"r");
  if(!in)
  {
    perror(argv[1]);
    return EXIT_FAILURE;
  }
  while((c=getc(in))!=EOF) numobjects+=c==':';
  rewind(in);
  {
    int*  objectcmdcount=malloc(sizeof(int)*numobjects);
    int** objectcmds=malloc(sizeof(int*)*numobjects);
    int*  wasblank=malloc(sizeof(int)*numobjects);
    i=numobjects;
    while(i--) objectcmdcount[i]=0;
    /* i is -1 */
    while((c=getc(in))!=EOF)
    {
      if(c==':') i++;
      if(c=='X'||c=='Y'||c=='Z'||c=='"'/*||c=='\''*/)
      {
        objectcmdcount[i]++;
        totalcmdcount++;
        wasblank[i]=0;
      }
    }
    i=numobjects;
    while(i--)
    {
      if(!objectcmdcount[i])
      {
        objectcmdcount[i]++;
        wasblank[i]=1;
        totalcmdcount++;
      }
      objectcmds[i]=malloc(sizeof(int)*objectcmdcount[i]);
      if(!objectcmds[i])
      {
        while(++i<numobjects) free(objectcmds[i]);
        fprintf(stderr,"Out of memory.");
        fclose(in);
        return EXIT_FAILURE;
      }
    }
    rewind(in);
    /* i is again -1 */
    while((c=getc(in))!=EOF)
    {
      if(c==':') {i++; j=0;}
      if(c=='X'||c=='Y'||c=='Z')
        fscanf(in,"%d",&objectcmds[i][j]);
      if(/*c=='\''||*/c=='"')
        objectcmds[i][j]=-getc(in);
      if(c=='X') objectcmds[i][j++]*=-1;
      if(c=='Y') objectcmds[i][j++]+=numobjects;
      if(c=='Z') j++;
      if(c=='"') objectcmds[i][j++]-=numobjects;
      /*if(c=='\'') objectcmds[i][j++]-=numobjects+1+(int)UCHAR_MAX;*/
    }
    fclose(in);
    /* Now the program has been read in; time to do the translation.
     * This is pretty mechanical. */
    i=totalcmdcount+5; /* Maximum line width */
    i-=printf("V-- BackFlip source for the ABCDXYZ program %s --",argv[1]);
    while(i-->0) putchar('-'); /* First line must be the longest */
    printf("\n\n     ");
    j=totalcmdcount;
    while(j--) putchar('V');
    printf("\n>    ");
    k=0;
    i=-1;
    while(++i < numobjects)
    {
      if(i)
      { /* Data storage block */
        printf("   VV");
        /* Write < for every X command pointing to this object */
        j=-1;
        while(++j < numobjects)
        {
          l=-1;
          while(++l < objectcmdcount[j])
          putchar(objectcmds[j][l]==-i?'<':' ');
        }
        putchar('\n');
        printf(" V / ");
        /* Write < for every Z command pointing to this object */
        j=-1;
        while(++j < numobjects)
        {
          l=-1;
          while(++l < objectcmdcount[j])
          putchar(objectcmds[j][l]==i?'<':' ');
        }
        putchar('\n');
        printf("  V  ");
        /* Write < for every Y command pointing to this object */
        j=-1;
        while(++j < numobjects)
        {
          l=-1;
          while(++l < objectcmdcount[j])
          putchar(objectcmds[j][l]==i+numobjects?'<':' ');
        }
        putchar('\n');
        printf("   V \n");
        printf("  >/<\n");
        printf("  ^\\^\n");
        printf("  > V\n");
        printf(" >/< \n");
        printf(" ^\\^ \n");
        printf(" VV <\n");
        printf(">/<  \n");
        printf(">\\^  \n");
        printf(" >   ");
      }
      /* The function */
      j=k;
      while(j--) putchar(' ');
      if(!wasblank[i])
      {
        j=-1;
        while(++j<objectcmdcount[i]-1)
        putchar(objrefhi(objectcmds[i][j],i)?'/':'\\');
        putchar(objrefhi(objectcmds[i][objectcmdcount[i]-1],i)?'^':'V');
      }
      else putchar('<');
      putchar('\n');
      k+=objectcmdcount[i];
    }
    printf("     ");
    k=totalcmdcount;
    j=-1;
    while(++j < numobjects)
    {
      l=-1;
      while(++l < objectcmdcount[j])
        putchar(objectcmds[j][l]<-numobjects&&
                objectcmds[j][l]>-numobjects-(int)UCHAR_MAX?
                -objectcmds[j][l]-numobjects:'^');
    }
    putchar('\n');
    i=numobjects;
    while(i--) free(objectcmds[i]);
    free(objectcmds);
    free(objectcmdcount);
    free(wasblank);
  }
  return 0;
}

It appears to be a compiler into BackFlip. I'm not sure how portable it is, but I found it alongside a DOS .exe file with the same name so it probably originally targeted DJGPP. --ais523 21:26, 10 April 2020 (UTC)