(* ----------------------------------------------------------------------------
 * $Id: MASLISP.mi,v 1.4 1995/11/05 08:55:36 kredel Exp $
 * ----------------------------------------------------------------------------
 * This file is part of MAS.
 * ----------------------------------------------------------------------------
 * Copyright (c) 1989 - 1992 Universitaet Passau
 * ----------------------------------------------------------------------------
 * $Log: MASLISP.mi,v $
 * Revision 1.4  1995/11/05 08:55:36  kredel
 * Support for small exit and corrections in terms of sorts.
 *
 * Revision 1.3  1992/10/15  16:27:47  kredel
 * Changed rcsid variable
 *
 * Revision 1.2  1992/02/12  17:32:22  pesch
 * Moved CONST definition to the right place
 *
 * Revision 1.1  1992/01/22  15:11:17  kredel
 * Initial revision
 *
 * ----------------------------------------------------------------------------
 *)

IMPLEMENTATION MODULE MASLISP;

(* MAS Lisp Implementation Module. *)



(* Import lists and declarations. *)

FROM MASSTOR IMPORT BETA, SIL, LIST, LENGTH, LISTVAR,
                    LIST1, ADV, FIRST, RED, COMP, INV, SFIRST, SRED;

FROM MASERR IMPORT ERROR, severe, harmless, spotless;

FROM MASBIOS IMPORT GWRITE, LISTS, BLINES, SWRITE, CWRITE;

FROM MASBIOSU IMPORT CLTIS;

FROM SACLIST IMPORT EQUAL, RED2, CINV, CONC, CCONC,
                    FIRST3, LIST3, LIST4, FIRST4, SECOND, THIRD, RED3,
                    FIRST2, ADV2, LIST2, COMP2, COMP3;

FROM MASSYM2 IMPORT SYMBOL, ASSOC, ASSOCQ, GET, PUT, SUBLIS; 

FROM MASSYM IMPORT ATOM, ELEMP, UREAD, UWRITE, UWRIT1, 
                   NOSHOW, UNIFY, GENARRAY, ARRAYDEC;

FROM MASLISPU IMPORT EXTYP, ARITY, SUBR, EXPR, PROCP,
                     Declare, CallCompiled, Signature,
                     Compiledp0, Compiledf2;

VAR  unwind: BOOLEAN;
     goto: LIST;

VAR  PVAL, PDESC, PTYP: LIST; (*patterns *)
CONST rcsidi = "$Id: MASLISP.mi,v 1.4 1995/11/05 08:55:36 kredel Exp $";
CONST copyrighti = "Copyright (c) 1989 - 1992 Universitaet Passau";



(* Procedure declarations. *)

PROCEDURE InitNames;
(*Initialize reserved names. *)
BEGIN
(*1*) (*indicators. *)
      Declare(ARROW,"ARROW");
(*2*) (*variables. *)
      Declare(ATM,"ATOM");        
      Declare(ANY,"ANY");         
      Declare(NULL,"NIL"); 
      Declare(WT,"T"); 
      Declare(PVAL,"VAL"); 
      Declare(PDESC,"DESC"); 
      Declare(PTYP,"TYPE"); 
      Declare(TDEF,"TYPEDEF"); 
      Declare(DEFAULT,"DEFAULT"); 
      Declare(LAMBDA,"LAMBDA");
      Declare(FLAMBDA,"FLAMBDA");
      Declare(MLAMBDA,"MLAMBDA");
      Declare(GLAMBDA,"GLAMBDA");
      Declare(RTN,"RETURN");
      Declare(FERx,"ForEachX");
      Declare(FELx,"ForEachY");
