الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

ماذا يعنى هذا الكود انا تايه فيه ؟

مغلق
بدأه hamada hassan ali في 28 سبتمبر 2005 · 4 رد · 552 مشاهدة · في هندسة البرمجيات
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

ياشباب مصر

ارجوكم حد يقولى ايه الخورازمية دى

اقتباس
/*  Unlambda interpreter / "Compiler".  */

/* Copyright 1999  Jacob L. Mandelson
 *  This software may be distributed and modified without charge
 *   for noncommercial recreational or educational purposes provided
 *   that this copyright and statement is included in all copies.
 */


#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>



/* Macros */
#define dupatom(A) (((A)->refcount++, (A)))
#define dupexpr(A) (((A)->refcount++, (A)))
#define freeatom(A) (--(A)->refcount ? 0 : Freeatom((A)))
#define freeexpr(A) (--(A)->refcount ? 0 : Freeexpr((A)))


#define NextContext() ((CurrentContext+1 ==   	 \
	CurrentContinuation.contextlist+CurrentContinuation.Ncontexts  \
     ? grow_context_list(&CurrentContinuation, &CurrentContext) \
 	 : 0),  CurrentContext+1)

/* Take care using these macros  */
#define PUSHCONTEXT   CurrentContext++; continue;
#define POPCONTEXT    if (CurrentContext == CurrentContinuation.contextlist) \
 	 { free(CurrentContext); return rv; }        \
        else { CurrentContext--; continue; }


#define MKA(x) ((struct atom*)(x))
#define MKE(x) ((struct expr*)(x))


#define STRING(x) #x
        /*  Make a #define  */
#define MKDF(x) "#define " #x " " STRING(x) "\n"

static char preamble [] =
  "#include <stdio.h>\n"
  "#include <stdlib.h>\n"
  "#include <termios.h>\n"
  "#define IN(x)\n"
  "#define output stdout\n"
  "#define input stdin\n"
  "#define atomI atom0002\n"
  "#define atomV atom0003\n"
  "#define zz ,\n"
  MKDF(dupatom(A))  MKDF(dupexpr(A))    MKDF(freeatom(A))
  MKDF(freeexpr(A)) MKDF(NextContext()) MKDF(PUSHCONTEXT)
  MKDF(POPCONTEXT)  MKDF(MKA(x))        MKDF(MKE(x));


#define IN(x) x  /* Stuff that's only in the interpreter, not in
    *  the compiler output.     */

#define zz ,  /*  Protect commas from the preprocessor  */

long Nmalloc, Nfree;
int debug;
int compile;
FILE *output, *input;
void error(char []);
struct atom;
void unparseA(struct atom* a);


static void *my_malloc(size_t size)
{  void *rv = malloc(size);
   Nmalloc++;
   if (!rv) error("Out of memory.");
   return rv;
}

static void *my_realloc(void *p, size_t size)
{  void *rv = realloc(p, size);
   if (!rv) error("Out of memory.");
   return rv;
}

#define malloc    my_malloc
#define realloc   my_realloc
#define free(x)   ((Nfree++, free(x)))


#define MKSC(x) #x; x 	 /* Make string and code */


