(* ---------------------------------------------------------------------------- * $Id: MASSPEC.mi,v 1.4 1995/11/05 08:58:48 kredel Exp $ * ---------------------------------------------------------------------------- * This file is part of MAS. * ---------------------------------------------------------------------------- * Copyright (c) 1989 - 1992 Universitaet Passau * ---------------------------------------------------------------------------- * $Log: MASSPEC.mi,v $ * Revision 1.4 1995/11/05 08:58:48 kredel * Small letter exit, more trace infos and correction. * * Revision 1.3 1992/10/15 16:27:52 kredel * Changed rcsid variable * * Revision 1.2 1992/02/12 17:32:30 pesch * Moved CONST definition to the right place * * Revision 1.1 1992/01/22 15:11:26 kredel * Initial revision * * ---------------------------------------------------------------------------- *) IMPLEMENTATION MODULE MASSPEC; (* MAS Specification Implementation Module. *) (* Import lists and declarations. *) FROM MASSTOR IMPORT BETA, SIL, LIST, LENGTH, LIST1, ADV, FIRST, RED, COMP, INV, SFIRST, SRED; FROM MASERR IMPORT ERROR, severe, harmless, spotless; FROM MASBIOS IMPORT LISTS, BLINES, SWRITE; 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, UWRITE, UWRIT1, UNIFY, GENARRAY, ARRAYDEC; FROM MASLISPU IMPORT EXTYP, ARITY, SUBR, EXPR, PROCP, CallCompiled, Signature; FROM MASLISP IMPORT FEXPR, MACRO, GENERIC, REP, FER, FERx, FEL, FELx, CONVVAL, CONVDES, trace, stricttyping, TDEF, DEFAULT, ARROW, (*indicators*) ENV, (*global environement (alist)*) NULL, WT, SCHLUSS, schluss, TINFO, EQS, NEQS, GTS, LTS, GEQ, LEQ, NOTS, UND, ODER, ADD, SUB, MUL, QUOT, REM, POW, QUOTE, SETQ, COND, LISTX, ASSIGN, READ, WRITE, DECREAD, DECWRITE, PROGN, VARS, IFS, WHL, RPT, STRNG, DE, DF, DM, DG, PROGA, GTO, LBEL, ARY, SETAV, ATM, RTN, ANY, UNIT, EXPOS, SPEC, SORT, SIG, IMPRT, IMPL, MODEL, MAP, AXIOM, RULE, WHEN, LAMBDA, FLAMBDA, MLAMBDA, GLAMBDA, SPECIALFORM, LAMBDAP, SEXPRP, SETV, EXTENDENV, COPYTOENV, DEFE, DEFF, DEFM, DEFMAP, DEFRULE, DEFPROC, DSPEC, DMIA, TYPEOF, TAG, VALOFTAG, DECOFTAG, TYPOFTAG, ECENV, DCENV, GENPL, GENTE; VAR unwind: BOOLEAN; goto: LIST; CONST rcsidi = "$Id: MASSPEC.mi,v 1.4 1995/11/05 08:58:48 kredel Exp $"; CONST copyrighti = "Copyright (c) 1989 - 1992 Universitaet Passau"; (* Procedure declarations. *) PROCEDURE APPLY(F, X: LIST; VAR ENV: LIST): LIST; (*Apply function. F is a function symbol or lambda expression. X is a list of un-evaluated arguments. F is applied to X. *) VAR XP, Y, Z, L, X1, X2, FP, A, B, EP, ES, I, O, OP: LIST; t: BOOLEAN; BEGIN (*1*) (*initialize*) Z:=SIL; IF ELEMP(F) THEN UWRITE(F); ERROR(severe,"APPLY: invalid function object."); RETURN(Z) END; IF trace THEN SWRITE("APPLY: "); UWRITE(COMP(F,X)) END; (*2*) (*branch on special function. *) IF SYMBOL(F) THEN X:=EVLIS(X,ENV); IF F = ADD THEN ADV(X,Z,XP); WHILE XP <> SIL DO ADV(XP,X1,XP); Z:=Z+X1 END; RETURN(Z) END; IF F = SUB THEN ADV(X,Z,XP); IF XP = SIL THEN Z:=-Z; RETURN(Z) END; WHILE XP <> SIL DO ADV(XP,X1,XP); Z:=Z-X1 END; RETURN(Z) END; IF F = NEQS THEN FIRST2(X,X1,X2); IF X1 <> X2 THEN Z:=WT END; RETURN(Z) END; IF F = GTS THEN FIRST2(X,X1,X2); IF X1 > X2 THEN Z:=WT END; RETURN(Z) END; IF F = LTS THEN FIRST2(X,X1,X2); IF X1 < X2 THEN Z:=WT END; RETURN(Z) END; IF F = LEQ THEN FIRST2(X,X1,X2); IF X1 <= X2 THEN Z:=WT END; RETURN(Z) END; IF F = GEQ THEN FIRST2(X,X1,X2); IF X1 >= X2 THEN Z:=WT END; RETURN(Z) END; IF F = EQS THEN FIRST2(X,X1,X2); IF X1 = X2 THEN Z:=WT END; RETURN(Z) END; IF F = MUL THEN ADV(X,Z,XP); WHILE XP <> SIL DO ADV(XP,X1,XP); Z:=Z*X1 END; RETURN(Z) END; IF F = QUOT THEN ADV(X,Z,XP); WHILE XP <> SIL DO ADV(XP,X1,XP); Z:=Z DIV X1 END; RETURN(Z) END; IF F = REM THEN ADV(X,Z,XP); WHILE XP <> SIL DO ADV(XP,X1,XP); Z:=Z MOD X1 END; RETURN(Z) END; IF F = NOTS THEN ADV(X,Z,XP); IF Z = SIL THEN Z:=WT ELSE Z:=SIL END; RETURN(Z) END; IF F = UND THEN FIRST2(X,X1,X2); IF (X1 <> SIL) AND (X2 <> SIL) THEN Z:=WT END; RETURN(Z) END; IF F = ODER THEN FIRST2(X,X1,X2); IF (X1 <> SIL) OR (X2 <> SIL) THEN Z:=WT END; RETURN(Z) END; IF F = RTN THEN Z:=FIRST(X); unwind:=TRUE; RETURN(Z) END; IF F = FEL THEN EP:=LIST2(QUOTE,ENV); EP:=LIST1(EP); X:=CCONC(X,EP); X:=COMP(FELx,X); Z:=EVALUATE(X,ENV); RETURN(Z) END; IF F = FER THEN EP:=LIST2(QUOTE,ENV); EP:=LIST1(EP); X:=CCONC(X,EP); X:=COMP(FERx,X); Z:=EVALUATE(X,ENV); RETURN(Z) END; IF F = CONVVAL THEN Z:=CONVvalue(X,ENV); RETURN(Z) END; IF F = CONVDES THEN Z:=CONVdesc(X,ENV); RETURN(Z) END; IF F = GTO THEN Z:=FIRST(X); goto:=Z; unwind:=TRUE; RETURN(Z) END; (* UWRITE(F); ERROR(severe,"APPLY: invalid function object.");*) Z:=COMP(F,X); RETURN(Z); END; ADV(F,L,FP); (*2*) (*typeinfo tag. *) IF L = TINFO THEN Z:=COMP(F,X); (*reconstruct list*) RETURN(Z) END; (*3*) (*lambda expression. *) IF L = LAMBDA THEN FIRST2(FP,A,B); FIRST2(A,I,O); EP:=ENV; t:=unwind; unwind:=FALSE; IF EXTENDVARENV(I,O,X,EP) THEN ES:=EP; Z:=EVALUATE(B,EP); XP:=CINV(X); OP:=O; WHILE OP <> SIL DO OP:=RED(OP); ADV(XP,X1,XP); ES:=RED(ES); ADV(ES,X2,ES); SETV(X1,X2,ENV) END; END; unwind:=t; RETURN(Z) END; (*4*) (*glambda expression. *) IF L = GLAMBDA THEN X:=EVLIS(X,ENV); Z:=EVGEN(FP,X,ENV); FIRST2(Z,XP,EP); EP:=DCENV(EP); t:=unwind; unwind:=FALSE; Z:=EVALUATE(XP,EP); unwind:=t; RETURN(Z); END; (*5*) (*not known.*) UWRITE(F); ERROR(severe,"APPLY: invalid function object."); RETURN(Z); (*6*) END APPLY; PROCEDURE APPLYCOMP(F, A: LIST; VAR ENV: LIST): LIST; (*Apply compiled function. F is a symbol of a compiled function. X is a list of evaluated arguments. F is applied to X.*) VAR B, Z, I, O, PI, PO, V: LIST; b, c, v, i: LIST; def, fu: BOOLEAN; BEGIN (*1*) (*initialize*) Z:=SIL; Signature(F,I,O,def); IF NOT def THEN UWRITE(F); ERROR(severe,"APPLYCOMP: unbound compiled procedure."); RETURN(Z) END; IF O < 0 THEN O:=0 END; (*2*) (*prepare input parameters. *) IF LENGTH(A) < I THEN UWRITE(F); ERROR(severe,"APPLYCOMP: too few input parameters."); RETURN(Z) END; B:=A; PI:=SIL; i:=1; WHILE i <= I DO i:=i+1; ADV(B,b,B); c:=EVALUATE(b,ENV); PI:=COMP(c,PI) END; PI:=INV(PI); V:=B; (*3*) (*prepare output parameters. *) IF LENGTH(B) < O THEN UWRITE(F); ERROR(severe,"APPLYCOMP: too few output parameters."); RETURN(Z) END; PO:=SIL; i:=1; WHILE i <= O DO i:=i+1; ADV(B,b,B); c:=ASSOC(b,ENV); IF c <> SIL THEN c:=FIRST(c) END; PO:=COMP(c,PO) END; PO:=INV(PO); IF B <> SIL THEN UWRITE(F); ERROR(severe,"APPLYCOMP: too many parameters."); RETURN(Z) END; (*4*) (*call compiled procedure. *) IF trace THEN SWRITE("EXTERN: "); UWRITE(COMP(F,CCONC(PI,PO))) END; CallCompiled(F,PI,PO,fu); IF fu THEN Z:=PO; RETURN(Z) END; (*5*) (*prepare output parameters. *) WHILE PO <> SIL DO ADV(PO,b,PO); ADV(V,v,V); SETV(v,b,ENV) END; RETURN(Z); (*4*) END APPLYCOMP; PROCEDURE EVALUATE(X: LIST; VAR ENV: LIST): LIST; (*Lisp evaluator. X is a S-expression. ENV is a binding environment. *) VAR F, Y, Z: LIST; BEGIN (*1*) (*initialize*) Z:=SIL; (*2*) (*atoms or symbols. *) IF ELEMP(X) THEN RETURN(X) END; IF SYMBOL(X) THEN Z:=ASSOC(X,ENV); IF Z = SIL THEN Z:=X ELSE ERROR(spotless,"s c"); (*stack check*) Z:=FIRST(Z); Z:=EVALUATE(Z,ENV) END; RETURN(Z) END; (*3*) (*S-expressions. *) IF X > BETA THEN ADV(X, F,Y); IF LAMBDAP(F) THEN RETURN(X) END; ERROR(spotless,"s c"); (*stack check*) F:=EVALUATE(F,ENV); IF SPECIALFORM(F) THEN Z:=COMP(F,Y); Z:=EVALSPFORM(Z,ENV); ELSE IF PROCP(F) THEN Z:=APPLYCOMP(F,Y,ENV) ELSE Z:=APPLY(F,Y,ENV) END; END; RETURN(Z) END; (*4*) (*not known.*) UWRITE(X); ERROR(severe,"EVALUATE: invalid form."); RETURN(Z); (*5*) END EVALUATE; PROCEDURE EVALSPFORM(X: LIST; VAR ENV: LIST): LIST; (*Evaluate special form. X is an S-expression. *) VAR M, XP, F, A, B, FP, Y, Z, EP, W, T, L: LIST; t: BOOLEAN; BEGIN (*1*) (*initialize*) Z:=SIL; ADV(X,F,XP); IF ELEMP(F) THEN UWRITE(F); ERROR(severe,"EVALSPFORM: invalid as function object."); RETURN(Z) END; IF trace THEN SWRITE("SPFORM: "); UWRITE(X) END; (*2*) (*branch on special function. *) IF SYMBOL(F) THEN IF F = ASSIGN THEN Z:=EVASS(XP,ENV); RETURN(Z) END; IF F = TINFO THEN RETURN(X) END; IF F = PROGN THEN Z:=EVPROGN(XP,ENV); RETURN(Z) END; IF F = IFS THEN ADV(XP,Z,XP); ADV(XP,Y,XP); Z:=EVALUATE(Z,ENV); IF Z = WT THEN Z:=EVALUATE(Y,ENV) ELSIF XP <> SIL THEN Z:=EVALUATE(FIRST(XP),ENV) END; RETURN(Z) END; IF F = WHL THEN Z:=EVWHL(XP,ENV); RETURN(Z) END; IF F = RPT THEN Z:=EVRPT(XP,ENV); RETURN(Z) END; IF F = QUOTE THEN Z:=FIRST(XP); RETURN(Z) END; IF F = STRNG THEN Z:=XP; RETURN(Z) END; IF F = LISTX THEN Z:=EVLIS(XP,ENV); RETURN(Z) END; IF F = SETQ THEN ADV(XP,Y,XP); W:=FIRST(XP); Z:=EVALUATE(W,ENV); SETV(Y,Z,ENV); RETURN(Z) END; IF F = SETAV THEN ADV(XP,Y,XP); W:=FIRST(XP); Z:=EVALUATE(W,ENV); SETaldesV(Y,Z,ENV); RETURN(Z) END; IF F = REP THEN RETURN(X) END; IF F = VARS THEN Z:=EVVAR(XP,ENV); RETURN(Z) END; IF F = DE THEN Z:=DEFE(XP,ENV); RETURN(Z) END; IF F = DF THEN Z:=DEFF(XP,ENV); RETURN(Z) END; IF F = DM THEN Z:=DEFM(XP,ENV); RETURN(Z) END; IF F = ARY THEN XP:=FIRST(XP); FIRST2(XP,Y,W); W:=EVLIS(W,ENV); XP:=LIST2(Y,W); Z:=GENARRAY(XP); Z:=EVALUATE(Z,ENV); RETURN(Z) END; IF F = SPEC THEN Z:=DSPEC(XP,ENV); RETURN(Z) END; IF F = IMPL THEN Z:=DMIA(X,ENV); RETURN(Z) END; IF F = MODEL THEN Z:=DMIA(X,ENV); RETURN(Z) END; IF F = AXIOM THEN Z:=DMIA(X,ENV); RETURN(Z) END; IF F = EXPOS THEN Z:=EVUNIT(XP,ENV); RETURN(Z) END; IF F = UNIT THEN RETURN(X) END; IF F = COND THEN Z:=EVCOND(XP,ENV); RETURN(Z) END; IF F = PROGA THEN Z:=EVPROGA(XP,ENV); RETURN(Z) END; IF F = LBEL THEN Z:=FIRST(XP); RETURN(Z) END; IF (F = SCHLUSS) OR (F = schluss) THEN RETURN(F) END; (*UWRITE(F); ERROR(severe,"EVALSPFORM: unknown function.");*) Z:=X; RETURN(Z); END; ADV(F,L,FP); (*3*) (*mlambda expression. *) IF L = MLAMBDA THEN FIRST2(FP,A,B); XP:=LIST1(LIST2(QUOTE,X)); EP:=ENV; t:=unwind; unwind:=FALSE; IF EXTENDENV(A,XP,EP) THEN Z:=EVALUATE(B,EP); Z:=EVALUATE(Z,EP); END; unwind:=t; RETURN(Z) END; (*4*) (*flambda expression. *) IF L = FLAMBDA THEN FIRST2(FP,A,B); XP:=LIST1(LIST2(QUOTE,XP)); EP:=ENV; t:=unwind; unwind:=FALSE; IF EXTENDENV(A,XP,EP) THEN Z:=EVALUATE(B,EP) END; unwind:=t; RETURN(Z) END; (*5*) (*not known.*) UWRITE(F); ERROR(severe,"EVALSPFORM: unknown function."); RETURN(Z); (*6*) END EVALSPFORM; PROCEDURE EVCOND(X: LIST; VAR ENV: LIST): LIST; (*Evaluate condition. X is the reductum of a COND S-expression. *) VAR XP, Y, Z, C, D: LIST; BEGIN (*1*) (*initialize*) Z:=SIL; XP:=X; (*2*) (*loop on list of pairs. *) WHILE XP <> SIL DO ADV(XP,Y,XP); ADV(Y,C,D); C:=EVALUATE(C,ENV); IF C <> SIL THEN Z:=EVPROGN(D,ENV); RETURN(Z) END; END; RETURN(Z); (*4*) END EVCOND; PROCEDURE EVPROGN(X: LIST; VAR ENV: LIST): LIST; (*Evaluate statement sequence. X is the reductum of a PROGN S-expression. *) VAR XP, Z, Y: LIST; BEGIN (*1*) (*initialize*) Z:=SIL; XP:=X; (*2*) (*loop on list. *) WHILE XP <> SIL DO ADV(XP,Y,XP); Z:=EVALUATE(Y,ENV); IF unwind THEN RETURN(Z) END; END; RETURN(Z); (*4*) END EVPROGN; PROCEDURE EVWHL(X: LIST; VAR ENV: LIST): LIST; (*Evaluate while. *) VAR C, B, Z: LIST; BEGIN (*1*) (*initialize*) C:=FIRST(X); B:=SECOND(X); Z:=SIL; (*2*) (*loop if condition is true. *) WHILE EVALUATE(C,ENV) <> SIL DO Z:=EVALUATE(B,ENV); IF unwind THEN RETURN(Z) END; END; RETURN(Z); (*4*) END EVWHL; PROCEDURE EVRPT(X: LIST; VAR ENV: LIST): LIST; (*Evaluate repeat. *) VAR C, B, Z: LIST; BEGIN (*1*) (*initialize*) B:=FIRST(X); C:=SECOND(X); (*2*) (*loop if condition is true. *) REPEAT Z:=EVALUATE(B,ENV); IF unwind THEN RETURN(Z) END; UNTIL EVALUATE(C,ENV) <> SIL; RETURN(Z); (*4*) END EVRPT; PROCEDURE EVLIS(X: LIST; VAR ENV: LIST): LIST; (*Evaluate list. *) VAR XP, Y, Z: LIST; BEGIN (*1*) (*initialize*) Z:=SIL; XP:=X; (*2*) (*loop on list. *) WHILE XP <> SIL DO ADV(XP,Y,XP); Y:=EVALUATE(Y,ENV); Z:=COMP(Y,Z) END; Y:=INV(Z); RETURN(Y); (*4*) END EVLIS; PROCEDURE EVASS(X: LIST; VAR ENV: LIST): LIST; (*Evaluate assignment statement. *) VAR XP, Z, Y, T, TP, W: LIST; nofu: BOOLEAN; BEGIN (*1*) (*initialize*) ADV(X,Y,XP); W:=FIRST(XP); nofu:=TRUE; (*2*) (*generic assignment ? *) IF NOT ATOM(W) THEN IF FIRST(W) = STRNG THEN T:=GET(Y,TDEF); IF T <> SIL THEN TP:=FIRST(T) ELSE TP:=SIL END; IF (TP # SIL) AND (TP # LISTX) AND (TP # STRNG) AND (TP # ANY) THEN Z:=CONVERT(T,READ,W,ENV); SETV(Y,Z,ENV); RETURN(Z) END; ELSE nofu:=FALSE (*function calls are allowed*) END; END; IF stricttyping AND nofu THEN UWRITE(Y); ERROR(severe,"EVASS: no type information available."); RETURN(SIL) END; (*3*) (*normal evaluate *) Z:=EVALUATE(W,ENV); SETV(Y,Z,ENV); RETURN(Z); (*4*) END EVASS; PROCEDURE CONVERT(T,P,S: LIST; VAR ENV: LIST): LIST; (*Evaluate generic conversion. T is the type of the target of the conversion. S is the conversion string. P is the conversion generic procedure. *) VAR x, D, Z, TP, W, L, F, A, EP: LIST; BEGIN (*1*) (*initialize*) Z:=SIL; F:=SIL; IF ELEMP(T) THEN UWRITE(T); ERROR(severe,"CONVERT: invalid as type."); RETURN(Z) END; TP:=TAG(SIL,T); TP:=LIST1(TP); (*2*) (*get actual procedure *) L:=ASSOC(P,ENV); IF L <> SIL THEN L:=FIRST(L) END; (* (glambda n M I E) *) IF L <> SIL THEN L:=RED(L) END; W:=EVGEN(L,TP,ENV); FIRST2(W,W,EP); EP:=DCENV(EP); IF FIRST(W) = QUOTE THEN UWRITE(T); ERROR(severe,"CONVERT: unbound generic procedure for signature."); RETURN(Z) END; (*3*) (*generate actual call *) A:=S; IF FIRST(A) = STRNG THEN A:=RED(A) END; (* remove string inidicator *) A:=CCONC(A,LISTS(" ")); (* add terminator *) CLTIS(A); (* put to input stream for read *) (*4*) (*evaluate *) Z:=EVALUATE(W,EP); RETURN(Z); (*5*) END CONVERT; PROCEDURE CONVvalue(X: LIST; VAR ENV: LIST): LIST; (*Evaluate conversion parse. X=(T,S), T is the type of the target of the conversion. S is the conversion string. *) VAR TP, T, S: LIST; BEGIN (*1*) IF X = SIL THEN RETURN(SIL) END; FIRST2(X,T,S); (*2*) TP:=CONVERT(T,READ,S,ENV); RETURN(TP); (*5*) END CONVvalue; PROCEDURE CONVdesc(X: LIST; VAR ENV: LIST): LIST; (*Evaluate conversion descriptor. X=(T,S), T is the type of the target of the conversion. S is the conversion string. *) VAR TP, T, S: LIST; BEGIN (*1*) IF X = SIL THEN RETURN(SIL) END; FIRST2(X,T,S); (*2*) TP:=CONVERT(LIST2(T,SIL),DECREAD,S,ENV); TP:=VALOFTAG(TP); RETURN(TP); (*5*) END CONVdesc; PROCEDURE EVVAR(X: LIST; VAR ENV: LIST): LIST; (*Evaluate var statement. *) VAR XP, XPP, Y, T, TS, S, V, v, vd, Z, n, i, s: LIST; t: BOOLEAN; BEGIN (*1*) (*initialize*) Z:=SIL; FIRST2(X, XP, T); T:=EVALUATE(T,ENV); TS:=T; IF NOT SYMBOL(TS) THEN TS:=FIRST(TS) END; V:=SIL; XPP:=SIL; v:=LIST2(DEFAULT,T); v:=EVALUATE(v,ENV); (*2*) (*loop on variable list. *) WHILE XP <> SIL DO ADV(XP,Y,XP); IF NOT ATOM(Y) THEN IF SYMBOL(Y) THEN PUT(Y,TDEF,T); V:=COMP(v,V); XPP:=COMP(Y,XPP); ELSIF FIRST(Y) = ARY THEN Y:=SECOND(Y); FIRST2(Y,n,i); i:=EVLIS(i,ENV); s:=LIST2(n,i); s:=ARRAYDEC(s); WHILE s <> SIL DO ADV(s,Y,s); PUT(Y,TDEF,T); V:=COMP(v,V); XPP:=COMP(Y,XPP); END; ELSE UWRITE(T); ERROR(severe,"EVVAR: invalid as variable."); END; END; END; V:=INV(V); XPP:=INV(XPP); (*3*) (*put into environment as local(!!!) variables *) t:=EXTENDENV(XPP,V,ENV); RETURN(TS); (*4*) END EVVAR; PROCEDURE EVSORT(X: LIST; VAR ENV: LIST): LIST; (*Evaluate sort statement. *) VAR XP, Z, Y: LIST; BEGIN (*1*) (*initialize*) Z:=SIL; XP:=X; (*2*) (*loop on sort list. *) WHILE XP <> SIL DO ADV(XP,Y,XP); Y:=EVALUATE(Y,ENV); IF SYMBOL(Y) THEN PUT(Y,SORT,WT); (* note sort indicator *) ELSE UWRITE(Y); ERROR(severe,"EVSORT: invalid as sort name."); END; END; RETURN(SIL); (*4*) END EVSORT; PROCEDURE EVIMPRT(X, SP, EP: LIST; VAR ENV: LIST): LIST; (*Evaluate import statement. *) VAR P, F, FP, XP, Z, N, V, U, UP, D, S, ES: LIST; BEGIN (*0*) (*syntax check. *) IF X = SIL THEN RETURN(SIL) END; (*1*) (*get specification. *) ADV(X,N,S); ADV(N,N,P); Z:=SIL; P:=FIRST(P); P:=EVLIS(P,ENV); IF S <> SIL THEN S:=FIRST(S) END; IF NOT SYMBOL(N) THEN UWRITE(N); ERROR(severe,"EVIMPRT: invalid as name."); RETURN(SIL) END; D:=EVALUATE(N,ENV); IF SYMBOL(D) THEN D:=EVALUATE(D,EP) END; (*search in global env *) IF D = SIL THEN UWRITE(N); UWRITE(D); ERROR(severe,"EVIMPRT: unknown unit."); RETURN(SIL) END; IF FIRST(D) <> UNIT THEN UWRITE(N); UWRITE(D); ERROR(severe,"EVIMPRT: unknown unit."); RETURN(SIL) END; D:=RED2(D); FIRST2(D,F,D); (*unit name parm spec ... *) ES:=ENV; IF EXTENDENV(F,P,ES) THEN (* ok *) END; (*parms for spec, global *) (*2*) (*substitute renamings *) S:=CCONC(SP,S); IF S <> SIL THEN D:=SUBLIS(S,D) END; IF trace THEN SWRITE("SPEC: "); UWRITE(D) END; XP:=RED2(D); ADV(XP,FP,XP); (*spec name parm body *) (* assert F = FP *) (*3*) (*evaluate specification *) WHILE XP <> SIL DO ADV(XP,U,XP); IF NOT ATOM(U) THEN ADV(U,UP,V); IF UP = IMPRT THEN V:=EVIMPRT(V,S,EP,ES); Z:=CONC(CINV(V),Z); ELSIF UP = SORT THEN V:=EVSORT(V,ES); ELSIF UP = SIG THEN V:=EVSIG(V,ES); Z:=COMP(V,Z); ELSE UWRITE(UP); ERROR(severe,"EVIMPRT: unknown function."); END; ELSE UWRITE(U); ERROR(severe,"EVIMPRT: atom invalid as function."); END; END; Z:=INV(Z); RETURN(Z); (*6*) END EVIMPRT; PROCEDURE EVUNIT(X: LIST; VAR ENV: LIST): LIST; (*Evaluate and expose unit. *) VAR ZP, F, P, YP, EP, DS, D, XP, Z, Y, XPP, U, UP, V, g, DP, n, d, dp, l: LIST; BEGIN (*0*) (*syntax check. *) IF X = SIL THEN RETURN(SIL) END; (*1*) (*initialize*) ADV(X, ZP, XP); ADV(ZP,Z,XP); P:=FIRST(XP); (* (name actual-parms) *) P:=EVLIS(P,ENV); IF NOT SYMBOL(Z) THEN UWRITE(Z); ERROR(severe,"EVUNIT: invalid as unit name."); RETURN(Z); END; YP:=ASSOC(Z,ENV); IF YP = SIL THEN UWRITE(Z); ERROR(severe,"EVUNIT: no unit defined."); RETURN(Z); END; YP:=FIRST(YP); (*unit name formal-parms body *) IF FIRST(YP) <> UNIT THEN UWRITE(Z); ERROR(severe,"EVUNIT: no unit defined."); RETURN(Z); END; XP:=RED2(YP); ADV(XP,F,XP); (*formal-parms *) (*3*) (*specification *) ADV(XP,U,XP); IF ATOM(U) THEN UWRITE(U); ERROR(severe,"EVUNIT: atom invalid as specification."); RETURN(SIL) END; ADV(U,UP,V); IF UP <> SPEC THEN UWRITE(UP); ERROR(severe,"EVUNIT: no specification defined."); RETURN(SIL) END; EP:=SIL; (*new scope block *) IF EXTENDENV(F,P,EP) THEN (* ok *) END; (*parms for spec *) D:=LIST2(ZP,SIL); DP:=EVIMPRT(D,SIL,ENV,EP); (*own specification *) DS:=DP; COPYTOENV(DS,ENV,EP); (*4*) (*prepare for global visiblity, loop on procedure names *) g:=LIST3(SIL,SIL,SIL); WHILE DP <> SIL DO ADV(DP,n,DP); d:=ASSOC(n,EP); IF d = SIL THEN l:=GET(n,EXTYP); IF (l = SIL) OR (l = GENERIC) THEN d:=COMP2(GLAMBDA,n,g); dp:=d; PUT(n,EXTYP,GENERIC); END; ELSE dp:=FIRST(d) END; (* () <> SIL *) IF d <> SIL THEN SETV(n,dp,EP) END; (*to local env *) END; (*5*) (*loop on body *) WHILE XP <> SIL DO ADV(XP,U,XP); IF NOT ATOM(U) THEN ADV(U,UP,V); IF UP = MODEL THEN V:=EVMOD(V,ENV,EP) ELSIF UP = IMPL THEN V:=EVIMPL(V,ENV,EP) ELSIF UP = AXIOM THEN V:=EVAXIOM(V,ENV,EP) ELSE UWRITE(UP); ERROR(severe,"EVUNIT: unknown function."); END; ELSE UWRITE(U); ERROR(severe,"EVUNIT: atom invalid as function."); END; END; (*6*) (*copy to global env. *) COPYTOENV(DS,EP,ENV); RETURN(Z); (*7*) END EVUNIT; PROCEDURE EVMOD(X, EP: LIST; VAR ENV: LIST): LIST; (*Evaluate model statement. *) VAR D, XP, Z, Y, XPP, U, UP, V, g, DP, n, d, l: LIST; BEGIN (*0*) (*syntax check. *) IF X = SIL THEN RETURN(SIL) END; (*1*) (*initialize*) ADV(X, Z, XP); (*name parm body *) IF NOT SYMBOL(Z) THEN UWRITE(Z); ERROR(severe,"EVMOD: invalid as model name."); RETURN(Z); END; XP:=RED(XP); (*3*) (*loop on body *) WHILE XP <> SIL DO ADV(XP,U,XP); IF NOT ATOM(U) THEN ADV(U,UP,V); IF UP = IMPRT THEN V:=EVIMPRT(V,SIL,EP,ENV); COPYTOENV(V,EP,ENV); ELSIF UP = SORT THEN V:=EVSORT(V,ENV); ELSIF UP = MAP THEN V:=DEFMAP(V,ENV) ELSE UWRITE(UP); ERROR(severe,"EVMOD: unknown function."); END; ELSE UWRITE(U); ERROR(severe,"EVMOD: atom invalid as function."); END; END; RETURN(Z); (*6*) END EVMOD; PROCEDURE EVAXIOM(X, EP: LIST; VAR ENV: LIST): LIST; (*Evaluate axiom statement. *) VAR g, n, d, l, DP, D, XP, Z, Y, XPP, U, UP, V: LIST; BEGIN (*0*) (*syntax check. *) IF X = SIL THEN RETURN(SIL) END; (*1*) (*initialize*) ADV(X, Z, XP); (*name parms body *) IF NOT SYMBOL(Z) THEN UWRITE(Z); ERROR(severe,"EVMOD: invalid as axioms name."); RETURN(Z); END; XP:=RED(XP); (*3*) (*loop on body *) WHILE XP <> SIL DO ADV(XP,U,XP); IF NOT ATOM(U) THEN ADV(U,UP,V); IF UP = IMPRT THEN V:=EVIMPRT(V,SIL,EP,ENV); COPYTOENV(V,EP,ENV); ELSIF UP = SORT THEN V:=EVSORT(V,ENV); ELSIF UP = RULE THEN V:=DEFRULE(V,ENV) ELSE UWRITE(UP); ERROR(severe,"EVAXIOM: unknown function."); END; ELSE UWRITE(U); ERROR(severe,"EVAXIOM: atom invalid as function."); END; END; RETURN(Z); (*6*) END EVAXIOM; PROCEDURE EVIMPL(X, EP: LIST; VAR ENV: LIST): LIST; (*Evaluate implementation statement. *) VAR D, XP, Z, Y, XPP, U, UP, V, g, DP, n, d, l: LIST; BEGIN (*0*) (*syntax check. *) IF X = SIL THEN RETURN(SIL) END; (*1*) (*initialize*) ADV(X, Z, XP); (*name parm body. *) IF NOT SYMBOL(Z) THEN UWRITE(Z); ERROR(severe,"EVMOD: invalid as implementation name."); RETURN(Z); END; XP:=RED(XP); (*3*) (*loop on body *) WHILE XP <> SIL DO ADV(XP,U,XP); IF NOT ATOM(U) THEN ADV(U,UP,V); IF UP = IMPRT THEN V:=EVIMPRT(V,SIL,EP,ENV); COPYTOENV(V,EP,ENV); ELSIF UP = SORT THEN V:=EVSORT(V,ENV); ELSIF UP = VARS THEN V:=EVVAR(V,ENV) ELSIF UP = DE THEN V:=DEFPROC(V,ENV) ELSE V:=EVALUATE(U,ENV) END; ELSE UWRITE(U); ERROR(severe,"EVIMPL: atom invalid as function."); END; END; RETURN(Z); (*6*) END EVIMPL; PROCEDURE EVGEN(L, X: LIST; VAR ENV: LIST): LIST; (*Evaluate generic function. L=(N, M,I,E), where N is the name of the generic function, M is a association list of signatures and function names. I is a closure, E is a set of rewrite rules. X is a list of actual parameters. *) VAR V, T, A, Y, Z, W, C, XS, XP, EP, D, N, M, I, E, LH, RH, S: LIST; BEGIN (*1*) (*initialize*) Z:=SIL; FIRST4(L,N,M,I,E); (*2*) (*generic function defined ?. *) IF M <> SIL THEN IF trace THEN SWRITE("parms: "); UWRITE(X); END; A:=TYPEOF(X); FIRST3(A,V,T,D); IF trace THEN SWRITE("typeof: "); UWRITE(A); END; W:=ASSOCQ(T,M); IF trace THEN SWRITE("assoc: "); UWRITE(W); END; IF W <> SIL THEN W:=FIRST(W); (* (mod func, cond) *) IF trace THEN SWRITE("MAP: "); UWRITE(W); END; ADV(W,W,C); Z:=WT; IF C <> SIL THEN C:=FIRST(C); ADV(C,Y,XP); XP:=FIRST(XP); XS:=GENPL(XP,V,T,D); (*combine descriptors and values*) Z:=COMP(Y,XS); (*real condition. *) Z:=EVALUATE(Z,ENV); END; IF Z <> SIL THEN ADV(W,Y,XP); XP:=FIRST(XP); XS:=GENPL(XP,V,T,D); (*combine descriptors and values*) Z:=COMP(Y,XS); (*real expression. *) IF D <> SIL THEN D:=FIRST(D) END; Z:=GENTE(Z,Y,D); (*build new typed expression. *) Z:=LIST2(Z,ECENV(ENV)); RETURN(Z); END; END; END; (*3*) (*closure defined ? *) IF I <> SIL THEN FIRST2(I,XP,EP); Z:=COMP(XP,X); Z:=LIST2(Z,EP); RETURN(Z); END; (*4*) (*rewrite rule defined ? *) IF E <> SIL THEN Z:=COMP(N,X); WHILE E <> SIL DO ADV(E,XP,E); ADV2(XP,LH,RH,XP); S:=SIL; IF UNIFY(Z,LH,S) THEN T:=WT; IF trace THEN SWRITE("UNIFY: "); UWRITE(RH); END; IF XP <> SIL THEN XP:=FIRST(XP); XP:=SUBLIS(S,XP); T:=EVALUATE(XP,ENV); END; IF T <> SIL THEN Z:=SUBLIS(S,RH); Z:=LIST2(Z,ECENV(ENV)); RETURN(Z); END; END; END; END; (*8*) (* unbound generic procedure, return term *) Z:=COMP(N,X); Z:=LIST2(QUOTE,Z); Z:=LIST2(Z,ECENV(ENV)); RETURN(Z); (*9*) END EVGEN; PROCEDURE EVSIG(X: LIST; VAR ENV: LIST): LIST; (*Evaluate signature declaration. *) VAR XP, Y, S, T, YP: LIST; BEGIN (*1*) (*initialize. *) ADV2(X,Y,S,XP); T:=FIRST(XP); (*evaluate Y once ! *) YP:=ASSOC(Y,ENV); IF YP <> SIL THEN YP:=FIRST(YP) END; IF SYMBOL(YP) THEN Y:=YP END; IF NOT SYMBOL(Y) THEN UWRITE(Y); ERROR(severe,"EVSIG: invalid as function name."); RETURN(SIL) END; (*2*) (*evaluate source and target. *) IF SYMBOL(S) THEN S:=LIST1(S) END; S:=EVLIS(S,ENV); IF SYMBOL(T) THEN T:=LIST1(T) END; T:=EVLIS(T,ENV); XP:=LIST3(S,Y,T); (*3*) (*define arrow. *) PUT(Y,ARROW,XP); RETURN(Y); (*4*) END EVSIG; PROCEDURE EXTENDVARENV(A, O, X: LIST; VAR ENV: LIST): BOOLEAN; (*Extend var environement. A and O are lists of symbols. X is a list of values. The environment ENV is extented by the bindings of the symbols in A and O to the values in X. The values bound to elements of A are evaluated, the values bound to elements of O are not evaluated, If the binding is possible, then TRUE is returned else FALSE. *) VAR XP, AP, OP, Y, Z, B: LIST; BEGIN (*1*) (*initialize*) Z:=ENV; XP:=X; AP:=A; OP:=O; (*2*) (*loop on input lists. *) WHILE (AP <> SIL) AND (XP <> SIL) DO ADV(AP,B,AP); ADV(XP,Y,XP); Y:=EVALUATE(Y,ENV); Z:=COMP2(B,Y,Z) END; (*3*) (*loop on output lists. *) WHILE (OP <> SIL) AND (XP <> SIL) DO ADV(OP,B,OP); ADV(XP,Y,XP); Z:=COMP2(B,Y,Z) END; (*4*) (*argument number mismatch. *) IF (AP <> SIL) OR (OP <> SIL) OR (XP <> SIL) THEN UWRITE(AP); UWRITE(OP); UWRITE(XP); ERROR(severe,"EXTENDVARENV: argument number mismatch."); RETURN(FALSE) END; ENV:=Z; RETURN(TRUE); (*5*) END EXTENDVARENV; (*Special part for ALDES. *) PROCEDURE EVPROGA(X: LIST; VAR ENV: LIST): LIST; (*Evaluate aldes statement sequence. X is the reductum of a PROGA S-expression. *) VAR XP, Z, L: LIST; BEGIN (*1*) (*initialize*) Z:=SIL; XP:=X; (*2*) (*loop on list. *) LOOP goto:=SIL; Z:=EVPROGN(XP,ENV); IF goto = SIL THEN RETURN(Z) END; unwind:=FALSE; XP:=X; LOOP IF XP = SIL THEN EXIT END; ADV(XP,L,XP); IF NOT ATOM(L) THEN IF FIRST(L) = LBEL THEN IF SECOND(L) = goto THEN EXIT END; END; END; END; IF XP = SIL THEN SWRITE("Goto "); UWRITE(goto); BLINES(0); ERROR(severe,"Undefined step number."); EXIT END; END; RETURN(Z); (*4*) END EVPROGA; PROCEDURE DEFA(X: LIST; VAR ENV: LIST): LIST; (*Define array. *) VAR x, s, a, n, i, Y: LIST; BEGIN (*0*) (*syntax check. *) IF X = SIL THEN RETURN(SIL) END; a:=LIST1(ANY); (*1*) (*generate names and define names. *) WHILE X <> SIL DO ADV(X,x,X); FIRST2(x,n,i); i:=EVLIS(i,ENV); x:=LIST2(n,i); s:=ARRAYDEC(x); s:=COMP(s,a); Y:=EVVAR(s,ENV); END; RETURN(Y); (*4*) END DEFA; PROCEDURE SETaldesV(V, A: LIST; VAR ENV: LIST); (*Set ALDES variable. *) VAR EP, Z, t, n: LIST; BEGIN (*1*) (*See if defined*) IF NOT SYMBOL(V) THEN IF NOT ATOM(V) THEN IF FIRST(V) = ARY THEN FIRST2(SECOND(V),n,t); t:=EVLIS(t,ENV); t:=LIST2(n,t); V:=GENARRAY(t) END; END; 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 END; (*2*) SETV(V,A,ENV); (*3*) END SETaldesV; END MASSPEC. (* -EOF- *)