(*4*) (*internal fexpr functions. *)
      Declare(SCHLUSS,"EXIT");    PUT(SCHLUSS,EXTYP,FEXPR);
      Declare(schluss,"exit");    PUT(schluss,EXTYP,FEXPR);
      Declare(QUOTE,"QUOTE");     PUT(QUOTE,EXTYP,FEXPR);
      Declare(SETQ,"SETQ");       PUT(SETQ,EXTYP,FEXPR);
      Declare(SETAV,"SETAV");     PUT(SETAV,EXTYP,FEXPR);
      Declare(ASSIGN,"ASSIGN");   PUT(ASSIGN,EXTYP,FEXPR);
      Declare(COND,"COND");       PUT(COND,EXTYP,FEXPR);
      Declare(PROGN,"PROGN");     PUT(PROGN,EXTYP,FEXPR);
      Declare(PROGA,"PROGA");     PUT(PROGA,EXTYP,FEXPR);
      Declare(LBEL,"LABEL");      PUT(LBEL,EXTYP,FEXPR);
      Declare(LISTX,"LIST");      PUT(LISTX,EXTYP,FEXPR);
      Declare(DE,"DE");           PUT(DE,EXTYP,FEXPR);
      Declare(DF,"DF");           PUT(DF,EXTYP,FEXPR);
      Declare(DM,"DM");           PUT(DM,EXTYP,FEXPR);
      Declare(DG,"DG");           PUT(DG,EXTYP,FEXPR);
      Declare(IFS,"IF");          PUT(IFS,EXTYP,FEXPR);
      Declare(WHL,"WHILE");       PUT(WHL,EXTYP,FEXPR);
      Declare(RPT,"REPEAT");      PUT(RPT,EXTYP,FEXPR);
      Declare(STRNG,"STRING");    PUT(STRNG,EXTYP,FEXPR);
      Declare(VARS,"VAR");        PUT(VARS,EXTYP,FEXPR);
      Declare(TINFO,"TYPEINFO");  PUT(TINFO,EXTYP,FEXPR);
      Declare(ARY,"ARRAY");       PUT(ARY,EXTYP,FEXPR);
      Declare(SPEC,"SPEC");       PUT(SPEC,EXTYP,FEXPR);
      Declare(SORT,"SORT");       PUT(SORT,EXTYP,FEXPR);
      Declare(SIG,"SIG");         PUT(SIG,EXTYP,FEXPR);
      Declare(IMPRT,"IMPORT");    PUT(IMPRT,EXTYP,FEXPR);
      Declare(EXPOS,"EXPOSE");    PUT(EXPOS,EXTYP,FEXPR);
      Declare(UNIT,"UNIT");       PUT(UNIT,EXTYP,FEXPR);
      Declare(IMPL,"IMPLEMENTATION"); PUT(IMPL,EXTYP,FEXPR);
      Declare(MODEL,"MODEL");     PUT(MODEL,EXTYP,FEXPR);
      Declare(MAP,"MAP");         PUT(MAP,EXTYP,FEXPR);
      Declare(AXIOM,"AXIOMS");    PUT(AXIOM,EXTYP,FEXPR);
      Declare(RULE,"RULE");       PUT(RULE,EXTYP,FEXPR);
      Declare(WHEN,"WHEN");       PUT(WHEN,EXTYP,FEXPR);
      Declare(REP,"REP");         PUT(REP,EXTYP,FEXPR);
(*5*) (*internal expr functions. *)
      Declare(EQS,"EQ");          PUT(EQS,EXTYP,EXPR);
      Declare(NEQS,"NE");         PUT(NEQS,EXTYP,EXPR);
      Declare(GTS,"GT");          PUT(GTS,EXTYP,EXPR);
      Declare(LTS,"LT");          PUT(LTS,EXTYP,EXPR);
      Declare(LEQ,"LEQ");         PUT(LEQ,EXTYP,EXPR);
      Declare(GEQ,"GEQ");         PUT(GEQ,EXTYP,EXPR);
      Declare(UND,"AND");         PUT(UND,EXTYP,EXPR);
      Declare(ODER,"OR");         PUT(ODER,EXTYP,EXPR);
      Declare(NOTS,"NOT");        PUT(NOTS,EXTYP,EXPR);
      Declare(ADD,"ADD");         PUT(ADD,EXTYP,EXPR);
      Declare(SUB,"SUB");         PUT(SUB,EXTYP,EXPR);
      Declare(MUL,"MUL");         PUT(MUL,EXTYP,EXPR);
      Declare(QUOT,"QUOT");       PUT(QUOT,EXTYP,EXPR);
      Declare(REM,"REM");         PUT(REM,EXTYP,EXPR);
      Declare(RTN,"RETURN");      PUT(RTN,EXTYP,EXPR);
      Declare(GTO,"GOTO");        PUT(GTO,EXTYP,EXPR);
      Declare(FER,"ForEachinRep"); PUT(FER,EXTYP,EXPR);
      Declare(FEL,"ForEachinList"); PUT(FEL,EXTYP,EXPR);
      Declare(CONVVAL,"CONVVAL"); PUT(CONVVAL,EXTYP,EXPR);
      Declare(CONVDES,"CONVDES"); PUT(CONVDES,EXTYP,EXPR);