char progbody[] = MKSC(
/*  Code common to the parser+interpreter and the 
 *   "compiled" (*cough*) interpreter. 
 */



/* Data structures.   */
/* Continuation is a list of contexts.  */

struct continuation {
IN(int tag;)
   long Ncontexts;
   struct context *contextlist;
};


/* Contexts contain the "stage" of execution, and arguments to execute.
 *  See comment below.          */
struct context { 
   enum Stage { Eval1 zz Eval2 zz Eval3 zz Apply1 zz S2a zz S2b zz D1a } stage;
   void *Arg1 zz *Arg2 zz *Int;
};


/*  The unlambda expression.
 *   Expression is either an atom, or `FG where F, G are unlambda expressions.
 */

struct atom {
IN(int tag;)
  long refcount;
  enum atomtype { K zz K1 zz S zz S1 zz S2 zz I zz V zz C zz C1 zz D zz D1 zz 
  Print zz Exit zz Read zz Query zz Reprint } type;
  /* Arguments:  K1, S1:  One atom.  D1: One expression.  S2: Two atoms. */
  /*             Print:  character.  C1:  continuation.   */
  union {
    char character;
    struct atom* oneatom;
    struct { struct atom *a1 zz *a2; } twoatom;
    struct expr* expression;
    struct continuation continuation;
  } d;
};

struct expr {
IN(int tag;)
  long refcount;
  enum  { ATOM zz APPLY } type;
  void *arg1;	/* struct atom* for ATOM, struct expr* for APPLY */
  struct expr *e2;   /* Not used if ATOM */
};


static int Freeexpr(struct expr *E);
void error(char []);
static void FreeContinuation(struct continuation , struct context *);


static int Freeatom(struct atom *A) 
{
   switch (A->type) {
     case S: case K: case I: case V: case C: case D: case Print:
     case Exit: case Read: case Query: case Reprint:
  /* Nothing.  A leaf.  */	break;
     case S1: case K1: 
	freeatom(A->d.oneatom); break;
     case S2:
	freeatom(A->d.twoatom.a1); freeatom(A->d.twoatom.a2); break;
     case D1:
	freeexpr(A->d.expression); break;
     case C1:
	FreeContinuation(A->d.continuation, 
  A->d.continuation.contextlist+A->d.continuation.Ncontexts-2);
	/* Last saved context is contextlist[Ncontexts-2] because current
  *  context wasn't saved when the continuation was saved.    */
	break;
     default:
	error("Unknown type to free!"); 
   }
   free(A);
   return 0;
}

static int Freeexpr(struct expr *E)
{
   if (E->type == ATOM) freeatom(MKA(E->arg1));
   else { freeexpr(MKE(E->arg1)); freeexpr(E->e2); }
   free(E);
   return 0;
}

void error(char msg[])
{
   fprintf(stderr, "Error: %s\n", msg);
   exit(-1);
}


/* Context element:
     [ Stage, Arg1, Arg2, RV, Int ]
   Arg{1,2} are arguments
   Int is intermediate value
   RV is return value from last step.  
	Not saved with continuatoin!  Just variable for passing value "up"
   the stack.
   Stage is Eval1: Arg1 is e
     Eval2: Arg1 is e, RV is eval(e.e1)
     Eval3: Arg1 is e, Int is eval(e.e1), RV is eval(e.e2)
     Eval4: Arg1 is e, RV is apply(eval(e.e1), eval(e.e2))
       Short-circuited to Apply1
     Apply1: Arg1 is a1, Arg2 is a2
     S2a: Arg1 is a1, Arg2 is a2, RV is apply(a1.a1, a2)
     S2b: Arg1 is a1, Arg2 is a2, 
 	 RV is apply(a1.a2, a2), Int is apply(a1.a1, a2)
     S2c: RV is apply( apply(a1.a1, a2), apply(a1.a2, a2) )
 	 Short-circuited to Apply1
     D1a: Arg2 is a2, RV is eval(a1.e)
     D1b: RV is apply( eval(a1.e), a2)
 	 Short-circuited to Apply1
*/


static int grow_context_list(struct continuation *CC, struct context **con)
{
    long cidx = *con - CC->contextlist;
    CC->Ncontexts += CC->Ncontexts/2 + 128;
    CC->contextlist = realloc(CC->contextlist, 
  CC->Ncontexts * sizeof(struct context) );
    *con = CC->contextlist + cidx;
    return 0;
}


IN(static int Ncontinuations;)
static int lastchar = EOF;

static struct continuation 
	SaveContinuation(struct continuation CC, struct context *cxt)
{
    struct continuation rv;

    IN(rv.tag = ++Ncontinuations;)
    rv.Ncontexts = cxt - CC.contextlist + 1;
    rv.contextlist = malloc(rv.Ncontexts * sizeof(*rv.contextlist));
    /* Save contexts up to (but not including) current context.
     *  Don't save current context because it is consumed by making the
     *   C call, and replaced by the argument when the continuation is resumed.
     */
    while (--cxt >= CC.contextlist) {
	rv.contextlist[cxt - CC.contextlist] = *cxt;
	switch (cxt->stage) {
    case Eval3:
  MKA(cxt->Int)->refcount++;
  /* FALLTHROUGH */
    case Eval2: 
  MKE(cxt->Arg1)->refcount++; 
  break;
    case S2b:
  MKA(cxt->Int)->refcount++;
  MKA(cxt->Arg1)->refcount++;
  break;
    case S2a:
  MKA(cxt->Arg1)->refcount++;
  /* FALLTHROUGH */
    case D1a:
  MKA(cxt->Arg2)->refcount++;
  break;
    case Eval1: case Apply1: default:
  error("Unknown stage to SaveContinuation!");
	}
    }

    return rv;
}

/* Free continuation, and contexts in continuation from 
 *   CC.contextlist[0] to ctx 	 */
static void FreeContinuation(struct continuation CC, struct context *ctx)
{  
   for (; ctx >= CC.contextlist; ctx--) {
      switch (ctx->stage) {
	case Eval3:
   freeatom(MKA(ctx->Int));
   /* FALLTHROUGH */
    case Eval2:
   freeexpr(MKE(ctx->Arg1));
   break;
	case S2b:
   freeatom(MKA(ctx->Int));
   freeatom(MKA(ctx->Arg1));
   break;
	case Apply1: case S2a:
   freeatom(MKA(ctx->Arg1));
   /* FALLTHROUGH */
	case D1a:
   freeatom(MKA(ctx->Arg2));
   break;
	case Eval1: default:
   error("Bad stage to FreeContinuation!");
      }
   }
   free(CC.contextlist);
}


/* Resuming a continuation must copy to the Current Continuation, not
 *  just make a ref., because changes to the CC in the course of execution
 *  should not affect copys of the continuation resumed.   */
void RestoreContinuation(struct continuation cont, struct continuation *CC,
    struct context **cxt)
{   long i;
    CC->Ncontexts = cont.Ncontexts;
    CC->contextlist = malloc(cont.Ncontexts * sizeof(*CC->contextlist));
    memcpy(CC->contextlist, cont.contextlist, 
 	 cont.Ncontexts * sizeof(*CC->contextlist));
    for (i = 0; i < cont.Ncontexts-1; i++) {
/* Ncontexts-1 because Current Context wasn't saved with the continuation. */
	switch (cont.contextlist.stage) {
    case Eval3:
  MKA(cont.contextlist.Int)->refcount++;
  /* FALLTHROUGH */
    case Eval2: 
  MKE(cont.contextlist.Arg1)->refcount++; 
  break;
    case S2b:
  MKA(cont.contextlist.Int)->refcount++;
  MKA(cont.contextlist.Arg1)->refcount++;
  break;
    case S2a:
  MKA(cont.contextlist.Arg1)->refcount++;
  /* FALLTHROUGH */
    case D1a:
  MKA(cont.contextlist.Arg2)->refcount++;
  break;
    case Eval1: case Apply1: default:
  error("Unknown stage to RestoreContinuation!");
	}
    }
    *cxt = &CC->contextlist[cont.Ncontexts-1];
}


/* Forward declerations */
extern struct atom atomV;
extern struct atom atomI;


/*  Evaluate an expression.  */
/*  Maintains an explicit call stack, because it needs to save the contexts
 *   of all the function calls when the continuation is saved.
 *  The NextContext()->Arg1 = rv stuff is just setting up the Arguments 
 *   for the next context in the computation, a la passing arguments to 
 *   functions in Assembly.
 *  For example, pasting the "function calls" together for S2 (the
 *   most complicated case), gives:
 *	rv = apply(dupatom(a1->d.twoatom.a1), dupatom(a2));
 *	rv = apply(rv, apply(dupatom(a1->d.twoatom.a2), a2));
 *	freeatom(a1); return rv;
 */

struct atom *eval(struct expr *e)	
{  struct atom *rv;
   struct continuation CurrentContinuation;
   struct context *CurrentContext;
   struct context *nc;	/* Next Context */
   
   IN(CurrentContinuation.tag = 0;)
   CurrentContinuation.Ncontexts = 1024;
   CurrentContext = CurrentContinuation.contextlist = 
	malloc(CurrentContinuation.Ncontexts * sizeof(struct context));

   CurrentContext->Arg1 = e;
   CurrentContext->stage = Eval1;

/* This state machine is the engine:  It interprets the unlambda expression. */
   for (;;) {
     switch (CurrentContext->stage) {
	case Eval1:
    e = CurrentContext->Arg1;
    if (e->type == ATOM) {
      rv = e->arg1;
      --e->refcount ? rv->refcount++ : free(e);
      POPCONTEXT
    } else /* APPLY */ {
      CurrentContext->stage = Eval2;
      (nc=NextContext())->stage = Eval1;
      nc->Arg1 = dupexpr(MKE(e->arg1));
      PUSHCONTEXT
    }
	case Eval2:  {
    struct atom *a1 = rv;
    e = CurrentContext->Arg1;
     
           if (a1->type == D) /* Delay */ {
        rv = malloc(sizeof *rv);
        rv->refcount = 1;
        rv->type = D1;
        rv->d.expression = e->e2;
        if (!--e->refcount) {
   freeexpr(MKE(e->arg1));
   free(e);
        } else {
   e->e2->refcount++;
        }
        if (!--a1->refcount) free(a1);
        POPCONTEXT
           } else {
        CurrentContext->stage = Eval3;
        CurrentContext->Int = a1;
        (nc=NextContext())->stage = Eval1;
        nc->Arg1 = dupexpr(e->e2);
        PUSHCONTEXT
    }
 	 }
	case Eval3:
    freeexpr(MKE(CurrentContext->Arg1));
    CurrentContext->stage = Apply1;
    CurrentContext->Arg2 = rv;
    CurrentContext->Arg1 = CurrentContext->Int;
    continue;
	case Apply1: {
    struct atom *a1 = CurrentContext->Arg1 zz
         *a2 = CurrentContext->Arg2;

	IN(if (debug) {
    printf("Applying: [%ld]", a1->refcount);
    unparseA(a1);
    printf(" to [%ld]", a2->refcount);
    unparseA(a2);
    putchar('\n');
	})

    switch (a1->type) {
      case K:	rv = malloc(sizeof *rv);
 	 rv->refcount = 1;
 	 rv->type = K1; rv->d.oneatom = a2; break;
      case K1:  rv = a1->d.oneatom; freeatom(a2);
 	 if (a1->refcount != 1) rv->refcount++;
 	 break;
      case S:  rv = malloc(sizeof *rv);
 	 rv->refcount = 1;
 	 rv->type = S1; rv->d.oneatom = a2; break;
      case S1:  rv = malloc(sizeof *rv);
 	 rv->refcount = 1;
 	 rv->type = S2; 
 	 rv->d.twoatom.a1 = a1->d.oneatom;
 	 rv->d.twoatom.a2 = a2;
 	 if (a1->refcount != 1) a1->d.oneatom->refcount++;
 	 break;
      case S2:   /* Can't check a1->refcount against 1, because one
    * of the apply's might save the continuation, making
    * a copy of a1.    */
 	 CurrentContext->stage = S2a;
 	 (nc=NextContext())->stage = Apply1;
 	 nc->Arg1 = dupatom(a1->d.twoatom.a1);
 	 nc->Arg2 = dupatom(a2);
 	 PUSHCONTEXT
      case D:	/* If 'd' is used as an argument to something that
    * applies its argument to something (eg, 'c'), 
    * then 'd' will be applied without "delay".
    * Fishy if you ask me, but the <``r`cd`.*`cd>
    * program relies on it. 	 */
 	 /* Treat like I */
      case I:	rv = a2; break;
      case V:	freeatom(a2); rv = a1; POPCONTEXT
      case C:  
 	 if (a2->type == V) {  /* <`cv> = v, no continuation. */
       rv = a2; break;
 	 }
 	 rv = malloc(sizeof *rv);
 	 rv->refcount = 1;
 	 rv->type = C1;
 	 rv->d.continuation = 
     SaveContinuation(CurrentContinuation, CurrentContext);
 	 freeatom(a1);
 	 CurrentContext->stage = Apply1;
 	 CurrentContext->Arg1 = a2;
 	 CurrentContext->Arg2 = rv;
 	 continue;
      case C1:   /* Current Continuation holds references to a1, a2, 
    *  so need to dup them before we free the CC.	*/
 	 rv = dupatom(a2);
 	 a1->refcount++;
 	 FreeContinuation(CurrentContinuation, CurrentContext);
 	 RestoreContinuation(a1->d.continuation,
     &CurrentContinuation, &CurrentContext);
 	 /* Now we can free a1. */   
 	 freeatom(a1);
 	 POPCONTEXT
      case D1:	CurrentContext->stage = D1a;
 	 (nc=NextContext())->stage = Eval1;
 	 nc->Arg1 = a1->d.expression;
 	 --a1->refcount ?
     a1->d.expression->refcount++ : free(a1);
 	 PUSHCONTEXT
      case Print: putc(a1->d.character, output); rv = a2; break;
      case Exit: exit(0);	/* Exit program */
      case Read: lastchar = getc(input);
 	 freeatom(a1);
 	 /* CurrentContext->stage = Apply1; */
 	 CurrentContext->Arg1 = a2;
 	 if (lastchar == EOF) CurrentContext->Arg2 = &atomV;
 	 else CurrentContext->Arg2 = &atomI;
 	 MKA(CurrentContext->Arg2)->refcount++;
 	 continue;
      case Query: 
 	 /* CurrentContext->stage = Apply1; */
 	 CurrentContext->Arg1 = a2;
 	 if (lastchar == a1->d.character) 
       CurrentContext->Arg2 = &atomI;
 	 else CurrentContext->Arg2 = &atomV;
 	 freeatom(a1); 
 	 MKA(CurrentContext->Arg2)->refcount++;
 	 continue;
      case Reprint:
 	 freeatom(a1);
 	 /* CurrentContext->stage = Apply1; */
 	 CurrentContext->Arg1 = a2;
 	 if (lastchar == EOF) {
       CurrentContext->Arg2 = &atomV;
       MKA(CurrentContext->Arg2)->refcount++;
 	 } else {
       CurrentContext->Arg2 = rv = malloc(sizeof *rv);
       rv->refcount = 1;
       rv->type = Print;
       rv->d.character = lastchar;
 	 }
 	 continue;
      default:  error("Unexpected type to apply!");
    }
    if (!--a1->refcount) free(a1);
    POPCONTEXT
	}

	case S2a:
    CurrentContext->Int = rv;
    CurrentContext->stage = S2b;
    (nc=NextContext())->stage = Apply1;
    nc->Arg1 = 
  dupatom(MKA(CurrentContext->Arg1)->d.twoatom.a2);
    nc->Arg2 = CurrentContext->Arg2;
    PUSHCONTEXT
	case S2b:
    freeatom(MKA(CurrentContext->Arg1));
    CurrentContext->stage = Apply1;
    CurrentContext->Arg1 = CurrentContext->Int;
    CurrentContext->Arg2 = rv;
    continue;
	case D1a:
    CurrentContext->stage = Apply1;
    CurrentContext->Arg1 = rv;
    /* CurrentContext->Arg2 = CurrentContext->Arg2; */
    continue;
	default:
    error("Unknown stage in evaluate!");
     }
   }
}


void unbuffer_io()
{  struct termios tio;
   IN(if (!debug || output != stdout)) setbuf(output, NULL);
   tcgetattr(fileno(input), &tio);
   tio.c_lflag &= ~ICANON;
   tio.c_cc[VMIN] = 1;
   tio.c_cc[VTIME] = 0;
   tcsetattr(fileno(input), TCSANOW, &tio);
}
)


