(* Copyright (C) 1992, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) MODULE M3CChkObsolete; IMPORT Text, PropertyV; IMPORT ASTWalk; IMPORT AST, M3AST_AS; IMPORT M3Error, M3CPragma; IMPORT SeqM3AST_AS_DEF_ID, SeqM3AST_AS_Used_interface_id; IMPORT M3AST_AS_F, M3AST_SM_F, M3AST_TM_F, M3AST_TL_F; REVEAL Handle = ASTWalk.Closure BRANDED OBJECT OVERRIDES callback := Node; END; (* record *) PROCEDURE Node( h: Handle; n: AST.NODE; vm: ASTWalk.VisitMode) RAISES {}= VAR used_id: M3AST_AS.USED_ID; BEGIN IF vm = ASTWalk.VisitMode.Entry THEN IF n.IsA_USED_ID(used_id) THEN TYPECASE used_id.sm_def OF | NULL => (* not bound *) | M3AST_AS.DEF_ID(d) => (* Now we can look at the pre-computed set of OBSOLETE DEF_IDs in "d.tmp_unit_id" *) IF IsObsolete(d) THEN M3Error.WarnWithId(used_id, "%s is OBSOLETE", used_id.lx_symrep); END; END; END; END; END Node; PROCEDURE NewHandle(cu: M3AST_AS.Compilation_Unit): Handle RAISES {}= BEGIN (* Set up information on OBSOLETE declarations for this unit, and all imported ones. *) TYPECASE cu.as_root OF | NULL => | M3AST_AS.UNIT_NORMAL(unit) => SetupDefIds(cu); VAR iter := SeqM3AST_AS_Used_interface_id.NewIter(unit.sm_import_s); used_id: M3AST_AS.Used_interface_id; BEGIN WHILE SeqM3AST_AS_Used_interface_id.Next(iter, used_id) DO TYPECASE used_id.sm_def OF | NULL => | M3AST_AS.UNIT_ID(unit_id)=> SetupDefIds(unit_id.sm_spec.sm_comp_unit); ELSE END; END; END ELSE END; RETURN NEW(Handle); END NewHandle; PROCEDURE SetupDefIds(cu: M3AST_AS.Compilation_Unit)= VAR iter := M3CPragma.NewIter(cu.lx_pragmas); pragma: M3CPragma.T; args: TEXT; follower: M3AST_AS.SRC_NODE; bad: BOOLEAN; BEGIN IF GetSeq(cu) # NIL THEN RETURN END; WITH usd = NEW(UniqSeqM3AST_AS_DEF_ID) DO PropertyV.Put(cu.tl_pset, usd); WHILE M3CPragma.Next(iter, pragma) DO IF M3CPragma.Match(pragma, "OBSOLETE", args) THEN follower := M3CPragma.FollowingNode(pragma); bad := FALSE; TYPECASE follower OF | NULL => bad := TRUE; | M3AST_AS.DECL_REVL(d) => ASTWalk.VisitNodes(d, NEW(SetupClosure, rs := usd)); ELSE bad := TRUE END; IF bad THEN M3Error.ReportAtPos(M3CPragma.Position(pragma), "OBSOLETE must precede a declaration or revelation"); END; END; END; END; END SetupDefIds; TYPE SetupClosure = ASTWalk.Closure OBJECT rs: UniqSeqM3AST_AS_DEF_ID; OVERRIDES callback := Setup END; UniqSeqM3AST_AS_DEF_ID = BRANDED REF SeqM3AST_AS_DEF_ID.T; PROCEDURE Setup(cl: SetupClosure; n: AST.NODE; vm: ASTWalk.VisitMode)= BEGIN TYPECASE n OF | M3AST_AS.DEF_ID(d) => SeqM3AST_AS_DEF_ID.AddFront(cl.rs^, d); ELSE END; END Setup; PROCEDURE IsObsolete(d: M3AST_AS.DEF_ID): BOOLEAN= BEGIN WITH cu = d.tmp_unit_id.sm_spec.sm_comp_unit DO VAR iter := SeqM3AST_AS_DEF_ID.NewIter(GetSeq(cu)^); od: M3AST_AS.DEF_ID; BEGIN WHILE SeqM3AST_AS_DEF_ID.Next(iter, od) DO IF d = od THEN RETURN TRUE END; END; END; END; RETURN FALSE; END IsObsolete; PROCEDURE GetSeq(cu: M3AST_AS.Compilation_Unit): UniqSeqM3AST_AS_DEF_ID= BEGIN RETURN PropertyV.Get(cu.tl_pset, TYPECODE(UniqSeqM3AST_AS_DEF_ID)); END GetSeq; BEGIN END M3CChkObsolete.