(*5*) (*internal gexpr functions. *)
      Declare(READ,"READ");         
      Declare(WRITE,"WRITE");       
      Declare(DECREAD,"DECREAD");   
      Declare(DECWRITE,"DECWRITE"); 
(*9*) END InitNames;


PROCEDURE InitLISP;
(*Initialize compiled procedures. *)
BEGIN
(*1*) InitNames;
(*2*) InitENV; 
(*3*) (*internal compiled procedures *)
      Compiledp0(InitENV,"NEW");
(*4*) (*external Compiled procedures *)
      Declare(POW,"POW");
(*9*) END InitLISP;


PROCEDURE InitENV;
(*Initialize environement. *)
BEGIN
(*1*) (*alist *) ENV:=SIL; LISTVAR(ENV); 
(*2*) (*special values *)
      ENV:=COMP2(NULL,SIL,ENV); 
(*3*) (*global variables *)
      unwind:=FALSE; 
      stricttyping:=FALSE;
      trace:=FALSE;
(*9*) END InitENV;


PROCEDURE ECENV(ENV: LIST): LIST;
(*Encode environment. The encoded environment E is returned. *)
BEGIN
(*0*) RETURN(LIST2(NOSHOW,ENV)) 
(*4*) END ECENV;


PROCEDURE DCENV(E: LIST): LIST;
(*Decode environment. The encoded environment E is decoded. *)
BEGIN
(*0*) RETURN(SECOND(E)) 
(*4*) END DCENV;


PROCEDURE SETV(V, A: LIST; VAR ENV: LIST);
(*Set variable. V is a symbol and A is an S-expression. 
A is associated to V in the environment ENV. *)
VAR   EP, Z, t, n: LIST;
BEGIN
(*1*) (*See if defined*) 
      IF NOT SYMBOL(V) THEN 
         UWRIT1(V); SWRITE(":="); UWRITE(A); 
         ERROR(severe,"SETV: invalid as variable."); 
         RETURN (*setv makes no sense in this case*) END;
      EP:=ASSOC(V,ENV);
(*2*) (*dont check for bound variable here*) 
      IF EP <> SIL THEN SFIRST(EP,A)
                   ELSE ENV:=COMP2(V,A,ENV) END; 
(*3*) END SETV;


PROCEDURE EXTENDENV(A, X: LIST; VAR ENV: LIST): BOOLEAN;
(*Extend environement. A is a list of symbols. X is a list 
of values. The environment ENV is extented by the bindings
of the symbols in A to the values in X. If the binding
is possible, then TRUE is returned else FALSE. *)
VAR XP, AP, Y, Z, B: LIST;
BEGIN
(*1*) (*initialize*) Z:=ENV; XP:=X; AP:=A;
(*2*) (*loop on lists. *)
      WHILE (AP <> SIL) AND (XP <> SIL) DO 
            ADV(AP,B,AP); ADV(XP,Y,XP); 
            Z:=COMP2(B,Y,Z) END;
(*3*) (*argument number mismatch. *)
      IF (AP <> SIL) OR (XP <> SIL) THEN UWRITE(AP); UWRITE(XP); 
         ERROR(severe,"EXTENDENV: argument number mismatch.");
         RETURN(FALSE) END;  
      ENV:=Z; RETURN(TRUE);
(*4*) END EXTENDENV;