struct atom atomK = { 0, 1, K, {0}};
struct atom atomS = { 1, 1, S, {0}};
struct atom atomI = { 2, 1, I, {0}};
struct atom atomV = { 3, 1, V, {0}};
struct atom atomC = { 4, 1, C, {0}};
struct atom atomD = { 5, 1, D, {0}};
struct atom atomR = { 6, 1, Print, {'\n'}};
struct atom atomE = { 7, 1, Exit, {0}};
struct atom atomAT = { 8, 1, Read, {0}};
struct atom atomPIPE = { 9, 1, Reprint, {0}};
struct expr exprK = { 0, 1, ATOM, &atomK };
struct expr exprS = { 1, 1, ATOM, &atomS };
struct expr exprI = { 2, 1, ATOM, &atomI };
struct expr exprV = { 3, 1, ATOM, &atomV };
struct expr exprC = { 4, 1, ATOM, &atomC };
struct expr exprD = { 5, 1, ATOM, &atomD };
struct expr exprR = { 6, 1, ATOM, &atomR };
struct expr exprE = { 7, 1, ATOM, &atomE };
struct expr exprAT = { 8, 1, ATOM, &atomAT };
struct expr exprPIPE = { 9, 1, ATOM, &atomPIPE };

struct atom *predefatomlist[] = { &atomK, &atomS, &atomI, &atomV, &atomC, 
    &atomD, &atomR, &atomE, &atomAT, &atomPIPE};
