home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Moscow ML 1.31 / source code / mosml / src / compiler / Synchk.sml < prev    next >
Encoding:
Text File  |  1996-07-03  |  9.9 KB  |  343 lines  |  [TEXT/R*ch]

  1.  
  2. open List Fnlib Mixture Const Globals Location Units Asynt Asyntfn
  3.  
  4. (* --- Syntactic restrictions --- *)
  5.  
  6. fun inIds (ii : IdInfo) (iis : IdInfo list) =
  7.   exists (fn ii' => #id(#qualid ii) = #id(#qualid ii')) iis
  8. ;
  9.  
  10. fun checkDuplIds (iis : IdInfo list) msg =
  11.   case iis of
  12.       [] => ()
  13.     | ii :: iis' =>
  14.         if inIds ii iis' then
  15.           errorMsg (#idLoc (#info ii)) msg
  16.         else checkDuplIds iis' msg
  17. ;
  18.  
  19. fun checkAllIdsIn xs ys msg =
  20.   app (fn ii => if inIds ii ys then () else errorMsg (#idLoc (#info ii)) msg)
  21.       xs
  22. ;
  23.  
  24. fun checkTy (loc, ty') =
  25.   case ty' of
  26.     TYVARty _ => ()
  27.   | RECty fs =>
  28.       (app_field checkTy fs;
  29.        if duplicates (map fst fs) then
  30.          errorMsg loc "The same label is bound twice in a record type"
  31.        else ())
  32.   | CONty(tys, _) =>
  33.       app checkTy tys
  34.   | FNty(ty, ty') =>
  35.       (checkTy ty; checkTy ty')
  36. ;
  37.  
  38. fun checkAsPatSource (loc, pat') =
  39.   case pat' of
  40.     VARpat _ => ()
  41.   | TYPEDpat((_, VARpat _), _) => ()
  42.   | _ => errorMsg loc "Ill-formed source of a layered pattern"
  43. ;
  44.  
  45. fun checkPat (loc, pat') =
  46.   case pat' of
  47.     SCONpat _ => ()
  48.   | VARpat _ => ()
  49.   | WILDCARDpat => ()
  50.   | NILpat _ => ()
  51.   | CONSpat(_, p) => checkPat p
  52.   | EXNILpat _ => ()
  53.   | EXCONSpat(_, p) => checkPat p
  54.   | EXNAMEpat _ => fatalError "checkPat"
  55.   | REFpat p => checkPat p
  56.   | RECpat(ref (RECrp(fs, _))) =>
  57.       (app_field checkPat fs;
  58.        if duplicates (map fst fs) then
  59.          errorMsg loc "The same label is bound twice in a record pattern"
  60.        else ())
  61.   | RECpat(ref (TUPLErp _)) => fatalError "checkPat"
  62.   | VECpat ps => app checkPat ps
  63.   | PARpat p => checkPat p
  64.   | INFIXpat _ => fatalError "checkPat"
  65.   | TYPEDpat(pat, ty) => (checkPat pat; checkTy ty)
  66.   | LAYEREDpat(pat1, pat2) =>
  67.       (checkAsPatSource pat1;
  68.        checkPat pat1; checkPat pat2)
  69. ;
  70.  
  71. fun isFnExp (_, exp') =
  72.   case exp' of
  73.     PARexp exp => isFnExp exp
  74.   | TYPEDexp(exp, ty) => isFnExp exp
  75.   | FNexp _ => true
  76.   | _ => false
  77. ;
  78.  
  79. fun checkFnExp exp =
  80.   if isFnExp exp then () else
  81.   errorMsg (xLR exp) "Non-functional rhs expression in val rec declaration"
  82. ;
  83.  
  84. fun tyconsOfTBs tbs = map (fn(_, tycon, _) => tycon) tbs;
  85. fun tyconsOfTDs tds = map (fn(_, tycon) => tycon) tds;
  86. fun tyconsOfDBs dbs = map (fn(_, tycon, _) => tycon) dbs;
  87. fun consOfDBs dbs =
  88.   concat( map (fn(_, _, cbs) => map (fn ConBind(ii,_) => ii) cbs) dbs );
  89.  
  90. fun consOfEBs ebs =
  91.   map (fn EXDECexbind(ii,_) => ii
  92.         | EXEQUALexbind(ii,_) => ii)
  93.       ebs
  94. ;
  95.  
  96. fun appOpt f u (SOME x) = f x
  97.   | appOpt f u NONE     = u
  98. ;
  99.  
  100. fun checkTypBind (tyvars, tycon, ty) =
  101. (
  102.   checkTy ty;
  103.   checkDuplIds tyvars
  104.     "Duplicate parameter in a type binding";
  105.   checkAllIdsIn (varsOfTy ty) tyvars
  106.     "Unbound parameter in the rhs of a type binding"
  107. );
  108.  
  109. fun checkTypDesc (tyvars, tycon) =
  110.   checkDuplIds tyvars
  111.     "Duplicate parameter in a prim_type binding"
  112. ;
  113.  
  114. fun checkDatBind (tyvars, tycon, cbs) =
  115. (
  116.   app (fn ConBind(_, SOME ty) =>
  117.                 (checkTy ty;
  118.                  checkAllIdsIn (varsOfTy ty) tyvars
  119.                    "Unbound parameter in the rhs of a datatype binding")
  120.         | ConBind(_, NONE) => ())
  121.           cbs;
  122.   checkDuplIds tyvars
  123.     "Duplicate parameter in a datatype binding"
  124. );
  125.  
  126. fun checkExBind (EXDECexbind(_, ty_opt)) = appOpt checkTy () ty_opt
  127.   | checkExBind (EXEQUALexbind(_, _)) = ()
  128. ;
  129.  
  130. fun checkInfixIds loc ids =
  131.   if duplicates ids then
  132.     errorMsg loc "An identifier appears twice in a fixity declaration"
  133.   else ()
  134. ;
  135.  
  136. fun patOfValBind (ValBind(pat, _)) = pat;
  137.  
  138. fun checkExp (loc, exp') =
  139.   case exp' of
  140.     SCONexp _ => ()
  141.   | VARexp _ => ()
  142.   | FNexp mrules =>
  143.       app checkMRule mrules
  144.   | APPexp(func, arg) =>
  145.       (checkExp func; checkExp arg)
  146.   | LETexp(dec, scope) =>
  147.       (checkDec false dec; checkExp scope)
  148.   | RECexp(ref (RECre fs)) =>
  149.       (app_field checkExp fs;
  150.        if duplicates (map fst fs) then
  151.          errorMsg loc "The same label is bound twice in a record expression"
  152.        else ())
  153.   | RECexp(ref (TUPLEre _)) => fatalError "checkExp"
  154.   | VECexp es =>
  155.       app checkExp es
  156.   | PARexp e => checkExp e
  157.   | INFIXexp _ => fatalError "checkExp"
  158.   | TYPEDexp(e, ty) =>
  159.       (checkExp e; checkTy ty)
  160.   | ANDALSOexp(e1, e2) =>
  161.       (checkExp e1; checkExp e2)
  162.   | ORELSEexp(e1, e2) =>
  163.       (checkExp e1; checkExp e2)
  164.   | HANDLEexp(e, mrules) =>
  165.       (checkExp e;
  166.        app checkMRule mrules)
  167.   | RAISEexp e =>
  168.       checkExp e
  169.   | IFexp(e0, e1, e2) =>
  170.       (checkExp e0; checkExp e1; checkExp e2)
  171.   | WHILEexp(e1, e2) =>
  172.       (checkExp e1; checkExp e2)
  173.   | SEQexp(e1, e2) =>
  174.       (checkExp e1; checkExp e2)
  175.  
  176. and checkMRule (MRule(pats, exp)) =
  177. (
  178.   app checkPat pats; checkExp exp;
  179.   checkDuplIds (foldR varsOfPatAcc [] pats)
  180.     "The same pattern variable is bound twice"
  181. )
  182.  
  183. and checkValBind (ValBind(pat, exp)) =
  184. (
  185.   checkPat pat; checkExp exp;
  186.   checkDuplIds (varsOfPatAcc pat [])
  187.     "The same variable is bound twice in a pattern"
  188. )
  189.  
  190. and checkDec onTop (loc, dec') =
  191.   case dec' of
  192.     VALdec (pvbs, rvbs) =>
  193.       (app checkValBind pvbs;
  194.        app checkValBind rvbs;
  195.        app (fn ValBind(_, exp) => checkFnExp exp) rvbs;
  196.        let val pat_vars =
  197.          foldR_map varsOfPatAcc patOfValBind
  198.            (foldR_map varsOfPatAcc patOfValBind [] rvbs) pvbs
  199.        in
  200.          checkDuplIds(pat_vars)
  201.             "The same variable is bound twice in a valbind"
  202.        end)
  203.   | PRIM_VALdec pbs =>
  204.       let val iis = map (fn (ii,_,_,_) => ii) pbs in
  205.         checkDuplIds iis
  206.           "The same variable is bound twice in a prim_valbind"
  207.       end
  208.   | FUNdec _ => fatalError "checkDec"
  209.   | TYPEdec tbs =>
  210.       (app checkTypBind tbs;
  211.        let val tycons = tyconsOfTBs tbs in
  212.          checkDuplIds tycons
  213.            "The same tycon is bound twice in a type declaration"
  214.        end)
  215.   | PRIM_TYPEdec(_, tds) =>
  216.       (app checkTypDesc tds;
  217.        let val tycons = tyconsOfTDs tds in
  218.          checkDuplIds tycons
  219.            "The same tycon is bound twice in a prim_type declaration"
  220.        end)
  221.   | DATATYPEdec(dbs, tbs_opt) =>
  222.       (app checkDatBind dbs;
  223.        appOpt (app checkTypBind) () tbs_opt;
  224.        let val tycons = tyconsOfDBs dbs @ appOpt tyconsOfTBs [] tbs_opt
  225.            val cons = consOfDBs dbs
  226.        in
  227.          checkDuplIds tycons
  228.            "The same tycon is bound twice in a datatype declaration";
  229.          checkDuplIds cons
  230.            "The same con is bound twice in a datatype declaration"
  231.        end)
  232.   | ABSTYPEdec(dbs, tbs_opt, dec2) =>
  233.       (app checkDatBind dbs;
  234.        appOpt (app checkTypBind) () tbs_opt;
  235.        let val tycons = tyconsOfDBs dbs @ appOpt tyconsOfTBs [] tbs_opt
  236.            val cons = consOfDBs dbs
  237.        in
  238.          checkDuplIds tycons
  239.            "The same tycon is bound twice in an abstype declaration";
  240.          checkDuplIds cons
  241.            "The same con is bound twice in an abstype declaration";
  242.          checkDec onTop dec2
  243.        end)
  244.   | EXCEPTIONdec ebs =>
  245.       (app checkExBind ebs;
  246.        checkDuplIds (consOfEBs ebs)
  247.          "The same excon is bound twice in an exception declaration")
  248.   | LOCALdec (dec1, dec2) =>
  249.       (checkDec false dec1; checkDec onTop dec2)
  250.   | OPENdec _ =>
  251.       (*
  252.       if not(!hasSpecifiedSignature) andalso
  253.          onTop & currentUnitName() <> "Top"
  254.       then
  255.         (msgIBlock 0;
  256.          errLocation loc;
  257.          errPrompt "`open' is not permitted at the top level,";
  258.          msgEOL();
  259.          errPrompt "unless the unit has explicitly specified signature";
  260.          msgEOL();
  261.          msgEBlock();
  262.          raise Toplevel); *)
  263.       ()
  264.   | EMPTYdec => ()
  265.   | SEQdec (dec1, dec2) =>
  266.       (checkDec onTop dec1; checkDec onTop dec2)
  267.   | FIXITYdec(_, ids) =>
  268.       checkInfixIds loc ids
  269. ;
  270.  
  271. (* --- Signatures --- *)
  272.  
  273. fun checkExDesc (_, ty_opt) = appOpt checkTy () ty_opt;
  274.  
  275. fun consOfEDs eds =
  276.   map (fn (ii,_) => ii) eds
  277. ;
  278.  
  279. fun checkSpec onTop (loc, spec') =
  280.   case spec' of
  281.     VALspec vds =>
  282.       (if not onTop then errorMsg loc
  283.          "Value specifications are permitted only at the top level"
  284.        else ();
  285.        let val iis = map (fn(ii,_) => ii) vds in
  286.          checkDuplIds iis
  287.            "The same variable is bound twice in a value description"
  288.        end)
  289.   | PRIM_VALspec pbs =>
  290.       (if not onTop then errorMsg loc
  291.          "Primitive value specifications are permitted only at the top level"
  292.        else ();
  293.        let val iis = map (fn(ii,_,_,_) => ii) pbs in
  294.          checkDuplIds iis
  295.            "The same variable is bound twice in a prim_valbind"
  296.        end)
  297.   | TYPEDESCspec(_, tds) =>
  298.       (if not onTop then errorMsg loc
  299.          "Abstract type specifications are permitted only at the top level"
  300.        else ();
  301.        app checkTypDesc tds;
  302.        let val tycons = tyconsOfTDs tds in
  303.          checkDuplIds tycons
  304.            "The same tycon is bound twice in a type description"
  305.        end)
  306.   | TYPEspec tbs =>
  307.       (app checkTypBind tbs;
  308.        let val tycons = tyconsOfTBs tbs in
  309.          checkDuplIds tycons
  310.            "The same tycon is bound twice in a manifest type description"
  311.        end)
  312.   | DATATYPEspec(dbs, tbs_opt) =>
  313.       (if not onTop then errorMsg loc
  314.          "Variant type specifications are permitted only at the top level"
  315.        else ();
  316.        app checkDatBind dbs;
  317.        appOpt (app checkTypBind) () tbs_opt;
  318.        let val tycons = tyconsOfDBs dbs @ appOpt tyconsOfTBs [] tbs_opt
  319.            val cons = consOfDBs dbs
  320.        in
  321.          checkDuplIds tycons
  322.            "The same tycon is bound twice in a datatype description";
  323.          checkDuplIds cons
  324.            "The same con is bound twice in a datatype description"
  325.        end)
  326.   | EXCEPTIONspec eds =>
  327.       (if not onTop then errorMsg loc
  328.          "Exception specifications are permitted only at the top level"
  329.        else ();
  330.        app checkExDesc eds;
  331.        checkDuplIds (consOfEDs eds)
  332.          "The same excon is bound twice in an exception description")
  333.   | LOCALspec (spec1, spec2) =>
  334.       (checkSpec false spec1; checkSpec onTop spec2)
  335.   | OPENspec _ =>
  336.       if onTop then errorMsg loc
  337.         "`open' is not permitted at the top level"
  338.       else ()
  339.   | EMPTYspec => ()
  340.   | SEQspec (spec1, spec2) =>
  341.       (checkSpec onTop spec1; checkSpec onTop spec2)
  342. ;
  343.