PROCEDURE COPYTOENV(V, EP: LIST; VAR ENV: LIST);
(*Copy to environement. V is a list of symbols. EP is an
environment. The environment ENV is extented by the bindings
of the symbols in V to the values in EP. *)
VAR   D, v: LIST;
BEGIN
(*0*) IF trace THEN SWRITE("IMP/EXP:   "); UWRITE(V); 
                    SWRITE("COPYTOENV: ");END;
(*1*) WHILE V <> SIL DO ADV(V,v,V); 
            D:=ASSOC(v,EP);
            IF D <> SIL THEN D:=FIRST(D); 
               IF trace THEN UWRIT1(v); SWRITE(" "); END;
               SETV(v,D,ENV) END; (*copy *)
            END;
      IF trace THEN BLINES(0) END;
(*4*) END COPYTOENV;


PROCEDURE SPECIALFORM(S: LIST): BOOLEAN;
(*Test if expression S is a special form. *)
VAR t: BOOLEAN;
    F, Y: LIST;
BEGIN
(*1*) (*initialize*) t:=FALSE;
      IF ELEMP(S) THEN RETURN(t) END;
(*2*) (*test property of symbol. *)  
      IF SYMBOL(S) THEN Y:=GET(S,EXTYP);
         IF (Y = FEXPR) OR (Y = MACRO) THEN t:=TRUE END;
         RETURN(t) END;
(*3*) (*test property of function. *) F:=FIRST(S);   
      IF F = FLAMBDA THEN RETURN(TRUE) END;
      IF F = MLAMBDA THEN RETURN(TRUE) END;
      RETURN(t); 
(*4*) END SPECIALFORM;


PROCEDURE LAMBDAP(S: LIST): BOOLEAN;
(*Test if expression S is a lambda form. *)
VAR t: BOOLEAN;
BEGIN
(*1*) (*initialize*) t:=FALSE;
      IF ELEMP(S) THEN RETURN(FALSE) END;
(*2*) (*test property of symbol. *)  
      IF NOT SYMBOL(S) THEN RETURN(FALSE) END;
(*3*) (*test if name = .lambda. *) t:=TRUE;  
      IF S = LAMBDA THEN RETURN(t) END; 
      IF S = FLAMBDA THEN RETURN(t) END; 
      IF S = MLAMBDA THEN RETURN(t) END; 
      IF S = GLAMBDA THEN RETURN(t) END; 
      RETURN(FALSE);
(*4*) END LAMBDAP;


PROCEDURE SEXPRP(X: LIST): BOOLEAN;
(*Test if X is a S-expression function. *)
VAR   T, Y: LIST;
BEGIN
(*1*) (*elemp. *) IF ELEMP(X) THEN RETURN(FALSE) END; 
(*1*) (*symbol. *) Y:=FIRST(X); 
      IF SYMBOL(Y) THEN T:=GET(Y,EXTYP);
         IF T <> SIL THEN RETURN(TRUE) END;
         RETURN(FALSE) END; 
(*2*) (*lambda expression. *) 
      IF LAMBDAP(FIRST(Y)) THEN RETURN(TRUE) END;
      RETURN(FALSE);
(*4*) END SEXPRP;


PROCEDURE DEFE(X: LIST; VAR ENV: LIST): LIST;
(*Define expr function. X is a DE expression. A LAMBDA expression 
generated from X is associated to name(X) in the environment ENV. *)
VAR   XP, Y, Z: LIST;
BEGIN
(*0*) (*syntax check. *) Z:=X;
      IF X = SIL THEN RETURN(SIL) END;
(*1*) (*define name. *) ADV(X,Y,XP); 
      IF NOT SYMBOL(Y) THEN UWRITE(Y);
         ERROR(severe,"DEFE: invalid as function name."); 
         RETURN(SIL) END; 
      PUT(Y,EXTYP,EXPR); 
(*3*) (*generate lambda expression. *)
      Z:=COMP(LAMBDA,XP); SETV(Y,Z,ENV); 
      RETURN(Y);
(*4*) END DEFE;


PROCEDURE DEFF(X: LIST; VAR ENV: LIST): LIST;
(*Define fexpr function. X is a DF expression. A FLAMBDA expression 
generated from X is associated to name(X) in the environment ENV.*)
VAR   XP, Y, Z: LIST;
BEGIN
(*0*) (*syntax check. *) 
      IF X = SIL THEN RETURN(SIL) END;