struct expr *predefexprlist[] = { &exprK, &exprS, &exprI, &exprV, &exprC, 
    &exprD, &exprR, &exprE, &exprAT, &exprPIPE};

struct atom **atomlist;
struct expr **exprlist;
int atomlistsz, exprlistsz;

#define N_PREDEF_ATOMS 10
static int Natoms = N_PREDEF_ATOMS;
static int Nexpr = N_PREDEF_ATOMS;

static void grow_exprlist()
{
   exprlist = realloc(exprlist, 
 	 (exprlistsz += exprlistsz / 2) * sizeof(*exprlist));
}

static void grow_atomlist()
{
   atomlist = realloc(atomlist, (atomlistsz += 100) * sizeof(*atomlist));
}

struct expr *parse(FILE *file)
{
   int ch;
   struct expr *rv;

   for (;;) {
	ch = getc(file);
        if (ch == EOF) error("Unexpected EOF.");
	if (isspace(ch)) continue;
 	 if (ch == '#') {
    for (;;) {
      ch = getc(file);
      if (ch == EOF) error("Unexpected EOF.");
      if (ch == '\n') break;
    }
    continue;
  }
	break;
   }

   switch (tolower(ch)) {
     case '`': { 
   struct expr E;
   int i;
   E.arg1 = parse(file);
   E.e2 = parse(file);
   if (compile)
    for (i=N_PREDEF_ATOMS; i < Nexpr; i++) {
      if (exprlist->type == APPLY &&
 	 exprlist->arg1 == E.arg1 &&
 	 exprlist->e2 == E.e2)
      return exprlist;
    }
         rv = malloc(sizeof *rv);
          rv->refcount = 0;
          rv->type = APPLY;
          MKE(rv->arg1 = E.arg1)->refcount++;
          (rv->e2 = E.e2)->refcount++;
          if (compile) exprlist[rv->tag=Nexpr] = rv; 
   Nexpr++;
   if (compile && Nexpr == exprlistsz) grow_exprlist();
          return rv;
        }
     case 'k': return &exprK;
     case 's': return &exprS;
     case 'i': return &exprI;
     case 'v': return &exprV;
     case 'c': return &exprC;
     case 'd': return &exprD;
     case 'r': return &exprR;
     case 'e': return &exprE;
     case '@': return &exprAT;
     case '|': return &exprPIPE;
     case '.': case '?': { 
   int i; 
   enum atomtype type = (ch == '?') ? Query : Print;
   ch = getc(file);
          if (ch == EOF) error("Unexpected EOF");
   if (compile)
    for (i = N_PREDEF_ATOMS; i < Nexpr; i++) {
      if (exprlist->type == ATOM &&
 	 MKA(exprlist->arg1)->type == type &&
 	 MKA(exprlist->arg1)->d.character == ch)
      return exprlist;
    }
          rv = malloc(sizeof *rv);
          if (compile) exprlist[rv->tag=Nexpr] = rv;
   Nexpr++;
   if (compile && Nexpr == exprlistsz) grow_exprlist();
          rv->refcount = 0;
          rv->type = ATOM;
          rv->arg1 = malloc(sizeof (struct atom));
          if (compile) atomlist[MKA(rv->arg1)->tag=Natoms] = rv->arg1;
   Natoms++;
   if (compile && Natoms == atomlistsz) grow_atomlist();
          MKA(rv->arg1)->refcount = 1;
          MKA(rv->arg1)->type = type;
          MKA(rv->arg1)->d.character = ch;
          return rv;
        }
     default: error("Unexpected character");
       return 0;
   }
}

