home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / glass / glass.lha / GLASS / contsens / contsens.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-08  |  57.0 KB  |  2,146 lines

  1.  
  2. /*   Copyright (C) 1990 Riet Oolman
  3.  
  4. This file is part of GLASS.
  5.  
  6. GLASS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GLASS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GLASS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* file: contsens.c
  21.    author: H. Oolman
  22.    last modified: 8-2-1991
  23.    purpose: procedures for context-sensitive checks on Glass
  24.    modifications: p2c translated, tmc access procs.
  25. */
  26.  
  27. #include "handleds.h"
  28. #include "check.ds.h"
  29. #include "check.var.h"
  30. #include "check.afuncs.h"
  31. #include "errorenv.h"
  32. #include "unification.h"
  33. #include "contsens.h"
  34.  
  35. Local typcrec *replacelocssome ();
  36.  
  37. typedef struct typcrec * adirindic ;
  38. /* to inidcate if a system application should be interpreted adirectionally
  39.    (if type APPSET) or unidirectionally (otherwise) */
  40.  
  41. #define makeadirwanted  BuildAPS()
  42. /* adirectional system application wanted */
  43. #define makedirwanted  BuildUNKNOWN(0L,false,false)
  44. /* unidirectional system application wanted */
  45. #define makewanted(t) replacelocssome(t,true)
  46. /* turn type into info on what kind of system appl. is wanted */
  47. /* These three make an adirindic */
  48.  
  49. Void splitwanted(ty, frst, scnd)
  50. /* split ty, which should be composed, in parts frst and scnd
  51.    to be used in subparts of a ':' expression */
  52. adirindic ty, *frst, *scnd;
  53. { while (ty->kind == kindINDIR) ty = ty->INDIR.tcind;
  54.   if (ty->kind == kindCT)
  55.   { *frst = ty->CT.tcfirst;
  56.     *scnd = ty->CT.tcrest;
  57.   }
  58.   else if (ty->kind == kindSOME)
  59.   { *frst = ty->SOME.tcpart;
  60.     *scnd = ty;
  61.   } else { *frst = makedirwanted;
  62.        *scnd = *frst;
  63.      }
  64. }
  65.  
  66. boolean adirwanted(ty)
  67. /* test if adirectional system application wanted */
  68. adirindic ty;
  69. { while (ty->kind == kindINDIR) ty = ty->INDIR.tcind;
  70.   return (ty->kind == kindAPS);
  71. }
  72.  
  73. Local typcrec *typeval PP((adirindic appnon, val vl, envrec *btns_,
  74.                   long splitlevel_));
  75.  
  76. Local Void WritesymbolNoext(f, nm)
  77. FILE *f;
  78. symbol nm;
  79. { /* Because it is not known beforehand if errors will occur,
  80.      all names are extended if uiq is true. But in printing
  81.      error messages it is nicer if they are not there.
  82.      This procedure prints a name nm without extension. */
  83.   long i, lth;
  84.  
  85.   lth = nm->length;
  86.   if (uniq) {
  87.     while (nm->body[lth - 1] != '_' && lth > 0)
  88.       lth--;
  89.     lth--;
  90.   }
  91.   for (i = 0; i < lth; i++)
  92.     putc(nm->body[i], f);
  93. }
  94.  
  95. Local Void unparsfp(f, fmp)
  96. FILE *f;
  97. fp fmp;
  98. { /* unparses fp's */
  99.   switch (fmp->tag) {
  100.  
  101.   case TAGFpComp:
  102.     putc('(', f);
  103.     unparsfp(f, fmp->FpComp.fpfirst);
  104.     fprintf(f, "): ");
  105.     unparsfp(f, fmp->FpComp.fprest);
  106.     break;
  107.  
  108.   case TAGFpEmpty:
  109.     fprintf(f, "[]");
  110.     break;
  111.  
  112.   case TAGFpList:
  113.     putc('[', f);
  114.     fmp = fmp->FpList.fplist;
  115.     while (fmp != NULL) {
  116.       unparsfp(f, fmp);
  117.       fmp = fmp->next;
  118.       if (fmp != NULL)
  119.      fprintf(f, ", ");
  120.     }
  121.     putc(']', f);
  122.     break;
  123.  
  124.   case TAGFpName:
  125.     WritesymbolNoext(f, fmp->FpName.fpsym);
  126.     break;
  127.  
  128.   case TAGFpInt:
  129.     fprint_inum(f, fmp->FpInt.fpi);
  130.     break;
  131.  
  132.   case TAGFpFlo:
  133.     fprint_fnum(f, fmp->FpFlo.fpf);
  134.     break;
  135.  
  136.   case TAGFpStr:
  137.     fprint_string(f, fmp->FpStr.fps);
  138.     break;
  139.  
  140.   case TAGFpBool:
  141.     if (fmp->FpBool.fpb)
  142.       fprintf(f, "TRUE");
  143.     else
  144.       fprintf(f, "FALSE");
  145.     break;
  146.   }
  147. }  /* unparsfp */
  148.  
  149. /* true <-> data struct. adaptations for the use of macro
  150.    expander the result of which is not handled by the type
  151.    checker */
  152.  
  153. Local Void unparsval(f, vl)
  154. FILE *f;
  155. val vl;
  156. { /* unparses (most) val's  */
  157.   long l;
  158.   string op;
  159.  
  160.   switch (vl->tag) {
  161.  
  162.   case TAGVValApply:
  163.     unparsval(f, vl->VValApply.avval);
  164.     fprintf(f, " (");
  165.     unparsval(f, vl->VValApply.avpar);
  166.     putc(')', f);
  167.     break;
  168.  
  169.   case TAGVSym:
  170.     WritesymbolNoext(f, vl->VSym.sym);
  171.     if (takewarning) {
  172.       fprintf(f, "/*");
  173.       myprint_orig(f,vl->VSym.symorig);
  174.       fprintf(f, "*/");
  175.     }
  176.     break;
  177.  
  178.   case TAGVInt:
  179.     fprint_inum(f,vl->VInt.i);
  180.     break;
  181.  
  182.   case TAGVFlo:
  183.     fprint_fnum(f,vl->VFlo.f);
  184.     break;
  185.  
  186.   case TAGVStr:
  187.     fprint_string(f,vl->VStr.s);
  188.     break;
  189.  
  190.   case TAGVBool:
  191.     if (vl->VBool.b)
  192.       fprintf(f, "TRUE");
  193.     else
  194.       fprintf(f, "FALSE");
  195.     break;
  196.  
  197.   case TAGVAtom:
  198.   case TAGVType:
  199.   case TAGVMacAlts:
  200.     error(10L, NULL, NULL, Buildsymbol( "unparsval", 9L), NULL, false);
  201.     break;
  202.  
  203.   case TAGVSysLambda:
  204.     putc('%', f);
  205.     unparsfp(f, vl->VSysLambda.slpar);
  206.     putc('.', f);
  207.     unparsval(f, vl->VSysLambda.slval);
  208.     break;
  209.  
  210.   case TAGVSysSigma:
  211.     putc('$', f);
  212.     unparsfp(f, vl->VSysSigma.sspar);
  213.     putc('.', f);
  214.     unparsval(f, vl->VSysSigma.ssval);
  215.     break;
  216.  
  217.   case TAGVSysApply:
  218.     unparsval(f, vl->VSysApply.asval);
  219.     fprintf(f, " (");
  220.     unparsval(f, vl->VSysApply.aspar);
  221.     putc(')', f);
  222.     break;
  223.  
  224.   case TAGVWhere:
  225.     unparsval(f, vl->VWhere.wval);
  226.     fprintf(f, " Where .... Endwhere");
  227.     break;
  228.  
  229.   case TAGVList:
  230.     putc('[', f);
  231.     vl = vl->VList.l;
  232.     while (vl != NULL) {
  233.       unparsval(f, vl);
  234.       vl = vl->next;
  235.       if (vl != NULL)
  236.      fprintf(f, ", ");
  237.     }
  238.     putc(']', f);
  239.     break;
  240.  
  241.   case TAGVAppset:
  242.     putc('{', f);
  243.     vl = vl->VAppset.aps;
  244.     while (vl != NULL) {
  245.       unparsval(f, vl);
  246.       vl = vl->next;
  247.       if (vl != NULL)
  248.      fprintf(f, ", ");
  249.     }
  250.     putc('}', f);
  251.     break;
  252.  
  253.   case TAGVSyn:
  254.     fprintf(f, "*[");
  255.     vl = vl->VSyn.synlist;
  256.     while (vl != NULL) {
  257.       unparsval(f, vl);
  258.       vl = vl->next;
  259.       if (vl != NULL)
  260.      fprintf(f, ", ");
  261.     }
  262.     putc(']', f);
  263.     break;
  264.  
  265.   case TAGVMacLambda:
  266.     if (vl->VMacLambda.mval == NULL)   /* !! used to pack fp */
  267.       unparsfp(f, vl->VMacLambda.mpar);
  268.     else {
  269.       fprintf(f, "\\(");
  270.       unparsfp(f, vl->VMacLambda.mpar);
  271.       fprintf(f, ").");
  272.       unparsval(f, vl->VMacLambda.mval);
  273.     }
  274.     break;
  275.  
  276.   case TAGVBuiltin:
  277.     op = vl->VBuiltin.oper;
  278.     if (cmp_string(op, "->")==0) {
  279.       unparsval(f, vl->VBuiltin.args);
  280.       fprintf(f, "->");
  281.       unparsval(f, vl->VBuiltin.args->next);
  282.       fprintf(f, "; ");
  283.       unparsval(f, vl->VBuiltin.args->next->next);
  284.     } else {
  285.       if (cmp_string(op,"[]")==0) {
  286.      unparsval(f, vl->VBuiltin.args);
  287.      fprintf(f, " (");
  288.      unparsval(f, vl->VBuiltin.args->next);
  289.      putc(')', f);
  290.       } else {
  291.      if (cmp_string(op, "[..]")==0) {
  292.        unparsval(f, vl->VBuiltin.args);
  293.        fprintf(f, " @(");
  294.        unparsval(f, vl->VBuiltin.args->next);
  295.        fprintf(f, ")...(");
  296.        unparsval(f, vl->VBuiltin.args->next->next);
  297.        putc(')', f);
  298.      } else {
  299.        if (cmp_string(op, "+1")==0) {
  300.          putc('+', f);
  301.          unparsval(f, vl->VBuiltin.args);
  302.        } else {
  303.          if (cmp_string(op, "-1")==0) {
  304.            putc('-', f);
  305.            unparsval(f, vl->VBuiltin.args);
  306.          } else {
  307.            if (cmp_string(op, "~")==0) {
  308.           putc('~', f);
  309.           unparsval(f, vl->VBuiltin.args);
  310.            } else {
  311.           if (cmp_string(op, "itof")==0) {
  312.             fprintf(f, "itof ");
  313.             unparsval(f, vl->VBuiltin.args);
  314.           } else {
  315.             if ((cmp_string(op, "^")==0) | (cmp_string(op,":")==0)) {
  316.               putc('(', f);
  317.               unparsval(f, vl->VBuiltin.args);
  318.               putc(')', f);
  319.               fprintf(f, op);
  320.               putc(' ', f);
  321.               unparsval(f, vl->VBuiltin.args->next);
  322.             } else {
  323.               if ((cmp_string(op,"=")==0) | (cmp_string(op,"/=")==0) |
  324.                  (cmp_string(op,"<")==0) | (cmp_string(op,"<=")==0) |
  325.                  (cmp_string(op,">=")==0) | (cmp_string(op,">")==0) |
  326.                  (cmp_string(op,"*")==0) | (cmp_string(op,"/")==0) |
  327.                  (cmp_string(op,"DIV")==0) | (cmp_string(op,"MOD")==0) |
  328.                  (cmp_string(op,"&")==0) | (cmp_string(op,"|")==0) |
  329.                  (cmp_string(op,"-2")==0) | (cmp_string(op,"+2")==0)) {
  330.                 unparsval(f, vl->VBuiltin.args);
  331.                 putc(' ', f);
  332.                 if (cmp_string(op,"-2")==0)
  333.                putc('-', f);
  334.                 else if (cmp_string(op, "+2")==0)
  335.                putc('+', f);
  336.                 else
  337.                fprintf(f, op);
  338.                 fprintf(f, " (");
  339.                 unparsval(f, vl->VBuiltin.args->next);
  340.                 putc(')', f);
  341.               } else
  342.         {l=0; while (op[l]!='\0') l++;
  343.                 error(10L, NULL, NULL, Buildsymbol(op,l), NULL, false);}
  344.             }
  345.           }
  346.            }
  347.          }
  348.        }
  349.      }
  350.       }
  351.     }
  352.     break;
  353.   }
  354. }  /* unparsval */
  355.  
  356. /* Local variables for convtype: */
  357. struct LOC_convtype {
  358.   envrec *btns;
  359.   orig typorig;
  360.   symbol loctyvars, boundnames;
  361. } ;
  362.  
  363. Local dirgraphrec *extractdirs(t)
  364. /* extract the directions in a systemtype. Easy for comparing */
  365. typ t;
  366. {
  367.  
  368.   switch (t->tag) {
  369.  
  370.   case TAGTypUni:
  371.     return BuildCd(BuildOd(BuildIN()),
  372.                BuildCd(BuildOd(BuildOUT()), BuildOd(BuildNON())));
  373.     break;
  374.  
  375.   case TAGTypNon:
  376.     return extractdirs(t->TypNon.nontyp);
  377.     break;
  378.  
  379.   case TAGTypProd:
  380.     if (t->TypProd.ptypes == NULL)
  381.       return BuildOd(BuildNON());
  382.     else {
  383.       return BuildCd(extractdirs(t->TypProd.ptypes),
  384.                  extractdirs(new_TypProd(t->TypProd.ptypes->next)));
  385.     }
  386.     break;
  387.  
  388.   case TAGTypAtom:
  389.     return BuildOd(BuildNON());
  390.     break;
  391.  
  392.   case TAGTypIn:
  393.     return BuildOd(BuildIN());
  394.     break;
  395.  
  396.   case TAGTypOut:
  397.     return BuildOd(BuildOUT());
  398.     break;
  399.  
  400.   case TAGTypPwr:
  401.     return BuildSd(extractdirs(t->TypPwr.pwrtyp),
  402.                      BuildOd(BuildNON()));
  403.     break;
  404.   case TAGTypStar:
  405.     return BuildSd(extractdirs(t->TypStar.startyp),
  406.                      BuildOd(BuildNON()));
  407.     break;
  408.  
  409.   case TAGTypLocal:
  410.     return extractdirs(t->TypLocal.loctyp);
  411.     break;
  412.  
  413.   case TAGTypSym:
  414.     return BuildOd(BuildNON());
  415.     break;
  416.  
  417.   case TAGTypAppset:
  418.   case TAGTypFun:
  419.   case TAGTypInt:
  420.   case TAGTypFlo:
  421.   case TAGTypBind:
  422.   case TAGTypBool:
  423.   case TAGTypString:
  424.     error(8L, NULL, NULL, NULL, NULL, false);
  425.     return BuildOd(BuildNON());
  426.     break;
  427.   }
  428. }
  429.  
  430. Local Void addnumnamestoenv(e)
  431.   /* adds names to curenv, with type INT, if not yet present;
  432.      otherwise redirects namepointer
  433.      e: expression in power type */
  434. val e;
  435. {
  436.   symbol nm;
  437.  
  438.   switch (e->tag) {
  439.  
  440.   case TAGVValApply:
  441.     addnumnamestoenv(e->VValApply.avpar);
  442.     addnumnamestoenv(e->VValApply.avval);
  443.     break;
  444.  
  445.   case TAGVSym:
  446.     nm = e->VSym.sym;
  447.     if (lookup(curenv, &nm) == NULL) {
  448.       error(21L, NULL, NULL, nm, NULL, true);
  449.       update(&curenv, nm, BuildINT());
  450.     } else
  451.       e->VSym.sym = nm;
  452.     break;
  453.  
  454.   case TAGVInt:
  455.   case TAGVFlo:
  456.   case TAGVStr:
  457.   case TAGVBool:   /* ready */
  458.     break;
  459.  
  460.   case TAGVList:
  461.     e = e->VList.l;
  462.     while (e != NULL) {
  463.       addnumnamestoenv(e);
  464.       e = e->next;
  465.     }
  466.     break;
  467.  
  468.   case TAGVBuiltin:
  469.     e = e->VBuiltin.args;
  470.     while (e != NULL) {
  471.       addnumnamestoenv(e);
  472.       e = e->next;
  473.     }
  474.     break;
  475.  
  476.   case TAGVType:
  477.   case TAGVSysLambda:
  478.   case TAGVSysSigma:
  479.   case TAGVSysApply:
  480.   case TAGVMacAlts:
  481.   case TAGVMacLambda:
  482.   case TAGVWhere:
  483.   case TAGVAppset:
  484.   case TAGVAtom:
  485.   case TAGVSyn:
  486.     error(20L, NULL, NULL, NULL, NULL, false);
  487.     break;
  488.   }
  489. }  /* addnumnamestoenv */
  490.  
  491. Local typcrec *conv(glty, mustconn, LINK)
  492.   /* make tc form for glty: names replaced by   
  493.      loc.ty.var/basetype/typename,
  494.      extract directions, listtypes to some, Prodtype to
  495.      comp.type; also some simple checks
  496.      mustconn: glty must be a connection type
  497.      check if no -:n names occur more than once in glty, and if
  498.      the expression in a power type give integers; make the int.
  499.      names unique if uniq */
  500. typ glty;
  501. boolean mustconn;
  502. struct LOC_convtype *LINK;
  503. { /* ass.: restrictions on type (except for names) checked by parser */
  504.   symbol n;
  505.   typcrec *tc, *Result;
  506.   envrec *cur;
  507.  
  508.   switch (glty->tag) {
  509.  
  510.   case TAGTypAtom:
  511.     Result = BuildBASETY(Copysymbol(glty->TypAtom.atomnm),     
  512.                          newname(),
  513.                          LINK->typorig);
  514.     /* make glty^.atomnm point to btns: */
  515.     n = glty->TypAtom.atomnm;
  516.     tc = lookup(LINK->btns, &n);
  517.     glty->TypAtom.atomnm = n;
  518.     return Result;
  519.     break;
  520.  
  521.   case TAGTypFun:
  522.     if (glty->TypFun.funpar->tag == TAGTypBind) {
  523.       n = glty->TypFun.funpar->TypBind.boundname;
  524.       addunequal(n, &LINK->boundnames);
  525.       update(&curenv, n, BuildINT());
  526.       cur = curenv;
  527.       tc = conv(glty->TypFun.funres, false, LINK);
  528.       /* unbound names from $e$ in $t^e$ types found in
  529.      funres are added to curenv */
  530.       if (adaptds && uniq)
  531.       addext(cur->name0, cur->uniqext);
  532.       cur->name0 = marker;
  533.        /* turn into marker: invisible */
  534.       return BuildSINGLEARROW(BuildINT(), tc);
  535.     } else
  536.       return BuildSINGLEARROW(
  537.                     conv(glty->TypFun.funpar, false, LINK),
  538.                     conv(glty->TypFun.funres, false, LINK));
  539.     break;
  540.  
  541.   case TAGTypIn:
  542.     return conv(glty->TypIn.ityp, true, LINK);
  543.     break;
  544.  
  545.   case TAGTypOut:
  546.     return conv(glty->TypOut.otyp, true, LINK);
  547.     break;
  548.  
  549.   case TAGTypUni:
  550.     return BuildSYSTY(extractdirs(glty),
  551.      BuildCT(conv(glty->TypUni.uityp, true, LINK),
  552.           BuildCT(conv(glty->TypUni.uotyp, true, LINK),
  553.                BuildSOME(BuildUNKNOWN(newname(), false, true),
  554.                       newname()))));
  555.     break;
  556.  
  557.   case TAGTypNon:
  558.     return BuildSYSTY(extractdirs(glty),
  559.                        conv(glty->TypNon.nontyp, true, LINK));
  560.     break;
  561.  
  562.   case TAGTypInt:
  563.     return BuildINT();
  564.     break;
  565.  
  566.   case TAGTypBind:
  567.     return BuildINT();
  568.     break;
  569.  
  570.   case TAGTypFlo:
  571.     return BuildFLOAT();
  572.     break;
  573.  
  574.   case TAGTypString:
  575.     return BuildSTRING();
  576.     break;
  577.  
  578.   case TAGTypBool:
  579.     return BuildBOOL();
  580.     break;
  581.  
  582.   case TAGTypAppset:
  583.     return BuildAPS();
  584.     break;
  585.  
  586.   case TAGTypPwr:
  587.     addnumnamestoenv(glty->TypPwr.pwrval);
  588.     compat(BuildINT(),
  589.            typeval(makedirwanted, glty->TypPwr.pwrval, NULL, 0L),
  590.            glty->TypPwr.pwrval);
  591.     return BuildSOME(conv(glty->TypPwr.pwrtyp, mustconn, LINK),
  592.                        newname());
  593.     break;
  594.  
  595.   case TAGTypProd:
  596.     if (glty->TypProd.ptypes == NULL) {
  597.       return BuildSOME(BuildUNKNOWN(newname(), false,
  598.                          mustconn), newname());
  599.       /* !! mog. foute invulling voor UNKNOWN false false */
  600.     } else {
  601.       return BuildCT
  602.                 (conv(glty->TypProd.ptypes, mustconn, LINK),
  603.                  conv(new_TypProd(glty->TypProd.ptypes->next),
  604.                       mustconn, LINK));
  605.     }
  606.     break;
  607.  
  608.   case TAGTypStar:
  609.     return BuildSOME
  610.                (conv(glty->TypStar.startyp, mustconn,  LINK),
  611.                 newname());
  612.     break;
  613.  
  614.   case TAGTypSym:
  615.     n = glty->TypSym.sym;
  616.     tc = lookup(LINK->btns, &n);
  617.     if (tc == NULL) 
  618.     { error(1L, NULL, NULL, n, NULL, false);
  619.       return BuildUNKNOWN(newname(), false, false);
  620.     } else 
  621.     { glty->TypSym.sym = n; return tc;}
  622.     break;
  623.   }
  624. }  /* conv */
  625.  
  626. Local nminstrec *convlocs(lnames)
  627.   /* lnames does not contain double names; in result all get inst. nr. 0 */
  628. symbol lnames;
  629. {
  630.   nminstrec *nmi;
  631.  
  632.   if (lnames == NULL) return NULL;
  633.   else {
  634.     nmi = Buildnminstptr(lnames, 0L);
  635.     nmi->next = convlocs(lnames->next);
  636.     return nmi;
  637.   }
  638. }  /* convlocs */
  639.  
  640. Local typcrec *convtype(glty, btns_, typorig_)
  641.   /* glty: glass type to be converted to tc form (and checked for
  642.            grammatical correctness)
  643.      btns_: BT/TN names plus types in glty
  644.      typorig_: orig, if glty is the typas of a DefTyp */
  645. typ glty;
  646. envrec *btns_;
  647. orig typorig_;
  648.   struct LOC_convtype V;
  649.   typcrec *Result;
  650.   symbol l1, l2, l2o;
  651.   envrec *oce;
  652.  
  653.   V.typorig = typorig_;
  654.   if (glty->tag == TAGTypLocal) {
  655.     V.loctyvars = glty->TypLocal.locsyms;
  656.     glty = glty->TypLocal.loctyp;
  657.   } else
  658.     V.loctyvars = NULL;
  659.   l1 = NULL;
  660.   l2 = V.loctyvars;
  661.   mark_(&btns_);
  662.   while (l2 != NULL) {/* remove double names from loctyvars */
  663.     if (!isin(l2, l1)) {
  664.       l2o = l2;
  665.       addcopy(l2, &l1);
  666.       update(&btns_,l2,BuildLOC(l2,0L));
  667.     } else
  668.       l2o->next = l2->next;
  669.     l2 = l2->next;
  670.   }
  671.   V.btns = btns_;
  672.   oce = curenv;
  673.   curenv = NULL;
  674.   mark_(&curenv);   /* for the -: n names */
  675.   V.boundnames = NULL;   /* the -:n names */
  676.   Result = BuildALL(convlocs(V.loctyvars), 
  677.                     conv(glty, false, &V));
  678.   while (curenv != NULL)
  679.     release_(&curenv, adaptds && uniq);
  680.   /* make -:n names and those in power types unique
  681.      while loop because of names made invisible by turning into marker */
  682.   curenv = oce;
  683.   release_(&btns_,adaptds && uniq); /* make loc. ty.vars. unique */
  684.   return Result;
  685. }  /* convtype */
  686.  
  687. Local envrec *extendbtns(elts, btns)
  688.   /* btns: environment of BASETYPE/TYPE names plus tc-form of
  689.            defining types;
  690.      elts: list of defs, the BASETYPEs/TYPEs from which are to
  691.            extend btns for forming the result;
  692.      in the tc types in this btns env. names for BT/TY have been
  693.      replaced by redirections to the defining types */
  694. def elts;
  695. envrec *btns;
  696. {
  697.   def hel;
  698.   symbol n, ens;
  699.   typcrec *ut, *t;
  700.   orig oo;
  701.  
  702.   hel = elts;
  703.   ens = NULL;
  704.   while (hel != NULL) {
  705.     if (hel->tag == TAGDefVal) {
  706.       addcopy(hel->DefVal.defval, &nestednames);
  707.       oo = nestednorig;
  708.       nestednorig = hel->DefVal.valorig;
  709.       addunequal(hel->DefVal.defval, &ens);
  710.       nestednames = nestednames->next;
  711.       nestednorig = oo;
  712.     } else {
  713.       if (hel->tag == TAGDefTyp) {
  714.      addcopy(hel->DefTyp.deftyp, &nestednames);
  715.      oo = nestednorig;
  716.      nestednorig = hel->DefTyp.typorig;
  717.      addunequal(hel->DefTyp.deftyp, &ens);
  718.      update(&btns, hel->DefTyp.deftyp,
  719.             BuildUNKNOWN(newname(), false, false));
  720.      /* fist put all in btns with unknown type */
  721.      nestednames = nestednames->next;
  722.      nestednorig = oo;
  723.       }
  724.     }
  725.     hel = hel->next;
  726.   }
  727.   hel = elts;
  728.   while (hel != NULL) {
  729.     if (hel->tag == TAGDefTyp) {
  730.       addcopy(hel->DefTyp.deftyp, &nestednames);
  731.       oo = nestednorig;
  732.       nestednorig = hel->DefTyp.typorig;
  733.       t = convtype(hel->DefTyp.typas, btns, hel->DefTyp.typorig);
  734.       n = hel->DefTyp.deftyp;
  735.       ut = lookup(btns, &n);
  736.       hel->DefTyp.deftyp = n;   /* for unique names */
  737.       if (occurs(ut->UNKNOWN.unknm, t))
  738.      error(0L, NULL, NULL, n, NULL, false);
  739.       else
  740.      becomes(ut, t);
  741.       /* replace the unknown type by indir. to the found one */
  742.       nestednames = nestednames->next;
  743.       nestednorig = oo;
  744.     }
  745.     hel = hel->next;
  746.   }
  747.   return btns;
  748. }  /* extendbtns */
  749.  
  750. Local nminstrec *wrl(lns, nr)
  751. nminstrec *lns;
  752. long nr;
  753. {
  754.   /* make a copy of the list lns, with nr as inst. nr. */
  755.   nminstrec *hn;
  756.  
  757.   if (lns == NULL)
  758.     return NULL;
  759.   else {
  760.     hn = Buildnminstptr(lns->nm, nr);
  761.     hn->next = wrl(lns->next, nr);
  762.     return hn;
  763.   }
  764. }  /* wrl */
  765.  
  766. Local Void wro(ty, inst, tyo, locnrd)
  767. typcrec *ty;
  768. long inst;
  769. typcrec **tyo;
  770. nminstrec **locnrd;
  771. {
  772.   /* ty can contain nested 'ALL's (because of typenamings)
  773.      tyo is ty with the ALLs removed (after supplying LOCs with
  774.      an instance nr.)
  775.      locnrd are the names from the ALLs in ty (with inst. nr.)
  776.      inst is the instance nr. for LOCs which are not within an
  777.      ALL (those get a different inst. nr.)
  778.   */
  779.   long nn;
  780.   typcrec *t1, *t2;
  781.   nminstrec *ln1, *ln2;
  782.  
  783.   *locnrd = NULL;
  784.   while (ty->kind == kindINDIR) ty = ty->INDIR.tcind;
  785.   switch (ty->kind) {
  786.  
  787.   case kindALL:
  788.     nn = newname();   /* inst. nr. for LOCs in ALL's scope */
  789.     wro(ty->ALL.tcall, nn, tyo, locnrd);
  790.     Appendnminstptr(wrl(ty->ALL.locs, nn), *locnrd, locnrd);
  791.     break;
  792.  
  793.   case kindLOC:
  794.     *tyo = BuildLOC(ty->LOC.locname, inst);
  795.     break;
  796.  
  797.   case kindSINGLEARROW:
  798.     wro(ty->SINGLEARROW.tcarg, inst, &t1, &ln1);
  799.     wro(ty->SINGLEARROW.tcres, inst, &t2, &ln2);
  800.     Appendnminstptr(ln2, ln1, locnrd);
  801.     *tyo = BuildSINGLEARROW(t1, t2);
  802.     break;
  803.  
  804.   case kindAPS:
  805.   case kindINT:
  806.   case kindBOOL:
  807.   case kindSTRING:
  808.   case kindFLOAT:
  809.   case kindBASETY:
  810.     *tyo = ty;
  811.     break;
  812.  
  813.   case kindSYSTY:
  814.     wro(ty->SYSTY.syscomp, inst, &t1, locnrd);
  815.     *tyo = BuildSYSTY(ty->SYSTY.sysdirs, t1);
  816.     break;
  817.  
  818.   case kindEMPTYT:
  819.     *tyo = ty;
  820.     break;
  821.  
  822.   case kindCT:
  823.     wro(ty->CT.tcfirst, inst, &t1, &ln1);
  824.     wro(ty->CT.tcrest, inst, &t2, &ln2);
  825.     *tyo = BuildCT(t1, t2);
  826.     Appendnminstptr(ln2, ln1, locnrd);
  827.     break;
  828.  
  829.   case kindUNKNOWN:
  830.     *tyo = BuildUNKNOWN(newname(), ty->UNKNOWN.mustendemp,
  831.                         ty->UNKNOWN.mustconn);
  832.     break;
  833.  
  834.   case kindSOME:
  835.     wro(ty->SOME.tcpart, inst, &t1, locnrd);
  836.     *tyo = BuildSOME(t1, newname());
  837.     break;
  838.  
  839.   }
  840. }  /* wro */
  841.  
  842. Local Void satistyp(t, mustconn, mustendemp)
  843. typcrec *t;
  844. boolean mustconn, mustendemp;
  845. {
  846.   /* checks that after replacing names by named type/ loctyvar/
  847.      basetype the result t is syntactically correct */
  848.   if ((((1L << ((long)t->kind)) & 
  849.      ((1L << ((long)kindAPS)) | (1L << ((long)kindSINGLEARROW)) |
  850.      (1L << ((long)kindSYSTY)) | (1L << ((long)kindINT)) |
  851.      (1L << ((long)kindFLOAT)) | (1L << ((long)kindSTRING)) |
  852.      (1L << ((long)kindBOOL)))) != 0 &&
  853.        (mustconn || mustendemp)) ||
  854.       (((1L << ((long)t->kind)) & ((1L << ((long)kindLOC)) | 
  855.         (1L << ((long)kindBASETY)))) !=0 && mustendemp)) {
  856.     /* << used for test if t->kind in a set */
  857.     error(18L, NULL, NULL, NULL, NULL, false);
  858.     t->kind = kindUNKNOWN;
  859.     t->UNKNOWN.unknm = newname();
  860.     t->UNKNOWN.mustendemp = false;
  861.     t->UNKNOWN.mustconn = false;
  862.   }
  863.   while (t->kind == kindINDIR) t = t->INDIR.tcind;
  864.   switch (t->kind) {
  865.  
  866.   case kindSINGLEARROW:
  867.     satistyp(t->SINGLEARROW.tcarg, false, false);
  868.     satistyp(t->SINGLEARROW.tcres, false, false);
  869.     break;
  870.  
  871.   case kindINT:
  872.   case kindFLOAT:
  873.   case kindSTRING:
  874.   case kindBOOL:
  875.   case kindAPS:
  876.   case kindUNKNOWN:
  877.   case kindEMPTYT:
  878.   case kindBASETY:
  879.   case kindLOC:   /* ready */
  880.     break;
  881.  
  882.   case kindSYSTY:
  883.     satistyp(t->SYSTY.syscomp, true, false);
  884.     break;
  885.  
  886.   /* it is not possible that there are nested directions */
  887.   case kindCT:
  888.     satistyp(t->CT.tcfirst, mustconn, false);
  889.     satistyp(t->CT.tcrest, mustconn, true);
  890.     break;
  891.  
  892.   case kindALL:
  893.     error(10L, NULL, NULL, Buildsymbol("satistyp",8L), NULL, false);
  894.     break;
  895.  
  896.   case kindSOME:
  897.     satistyp(t->SOME.tcpart, mustconn, false);
  898.     break;
  899.  
  900.   }
  901. }  /* satistyp */
  902.  
  903. Local typcrec *writeout(ty)
  904. typcrec *ty;
  905. {
  906.   /* move the 'ALL' constructors in ty outward, of course after
  907.     supplying names with an unique instance number, to get the
  908.     result */
  909.   typcrec *tyo;
  910.   nminstrec *locnrd;
  911.  
  912.   wro(ty, 0L, &tyo, &locnrd);
  913.   /* 0 is dummy, because ty has an 'ALL' on the outside */
  914.   satistyp(tyo, false, false);
  915.   return (BuildALL(locnrd, tyo));
  916. }  /* writeout */
  917.  
  918. Local Void TypSymtoTypAtom(t, locs, btns)
  919. typ t;
  920. symbol locs;
  921. envrec *btns;
  922. {
  923.   /* the occurrences in t of 'TypSym n' with n bound by 
  924.      'BASETYPE n' are replaced by 'TypAtom n'. This for the
  925.      benefit of tha macro-expander (it needs not find out
  926.      bindings in types now)
  927.      locs: local type variables
  928.      btns: BASETYPE's, TYPEnamings in scope */
  929.   symbol nm;
  930.   typcrec *tc;
  931.   typ nxt;
  932.  
  933.   switch (t->tag) {
  934.  
  935.   case TAGTypSym:
  936.     nm = t->TypSym.sym;
  937.     if (!isin(nm, locs)) {
  938.       tc = lookup(btns, &nm);
  939.       if (tc != NULL) {
  940.      nxt = t->next;
  941.      if (tc->kind != kindINDIR) {
  942.        /* tc is an indir., because of the way extendbtns works */
  943.        error(10L, NULL, NULL, Buildsymbol( "TypSymtoTypAtom1",16L),NULL,false);
  944.      } else {
  945.        if (tc->INDIR.tcind->kind != kindALL)   /* added by convtype */
  946.          error(10L, NULL, NULL, Buildsymbol("TypSymtoTypAtom2",16L),NULL,false);
  947.        else {
  948.          if (tc->INDIR.tcind->ALL.tcall->kind == kindBASETY) {
  949.            t->tag = TAGTypAtom;
  950.            t->TypAtom.atomnm = nm;
  951.            t->next = nxt;
  952.          }
  953.        }
  954.      }
  955.       }
  956.     }
  957.     break;
  958.  
  959.   case TAGTypLocal:
  960.     TypSymtoTypAtom(t->TypLocal.loctyp, t->TypLocal.locsyms,
  961.                     btns);
  962.     break;
  963.  
  964.   case TAGTypFun:
  965.     TypSymtoTypAtom(t->TypFun.funpar, locs, btns);
  966.     TypSymtoTypAtom(t->TypFun.funres, locs, btns);
  967.     break;
  968.  
  969.   case TAGTypIn:
  970.     TypSymtoTypAtom(t->TypIn.ityp, locs, btns);
  971.     break;
  972.  
  973.   case TAGTypOut:
  974.     TypSymtoTypAtom(t->TypOut.otyp, locs, btns);
  975.     break;
  976.  
  977.   case TAGTypUni:
  978.     TypSymtoTypAtom(t->TypUni.uityp, locs, btns);
  979.     TypSymtoTypAtom(t->TypUni.uotyp, locs, btns);
  980.     break;
  981.  
  982.   case TAGTypNon:
  983.     TypSymtoTypAtom(t->TypNon.nontyp, locs, btns);
  984.     break;
  985.  
  986.   case TAGTypPwr:
  987.     TypSymtoTypAtom(t->TypPwr.pwrtyp, locs, btns);
  988.     break;
  989.  
  990.   case TAGTypProd:
  991.     t = t->TypProd.ptypes;
  992.     while (t != NULL) {
  993.       TypSymtoTypAtom(t, locs, btns);
  994.       t = t->next;
  995.     }
  996.     break;
  997.  
  998.   case TAGTypStar:
  999.     TypSymtoTypAtom(t->TypStar.startyp, locs, btns);
  1000.     break;
  1001.  
  1002.   case TAGTypAtom:
  1003.   case TAGTypInt:
  1004.   case TAGTypBind:
  1005.   case TAGTypFlo:
  1006.   case TAGTypString:
  1007.   case TAGTypBool:
  1008.   case TAGTypAppset:   /* ready */
  1009.     break;
  1010.   }
  1011. }  /* TypSymtoTypAtom */
  1012.  
  1013. Local Void extendenvloc(elts, btns)
  1014. def elts;
  1015. envrec *btns;
  1016. { /* put types of ATOMs, DEFs and MACROs in curenv, given btns
  1017.      for names in the declared types */
  1018.   /* ! btns': envptr; btnslist: envlistptr */
  1019.   def hel;
  1020.   orig oo;
  1021.  
  1022.   hel = elts;
  1023.   /* ! btnslist:=nil */
  1024.   while (hel != NULL) {
  1025.     if (hel->tag == TAGDefVal) 
  1026.     { addcopy(hel->DefVal.defval, &nestednames);
  1027.       oo = nestednorig;
  1028.       nestednorig = hel->DefVal.valorig;   /* !' */
  1029.       /* ! if hel^.valas^.vtval^.tag=TAGVAtom then btns':=btns
  1030.            else begin btns' := extendbtns(..wat bij
  1031.            macro?..,btns); appendbtns(btns',btnslist) end
  1032.       */
  1033.       /* assumption: hel^.valas^.tag=TAGVType */
  1034.       update(&curenv, hel->DefVal.defval,
  1035.              writeout(convtype(hel->DefVal.valas->VType.vttyp,
  1036.                                btns, NULL)));
  1037.       if (adaptds)
  1038.      TypSymtoTypAtom(hel->DefVal.valas->VType.vttyp, NULL, btns);
  1039.       nestednorig = oo;
  1040.       nestednames = nestednames->next;
  1041.       if (hel->DefVal.valas->VType.vtval->tag == TAGVAtom)
  1042.      hel->DefVal.valas->VType.vtval->VAtom.atomnm 
  1043.                   = hel->DefVal.defval;
  1044.       /* make it point to the same, for making unique */
  1045.     } else 
  1046.     { if (hel->tag == TAGDefTyp && adaptds)
  1047.      TypSymtoTypAtom(hel->DefTyp.typas, NULL, btns);
  1048.     }
  1049.     hel = hel->next;
  1050.   }
  1051. }  /* extendenvloc */
  1052.  
  1053. typedef struct unkrec {
  1054.   struct unkrec *next;
  1055.   typcrec *unk;
  1056. } unkrec;
  1057.  
  1058. /* Local variables for replacelocssome: */
  1059. struct LOC_replacelocssome {
  1060.   boolean justcopy;
  1061.   nminstrec *alllocnames;
  1062.   unkrec *freshlocnames;
  1063. } ;
  1064.  
  1065. Local typcrec *freshcopy(t, LINK)
  1066. typcrec *t;
  1067. struct LOC_replacelocssome *LINK;
  1068. { /* replace each LOCname by a fresh name */
  1069.   nminstrec *hs;
  1070.   unkrec *hn;
  1071.  
  1072.   while (t->kind == kindINDIR) t = t->INDIR.tcind;
  1073.   switch (t->kind) {
  1074.  
  1075.   case kindLOC:
  1076.     if (!LINK->justcopy) {
  1077.       hs = LINK->alllocnames;
  1078.       hn = LINK->freshlocnames;
  1079.       while (!(Equalsymbol(hs->nm, t->LOC.locname) &&
  1080.             hs->inst == t->LOC.inst)) {
  1081.      hs = hs->next;
  1082.      hn = hn->next;
  1083.      if (hs==NULL)
  1084.      { error(10L, NULL, NULL, Buildsymbol( "freshcopy", 9L), NULL, false);
  1085.        return t;
  1086.        break; }
  1087.       }
  1088.       if (hn!=NULL) return hn->unk; 
  1089.     } else
  1090.       return t;
  1091.     break;
  1092.  
  1093.   case kindSINGLEARROW:
  1094.     return BuildSINGLEARROW(freshcopy(t->SINGLEARROW.tcarg, LINK),
  1095.                      freshcopy(t->SINGLEARROW.tcres, LINK));
  1096.     break;
  1097.  
  1098.   case kindSYSTY:
  1099.     return BuildSYSTY(t->SYSTY.sysdirs, 
  1100.                         freshcopy(t->SYSTY.syscomp, LINK));
  1101.     break;
  1102.  
  1103.   case kindCT:
  1104.     return BuildCT(freshcopy(t->CT.tcfirst, LINK),
  1105.                freshcopy(t->CT.tcrest, LINK));
  1106.     break;
  1107.  
  1108.   case kindUNKNOWN:
  1109.     if (LINK->justcopy)
  1110.       return BuildUNKNOWN(t->UNKNOWN.unknm, t->UNKNOWN.mustendemp,
  1111.                    t->UNKNOWN.mustconn);
  1112.     else
  1113.       return BuildUNKNOWN(newname(), t->UNKNOWN.mustendemp,
  1114.                    t->UNKNOWN.mustconn);
  1115.     break;
  1116.  
  1117.   case kindINT:
  1118.   case kindFLOAT:
  1119.   case kindBOOL:
  1120.   case kindSTRING:
  1121.   case kindEMPTYT:
  1122.   case kindBASETY:
  1123.   case kindAPS:
  1124.     return t;
  1125.     break;
  1126.  
  1127.   case kindSOME:
  1128.     if (LINK->justcopy)
  1129.       return BuildSOME(freshcopy(t->SOME.tcpart, LINK),
  1130.                                    t->SOME.somnr);
  1131.     else
  1132.       return BuildSOME(freshcopy(t->SOME.tcpart, LINK), 
  1133.                          newname());
  1134.     break;
  1135.  
  1136.   case kindALL:   /* should not occur here */
  1137.     error(10L, NULL, NULL, Buildsymbol( "freshcopy", 9L), NULL, false);
  1138.     return t;
  1139.     break;
  1140.   }
  1141. }  /* freshcopy */
  1142.  
  1143. /* Local typcrec *replacelocssome PP((typcrec *t, boolean justcopy_)) */
  1144. Local typcrec *replacelocssome(t, justcopy_) 
  1145. typcrec *t;
  1146. boolean justcopy_;
  1147. {
  1148.   /* if justcopy_, make a fresh copy of t; otherwise
  1149.      if t is a ALL type then replace all LOC names , UNKNOWN and 
  1150.      SOME numbers by fresh ones, since at each use a new value
  1151.      may be used for them */
  1152.   struct LOC_replacelocssome V;
  1153.   unkrec *hup;
  1154.  
  1155.   V.justcopy = justcopy_;
  1156.   while (t->kind == kindINDIR) t = t->INDIR.tcind;
  1157.   if (t->kind == kindALL)   /* generate new names */
  1158.   { V.alllocnames = t->ALL.locs;
  1159.     V.freshlocnames = NULL;
  1160.     while (V.alllocnames != NULL) 
  1161.     { hup = (unkrec *)malloc(sizeof(unkrec));
  1162.       hup->unk = BuildUNKNOWN(newname(), false, true);
  1163.       hup->next = V.freshlocnames;
  1164.       V.freshlocnames = hup;
  1165.       V.alllocnames = V.alllocnames->next;
  1166.     }
  1167.     V.alllocnames = t->ALL.locs;
  1168.     return (freshcopy(t->ALL.tcall, &V));
  1169.   } else {
  1170.     if (V.justcopy)
  1171.       return (freshcopy(t, &V));
  1172.     else
  1173.       return t;
  1174.   }
  1175. }  /* replacelocssome */
  1176.  
  1177. #define forcefptoval(f) new_VMacLambda(f,NULL)
  1178. /* forcefptoval(f) new_VMacLambda(f,NULL):
  1179.      forces an fp to look like a val by putting a TAGVMacLambda
  1180.      with empty mval field around it */
  1181.  
  1182. Local typcrec *typefp(iscon, fmp)
  1183. boolean iscon;
  1184. fp fmp;
  1185. { /* gives type of fp; adds types for names to curenv; type for
  1186.      name not overwritten if iscon (is formal connection) */
  1187.   typcrec *t1, *t2;
  1188.   symbol hn;
  1189.   boolean rb;
  1190.  
  1191.   switch (fmp->tag) {
  1192.  
  1193.   case TAGFpComp:
  1194.     t1 = typefp(iscon, fmp->FpComp.fprest);
  1195.     rb = restrictable(true, false, t1, forcefptoval(fmp->FpComp.fprest));
  1196.     /* must end in empty */
  1197.     return BuildCT(typefp(iscon, fmp->FpComp.fpfirst), t1);
  1198.     break;
  1199.  
  1200.   case TAGFpEmpty:
  1201.     return BuildSOME(BuildUNKNOWN(newname(), false, iscon),
  1202.                        newname());
  1203.     break;
  1204.  
  1205.   /* !! mog. foute inv. als iscon false */
  1206.   case TAGFpList:
  1207.     if (fmp->FpList.fplist == NULL) {
  1208.       return BuildSOME(BuildUNKNOWN(newname(), false, iscon),
  1209.                          newname());
  1210.       /* !! mog. foute inv. als iscon false */
  1211.     } else {      
  1212.       t1 = typefp(iscon, fmp->FpList.fplist);
  1213.       t2 = typefp(iscon, new_FpList(fmp->FpList.fplist->next));
  1214.       /* t1, t2 used so that name extension numbers are independent of the
  1215.      order in which the C implementation evaluates function arguments */
  1216.       return BuildCT(t1, t2);
  1217.     }
  1218.     break;
  1219.  
  1220.   case TAGFpName:
  1221.     if (iscon) {
  1222.       hn = fmp->FpName.fpsym;
  1223.       t1 = lookup(curenv, &hn);
  1224.       if (t1 == NULL) {
  1225.      t1 = BuildUNKNOWN(newname(), false, true);
  1226.      update(&curenv, hn, t1);
  1227.      return t1;
  1228.       } else {
  1229.      fmp->FpName.fpsym = hn;
  1230.      return t1;
  1231.       }
  1232.     } else {
  1233.       t1 = BuildUNKNOWN(newname(), false, false);
  1234.       update(&curenv, fmp->FpName.fpsym, t1);
  1235.       return t1;
  1236.     }
  1237.     break;
  1238.  
  1239.   case TAGFpStr:
  1240.     return BuildSTRING();
  1241.     break;
  1242.  
  1243.   case TAGFpInt:
  1244.     return BuildINT();
  1245.     break;
  1246.  
  1247.   case TAGFpFlo:
  1248.     return BuildFLOAT();
  1249.     break;
  1250.  
  1251.   case TAGFpBool:
  1252.     return BuildBOOL();
  1253.     break;
  1254.   }
  1255. }  /* typefp */
  1256.  
  1257. Local symbol unusedname()
  1258. { /* delivers string-name not appearing in the Glass volume */
  1259.   symbol hs;
  1260.  
  1261.   hs = Buildsymbol(specstr, 3L);
  1262.   addext(hs, newname());
  1263.   return hs;
  1264. }  /* unusedname */
  1265.  
  1266. Local Void addetapar(vl, nm)
  1267. val *vl;
  1268. symbol nm;
  1269. {/* change vl to application of vl to nm (distr. over where,
  1270.     cond.) */
  1271.   val fnc;
  1272.   if ((*vl)->tag == TAGVWhere) {
  1273.     addetapar(&(*vl)->VWhere.wval, nm);
  1274.     return;
  1275.   }
  1276.   if ((*vl)->tag == TAGVBuiltin) {
  1277.     if (cmp_string((*vl)->VBuiltin.oper, "->")==0) {
  1278.       addetapar(&(*vl)->VBuiltin.args->next, nm); /* then br. */
  1279.       /* else br. */
  1280.       addetapar(&(*vl)->VBuiltin.args->next->next, nm);
  1281.     }
  1282.     return;
  1283.   }
  1284.   fnc = (val)malloc(sizeof(*fnc));
  1285.   *fnc = **vl;
  1286.   fnc->next = NULL;
  1287.   (*vl)->tag = TAGVValApply;
  1288.   (*vl)->VValApply.avval = fnc;
  1289.   (*vl)->VValApply.avpar = new_VSym(new_orig("no_file", 0L), nm);
  1290. }  /* addetapar */
  1291.  
  1292. Local Void fcnamesuniq(notformcon, par, parnames, ncjustname)
  1293. boolean notformcon;
  1294. fp par;
  1295. symbol *parnames;
  1296. boolean ncjustname;
  1297. {
  1298.   /* check if par does not already appear in parnames (error);
  1299.      if notformcon add it to parnames
  1300.      if notformcon and ncjustname only TAGFpName allowed 
  1301.      (othw. error) */
  1302.   if (notformcon && ncjustname && par->tag != TAGFpName)
  1303.     error(19L, NULL, NULL, NULL, NULL, false);
  1304.   switch (par->tag) {
  1305.  
  1306.   case TAGFpComp:
  1307.     fcnamesuniq(notformcon,par->FpComp.fpfirst, parnames, false);
  1308.     fcnamesuniq(notformcon, par->FpComp.fprest, parnames, false);
  1309.     break;
  1310.  
  1311.   case TAGFpList:
  1312.     par = par->FpList.fplist;
  1313.     while (par != NULL) {
  1314.       fcnamesuniq(notformcon, par, parnames, false);
  1315.       par = par->next;
  1316.     }
  1317.     break;
  1318.  
  1319.   case TAGFpName:
  1320.     if (notformcon)
  1321.       addunequal(par->FpName.fpsym, parnames);
  1322.     else {
  1323.       if (isin(par->FpName.fpsym, *parnames))
  1324.      error(9L, NULL, NULL, par->FpName.fpsym, NULL, false);
  1325.     }
  1326.     break;
  1327.  
  1328.   case TAGFpEmpty:
  1329.   case TAGFpInt:
  1330.   case TAGFpBool:
  1331.   case TAGFpStr:   /* ok */
  1332.     break;
  1333.   }
  1334. }  /* fcnamesuniq */
  1335.  
  1336. Local Void supplyapsbrc(vl)
  1337. val vl;
  1338. {
  1339.   /* surround vl (with appset type) by appset brackets, if there
  1340.      are none. Distributed over conditional and where */
  1341.   val hv;
  1342.  
  1343.   switch (vl->tag) {
  1344.  
  1345.   case TAGVSysApply:
  1346.   case TAGVValApply:
  1347.     error(28,NULL,NULL,NULL,vl,true);
  1348.     hv = (val)malloc(sizeof(*hv));
  1349.     *hv = *vl;
  1350.     hv->next = NULL;
  1351.     vl->tag = TAGVAppset;
  1352.     vl->VAppset.aps = hv;
  1353.     break;
  1354.  
  1355.   case TAGVWhere:
  1356.     supplyapsbrc(vl->VWhere.wval);
  1357.     break;
  1358.  
  1359.   case TAGVBuiltin:
  1360.     if (cmp_string(vl->VBuiltin.oper, "->")==0) {
  1361.       supplyapsbrc(vl->VBuiltin.args->next);
  1362.       supplyapsbrc(vl->VBuiltin.args->next->next);
  1363.     }
  1364.     break;
  1365.  
  1366.   case TAGVSym:
  1367.   case TAGVInt:
  1368.   case TAGVFlo:
  1369.   case TAGVStr:
  1370.   case TAGVBool:
  1371.   case TAGVType:
  1372.   case TAGVSysLambda: case TAGVSysSigma:
  1373.   case TAGVList:
  1374.   case TAGVAppset:
  1375.   case TAGVAtom:
  1376.   case TAGVSyn:   /* ready */
  1377.     break;
  1378.   }
  1379. }  /* supplyapsbrc */
  1380.  
  1381. boolean seemsadir(vl)
  1382. val vl;
  1383. { /* heuristic to guess if the description was meant to be adirectional */
  1384. string op;
  1385.  
  1386. switch (vl->tag) {
  1387. case TAGVSysSigma:
  1388. case TAGVSyn:
  1389. case TAGVAppset:
  1390.   return true;
  1391. case TAGVWhere:
  1392.   return seemsadir(vl->VWhere.wval);
  1393. case TAGVBuiltin:
  1394.   {op = vl->VBuiltin.oper;
  1395.    if(cmp_string(op,"->")==0) 
  1396.    { return ((seemsadir(vl->VBuiltin.args->next)) ||
  1397.              (seemsadir(vl->VBuiltin.args->next->next)));
  1398.    } else {return false;}
  1399.   };
  1400. default:
  1401.   return false;
  1402. }
  1403. } /* seemsadir */
  1404.  
  1405. Local Void checkbody(dm, ty, btns, isdef, parnames)
  1406. val dm;
  1407. typcrec *ty;
  1408. envrec *btns;
  1409. boolean isdef;
  1410. symbol parnames;
  1411. { /* check if this alternative body dm has the type ty.
  1412.      btns: BT/TN holding here
  1413.      isdef: only single names allowed as (non-conn.) parameter
  1414.      parnames: names for (non-formal connection)parameters
  1415.                already encountered */
  1416.   symbol nm;
  1417.   val rest;
  1418.   fp etapar, fmp;
  1419.   typcrec *t1, *t2;
  1420.   errorrec *err, *errad;
  1421.   boolean adok, ado;
  1422.  
  1423.   while (ty->kind == kindINDIR) ty = ty->INDIR.tcind;
  1424.   if (ty->kind == kindSINGLEARROW || ty->kind == kindSYSTY) 
  1425.   { if (dm->tag != TAGVMacLambda)  /* add eta-parameter */
  1426.     { nm = unusedname();
  1427.       etapar = new_FpName(nm);
  1428.       rest = (val)malloc(sizeof(*rest));
  1429.       *rest = *dm;
  1430.       rest->next = NULL;
  1431.       addetapar(&rest, nm);
  1432.       dm->tag = TAGVMacLambda;
  1433.       dm->VMacLambda.mpar = etapar;
  1434.       dm->VMacLambda.mval = rest;
  1435.     }
  1436.   }
  1437.   if (ty->kind == kindSINGLEARROW)    /* dm->tag=TAGVMacLambda */
  1438.   { fcnamesuniq(true, dm->VMacLambda.mpar, &parnames, isdef);
  1439.     compat(typefp(false, dm->VMacLambda.mpar),
  1440.            ty->SINGLEARROW.tcarg, forcefptoval(dm->VMacLambda.mpar));
  1441.     checkbody(dm->VMacLambda.mval, ty->SINGLEARROW.tcres, btns, isdef,
  1442.               parnames);
  1443.     return;
  1444.   }
  1445.   mark_(&curenv);
  1446.   if (ty->kind == kindSYSTY)   /* dm^.tag=TAGVMacLambda */
  1447.   { fcnamesuniq(false, dm->VMacLambda.mpar, &parnames, false);
  1448.     ado = adaptds;
  1449.     adaptds = false;
  1450.      /* to prevent making names unique twice */
  1451.     err = errorlist;/* try if can be interpreted adirectionally*/
  1452.     t1 = BuildUNKNOWN(newname(),false,true);    
  1453.     compat(BuildSYSTY(BuildOd(BuildNON()), t1),
  1454.            replacelocssome(ty, true), dm);
  1455.     /* order: for directionsin the system type */
  1456.     compat(typefp(true, dm->VMacLambda.mpar),t1 ,
  1457.        forcefptoval(dm->VMacLambda.mpar));
  1458.     compat(BuildAPS(),
  1459.            typeval(makeadirwanted,dm->VMacLambda.mval,btns,0L),
  1460.            dm->VMacLambda.mval);
  1461.     adok = (errorlist == err);
  1462.     release_(&curenv, false); /* types for conn. names removed */
  1463.     adaptds = ado;
  1464.     mark_(&curenv);
  1465.     errad = errorlist;
  1466.     errorlist = err;/* try if can be interpreted unidirectionally */
  1467.     t1 = BuildUNKNOWN(newname(),false,true);    
  1468.     t2 = BuildUNKNOWN(newname(),false,true);    
  1469.     compat(BuildSYSTY(BuildCd(BuildOd(BuildIN()),
  1470.                BuildCd(BuildOd(BuildOUT()), BuildOd(BuildNON()))),
  1471.            BuildCT(t1,
  1472.              BuildCT(t2,BuildSOME(BuildUNKNOWN(newname(),false,true),newname())))), 
  1473.              ty, dm);
  1474.     compat(typefp(true, dm->VMacLambda.mpar),t1 ,
  1475.        forcefptoval(dm->VMacLambda.mpar));
  1476.     compat(t2,typeval(makedirwanted,dm->VMacLambda.mval,btns,0L),
  1477.        dm->VMacLambda.mval);
  1478.     if (adok) 
  1479.     { if (errorlist == err)    /* both adir and dir ok: warning */
  1480.       { error(2L, NULL, NULL, NULL, NULL, true);
  1481.         if (!takewarning && adaptds)
  1482.         { /* TAGVMacLambda fp rest -> TAGVSysLambda fp rest: */
  1483.           fmp = dm->VMacLambda.mpar;
  1484.           rest = dm->VMacLambda.mval;
  1485.           dm->tag = TAGVSysLambda;
  1486.           dm->VSysLambda.slpar = fmp;
  1487.           dm->VSysLambda.slval = rest;
  1488.         }
  1489.       } else  /* adir. ok, unidir not */
  1490.       { errorlist = err;
  1491.         supplyapsbrc(dm->VMacLambda.mval);
  1492.         if (adaptds) 
  1493.         { /* TAGVMacLambda fp rest -> TAGVSysSigma fp rest: */
  1494.           fmp = dm->VMacLambda.mpar;
  1495.           rest = dm->VMacLambda.mval;
  1496.           dm->tag = TAGVSysSigma;
  1497.           dm->VSysSigma.sspar = fmp;
  1498.           dm->VSysSigma.ssval = rest;
  1499.         }
  1500.       }
  1501.     } else 
  1502.       if (errorlist == err) /* unidir ok, adir not */
  1503.       {if (adaptds) 
  1504.         { /* VMacLambda f r -> VSysLambda f r */
  1505.         fmp = dm->VMacLambda.mpar;
  1506.           rest = dm->VMacLambda.mval;
  1507.           dm->tag = TAGVSysLambda;
  1508.           dm->VSysLambda.slpar = fmp;
  1509.           dm->VSysLambda.slval = rest;
  1510.         } 
  1511.       } else /* unidir and adir both wrong */
  1512.        { if (seemsadir(dm->VMacLambda.mval)) {errorlist = errad;};
  1513.          error(3L, NULL, NULL, NULL, NULL, true);
  1514.        }
  1515.   } 
  1516.   else
  1517.     compat(ty, typeval(makewanted(ty), dm, btns, 0L), dm);
  1518.     release_(&curenv, adaptds && uniq); /* remove conn. names */
  1519. }  /* checkbody */
  1520.  
  1521. Local Void checkdm(dm, ty, btns)
  1522. val dm;
  1523. typcrec *ty;
  1524. envrec *btns;
  1525. { /* check if def/macro dm has required type ty (and some simple checks)
  1526.      dm: TAGVMacAlts?is macro; is def
  1527.      ty: type of dm, with all local type names in front (ALL)
  1528.      btns BT/TNs holding on this level ( ! and local defs) */
  1529.   typcrec *typc;
  1530.   boolean isdef;
  1531.  
  1532.   if (dm->tag == TAGVMacAlts) {
  1533.     dm = dm->VMacAlts.alts;
  1534.     isdef = false;
  1535.   } else isdef = true;
  1536.     typc = ty; 
  1537.     while (typc->kind==kindINDIR) typc=typc->INDIR.tcind;
  1538.     if (typc->kind!=kindALL) 
  1539.     {error(10L,NULL,NULL,Buildsymbol("checkdm",7L),NULL,false);
  1540.      return;}
  1541.     while (dm != NULL) {
  1542.     mark_(&curenv);   /* before the parameters */
  1543.     checkbody(dm, replacelocssome(typc->ALL.tcall, true), btns, isdef, NULL);
  1544.     /* replace...: ALL removed, SOME/UNKNOWN numbers renewed,
  1545.        so that empty type stays that */
  1546.     release_(&curenv, adaptds && uniq);
  1547.     dm = dm->next;
  1548.   }
  1549. }  /* checkdm */
  1550.  
  1551. Local Void checkdms(elts, btns)
  1552. def elts;
  1553. envrec *btns;
  1554. { /* check each DEF/MACRO in the elts-list for cont.sens. corr.,
  1555.      given btns for names in the declared types */
  1556.   def hel;
  1557.   /* ! btns': envptr */
  1558.   symbol n;
  1559.   orig oo;
  1560.  
  1561.   hel = elts;
  1562.   /* ! btns':=btnslist */
  1563.   while (hel != NULL) {
  1564.     if (hel->tag == TAGDefVal) {
  1565.       if (hel->DefVal.valas->VType.vtval->tag != TAGVAtom)
  1566.       {   /* ass.: hel^.valas^.tag=TAGVType */
  1567.      n = hel->DefVal.defval;
  1568.      addcopy(n, &nestednames);
  1569.      oo = nestednorig;
  1570.      nestednorig = hel->DefVal.valorig;   /*! slist^.el */
  1571.      checkdm(hel->DefVal.valas->VType.vtval, lookup(curenv, &n), btns);
  1572.      hel->DefVal.defval = n;
  1573.      nestednames = nestednames->next;
  1574.      nestednorig = oo;
  1575.      /* ! ; btnslist:=btnslist^.next */
  1576.       }
  1577.     }
  1578.     hel = hel->next;
  1579.   }
  1580. }  /* checkdms */
  1581.  
  1582. /* Local variables for typeval: */
  1583. struct LOC_typeval {
  1584.   envrec *btns;
  1585.   long splitlevel;
  1586. } ;
  1587.  
  1588. /* Local variables for typeBuiltin: */
  1589. struct LOC_typeBuiltin {
  1590.   typcrec *Result;
  1591.   val args;
  1592.   typcrec *targ1, *targ2;
  1593. } ;
  1594.  
  1595. Local boolean try(ta1, ta2, restype, LINK)
  1596. typcrec *ta1, *ta2, *restype;
  1597. struct LOC_typeBuiltin *LINK;
  1598. {
  1599.   /* gives true if targ1 is compatible with ta1; if so checks if
  1600.      ta2 (if not nil) is compatible with targ2, and assigns
  1601.      restype to typeBuiltin */
  1602.   boolean Result;
  1603.   errorrec *er;
  1604.  
  1605.   er = errorlist;
  1606.   errorlist = NULL;
  1607.   compat(ta1, LINK->targ1, LINK->args);
  1608.   Result = (errorlist == NULL);
  1609.   if (errorlist != NULL) {
  1610.     errorlist = er;
  1611.     return Result;
  1612.   }
  1613.   errorlist = er;
  1614.   if (ta2 != NULL)
  1615.     compat(ta2, LINK->targ2, LINK->args->next);
  1616.   LINK->Result = restype;
  1617.   return Result;
  1618. }  /* try */
  1619.  
  1620. Local typcrec *typeBuiltin(appnon, vl, LINK)
  1621. adirindic appnon;
  1622. val vl;
  1623. struct LOC_typeval *LINK;
  1624. {
  1625.   /* deliver type of builtin operator op, with its arguments 
  1626.      (1, 2 or 3) in args; appnon: application in snd or third arg.
  1627.      to be interpreted adirectionally  */
  1628.   string op;
  1629.   struct LOC_typeBuiltin V;
  1630.   typcrec *targ3;
  1631.   boolean rb;
  1632.   long l;
  1633.   adirindic apn1, apn2, apn3;
  1634.  
  1635.   V.args = vl->VBuiltin.args;
  1636.   op=vl->VBuiltin.oper;
  1637.   if (cmp_string(op,"->")==0) {apn1 = makedirwanted; apn2 = apn3 = appnon;}
  1638.   else
  1639.   if (cmp_string(op,"[..]")==0) {apn1 = appnon; apn2 = apn3 = makedirwanted;}
  1640.   else
  1641.   if (cmp_string(op,":")==0) splitwanted(appnon,&apn1,&apn2);
  1642.   else apn1 = apn2 = makedirwanted;
  1643.   V.targ1 = typeval(apn1, V.args, LINK->btns, LINK->splitlevel);
  1644.   if (V.args->next != NULL) {
  1645.     V.targ2 = typeval(apn2, V.args->next, LINK->btns, LINK->splitlevel);
  1646.     if (V.args->next->next != NULL)
  1647.       targ3 = typeval(apn3, V.args->next->next, LINK->btns, LINK->splitlevel);
  1648.   }
  1649.   else {V.targ2 = NULL;}
  1650.   if ((cmp_string(op, "=")==0) | (cmp_string(op, "/=")==0)) {
  1651.     if (try(BuildINT(), BuildINT(), BuildBOOL(), &V))
  1652.       return V.Result;
  1653.     if (try(BuildFLOAT(), BuildFLOAT(), BuildBOOL(), &V))
  1654.       return V.Result;
  1655.     if (try(BuildBOOL(), BuildBOOL(), BuildBOOL(), &V))
  1656.       return V.Result;
  1657.     if (!try(BuildSTRING(), BuildSTRING(), BuildBOOL(), &V)) {
  1658.       error(6L, V.targ1, V.targ2, NULL, vl, false);
  1659.       return (BuildBOOL());
  1660.     }
  1661.     return V.Result;
  1662.   }
  1663.   if ((cmp_string(op,"+2")==0) | (cmp_string(op,"*")==0) |
  1664.       (cmp_string(op,"-2")==0) | (cmp_string(op,"^")==0) |
  1665.       (cmp_string(op,"MOD")==0)) {
  1666.     if (try(BuildINT(), BuildINT(), BuildINT(), &V))
  1667.       return V.Result;
  1668.     if (!try(BuildFLOAT(), BuildFLOAT(), BuildFLOAT(), &V)) {
  1669.       error(6L, V.targ1, V.targ2, NULL, vl, false);
  1670.       return (BuildUNKNOWN(newname(), false, false));
  1671.     }
  1672.     return V.Result;
  1673.   }
  1674.   if (cmp_string(op, "/")==0) {
  1675.     if (try(BuildINT(), BuildINT(), BuildFLOAT(), &V))
  1676.       return V.Result;
  1677.     if (!try(BuildFLOAT(), BuildFLOAT(), BuildFLOAT(), &V)) {
  1678.       error(6L, V.targ1,V.targ2, NULL, vl, false);
  1679.       return (BuildFLOAT());
  1680.     }
  1681.     return V.Result;
  1682.   }
  1683.   if (cmp_string(op,"DIV")==0) {
  1684.     if (try(BuildINT(), BuildINT(), BuildINT(), &V))
  1685.       return V.Result;
  1686.     if (!try(BuildFLOAT(), BuildFLOAT(), BuildINT(), &V)) {
  1687.       error(6L, V.targ1,V.targ2, NULL, vl, false);
  1688.       return (BuildINT());
  1689.     }
  1690.     return V.Result;
  1691.   }
  1692.   if ((cmp_string(op, "<")==0) | (cmp_string(op,"<=")==0) |
  1693.       (cmp_string(op,">")==0) | (cmp_string(op,">=")==0)) {
  1694.     if (try(BuildINT(), BuildINT(), BuildBOOL(), &V))
  1695.       return V.Result;
  1696.     if (!try(BuildFLOAT(), BuildFLOAT(), BuildBOOL(), &V)) {
  1697.       error(6L, V.targ1, V.targ2, NULL, vl, false);
  1698.       return (BuildBOOL());
  1699.     }
  1700.     return V.Result;
  1701.   }
  1702.   if ((cmp_string(op,"&")==0) | (cmp_string(op,"|")==0)) {
  1703.     if (!try(BuildBOOL(), BuildBOOL(), BuildBOOL(), &V)) {
  1704.       error(6L, V.targ1, V.targ2, NULL, vl,false);
  1705.       return (BuildBOOL());
  1706.     }
  1707.     return V.Result;
  1708.   }
  1709.   if (cmp_string(op,":")==0) {
  1710.     rb = restrictable(true, false, V.targ2, V.args->next);
  1711.     /* true: must end in empty! */
  1712.     return (BuildCT(V.targ1, V.targ2));
  1713.   }
  1714.   if ((cmp_string(op, "-1")==0) | (cmp_string(op,"+1")==0)) {
  1715.     if (try(BuildINT(), NULL, BuildINT(), &V))
  1716.       return V.Result;
  1717.     if (!try(BuildFLOAT(), NULL, BuildFLOAT(), &V)) {
  1718.       error(6L, V.targ1, V.targ2, NULL, vl, false);
  1719.       return (BuildUNKNOWN(newname(), false, false));
  1720.     }
  1721.     return V.Result;
  1722.   }
  1723.   if (cmp_string(op,"~")==0) {
  1724.     if (!try(BuildBOOL(), NULL, BuildBOOL(), &V)) {
  1725.       error(6L, V.targ1, V.targ2, NULL, vl, false);
  1726.       return (BuildBOOL());
  1727.     }
  1728.     return V.Result;
  1729.   }
  1730.   if (cmp_string(op,"->")==0) {
  1731.     compat(BuildBOOL(), V.targ1, V.args);
  1732.     return (upper(V.targ2, targ3, V.args->next->next));
  1733.     /* for the last arg., args^.next could have been taken */
  1734.   }
  1735.   if (cmp_string(op,"[..]")==0) {
  1736.     V.Result = BuildSOME(uppercomps(V.targ1, V.args), newname());
  1737.     /* !! this may introduce wrong fill-ins, if uppercomps
  1738.           contains UNKNOWN */
  1739.     compat(BuildINT(), V.targ2, V.args->next);
  1740.     compat(BuildINT(), targ3, V.args->next->next);
  1741.     return V.Result;
  1742.   }
  1743.   if (!cmp_string(op,"itof")==0) 
  1744.   { l=0; while (op[l]!='\0') l++;
  1745.     error(10L, NULL, NULL, Buildsymbol(op,l), NULL, false);
  1746.     return (BuildUNKNOWN(newname(), false, false));
  1747.   }
  1748.   if (!try(BuildINT(), NULL, BuildFLOAT(), &V)) {
  1749.       error(6L, V.targ1, V.targ2, NULL, vl, false);
  1750.     return (BuildFLOAT());
  1751.   }
  1752.   return V.Result;
  1753. }  /* typeBuiltin */
  1754.  
  1755. Local typcrec *typename(n)
  1756. symbol *n;
  1757. {
  1758.   /* find type of n in curenv; 
  1759.      if not there, give it any conn. type */
  1760.   typcrec *t;
  1761.  
  1762.   t = lookup(curenv, n);
  1763.   if (t == NULL) {
  1764.     t = BuildUNKNOWN(newname(), false, true);
  1765.     update(&curenv, *n, t);
  1766.     return t;
  1767.   } else
  1768.     return (replacelocssome(t, false));
  1769. }  /* typename */
  1770.  
  1771. Local typcrec *typeld(ld, btns, splitlevel)
  1772. def ld;
  1773. envrec *btns;
  1774. long splitlevel;
  1775. {
  1776.   /* if ld (appearing in where) is of the form "ns=e" or appset
  1777.      then check its type; result type is APS
  1778.      btns, splitlevel: same function as in typeval */
  1779.   typcrec *t1;
  1780.  
  1781.   if (ld->tag == TAGDefCon) /* appsets in where not (yet) in d.s. */
  1782.   { t1 = BuildUNKNOWN(newname(), false, true);
  1783.     compat(t1, typeval(makedirwanted, ld->DefCon.defcon, btns, splitlevel),
  1784.            ld->DefCon.defcon);
  1785.     compat(t1, typeval(makedirwanted, ld->DefCon.conas, btns, splitlevel),
  1786.            ld->DefCon.conas);
  1787.   }
  1788.   return (BuildAPS());
  1789. }  /* typeld */
  1790.  
  1791. Local Void splitcurenv(splitlevel, ce, le)
  1792. long splitlevel;
  1793. envrec **ce, **le;
  1794. {
  1795.   /* curenv contains:
  1796.        conn. names;mark;ADMnames_n;mark;conn.names_n;mark; 
  1797.        ... ;ADMnames_0; mark; connnames_0; mark;
  1798.        explicitly declared names
  1799.      ce will contain: 
  1800.        conn. names;conn. names_n;mark; ... ; ADMnames_0; mark;
  1801.        connnames_0; mark; explicitly declared names
  1802.      le will contain: 
  1803.        ADMnames_n;mark;...;ADMnames_0;explicitly declared names
  1804.      n = splitlevel
  1805.   */
  1806.   envrec *h, *h2, *hold;
  1807.   long i;
  1808.  
  1809.   hold = NULL;
  1810.   h = curenv;
  1811.   while (!ismark(h)) {
  1812.     hold = h;
  1813.     h = h->next;
  1814.   }
  1815.   h = h->next;
  1816.   *le = h;
  1817.   while (!ismark(h))
  1818.     h = h->next;
  1819.   if (hold == NULL)
  1820.     *ce = h->next;
  1821.   else {
  1822.     *ce = curenv;
  1823.     hold->next = h->next;
  1824.   }
  1825.   hold = h;
  1826.   h = h->next;
  1827.   for (i = 1; i <= splitlevel; i++) {
  1828.     while (!ismark(h))
  1829.       h = h->next;
  1830.     h = h->next;
  1831.     while (!ismark(h)) {
  1832.       h2 = (envrec *)malloc(sizeof(envrec));
  1833.       *h2 = *h;
  1834.       hold->next = h2;
  1835.       hold = h2;
  1836.       h = h->next;
  1837.     }
  1838.   }
  1839.   while (!ismark(h))
  1840.     h = h->next;
  1841.   hold->next = h->next;
  1842. }  /* splitcurenv */
  1843.  
  1844. Local typcrec *typeval(appnon, vl, btns_, splitlevel_)
  1845. adirindic appnon;
  1846. val vl;
  1847. envrec *btns_;
  1848. long splitlevel_;
  1849. {
  1850. /* gives type of vl in type-environment curenv;
  1851.    appnon is the appset type: system application taken as adirectional
  1852.    btns_: basetypes and typenamings holding in types found in vl
  1853.    splitlevel_: nr. of ATO/DEF/MAC typedecl. blockss to be
  1854.                selected if creating an environment with only
  1855.                explicit declarations */
  1856.  
  1857.   struct LOC_typeval V;
  1858.   typcrec *ta, *tf, *t1, *t2;
  1859.   errorrec *er;
  1860.   symbol hnm;
  1861.   envrec *conenv, *locenv;
  1862.   def hl;
  1863.   val hv, hv2;
  1864.   adirindic appfirst, apprest;
  1865.  
  1866.   V.btns = btns_;
  1867.   V.splitlevel = splitlevel_;
  1868.   switch (vl->tag) {
  1869.  
  1870.   case TAGVValApply:
  1871.     tf = typeval(makedirwanted, vl->VValApply.avval, V.btns,V.splitlevel);
  1872.     er = errorlist;
  1873.     errorlist = NULL;
  1874.     t1 = BuildUNKNOWN(newname(), false, false);
  1875.     t2 = BuildUNKNOWN(newname(), false, false);
  1876.     compat(BuildSINGLEARROW(t1, t2), tf, vl->VValApply.avval);
  1877.     if (errorlist == NULL) {   /* tf function type */
  1878.       errorlist = er;
  1879.       compat(t1, typeval(makewanted(t1),vl->VValApply.avpar,V.btns,
  1880.              V.splitlevel), 
  1881.          vl->VValApply.avpar);
  1882.       return t2;
  1883.     } 
  1884.       else { /* try if it is a system appl. */
  1885.       errorlist = NULL;
  1886.       t1 = BuildUNKNOWN(newname(), false, true);
  1887.       compat(BuildSYSTY(BuildOd(BuildNON()), t1), tf,vl->VValApply.avval);
  1888.       if (errorlist==NULL)
  1889.       { /* it IS a system application */
  1890.     if (adaptds)
  1891.     { /*  TAGVValApply s c -> TAGVSysApply s c: */
  1892.           hv = vl->VValApply.avval;
  1893.           hv2 = vl->VValApply.avpar;
  1894.           vl->tag = TAGVSysApply;
  1895.           vl->VSysApply.asval = hv;
  1896.           vl->VSysApply.aspar = hv2;
  1897.     }
  1898.        if (adirwanted(appnon)) 
  1899.        { errorlist = er;
  1900.          compat(t1, typeval(makedirwanted, vl->VValApply.avpar, V.btns, 
  1901.                 V.splitlevel), 
  1902.         vl->VValApply.avpar);
  1903.      return BuildAPS();
  1904.        } 
  1905.        else  /* appnon is not appset type, should be unidir. sys. appl. */
  1906.        {t1 = BuildUNKNOWN(newname(), false, true);
  1907.         t2 = BuildUNKNOWN(newname(), false, true);
  1908.         compat(BuildSYSTY(BuildCd(BuildOd(BuildIN()),
  1909.                         BuildCd(BuildOd(BuildOUT()),
  1910.                              BuildOd(BuildNON()))), BuildCT(t1,
  1911.                      BuildCT(t2,BuildSOME(BuildUNKNOWN(newname(),
  1912.                                                        false,
  1913.                                                        true),
  1914.                                           newname())))), 
  1915.                tf, vl->VValApply.avval);
  1916.        if (errorlist == NULL)  /* tf IS an unidir sys.type */
  1917.        { errorlist = er;
  1918.          compat(t1,
  1919.         typeval(makedirwanted,vl->VValApply.avpar,V.btns, V.splitlevel),
  1920.         vl->VValApply.avpar);
  1921.          return t2;
  1922.        } else
  1923.      { errorlist = er;
  1924.            error(5L, tf, NULL, NULL, vl->VValApply.avval, false);
  1925.            return BuildUNKNOWN(newname(), false, true);
  1926.          }
  1927.      }
  1928.     }
  1929.     else 
  1930.     { errorlist = NULL;
  1931.       ta = typeval(makedirwanted,vl->VValApply.avpar,V.btns,V.splitlevel);
  1932.       compat (BuildINT(), ta, vl->VValApply.avpar);
  1933.       if (errorlist == NULL)    /* indexing */
  1934.      {errorlist = er;
  1935.      if (adaptds)
  1936.      { /* TAGVValApply l i -> TAGVBuiltin "[]" [l,i]: */
  1937.        hv = vl->VValApply.avval;
  1938.        hv2 = vl->VValApply.avpar;
  1939.        hv->next = hv2;
  1940.        hv2->next = NULL;
  1941.        vl->tag = TAGVBuiltin;
  1942.        vl->VBuiltin.oper = "[]";
  1943.        vl->VBuiltin.args = hv;
  1944.      }
  1945.      return uppercomps(tf, vl->VValApply.avval);
  1946.      } else 
  1947.        { errorlist = er;
  1948.          error(6L, tf, ta, NULL, vl, false);
  1949.          return BuildUNKNOWN(newname(), false, false);
  1950.        }
  1951.      }
  1952.     }
  1953.     break;
  1954.  
  1955.   case TAGVSysApply:
  1956.     error(10L, NULL, NULL, Buildsymbol( "typeval", 7L), NULL, false);
  1957.     return BuildUNKNOWN(newname(), false, false);
  1958.     break;
  1959.  
  1960.   case TAGVSym:
  1961.     hnm = vl->VSym.sym;
  1962.     t1 = typename(&hnm);
  1963.     /* no test anymore if name in fc lud lhs and synonyms wasn't
  1964.        declared as something else */
  1965.     vl->VSym.sym = hnm;
  1966.     return t1;
  1967.     break;
  1968.  
  1969.   case TAGVInt:
  1970.     return BuildINT();
  1971.     break;
  1972.  
  1973.   case TAGVFlo:
  1974.     return BuildFLOAT();
  1975.     break;
  1976.  
  1977.   case TAGVStr:
  1978.     return BuildSTRING();
  1979.     break;
  1980.  
  1981.   case TAGVBool:
  1982.     return BuildBOOL();
  1983.     break;
  1984.  
  1985.   case TAGVSysLambda:
  1986.     mark_(&curenv);
  1987.     mark_(&curenv);
  1988.     /* simulate empty block of ATOM/DEF/MAC decls.,
  1989.        because splitcurenv assumes at least one A/D/M block */
  1990.     splitcurenv(V.splitlevel, &conenv, &locenv);
  1991.     curenv = locenv;
  1992.     t1 = typefp(true, vl->VSysLambda.slpar);
  1993.     t2 = typeval(makedirwanted, vl->VSysLambda.slval, V.btns, 0L);
  1994.     if (restrictable(false, true, t1, forcefptoval(vl->VSysLambda.slpar)) &
  1995.      restrictable(false, true, t2, vl->VSysLambda.slval))
  1996.       ta = BuildSYSTY(BuildCd(BuildOd(BuildIN()),
  1997.          BuildCd(BuildOd(BuildOUT()), BuildOd(BuildNON()))),
  1998.        BuildCT(t1, BuildCT(t2, BuildSOME(BuildUNKNOWN(newname(),
  1999.                                                      false,true),
  2000.                                          newname()))));
  2001.     else
  2002.       ta = BuildUNKNOWN(newname(), false, false);
  2003.     release_(&curenv, adaptds && uniq);
  2004.     /* the local connames of this lambda abstr. */
  2005.     curenv = conenv;
  2006.     return ta;
  2007.     break;
  2008.  
  2009.   case TAGVSysSigma:
  2010.     mark_(&curenv);
  2011.     mark_(&curenv);
  2012.     /* simulate empty block of ATOM/DEF/MAC decls.,
  2013.        because splitcurenv assumes at least one A/D/M block */
  2014.     splitcurenv(V.splitlevel, &conenv, &locenv);
  2015.     curenv = locenv;
  2016.     t1 = typefp(true, vl->VSysSigma.sspar);
  2017.     er = errorlist;
  2018.     compat(BuildAPS(), 
  2019.           typeval(makeadirwanted, vl->VSysSigma.ssval, V.btns, 0L),
  2020.           vl->VSysSigma.ssval);
  2021.     if (restrictable(false, true, t1, forcefptoval(vl->VSysSigma.sspar)) &&
  2022.      errorlist == er)
  2023.       ta = BuildSYSTY(BuildOd(BuildNON()), t1);
  2024.     else
  2025.       ta = BuildUNKNOWN(newname(), false, false);
  2026.     release_(&curenv, adaptds && uniq);
  2027.     /* the local connames of this sigma abstr. */
  2028.     curenv = conenv;
  2029.     return ta;
  2030.     break;
  2031.  
  2032.   case TAGVType:   /* does not appear here */
  2033.     error(10L, NULL, NULL, Buildsymbol( "typeval", 7L), NULL, false);
  2034.     return BuildUNKNOWN(newname(), false, false);
  2035.     break;
  2036.  
  2037.   case TAGVWhere:
  2038.     mark_(&curenv);   /* after  formcons and conn. names */
  2039.     mark_(&V.btns);
  2040.     V.btns = extendbtns(vl->VWhere.wdefs, V.btns);
  2041.     extendenvloc(vl->VWhere.wdefs, V.btns);
  2042.     mark_(&curenv);   /* after ATOM/DEF/Mac names */
  2043.     hl = vl->VWhere.wdefs;
  2044.     while (hl != NULL) {
  2045.       compat(BuildAPS(),typeld(hl,V.btns,V.splitlevel+1,&V), NULL);
  2046.       /* compat always correct, so nil does not matter */
  2047.       hl = hl->next;
  2048.     }
  2049.     ta = typeval(appnon, vl->VWhere.wval, V.btns, V.splitlevel + 1);
  2050.     splitcurenv(V.splitlevel, &conenv, &locenv);
  2051.     curenv = locenv;
  2052.     checkdms(vl->VWhere.wdefs, V.btns);
  2053.     release_(&V.btns, adaptds && uniq);
  2054.     release_(&curenv, adaptds && uniq);
  2055.      /* local ATOM/DEF/MACs removed */
  2056.     curenv = conenv;
  2057.     return ta;
  2058.     break;
  2059.  
  2060.   case TAGVList:
  2061.     if (vl->VList.l == NULL) {
  2062.       return BuildSOME(BuildUNKNOWN(newname(), false, false), newname());
  2063.       /* !! mog. foute inv. */
  2064.     } else {
  2065.       splitwanted(appnon,&appfirst,&apprest);
  2066.       t1 = typeval(appfirst, vl->VList.l, V.btns, V.splitlevel);
  2067.       t2 = typeval(apprest, new_VList(vl->VList.l->next), V.btns, V.splitlevel);
  2068.       /* t1, t2 used so that name extension numbers are independent of the
  2069.      order in which the C implementation evaluates function arguments */
  2070.       return BuildCT(t1,t2);
  2071.     }
  2072.     break;
  2073.  
  2074.   case TAGVAppset:
  2075.     t1 = BuildAPS();
  2076.     hv = vl->VAppset.aps;
  2077.     while (hv != NULL) {
  2078.       compat(t1, typeval(makeadirwanted,hv,V.btns,V.splitlevel), hv);
  2079.       hv = hv->next;
  2080.     }
  2081.     return t1;
  2082.     break;
  2083.  
  2084.   case TAGVAtom:   /* need not be treated here */
  2085.     error(10L, NULL, NULL, Buildsymbol( "typeval", 7L), NULL, false);
  2086.     return BuildUNKNOWN(newname(), false, false);
  2087.     break;
  2088.  
  2089.   case TAGVSyn:
  2090.     t1 = BuildUNKNOWN(newname(), false, true);
  2091.     hv = vl->VSyn.synlist;
  2092.     while (hv != NULL) {
  2093.       compat(t1,typeval(makedirwanted,hv,V.btns,V.splitlevel), hv);
  2094.       hv = hv->next;
  2095.     }
  2096.     return BuildAPS();
  2097.     break;
  2098.  
  2099.   case TAGVBuiltin:
  2100.     return typeBuiltin(appnon, vl, &V);
  2101.     break;
  2102.  
  2103.   case TAGVMacLambda:
  2104.     /* only encountered when a def/mac has more parameters
  2105.                    than types for them */
  2106.     error(4L, NULL, NULL, NULL, NULL, false);
  2107.     t1 =typeval(appnon,vl->VMacLambda.mval,V.btns,V.splitlevel);
  2108.     return BuildUNKNOWN(newname(), false, false);
  2109.     break;
  2110.  
  2111.   case TAGVMacAlts:   /* need not be treated here */
  2112.     error(10L, NULL, NULL, Buildsymbol( "typeval", 7L), NULL, false);
  2113.     return BuildUNKNOWN(newname(), false, false);
  2114.     break;
  2115.   }/* case */
  2116. }  /* typeval */
  2117.  
  2118. Void checkglasstext(glass)
  2119. def_list glass;
  2120. {  /* do simple context-sensitive and typing demand checks for a Glass volume;
  2121.      if errors found, deliver errors, otherwise changed data structure */
  2122.   envrec *btns;
  2123.   _PROCEDURE TEMP;
  2124.  
  2125.   adaptds = true;
  2126.   marker = Buildsymbol("",0L); /* initialisation of a constant */
  2127.   errordiscovered = false;
  2128.   forfull = true;
  2129.   namessupply = 0;
  2130.   nestednames = NULL;
  2131.   nestednorig = NULL;
  2132.   extsupply = 0;
  2133.   btns = emptyenv;
  2134.   mark_(&btns);
  2135.   btns = extendbtns(glass, btns);
  2136.   curenv = emptyenv;
  2137.   mark_(&curenv);
  2138.   extendenvloc(glass, btns);
  2139.   checkdms(glass, btns);
  2140.   release_(&btns, uniq);
  2141.   release_(&curenv, uniq);
  2142.   TEMP.proc = (Anyptr)unparsval;
  2143.   printerrors(TEMP, errorlist);
  2144. }  /* checkglasstext */
  2145.