(*1*) (*define name. *) ADV(X,Y,XP); 
      IF NOT SYMBOL(Y) THEN UWRITE(Y);
         ERROR(severe,"DEFF: invalid as function name."); 
         RETURN(SIL) END; 
      PUT(Y,EXTYP,EXPR); 
(*2*) (*generate flambda expression. *)
      Z:=COMP(FLAMBDA,XP); SETV(Y,Z,ENV); 
      RETURN(Y);
(*4*) END DEFF;


PROCEDURE DEFM(X: LIST; VAR ENV: LIST): LIST;
(*Define macro function. X is a DM expression. A MLAMBDA expression 
generated from X is associated to name(X) in the environment ENV.*)
VAR   XP, Y, Z: LIST;
BEGIN
(*0*) (*syntax check. *) 
      IF X = SIL THEN RETURN(SIL) END;
(*1*) (*define name. *) ADV(X,Y,XP); 
      IF NOT SYMBOL(Y) THEN UWRITE(Y);
         ERROR(severe,"DEFM: invalid as function name."); 
         RETURN(SIL) END; 
      PUT(Y,EXTYP,MACRO); 
(*2*) (*generate mlambda expression. *)
      Z:=COMP(MLAMBDA,XP); SETV(Y,Z,ENV); 
      RETURN(Y);
(*4*) END DEFM;


PROCEDURE DEFMAP(X: LIST; VAR ENV: LIST): LIST;
(*Define generic map function. X is a MAP expression. A 
GLAMBDA expression generated from X is associated to name(X) 
in the environment ENV. *)
VAR   MP, XP, Y, Z, L, R, M, I, IP, E, N: LIST;
BEGIN
(*0*) (*syntax check. *) 
      IF X = SIL THEN RETURN(SIL) END;
(*1*) (*get name. *) ADV(X,L,XP); (* (name, (sig)), mod func, cond. *)
      ADV(L,Y,L); L:=FIRST(L); 
      IF NOT SYMBOL(Y) THEN UWRITE(Y);
         ERROR(severe,"DEFMAP: invalid as function name."); 
         RETURN(SIL) END; 
      IP:=SIL; 
      Z:=ASSOC(Y,ENV); (*get generic function list*)
      IF Z <> SIL THEN Z:=FIRST(Z);
         IF Z <> SIL THEN  
            IF FIRST(Z) = GLAMBDA THEN Z:=RED(Z) 
         ELSIF LAMBDAP(FIRST(Z)) THEN IP:=LIST2(Z,ECENV(ENV)); Z:=SIL;  
          ELSE Z:=SIL; UWRITE(Y);
               ERROR(severe,"DEFMAP: variable defined generic."); 
               END;
            END;
         END;
      (*decompose *)
      IF Z = SIL THEN N:=Y; M:=SIL; I:=IP; E:=SIL; PUT(Y,EXTYP,GENERIC); 
                 ELSE FIRST4(Z,N,M,I,E) END;
(*2*) (*generate map match list. *) 
      MP:=ASSOCQ(L,M); (* avoid multiple entries *) 
      IF MP <> SIL THEN SFIRST(MP,XP)
                   ELSE XP:=LIST2(L,XP); (*sig, mod func *)
                        M:=CCONC(M,XP) END; 
(*3*) (*generate glambda expression. *) Z:=LIST4(N,M,I,E);
      Z:=COMP(GLAMBDA,Z); SETV(Y,Z,ENV); 
      RETURN(Y);
(*4*) END DEFMAP;


PROCEDURE DEFPROC(X: LIST; VAR ENV: LIST): LIST;
(*Define generic proc function. X is a DE expression. 
A GLAMBDA expression generated from X is associated to 
name(X) in the environment ENV.*)
VAR   XP, Y, Z, M, I, IP, E, N: LIST;
BEGIN
(*0*) (*syntax check. *) 
      IF X = SIL THEN RETURN(SIL) END;