void print_parse_tree()
{
   int i;
   char *atype[] = { "K", "K1", "S", "S1", "S2", "I", "V", "C", "C1", 
       "D", "D1", "Print", "Exit", "Read", "Query", "Reprint"};

   for (i=0; i < Natoms; i++)
     fprintf(output, "struct atom atom%04d = { %ld, %s, '\\x%X' };\n",
  i, atomlist->refcount+1, atype[atomlist->type], 
 	 atomlist->d.character);
   for (i=0; i < Nexpr; i++)
     if (exprlist->type == ATOM)
	fprintf(output, "struct expr expr%04d = { %ld, ATOM, &atom%04d };\n",
  i, exprlist->refcount+1, 
 	 MKA(exprlist->arg1)->tag);
     else
      fprintf(output, 
	"struct expr expr%04d = { %ld, APPLY, &expr%04d, &expr%04d };\n",
  i, exprlist->refcount+1, MKE(exprlist->arg1)->tag,
         exprlist->e2->tag);
}

void print_epilog(struct expr *toplevel)
{
   fprintf(output, "int main() { if (isatty(fileno(input))) unbuffer_io();\n"
    "eval(&expr%04d); return 0; }\n", 
      toplevel->tag);
}

void unparseE(struct expr* e);

void unparseA(struct atom* a)
{
   switch (a->type) {
     case K: putchar('k'); return;
     case K1: putchar('`'); putchar('k'); unparseA(a->d.oneatom); return;
     case S: putchar('s'); return;
     case S1: putchar('`'); putchar('s'); unparseA(a->d.oneatom); return;
     case S2: putchar('`'); putchar('`'); putchar('s');
       unparseA(a->d.twoatom.a1); unparseA(a->d.twoatom.a2); return;
     case I: putchar('i'); return;
     case V: putchar('v'); return;
     case C: putchar('c'); return;
     case C1: printf("<cont%d>", a->d.continuation.tag); return;
     case D: putchar('d'); return;
     case D1: putchar('`'); putchar('d'); unparseE(a->d.expression); return;
     case Print: a->d.character == '\n' ? putchar('r') : 
      (putchar('.'), putchar(a->d.character));
   return;
     case Exit: putchar('e'); return;
     case Read: putchar('@'); return;
     case Query: putchar('?'); putchar(a->d.character); return;
     case Reprint: putchar('|'); return;
     default: error("Unexpected type to unparse!");
  }
}

