home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
500-599
/
ff524.lzh
/
Kamin
/
src.lzh
/
apl.c
next >
Wrap
C/C++ Source or Header
|
1991-06-28
|
41KB
|
1,877 lines
/* Output from p2c, the Pascal-to-C translator */
/* From input file "apl.p" */
/*****************************************************************
* DECLARATIONS *
*****************************************************************/
#include <p2c/p2c.h>
#define NAMELENG 20 /* Maximum length of a name */
#define MAXNAMES 100 /* Maximum number of different names */
#define MAXINPUT 500 /* Maximum length of an input */
#define PROMPT "-> "
#define PROMPT2 "> "
#define COMMENTCHAR ";"
#define TABCODE 9 /* in ASCII */
typedef Char NAMESTRING[NAMELENG];
/* a NAME is an index in printNames */
typedef enum {
IFOP, WHILEOP, SETOP, BEGINOP, PLUSOP, MINUSOP, TIMESOP, DIVOP, MAXOP, OROP,
ANDOP, EQOP, LTOP, GTOP, REDPLUSOP, REDMINUSOP, REDTIMESOP, REDDIVOP,
REDMAXOP, REDOROP, REDANDOP, COMPRESSOP, SHAPEOP, RAVELOP, RESTRUCTOP,
CATOP, INDXOP, TRANSOP, SUBOP, PRINTOP
} BUILTINOP;
typedef enum {
SCALAR, VECTOR, MATRIX
} RANK;
typedef struct APLVALUEREC {
struct INTLISTREC *intvals;
RANK rnk;
union {
long leng;
struct {
long rows, cols;
} U2;
} UU;
} APLVALUEREC;
typedef struct INTLISTREC {
long int_;
struct INTLISTREC *nextint;
} INTLISTREC;
typedef enum {
VALEXP, VAREXP, APEXP
} EXPTYPE;
typedef struct EXPREC {
EXPTYPE etype;
union {
APLVALUEREC *aplval;
char varble;
struct {
char optr;
struct EXPLISTREC *args;
} U2;
} UU;
} EXPREC;
typedef struct EXPLISTREC {
EXPREC *head;
struct EXPLISTREC *tail;
} EXPLISTREC;
typedef struct VALUELISTREC {
APLVALUEREC *head;
struct VALUELISTREC *tail;
} VALUELISTREC;
typedef struct NAMELISTREC {
char head;
struct NAMELISTREC *tail;
} NAMELISTREC;
typedef struct ENVREC {
NAMELISTREC *vars;
VALUELISTREC *values;
} ENVREC;
typedef struct FUNDEFREC {
char funname;
NAMELISTREC *formals;
EXPREC *body;
struct FUNDEFREC *nextfundef;
} FUNDEFREC;
Static FUNDEFREC *fundefs;
Static ENVREC *globalEnv;
Static EXPREC *currentExp;
Static Char userinput[MAXINPUT];
Static short inputleng, pos_;
Static NAMESTRING printNames[MAXNAMES];
Static char numNames, numBuiltins;
Static boolean quittingtime;
/*****************************************************************
* DATA STRUCTURE OP'S *
*****************************************************************/
/* mkVALEXP - return an EXP of type VALEXP with aplval a */
Static EXPREC *mkVALEXP(a)
APLVALUEREC *a;
{
EXPREC *e;
e = (EXPREC *)Malloc(sizeof(EXPREC));
e->etype = VALEXP;
e->UU.aplval = a;
return e;
} /* mkVALEXP */
/* mkVAREXP - return an EXP of type VAREXP with varble nm */
Static EXPREC *mkVAREXP(nm)
char nm;
{
EXPREC *e;
e = (EXPREC *)Malloc(sizeof(EXPREC));
e->etype = VAREXP;
e->UU.varble = nm;
return e;
} /* mkVAREXP */
/* mkAPEXP - return EXP of type APEXP w/ optr op and args el */
Static EXPREC *mkAPEXP(op, el)
char op;
EXPLISTREC *el;
{
EXPREC *e;
e = (EXPREC *)Malloc(sizeof(EXPREC));
e->etype = APEXP;
e->UU.U2.optr = op;
e->UU.U2.args = el;
return e;
} /* mkAPEXP */
/* mkExplist - return an EXPLIST with head e and tail el */
Static EXPLISTREC *mkExplist(e, el)
EXPREC *e;
EXPLISTREC *el;
{
EXPLISTREC *newel;
newel = (EXPLISTREC *)Malloc(sizeof(EXPLISTREC));
newel->head = e;
newel->tail = el;
return newel;
} /* mkExplist */
/* mkNamelist - return a NAMELIST with head n and tail nl */
Static NAMELISTREC *mkNamelist(nm, nl)
char nm;
NAMELISTREC *nl;
{
NAMELISTREC *newnl;
newnl = (NAMELISTREC *)Malloc(sizeof(NAMELISTREC));
newnl->head = nm;
newnl->tail = nl;
return newnl;
} /* mkNamelist */
/* mkValuelist - return an VALUELIST with head a and tail vl */
Static VALUELISTREC *mkValuelist(a, vl)
APLVALUEREC *a;
VALUELISTREC *vl;
{
VALUELISTREC *newvl;
newvl = (VALUELISTREC *)Malloc(sizeof(VALUELISTREC));
newvl->head = a;
newvl->tail = vl;
return newvl;
} /* mkValuelist */
/* mkEnv - return an ENV with vars nl and values vl */
Static ENVREC *mkEnv(nl, vl)
NAMELISTREC *nl;
VALUELISTREC *vl;
{
ENVREC *rho;
rho = (ENVREC *)Malloc(sizeof(ENVREC));
rho->vars = nl;
rho->values = vl;
return rho;
} /* mkEnv */
/* lengthVL - return length of VALUELIST vl */
Static long lengthVL(vl)
VALUELISTREC *vl;
{
long i;
i = 0;
while (vl != NULL) {
i++;
vl = vl->tail;
}
return i;
} /* lengthVL */
/* lengthNL - return length of NAMELIST nl */
Static long lengthNL(nl)
NAMELISTREC *nl;
{
long i;
i = 0;
while (nl != NULL) {
i++;
nl = nl->tail;
}
return i;
} /* lengthNL */
/* lengthIL - return length of INTLIST il */
Static long lengthIL(il)
INTLISTREC *il;
{
long i;
i = 0;
while (il != NULL) {
i++;
il = il->nextint;
}
return i;
} /* lengthIL */
/*****************************************************************
* NAME MANAGEMENT *
*****************************************************************/
/* fetchFun - get function definition of fname from fundefs */
Static FUNDEFREC *fetchFun(fname)
char fname;
{
FUNDEFREC *f;
boolean found;
found = false;
f = fundefs;
while (f != NULL && !found) {
if (f->funname == fname)
found = true;
else
f = f->nextfundef;
}
return f;
} /* fetchFun */
/* newFunDef - add new function fname w/ parameters nl, body e */
Static Void newFunDef(fname, nl, e)
char fname;
NAMELISTREC *nl;
EXPREC *e;
{
FUNDEFREC *f;
f = fetchFun(fname);
if (f == NULL) { /* fname not yet defined as a function */
f = (FUNDEFREC *)Malloc(sizeof(FUNDEFREC));
f->nextfundef = fundefs; /* place new FUNDEFREC */
fundefs = f; /* on fundefs list */
}
f->funname = fname;
f->formals = nl;
f->body = e;
} /* newFunDef */
/* initNames - place all pre-defined names into printNames */
Static Void initNames()
{
long i;
fundefs = NULL;
i = 1;
memcpy(printNames[i - 1], "if ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "while ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "set ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "begin ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "+ ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "- ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "* ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "/ ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "max ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "or ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "and ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "= ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "< ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "> ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "+/ ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "-/ ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "*/ ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "// ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "max/ ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "or/ ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "and/ ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "compress ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "shape ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "ravel ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "restruct ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "cat ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "indx ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "trans ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "[] ", sizeof(NAMESTRING));
i++;
memcpy(printNames[i - 1], "print ", sizeof(NAMESTRING));
numNames = i;
numBuiltins = i;
} /* initNames */
Static jmp_buf _JL99;
/* install - insert new name into printNames */
Static char install(nm)
Char *nm;
{
long i;
boolean found;
i = 1;
found = false;
while (i <= numNames && !found) {
if (!memcmp(nm, printNames[i - 1], sizeof(NAMESTRING)))
found = true;
else
i++;
}
if (found)
return i;
if (i > MAXNAMES) {
printf("No more room for names\n");
longjmp(_JL99, 1);
}
numNames = i;
memcpy(printNames[i - 1], nm, sizeof(NAMESTRING));
return i;
} /* install */
/* prName - print name nm */
Static Void prName(nm)
char nm;
{
long i;
i = 1;
while (i <= NAMELENG) {
if (printNames[nm - 1][i - 1] != ' ') {
putchar(printNames[nm - 1][i - 1]);
i++;
} else
i = NAMELENG + 1;
}
} /* prName */
/* primOp - translate NAME optr to corresponding BUILTINOP */
Static BUILTINOP primOp(optr)
char optr;
{
BUILTINOP op;
long i;
op = IFOP; /* N.B. IFOP is first value in BUILTINOPS */
for (i = 1; i < optr; i++)
op = (BUILTINOP)((long)op + 1);
return op;
} /* primOp */
/*****************************************************************
* INPUT *
*****************************************************************/
/* isDelim - check if c is a delimiter */
Static boolean isDelim(c)
Char c;
{
return (c == ';' || c == ' ' || c == ')' || c == '(');
} /* isDelim */
/* skipblanks - return next non-blank position in userinput */
Static long skipblanks(p)
long p;
{
while (userinput[p - 1] == ' ')
p++;
return p;
} /* skipblanks */
/* matches - check if string nm matches userinput[s .. s+leng] */
Static boolean matches(s, leng, nm)
long s;
char leng;
Char *nm;
{
boolean match;
long i;
match = true;
i = 1;
while (match && i <= leng) {
if (userinput[s - 1] != nm[i - 1])
match = false;
i++;
s++;
}
if (!isDelim(userinput[s - 1]))
match = false;
return match;
} /* matches */
/* nextchar - read next char - filter tabs and comments */
Local Void nextchar(c)
Char *c;
{
Char STR1[256];
*c = getchar();
if (*c == '\n')
*c = ' ';
if (*c == (Char)TABCODE) {
*c = ' ';
return;
}
sprintf(STR1, "%c", *c);
if (strcmp(STR1, COMMENTCHAR))
return;
while (!P_eoln(stdin)) {
*c = getchar();
if (*c == '\n')
*c = ' ';
}
*c = ' ';
} /* nextchar */
/* readParens - read char's, ignoring newlines, to matching ')' */
Local Void readParens()
{
long parencnt; /* current depth of parentheses */
Char c;
parencnt = 1; /* '(' just read */
do {
if (P_eoln(stdin))
fputs(PROMPT2, stdout);
nextchar(&c);
pos_++;
if (pos_ == MAXINPUT) {
printf("User input too long\n");
longjmp(_JL99, 1);
}
userinput[pos_ - 1] = c;
if (c == '(')
parencnt++;
if (c == ')')
parencnt--;
} while (parencnt != 0); /* readParens */
}
Local Void readInput()
{
Char c;
fputs(PROMPT, stdout);
pos_ = 0;
do {
pos_++;
if (pos_ == MAXINPUT) {
printf("User input too long\n");
longjmp(_JL99, 1);
}
nextchar(&c);
userinput[pos_ - 1] = c;
if (userinput[pos_ - 1] == '(')
readParens();
} while (!P_eoln(stdin));
inputleng = pos_;
userinput[pos_] = ';'; /* sentinel */
} /* readInput */
/* reader - read char's into userinput; be sure input not blank */
Static Void reader()
{
/* readInput - read char's into userinput */
do {
readInput();
pos_ = skipblanks(1L); /* ignore blank lines */
} while (pos_ > inputleng); /* reader */
}
/* parseName - return (installed) NAME starting at userinput[pos]*/
Static char parseName()
{
NAMESTRING nm; /* array to accumulate characters */
char leng; /* length of name */
leng = 0;
while ((pos_ <= inputleng) & (!isDelim(userinput[pos_ - 1]))) {
if (leng == NAMELENG) {
printf("Name too long, begins: %.*s\n", NAMELENG, nm);
longjmp(_JL99, 1);
}
leng++;
nm[leng - 1] = userinput[pos_ - 1];
pos_++;
}
if (leng == 0) {
printf("Error: expected name, instead read: %c\n", userinput[pos_ - 1]);
longjmp(_JL99, 1);
}
for (; leng < NAMELENG; leng++)
nm[leng] = ' ';
pos_ = skipblanks((long)pos_); /* skip blanks after name */
return (install(nm));
} /* parseName */
Local boolean isDigits(pos)
long pos;
{
boolean Result;
if (!isdigit(userinput[pos - 1]))
return false;
Result = true;
while (isdigit(userinput[pos - 1]))
pos++;
if (!isDelim(userinput[pos - 1]))
return false;
return Result;
} /* isDigits */
/* isNumber - check if a number begins at pos */
Static boolean isNumber(pos)
long pos;
{
/* isDigits - check if sequence of digits begins at pos */
return (isDigits(pos) | ((userinput[pos - 1] == '-') & isDigits(pos + 1)));
} /* isNumber */
/* isValue - check if a number or vector const begins at pos */
Static boolean isValue(pos)
long pos;
{
return ((userinput[pos - 1] == '\'') | isNumber(pos));
} /* isValue */
/* parseInt - return number starting at userinput[pos] */
Local long parseInt()
{
long n, sign;
n = 0;
sign = 1;
if (userinput[pos_ - 1] == '-') {
sign = -1;
pos_++;
}
while (isdigit(userinput[pos_ - 1])) {
n = n * 10 + userinput[pos_ - 1] - '0';
pos_++;
}
pos_ = skipblanks((long)pos_); /* skip blanks after number */
return (n * sign);
} /* parseInt */
/* parseVec - return INTLIST starting at userinput[pos] */
Local INTLISTREC *parseVec()
{
INTLISTREC *il;
if (userinput[pos_ - 1] == ')') {
pos_ = skipblanks(pos_ + 1L); /* skip ') ...' */
il = NULL;
return il;
}
il = (INTLISTREC *)Malloc(sizeof(INTLISTREC));
il->int_ = parseInt();
il->nextint = parseVec();
return il;
} /* parseVec */
/* parseVal - return APL value starting at userinput[pos] */
Static APLVALUEREC *parseVal()
{
APLVALUEREC *result;
result = (APLVALUEREC *)Malloc(sizeof(APLVALUEREC));
if (userinput[pos_ - 1] == '\'') {
result->rnk = VECTOR;
pos_ = skipblanks(pos_ + 2L); /* skip "'(..." */
result->intvals = parseVec();
result->UU.leng = lengthIL(result->intvals);
return result;
}
result->rnk = SCALAR;
result->intvals = (INTLISTREC *)Malloc(sizeof(INTLISTREC));
result->intvals->int_ = parseInt();
result->intvals->nextint = NULL;
return result;
} /* parseVal */
Static EXPLISTREC *parseEL PV();
/* parseExp - return EXP starting at userinput[pos] */
Static EXPREC *parseExp()
{
char nm;
EXPLISTREC *el;
if (userinput[pos_ - 1] == '(') { /* APEXP */
pos_ = skipblanks(pos_ + 1L); /* skip '( ..' */
nm = parseName();
el = parseEL();
return (mkAPEXP(nm, el));
} else if (isValue((long)pos_))
return (mkVALEXP(parseVal())); /* VALEXP */
else
return (mkVAREXP(parseName())); /* VAREXP */
} /* parseExp */
/* parseEL - return EXPLIST starting at userinput[pos] */
Static EXPLISTREC *parseEL()
{
EXPREC *e;
EXPLISTREC *el;
if (userinput[pos_ - 1] == ')') {
pos_ = skipblanks(pos_ + 1L); /* skip ') ..' */
return NULL;
} else {
e = parseExp();
el = parseEL();
return (mkExplist(e, el));
}
} /* parseEL */
/* parseNL - return NAMELIST starting at userinput[pos] */
Static NAMELISTREC *parseNL()
{
char nm;
NAMELISTREC *nl;
if (userinput[pos_ - 1] == ')') {
pos_ = skipblanks(pos_ + 1L); /* skip ') ..' */
return NULL;
} else {
nm = parseName();
nl = parseNL();
return (mkNamelist(nm, nl));
}
} /* parseNL */
/* parseDef - parse function definition at userinput[pos] */
Static char parseDef()
{
char fname; /* function name */
NAMELISTREC *nl; /* formal parameters */
EXPREC *e; /* body */
pos_ = skipblanks(pos_ + 1L); /* skip '( ..' */
pos_ = skipblanks(pos_ + 6L); /* skip 'define ..' */
fname = parseName();
pos_ = skipblanks(pos_ + 1L); /* skip '( ..' */
nl = parseNL();
e = parseExp();
pos_ = skipblanks(pos_ + 1L); /* skip ') ..' */
newFunDef(fname, nl, e);
return fname;
} /* parseDef */
/*****************************************************************
* ENVIRONMENTS *
*****************************************************************/
/* emptyEnv - return an environment with no bindings */
Static ENVREC *emptyEnv()
{
return (mkEnv(NULL, NULL));
} /* emptyEnv */
/* bindVar - bind variable nm to value a in environment rho */
Static Void bindVar(nm, a, rho)
char nm;
APLVALUEREC *a;
ENVREC *rho;
{
rho->vars = mkNamelist(nm, rho->vars);
rho->values = mkValuelist(a, rho->values);
} /* bindVar */
/* findVar - look up nm in rho */
Static VALUELISTREC *findVar(nm, rho)
char nm;
ENVREC *rho;
{
NAMELISTREC *nl;
VALUELISTREC *vl;
boolean found;
found = false;
nl = rho->vars;
vl = rho->values;
while (nl != NULL && !found) {
if (nl->head == nm)
found = true;
else {
nl = nl->tail;
vl = vl->tail;
}
}
return vl;
} /* findVar */
/* assign - assign value a to variable nm in rho */
Static Void assign(nm, a, rho)
char nm;
APLVALUEREC *a;
ENVREC *rho;
{
VALUELISTREC *varloc;
varloc = findVar(nm, rho);
varloc->head = a;
} /* assign */
/* fetch - return number bound to nm in rho */
Static APLVALUEREC *fetch(nm, rho)
char nm;
ENVREC *rho;
{
VALUELISTREC *vl;
vl = findVar(nm, rho);
return (vl->head);
} /* fetch */
/* isBound - check if nm is bound in rho */
Static boolean isBound(nm, rho)
char nm;
ENVREC *rho;
{
return (findVar(nm, rho) != NULL);
} /* isBound */
Local Void prIntlist(il, dim1, dim2)
INTLISTREC *il;
long dim1, dim2;
{
long i, j;
for (i = 1; i <= dim1; i++) {
for (j = 1; j <= dim2; j++) {
printf("%6ld ", il->int_);
il = il->nextint;
}
putchar('\n');
}
} /* prIntlist */
/*****************************************************************
* APL VALUES *
*****************************************************************/
/* prValue - print APL value a */
Static Void prValue(a)
APLVALUEREC *a;
{
/* prIntlist - print INTLIST il as dim1 x dim2 matrix */
switch (a->rnk) {
case SCALAR:
prIntlist(a->intvals, 1L, 1L);
break;
case VECTOR:
prIntlist(a->intvals, 1L, a->UU.leng);
break;
case MATRIX:
prIntlist(a->intvals, a->UU.U2.rows, a->UU.U2.cols);
break;
}
} /* prValue */
/* isTrueVal - return true if first value in a is one */
Static boolean isTrueVal(a)
APLVALUEREC *a;
{
if (a->intvals == NULL)
return false;
else
return (a->intvals->int_ == 1);
} /* isTrueVal */
/* Local variables for applyValueOp: */
struct LOC_applyValueOp {
APLVALUEREC *result;
} ;
/* size - return number of elements in a */
Local long size(a, LINK)
APLVALUEREC *a;
struct LOC_applyValueOp *LINK;
{
long Result;
switch (a->rnk) {
case SCALAR:
Result = 1;
break;
case VECTOR:
Result = a->UU.leng;
break;
case MATRIX:
Result = a->UU.U2.rows * a->UU.U2.cols;
break;
}
return Result;
} /* size */
/* skipover - return pointer to nth record in il */
Local INTLISTREC *skipover(n, il, LINK)
long n;
INTLISTREC *il;
struct LOC_applyValueOp *LINK;
{
while (n > 0) {
il = il->nextint;
n--;
}
return il;
} /* skipover */
Local Void copyrank(a, r)
APLVALUEREC *a, *r;
{
r->rnk = a->rnk;
switch (r->rnk) { /* with */
case SCALAR:
/* blank case */
break;
case VECTOR:
r->UU.leng = a->UU.leng;
break;
case MATRIX:
r->UU.U2.rows = a->UU.U2.rows;
r->UU.U2.cols = a->UU.U2.cols;
break;
}/* case */
} /* copyrank */
/* applyOp - apply VALUEOP op to integer arguments */
Local long applyOp(op, i, j)
BUILTINOP op;
long i, j;
{
long Result;
switch (op) {
case PLUSOP:
Result = i + j;
break;
case MINUSOP:
Result = i - j;
break;
case TIMESOP:
Result = i * j;
break;
case DIVOP:
Result = i / j;
break;
case MAXOP:
if (i > j)
Result = i;
else
Result = j;
break;
case OROP:
if (i == 1 || j == 1)
Result = 1;
else
Result = 0;
break;
case ANDOP:
if (i == 1 && j == 1)
Result = 1;
else
Result = 0;
break;
case EQOP:
if (i == j)
Result = 1;
else
Result = 0;
break;
case LTOP:
if (i < j)
Result = 1;
else
Result = 0;
break;
case GTOP:
if (i > j)
Result = 1;
else
Result = 0;
break;
}/* case */
return Result;
} /* applyOp */
/* applyIntlis - apply op to two lists, extending appropriately */
Local INTLISTREC *applyIntlis(op, il1, il2, il1leng, il2leng)
BUILTINOP op;
INTLISTREC *il1, *il2;
long il1leng, il2leng;
{
INTLISTREC *il;
if (il1 == NULL || il2 == NULL)
return NULL;
else {
il = (INTLISTREC *)Malloc(sizeof(INTLISTREC));
il->int_ = applyOp(op, il1->int_, il2->int_);
if (il1leng == 1) {
il->nextint = applyIntlis(op, il1, il2->nextint, il1leng, il2leng);
return il;
}
if (il2leng == 1)
il->nextint = applyIntlis(op, il1->nextint, il2, il1leng, il2leng);
else
il->nextint = applyIntlis(op, il1->nextint, il2->nextint, il1leng,
il2leng);
return il; /* with */
}
} /* applyIntlis */
/* applyArithOp - apply binary operator to a1 and a2 */
Local Void applyArithOp(op, a1, a2, LINK)
BUILTINOP op;
APLVALUEREC *a1, *a2;
struct LOC_applyValueOp *LINK;
{
/* copyrank - copy rank and shape of a to r */
LINK->result = (APLVALUEREC *)Malloc(sizeof(APLVALUEREC));
if (a1->rnk == SCALAR)
copyrank(a2, LINK->result);
else if (a2->rnk == SCALAR)
copyrank(a1, LINK->result);
else if (size(a1, LINK) == 1)
copyrank(a2, LINK->result);
else
copyrank(a1, LINK->result);
LINK->result->intvals = applyIntlis(op, a1->intvals, a2->intvals,
size(a1, LINK), size(a2, LINK));
} /* applyArithOp */
/* Local variables for applyRedOp: */
struct LOC_applyRedOp {
struct LOC_applyValueOp *LINK;
BUILTINOP op;
} ;
Local long applyOp_(op, i, j, LINK)
BUILTINOP op;
long i, j;
struct LOC_applyRedOp *LINK;
{
long Result;
switch (op) {
case REDPLUSOP:
Result = i + j;
break;
case REDMINUSOP:
Result = i - j;
break;
case REDTIMESOP:
Result = i * j;
break;
case REDDIVOP:
Result = i / j;
break;
case REDMAXOP:
if (i > j)
Result = i;
else
Result = j;
break;
case REDOROP:
if (i == 1 || j == 1)
Result = 1;
else
Result = 0;
break;
case REDANDOP:
if (i == 1 && j == 1)
Result = 1;
else
Result = 0;
break;
}/* case */
return Result;
} /* applyOp */
/* redVec - reduce op (argument to applyRedOp) over list */
Local long redVec(il, leng, LINK)
INTLISTREC *il;
long leng;
struct LOC_applyRedOp *LINK;
{
if (leng == 0)
return 0;
else if (leng == 1)
return (il->int_);
else
return (applyOp_(LINK->op, il->int_, redVec(il->nextint, leng - 1, LINK),
LINK));
} /* redVec */
/* redMat - reduce op (argument to applyRedOp) over matrix */
Local INTLISTREC *redMat(il, cols, rows, LINK)
INTLISTREC *il;
long cols, rows;
struct LOC_applyRedOp *LINK;
{
INTLISTREC *ilnew;
if (rows == 0)
return NULL;
else {
ilnew = (INTLISTREC *)Malloc(sizeof(INTLISTREC));
ilnew->int_ = redVec(il, cols, LINK);
ilnew->nextint = redMat(skipover(cols, il, LINK->LINK), cols, rows - 1,
LINK);
return ilnew;
}
} /* redmat */
/* applyRedOp - apply reduction operator */
Local Void applyRedOp(op_, a, LINK)
BUILTINOP op_;
APLVALUEREC *a;
struct LOC_applyValueOp *LINK;
{
/* applyOp - apply base operator of reduction operator */
struct LOC_applyRedOp V;
APLVALUEREC *WITH;
V.LINK = LINK;
V.op = op_;
LINK->result = (APLVALUEREC *)Malloc(sizeof(APLVALUEREC));
switch (a->rnk) {
case SCALAR:
LINK->result = a;
break;
case VECTOR:
WITH = LINK->result;
WITH->rnk = SCALAR;
WITH->intvals = (INTLISTREC *)Malloc(sizeof(INTLISTREC));
WITH->intvals->int_ = redVec(a->intvals, a->UU.leng, &V);
WITH->intvals->nextint = NULL;
break;
case MATRIX:
WITH = LINK->result;
WITH->rnk = VECTOR;
WITH->UU.leng = a->UU.U2.rows;
WITH->intvals = redMat(a->intvals, a->UU.U2.cols, WITH->UU.leng, &V);
break;
}/* case */
} /* applyRedOp */
/* append - append il2 to il1; il1 is altered */
Local INTLISTREC *append(il1, il2, LINK)
INTLISTREC *il1, *il2;
struct LOC_applyValueOp *LINK;
{
INTLISTREC *Result;
if (il1 == NULL)
return il2;
Result = il1;
while (il1->nextint != NULL)
il1 = il1->nextint;
il1->nextint = il2;
return Result;
} /* append */
/* ncopy - copy elements of src until list has reps elements */
Local INTLISTREC *ncopy(src, reps, LINK)
INTLISTREC *src;
long reps;
struct LOC_applyValueOp *LINK;
{
INTLISTREC *Result, *il, *suffix;
long i;
if (reps == 0)
return NULL;
il = (INTLISTREC *)Malloc(sizeof(INTLISTREC));
Result = il;
il->int_ = src->int_;
suffix = src->nextint;
for (i = 2; i <= reps; i++) {
if (suffix == NULL) /* exhausted src */
suffix = src;
/* start over */
il->nextint = (INTLISTREC *)Malloc(sizeof(INTLISTREC));
il = il->nextint;
il->int_ = suffix->int_;
suffix = suffix->nextint;
}
il->nextint = NULL;
return Result;
} /* ncopy */
/* Local variables for compress: */
struct LOC_compress {
struct LOC_applyValueOp *LINK;
} ;
/* ilcompress - il1 over il2, taking il2 in chunks of size width */
Local INTLISTREC *ilcompress(il1, il2, width, LINK)
INTLISTREC *il1, *il2;
long width;
struct LOC_compress *LINK;
{
INTLISTREC *il;
if (il1 == NULL)
return NULL;
else if (il1->int_ == 1) {
il = ncopy(il2, width, LINK->LINK);
il = append(il, ilcompress(il1->nextint, skipover(width, il2, LINK->LINK),
width, LINK), LINK->LINK);
return il;
} else
return (ilcompress(il1->nextint, skipover(width, il2, LINK->LINK), width,
LINK));
} /* ilcompress */
/* countones - count ones in il */
Local long countones(il, LINK)
INTLISTREC *il;
struct LOC_compress *LINK;
{
long i;
i = 0;
while (il != NULL) {
if (il->int_ == 1)
i++;
il = il->nextint;
}
return i;
} /* countones */
/* compress - compress a1 over a2 */
Local Void compress(a1, a2, LINK)
APLVALUEREC *a1, *a2;
struct LOC_applyValueOp *LINK;
{
struct LOC_compress V;
long width;
APLVALUEREC *WITH;
V.LINK = LINK;
if (a2->rnk == VECTOR)
width = 1;
else
width = a2->UU.U2.cols;
LINK->result = (APLVALUEREC *)Malloc(sizeof(APLVALUEREC));
WITH = LINK->result;
WITH->rnk = a2->rnk;
WITH->intvals = ilcompress(a1->intvals, a2->intvals, width, &V);
if (WITH->rnk == VECTOR) /* with */
WITH->UU.leng = countones(a1->intvals, &V);
else {
WITH->UU.U2.cols = a2->UU.U2.cols;
WITH->UU.U2.rows = countones(a1->intvals, &V);
}
} /* compress */
/* shape - return vector giving dimensions of a */
Local Void shape(a, LINK)
APLVALUEREC *a;
struct LOC_applyValueOp *LINK;
{
INTLISTREC *il;
LINK->result = (APLVALUEREC *)Malloc(sizeof(APLVALUEREC));
LINK->result->rnk = VECTOR;
switch (a->rnk) {
case SCALAR:
LINK->result->UU.leng = 0;
LINK->result->intvals = NULL;
break;
case VECTOR:
LINK->result->UU.leng = 1;
il = (INTLISTREC *)Malloc(sizeof(INTLISTREC));
LINK->result->intvals = il;
il->int_ = a->UU.leng;
il->nextint = NULL;
break;
case MATRIX:
LINK->result->UU.leng = 2;
il = (INTLISTREC *)Malloc(sizeof(INTLISTREC));
LINK->result->intvals = il;
il->int_ = a->UU.U2.rows;
il->nextint = (INTLISTREC *)Malloc(sizeof(INTLISTREC));
il = il->nextint;
il->int_ = a->UU.U2.cols;
il->nextint = NULL;
break;
}/* case */
} /* shape */
/* ravel - transform a to a vector without changing elements */
Local Void ravel(a, LINK)
APLVALUEREC *a;
struct LOC_applyValueOp *LINK;
{
long size;
APLVALUEREC *WITH;
LINK->result = (APLVALUEREC *)Malloc(sizeof(APLVALUEREC));
switch (a->rnk) {
case SCALAR:
size = 1;
break;
case VECTOR:
size = a->UU.leng;
break;
case MATRIX:
size = a->UU.U2.rows * a->UU.U2.cols;
break;
}
WITH = LINK->result;
WITH->rnk = VECTOR;
WITH->UU.leng = size;
WITH->intvals = a->intvals;
} /* ravel */
/* restruct - restructure valuevec according to shapevec */
Local Void restruct(shapevec, valuevec, LINK)
APLVALUEREC *shapevec, *valuevec;
struct LOC_applyValueOp *LINK;
{
RANK newrank;
long dim1, dim2;
APLVALUEREC *WITH;
if (valuevec->intvals == NULL) {
printf("Cannot restructure null vector\n");
longjmp(_JL99, 1);
}
if (shapevec->rnk == SCALAR) {
newrank = VECTOR;
dim1 = shapevec->intvals->int_;
dim2 = 1;
} else if (shapevec->UU.leng == 0) {
newrank = SCALAR;
dim1 = 1;
dim2 = 1;
} else if (shapevec->UU.leng == 1) {
newrank = VECTOR;
dim1 = shapevec->intvals->int_;
dim2 = 1;
} else {
newrank = MATRIX;
dim1 = shapevec->intvals->int_;
dim2 = shapevec->intvals->nextint->int_;
}
LINK->result = (APLVALUEREC *)Malloc(sizeof(APLVALUEREC));
WITH = LINK->result;
WITH->rnk = newrank;
if (WITH->rnk == VECTOR)
WITH->UU.leng = dim1;
else if (WITH->rnk == MATRIX) {
WITH->UU.U2.rows = dim1;
WITH->UU.U2.cols = dim2;
}
WITH->intvals = ncopy(valuevec->intvals, dim1 * dim2, LINK); /* with */
/* with */
} /* restruct */
/* copyIntlis - make a fresh copy of il */
Local INTLISTREC *copyIntlis(il, LINK)
INTLISTREC *il;
struct LOC_applyValueOp *LINK;
{
return (ncopy(il, lengthIL(il), LINK));
} /* copyIntlis */
/* cat - create a vector by joining ravels of a1 and a2 */
Local Void cat(a1, a2, LINK)
APLVALUEREC *a1, *a2;
struct LOC_applyValueOp *LINK;
{
APLVALUEREC *WITH;
LINK->result = (APLVALUEREC *)Malloc(sizeof(APLVALUEREC));
WITH = LINK->result;
WITH->rnk = VECTOR;
WITH->UU.leng = size(a1, LINK) + size(a2, LINK);
WITH->intvals = copyIntlis(a1->intvals, LINK);
WITH->intvals = append(WITH->intvals, a2->intvals, LINK);
} /* cat */
/* indx - perform index generation, using first value in a */
Local Void indx(a, LINK)
APLVALUEREC *a;
struct LOC_applyValueOp *LINK;
{
long i;
INTLISTREC *il;
APLVALUEREC *WITH;
i = a->intvals->int_;
LINK->result = (APLVALUEREC *)Malloc(sizeof(APLVALUEREC));
WITH = LINK->result;
WITH->rnk = VECTOR;
WITH->intvals = NULL;
WITH->UU.leng = i;
while (i > 0) { /* with */
il = (INTLISTREC *)Malloc(sizeof(INTLISTREC));
il->int_ = i;
il->nextint = WITH->intvals;
WITH->intvals = il;
i--;
} /* while */
} /* indx */
/* Local variables for trans: */
struct LOC_trans {
struct LOC_applyValueOp *LINK;
} ;
/* skiplist - subscript il by cols and rows */
Local INTLISTREC *skiplist(il, cols, rows, LINK)
INTLISTREC *il;
long cols, rows;
struct LOC_trans *LINK;
{
INTLISTREC *ilnew;
ilnew = (INTLISTREC *)Malloc(sizeof(INTLISTREC));
if (rows == 1) {
ilnew->int_ = il->int_;
ilnew->nextint = NULL;
} else {
ilnew->int_ = il->int_;
ilnew->nextint = skiplist(skipover(cols, il, LINK->LINK), cols, rows - 1,
LINK);
}
return ilnew;
} /* skiplist */
/* trans - perform "trans" */
Local Void trans(a, LINK)
APLVALUEREC *a;
struct LOC_applyValueOp *LINK;
{
struct LOC_trans V;
INTLISTREC *il, *ilnew;
long i;
APLVALUEREC *WITH;
long FORLIM;
V.LINK = LINK;
if (a->rnk != MATRIX || a->intvals == NULL) {
LINK->result = a;
return;
}
LINK->result = (APLVALUEREC *)Malloc(sizeof(APLVALUEREC));
WITH = LINK->result;
WITH->rnk = MATRIX;
WITH->UU.U2.cols = a->UU.U2.rows;
WITH->UU.U2.rows = a->UU.U2.cols;
il = a->intvals;
ilnew = NULL;
FORLIM = WITH->UU.U2.rows;
for (i = 1; i <= FORLIM; i++) {
ilnew = append(ilnew,
skiplist(il, WITH->UU.U2.rows, WITH->UU.U2.cols, &V),
LINK);
il = il->nextint;
}
WITH->intvals = ilnew; /* with */
} /* trans */
/* Local variables for subscript: */
struct LOC_subscript {
struct LOC_applyValueOp *LINK;
} ;
/* sub - find nth chunk in il, each chunk having width elements */
Local INTLISTREC *sub(il, n, width, LINK)
INTLISTREC *il;
long n, width;
struct LOC_subscript *LINK;
{
long i, j;
for (i = 1; i < n; i++) {
for (j = 1; j <= width; j++)
il = il->nextint;
}
return il;
} /* sub */
/* ilsub - subscript src by subs in chunks of size width */
Local INTLISTREC *ilsub(src, subs, width, LINK)
INTLISTREC *src, *subs;
long width;
struct LOC_subscript *LINK;
{
INTLISTREC *il;
if (subs == NULL) {
il = NULL;
return il;
}
il = sub(src, subs->int_, width, LINK);
il = ncopy(il, width, LINK->LINK);
il = append(il, ilsub(src, subs->nextint, width, LINK), LINK->LINK);
return il;
} /* ilsub */
/* subscript - "[]" operation; a1 a vector or matrix, a2 vector */
Local Void subscript(a1, a2, LINK)
APLVALUEREC *a1, *a2;
struct LOC_applyValueOp *LINK;
{
struct LOC_subscript V;
long width;
APLVALUEREC *WITH;
V.LINK = LINK;
LINK->result = (APLVALUEREC *)Malloc(sizeof(APLVALUEREC));
WITH = LINK->result;
WITH->rnk = a1->rnk;
if (WITH->rnk == VECTOR) {
if (a2->rnk == SCALAR)
WITH->UU.leng = 1;
else
WITH->UU.leng = a2->UU.leng;
width = 1;
} else {
if (a2->rnk == SCALAR)
WITH->UU.U2.rows = 1;
else
WITH->UU.U2.rows = a2->UU.leng;
WITH->UU.U2.cols = a1->UU.U2.cols;
width = WITH->UU.U2.cols;
}
WITH->intvals = ilsub(a1->intvals, a2->intvals, width, &V); /* with */
} /* subscript */
/* arity - return number of arguments expected by op */
Local long arity(op, LINK)
BUILTINOP op;
struct LOC_applyValueOp *LINK;
{
if (((1L << ((long)op)) & (((1L << ((long)GTOP + 1)) - (1 << ((long)PLUSOP))) |
(1 << ((long)COMPRESSOP)) | (1 << ((long)RESTRUCTOP)) |
(1 << ((long)CATOP)) | (1 << ((long)SUBOP)))) != 0)
return 2;
else
return 1;
} /* arity */
/* applyValueOp - apply VALUEOP op to arguments in VALUELIST vl */
Static APLVALUEREC *applyValueOp(op, vl)
BUILTINOP op;
VALUELISTREC *vl;
{
struct LOC_applyValueOp V;
APLVALUEREC *a1, *a2;
if (arity(op, &V) != lengthVL(vl)) {
printf("Wrong number of arguments to ");
prName((int)op + 1);
putchar('\n');
longjmp(_JL99, 1);
}
a1 = vl->head; /* 1st actual */
if (arity(op, &V) == 2) /* 2nd actual */
a2 = vl->tail->head;
switch (op) {
case PLUSOP:
case MINUSOP:
case TIMESOP:
case DIVOP:
case MAXOP:
case OROP:
case ANDOP:
case EQOP:
case LTOP:
case GTOP:
applyArithOp(op, a1, a2, &V);
break;
case REDPLUSOP:
case REDMINUSOP:
case REDTIMESOP:
case REDDIVOP:
case REDMAXOP:
case REDOROP:
case REDANDOP:
applyRedOp(op, a1, &V);
break;
case COMPRESSOP:
compress(a1, a2, &V);
break;
case SHAPEOP:
shape(a1, &V);
break;
case RAVELOP:
ravel(a1, &V);
break;
case RESTRUCTOP:
restruct(a1, a2, &V);
break;
case CATOP:
cat(a1, a2, &V);
break;
case INDXOP:
indx(a1, &V);
break;
case TRANSOP:
trans(a1, &V);
break;
case SUBOP:
subscript(a1, a2, &V);
break;
case PRINTOP:
prValue(a1);
V.result = a1;
break;
}/* case */
return V.result;
} /* applyValueOp */
Static APLVALUEREC *eval PP((EXPREC *e, ENVREC *rho));
/* Local variables for eval: */
struct LOC_eval {
ENVREC *rho;
} ;
/* evalList - evaluate each expression in el */
Local VALUELISTREC *evalList(el, LINK)
EXPLISTREC *el;
struct LOC_eval *LINK;
{
APLVALUEREC *h;
VALUELISTREC *t;
if (el == NULL)
return NULL;
else {
h = eval(el->head, LINK->rho);
t = evalList(el->tail, LINK);
return (mkValuelist(h, t));
}
} /* evalList */
/* applyUserFun - look up definition of nm and apply to actuals */
Local APLVALUEREC *applyUserFun(nm, actuals, LINK)
char nm;
VALUELISTREC *actuals;
struct LOC_eval *LINK;
{
FUNDEFREC *f;
ENVREC *rho;
f = fetchFun(nm);
if (f == NULL) {
printf("Undefined function: ");
prName(nm);
putchar('\n');
longjmp(_JL99, 1);
}
if (lengthNL(f->formals) != lengthVL(actuals)) {
printf("Wrong number of arguments to: ");
prName(nm);
putchar('\n');
longjmp(_JL99, 1);
}
rho = mkEnv(f->formals, actuals);
return (eval(f->body, rho));
} /* applyUserFun */
/* applyCtrlOp - apply CONTROLOP op to args in rho */
Local APLVALUEREC *applyCtrlOp(op, args, LINK)
BUILTINOP op;
EXPLISTREC *args;
struct LOC_eval *LINK;
{
APLVALUEREC *Result, *a;
EXPLISTREC *WITH;
WITH = args;
switch (op) {
case IFOP:
if (isTrueVal(eval(WITH->head, LINK->rho)))
Result = eval(WITH->tail->head, LINK->rho);
else
Result = eval(WITH->tail->tail->head, LINK->rho);
break;
case WHILEOP:
a = eval(WITH->head, LINK->rho);
while (isTrueVal(a)) {
a = eval(WITH->tail->head, LINK->rho);
a = eval(WITH->head, LINK->rho);
}
Result = a;
break;
case SETOP:
a = eval(WITH->tail->head, LINK->rho);
if (isBound(WITH->head->UU.varble, LINK->rho))
assign(WITH->head->UU.varble, a, LINK->rho);
else if (isBound(WITH->head->UU.varble, globalEnv))
assign(WITH->head->UU.varble, a, globalEnv);
else
bindVar(WITH->head->UU.varble, a, globalEnv);
Result = a;
break;
case BEGINOP:
while (args->tail != NULL) {
a = eval(args->head, LINK->rho);
args = args->tail;
}
Result = eval(args->head, LINK->rho);
break;
}/* case and with */
return Result;
} /* applyCtrlOp */
/*****************************************************************
* EVALUATION *
*****************************************************************/
/* eval - return value of expression e in local environment rho */
Static APLVALUEREC *eval(e, rho_)
EXPREC *e;
ENVREC *rho_;
{
struct LOC_eval V;
APLVALUEREC *Result;
BUILTINOP op;
V.rho = rho_;
switch (e->etype) {
case VALEXP:
Result = e->UU.aplval;
break;
case VAREXP:
if (isBound(e->UU.varble, V.rho))
Result = fetch(e->UU.varble, V.rho);
else if (isBound(e->UU.varble, globalEnv))
Result = fetch(e->UU.varble, globalEnv);
else {
printf("Undefined variable: ");
prName(e->UU.varble);
putchar('\n');
longjmp(_JL99, 1);
}
break;
case APEXP:
if (e->UU.U2.optr > numBuiltins)
Result = applyUserFun(e->UU.U2.optr, evalList(e->UU.U2.args, &V), &V);
else {
op = primOp(e->UU.U2.optr);
if (((1L << ((long)op)) &
((1 << ((long)BEGINOP + 1)) - (1 << ((long)IFOP)))) != 0)
Result = applyCtrlOp(op, e->UU.U2.args, &V);
else
Result = applyValueOp(op, evalList(e->UU.U2.args, &V));
}
break;
}/* case and with */
return Result;
} /* eval */
/*****************************************************************
* READ-EVAL-PRINT LOOP *
*****************************************************************/
main(argc, argv)
int argc;
Char *argv[];
{ /* apl main */
PASCAL_MAIN(argc, argv);
if (setjmp(_JL99))
goto _L99;
initNames();
globalEnv = emptyEnv();
quittingtime = false;
_L99:
while (!quittingtime) {
reader();
if (matches((long)pos_, 4, "quit ")) {
quittingtime = true;
break;
}
if ((userinput[pos_ - 1] == '(') & matches(skipblanks(pos_ + 1L), 6,
"define ")) {
prName(parseDef());
putchar('\n');
} else {
currentExp = parseExp();
prValue(eval(currentExp, emptyEnv()));
printf("\n\n");
}
} /* while */
exit(0);
} /* apl */
/* End. */