(*1*) (*get name. *) ADV(X,Y,XP); (*name, parm, body. *)
      IF NOT SYMBOL(Y) THEN UWRITE(Y);
         ERROR(severe,"DEFPROC: invalid as function name."); 
         RETURN(SIL) END; 
      IP:=SIL;
      Z:=ASSOC(Y,ENV); (*get generic function list*)
      IF Z <> SIL THEN Z:=FIRST(Z);
         IF Z <> SIL THEN  
            IF FIRST(Z) = GLAMBDA THEN Z:=RED(Z) 
         ELSIF LAMBDAP(FIRST(Z)) THEN IP:=LIST2(Z,ECENV(ENV)); Z:=SIL;  
          ELSE Z:=SIL; UWRITE(Y);
               ERROR(severe,"DEFPROC: variable defined generic."); 
               END;
            END;
         END;
      (*decompose *)
      IF Z = SIL THEN N:=Y; M:=SIL; I:=IP; E:=SIL; PUT(Y,EXTYP,GENERIC); 
                 ELSE FIRST4(Z,N,M,I,E) END;
(*2*) (*generate proc closure. *) 
      XP:=COMP(LAMBDA,XP);
      I:=LIST2(XP,ECENV(ENV)); (*closure: lambda, env *)
(*3*) (*generate glambda expression. *) Z:=LIST4(N,M,I,E);
      Z:=COMP(GLAMBDA,Z); SETV(Y,Z,ENV); 
      RETURN(Y);
(*4*) END DEFPROC;


PROCEDURE DEFRULE(X: LIST; VAR ENV: LIST): LIST;
(*Define generic rule function. X is a RULE expression. 
A GLAMBDA expression generated from X is associated to 
name(X) in the environment ENV.*)
VAR   XP, Y, Z, M, I, IP, E, N, L, R: LIST;
BEGIN
(*0*) (*syntax check. *) 
      IF X = SIL THEN RETURN(SIL) END;
(*1*) (*get name. *) ADV(X,L,XP); (*lhs, rhs *)
      Y:=FIRST(L);
      IF ATOM(Y) THEN UWRITE(Y);
         ERROR(severe,"DEFRULE: atom invalid as function name."); 
         RETURN(SIL) END; 
      IP:=SIL;
      Z:=ASSOC(Y,ENV); (*get generic function list*)
      IF Z <> SIL THEN Z:=FIRST(Z);
         IF Z <> SIL THEN  
            IF FIRST(Z) = GLAMBDA THEN Z:=RED(Z) 
         ELSIF LAMBDAP(FIRST(Z)) THEN IP:=LIST2(Z,ECENV(ENV)); Z:=SIL;  
          ELSE Z:=SIL; UWRITE(Y);
               ERROR(severe,"DEFRULE: variable defined generic."); 
               END;
            END;
         END;
      (*decompose *)
      IF Z = SIL THEN N:=Y; M:=SIL; I:=IP; E:=SIL; PUT(Y,EXTYP,GENERIC); 
                 ELSE FIRST4(Z,N,M,I,E) END;
(*2*) (*generate match list. *) 
      E:=CCONC(E,LIST1(X)); (*add lhs = rhs *)
(*3*) (*generate glambda expression. *) Z:=LIST4(N,M,I,E);
      Z:=COMP(GLAMBDA,Z); SETV(Y,Z,ENV); 
      RETURN(Y);
(*4*) END DEFRULE;


PROCEDURE DSPEC(X: LIST; VAR ENV: LIST): LIST;
(*Define specification. X is a SPEC expression. An UNIT expression 
generated from X is associated to name(X) in the environment ENV.*)
VAR   XP, Y, Z: LIST;
BEGIN
(*0*) (*syntax check. *) 
      IF X = SIL THEN RETURN(SIL) END;
(*1*) (*define name. *) ADV(X,Y,XP);   
      IF NOT SYMBOL(Y) THEN UWRITE(Y);
         ERROR(severe,"DSPEC: invalid as unit name."); 
         RETURN(SIL) END; 
      PUT(Y,EXTYP,FEXPR); 
(*2*) (*generate spec expression and set/reset unit. *)
      Z:=COMP2(SPEC,Y,XP); 
      Z:=LIST4(UNIT,Y,FIRST(XP),Z); (*unit name parms spec other *)
      SETV(Y,Z,ENV); 
      RETURN(Y);