void unparseE(struct expr* e)
{
   if (e->type == APPLY) {
     putchar('`');
     unparseE(e->arg1);
     unparseE(e->e2);
   } else unparseA(e->arg1);
}




static void bad_usage()
{
   error("Incorrect command-line usage.\n\"unlambda -h\" for help.");
}

static void print_usage_message()
{
   char *usemsg =
	"Usage: unlambda [-c] [-i infile] [-o outfile] [-d] [-h] unlfile\n"
	"  Options:  -c    Compile (save parse tree)\n"
	"            -i    Use <infile> for input (default: std input)\n"
	"            -o    Use <outfile> for output (default: std output)\n"
	"            -d    Print debug information\n"
	"            -h    Print usage message and exit\n\n"
	"  Argument: unlfile   unlambda program (\"-\" specifies std input)\n";

   fputs(usemsg, stdout);
}

int main(int argc, char *argv[])
{  FILE *file;
   struct expr *toplevel;
   struct atom *ret;
   int c;
   char *infile = NULL, *outfile = NULL;
   
   while ((c = getopt(argc, argv, "co:i:dh")) != EOF)
     switch (c) {
	case 'c':
   compile = 1;
   break;
	case 'o':
   outfile = optarg;
   break;
	case 'i':
   infile = optarg;
   break;
	case 'd':
   debug = 1;
   break;
	case 'h':
   print_usage_message();
   exit(0);
	default:
   bad_usage();
     }

   if (compile && (debug || infile)) 
	error("-c option cannot be used with -i or -d.");
   if (optind != argc-1) bad_usage();
   if (strcmp(argv[optind], "-"))
       file = fopen(argv[optind], "r");
   else
       file = stdin;
   if (!file) error("Error opening unlambda program.");
   if (outfile) {
       if (!(output = fopen(outfile, "w")))
   error("Error opening output file.");
   } else output = stdout;
   if (infile) {
       if (!(input = fopen(infile, "r")))
   error("Error opening input file.");
   } else input = stdin;

   if (compile) {	/* Set up atomlist & exprlist */
      atomlist = malloc((atomlistsz = 100) * sizeof(*atomlist));
      exprlist = malloc((exprlistsz = 1024) * sizeof(*exprlist));
      memcpy(atomlist, predefatomlist, N_PREDEF_ATOMS * sizeof(*atomlist));
      memcpy(exprlist, predefexprlist, N_PREDEF_ATOMS * sizeof(*exprlist));
   }
   toplevel = parse(file);
   toplevel->refcount++;
   fclose(file);
   if (compile) {
      time_t now = time(NULL);
      fprintf(output, 
  "/* Autogenerated by unlambda from file \"%s\" on\n\t%s*/\n",
  argv[optind], asctime(localtime(&now)));
      fputs(preamble, output);
      fputs(progbody, output);
      print_parse_tree();
      print_epilog(toplevel);
   } else {
      if (isatty(fileno(input))) unbuffer_io();
      ret = eval(toplevel);
      freeatom(ret);
      if (debug) { 
	printf("# mallocs: %ld.  # frees: %ld.\n", Nmalloc, Nfree);
        printf("# atoms: %d.   # expr: %d.\n", Natoms, Nexpr);
      }
   }
   return 0;
}

_____________________________

C Language && Windwos_API

_____________________________

#2

مصرف او مترجم لاحدى اللغات و هي Unlambda. انت يا hamada hassan ali ما تعرفش حد غير مصري ؟؟ :D ..... ولا مصر هنا بمعنى انك تصر ؟

39_22.gif

تزود من التقوى فإنك لا تدري *** إذا جن ليل هل تعيش إلى الفجر

فكم من فتى أمسى وأصبح ضاحكاً *** وقد نسجت أكفانه وهو لا يدري

لقراءة القرآن الكريم و سماعه و تفسيره ........

ماذا يعني انني مسلم سني؟

قصة غريبة

ConflictResolution.gif

#3

كيف يكون هذا مترجم لاحدى اللغات كيف عرفت

_____________________________

C Language && Windwos_API

_____________________________

#5

السلام عليكم

هو انا مش فاهم بالضبط الكود بيعمل ايه بس تقريبا هو بيطلع كود Unlambada لان الكود اصلا مكتوب C

عموما اللنك دا فيه نبذة عن Unlambada

http://www.madore.org/~david/programs/unlambda/

هذا الموضوع مغلق.

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…