(*4*) END DSPEC;


PROCEDURE DMIA(X: LIST; VAR ENV: LIST): LIST;
(*Define model, implementation or axioms. X is a MODEL, 
IMPLEMENTATION or AXIOMS expression. An UNIT expression 
associated to name(X) is modified by a generated expression 
of X. *)
VAR   XPP, XP, Y, Z, W, T: LIST;
BEGIN
(*0*) (*syntax check. *) 
      IF X = SIL THEN RETURN(SIL) END;
(*1*) (*define name. *) ADV2(X,T,Y,XP);  
      IF NOT SYMBOL(Y) THEN UWRITE(Y);
         ERROR(severe,"DMIA: invalid as unit name."); 
         RETURN(SIL) END; 
      W:=ASSOC(Y,ENV);
      IF W = SIL THEN UWRITE(Y);
         ERROR(severe,"DMIA: no specification defined."); 
         RETURN(SIL) END; 
      W:=FIRST(W);
      IF FIRST(W) <> UNIT THEN UWRITE(Y);
         ERROR(severe,"DMIA: no unit defined."); 
         RETURN(SIL) END;
(*2*) (*generate m/i/a expression and add to unit. *)
      Z:=LIST1(X); Z:=CONC(W,Z);
      RETURN(Y);
(*4*) END DMIA;


PROCEDURE TYPEOF(X: LIST): LIST;
(*Type of S-expression. X is an S-expression. A list of types, 
values and descriptors of X is returend. *)
VAR   D, DS, XP, x, y, xs, d, XS, Y, YS, W, A: LIST;
BEGIN
(*1*) (*elementary. *) Y:=SIL; D:=SIL; 
      IF ATOM(X) THEN XS:=LIST1(X); Y:=ATM;
         RETURN(LIST3(XS,Y,D)) END; 
(*2*) (*symbol. *) 
      IF SYMBOL(X) THEN Y:=SIL; D:=SIL;         
         Y:=GET(X,SORT); 
         IF Y <> SIL THEN RETURN(LIST3(SIL,X,D)) END; 
         Y:=GET(X,TDEF); 
         IF (Y > SIL) AND NOT SYMBOL(Y) THEN FIRST2(Y,Y,D) END;  
         X:=LIST1(X); 
         IF Y <> SIL THEN Y:=LIST1(Y) END; 
         IF D <> SIL THEN D:=LIST1(D) END; 
         RETURN(LIST3(X,Y,D)) END; 
(*3*) (*with type info. *) 
      IF FIRST(X) = TINFO THEN XS:=VALOFTAG(X); 
         Y:=TYPOFTAG(X); D:=DECOFTAG(X);  
         XS:=LIST1(XS); 
         IF Y <> SIL THEN Y:=LIST1(Y) END; 
         IF D <> SIL THEN D:=LIST1(D) END; 
         RETURN(LIST3(XS,Y,D)) END; 
(*4*) (*term of sorts. *) (*problem*)
      IF GET(FIRST(X),SORT) <> SIL THEN FIRST2(X, X,D); 
         IF X <> SIL THEN X:=LIST1(X) END; 
         IF D <> SIL THEN D:=LIST1(D) END; 
         RETURN(LIST3(SIL,X,D)) END; 
(*5*) (*un-evaluated function term. *) 
      A:=GET(FIRST(X),ARROW);
      IF A <> SIL THEN  XS:=X; D:=SIL; 
         FIRST3(A,x,y,Y); IF Y <> SIL THEN Y:=FIRST(Y) END; 
         XS:=LIST1(XS); 
         IF Y <> SIL THEN Y:=LIST1(Y) END; 
         IF D <> SIL THEN D:=LIST1(D) END; 
         RETURN(LIST3(XS,Y,D)) END; 
(*6*) (*list. *) XP:=X; XS:=SIL; 
      WHILE XP <> SIL DO ADV(XP,x,XP); W:=TYPEOF(x);
            FIRST3(W,xs,y,d);
            XS:=CCONC(XS,xs); Y:=CCONC(Y,y); D:=CCONC(D,d) END;
      RETURN(LIST3(XS,Y,D)) 
(*9*) END TYPEOF;


PROCEDURE TAG(V,T: LIST): LIST;
(*Tag object. V is an S-expression, T is a type expression.
A tagged TYPEINFO S-expression is returned. *)
VAR   O: LIST;
BEGIN
(*1*) (*check type indicator *)
      IF ELEMP(T) THEN UWRITE(T); 
         ERROR(severe,"TAG: invalid as type indicator."); 
         RETURN(SIL) END; 
(*2*) (*construct list *)
      O:=LIST3(TINFO,V,T);
      RETURN(O); 
(*3*) END TAG;


PROCEDURE VALOFTAG(L: LIST): LIST;
(*Value of tagged object. L is a tagged S-expression. 
The value component of L is returned. *)
BEGIN
(*1*) (*check tag *)
      IF ATOM(L) THEN RETURN(L) END; 
      IF FIRST(L) <> TINFO THEN RETURN(L) END; 
      RETURN(SECOND(L)); 
(*3*) END VALOFTAG;


PROCEDURE TYPOFTAG(L: LIST): LIST;
(*Type of tagged object. L is a tagged S-expression. 
The type component of L is returned.*)
VAR   T: LIST;
BEGIN
(*1*) (*check tag *)
      IF ATOM(L) THEN RETURN(SIL) END; 
      IF FIRST(L) <> TINFO THEN RETURN(SIL) END; 
      T:=THIRD(L); (*tinfo val type*)
      T:=FIRST(T);
      RETURN(T); 
(*3*) END TYPOFTAG;


PROCEDURE DECOFTAG(L: LIST): LIST;
(*Descriptor of tagged object. L is a tagged S-expression. 
The descriptor component of L is returned. *)
VAR   D, T: LIST;
BEGIN
(*1*) (*check tag *) 
      IF ATOM(L) THEN RETURN(SIL) END; 
      IF FIRST(L) <> TINFO THEN RETURN(SIL) END; 
      T:=THIRD(L); (*tinfo val type*)
      T:=RED(T);
      IF T <> SIL THEN D:=FIRST(T) ELSE D:=SIL END;
      RETURN(D); 
(*3*) END DECOFTAG;


PROCEDURE GENPL(P,V,T,D: LIST): LIST;
(*Generate parameter list. P is a list of patterns. 
V is a list of values. T is a list of types and D is a 
list of descriptors. A parameter list is returned. *)
VAR   L, p, x: LIST;
BEGIN
(*1*) (*check patterns. *) L:=SIL;
      WHILE P <> SIL DO ADV(P,p,P); 
            IF p = PVAL  THEN ADV(V,x,V); L:=COMP(x,L);
         ELSIF p = PDESC THEN ADV(D,x,D); L:=COMP(x,L);
         ELSIF p = PTYP  THEN ADV(T,x,T); L:=COMP(x,L);
          ELSE UWRITE(p);
               ERROR(severe,"GENPL: invalid pattern skipped."); 
               END;
            END;
      L:=INV(L); RETURN(L);
(*4*) END GENPL;


PROCEDURE GENTE(Z,N,D: LIST): LIST;
(*Generate typed expression. Z is an S-expression,
N is a function name, D is a descriptor. A typed S-expression 
for evaluation is returned. *)
VAR   A: LIST;
BEGIN
(*1*) (*get arrow *)
      A:=GET(N,ARROW); 
      IF A = SIL THEN UWRITE(N);
         ERROR(severe,"GENTE: no signature defined."); 
         RETURN(Z) END; 
(*2*) (*get target *)
      A:=THIRD(A); 
      IF A = SIL THEN RETURN(Z) END; 
      IF RED(A) = SIL THEN A:=FIRST(A) END; (*single value*)  
      IF A = SIL THEN RETURN(Z) END; 
(*3*) (*combine *)
      A:=LIST2(A,D);
      Z:=TAG(Z,A); Z:=COMP(LISTX,Z);          
      RETURN(Z);
(*4*) END GENTE;


(* Execution part. *)
BEGIN

InitLISP;

END MASLISP.


(* -EOF- *)