Copyright (C) 1992, Digital Equipment Corporation
All rights reserved.
See the file COPYRIGHT for a full description.
MODULE M3CharExprsToConsider;
IMPORT AST, ASTWalk;
IMPORT M3AST_AS, M3AST_PG;
IMPORT M3AST_AS_F, M3AST_SM_F, M3AST_PG_F;
IMPORT SeqM3AST_AS_EXP;
IMPORT M3CStdProcs;
IMPORT M3Error;
IMPORT M3CharPreds;
TYPE
BitStack = REF RECORD
head: AST.NODE;
tail: BitStack END;
(* head=NIL is where Es warnings should be skipped *)
PROCEDURE Cons (head: AST.NODE; tail: BitStack): BitStack
RAISES {} =
BEGIN
RETURN NEW(BitStack, head := head, tail := tail)
END Cons;
REVEAL
Handle = Public BRANDED OBJECT
consider, distant: BOOLEAN;
inType : BitStack := NIL
OVERRIDES
callback := Node; END;
PROCEDURE NewHandle (consider, distant: BOOLEAN): Handle
RAISES {} =
BEGIN
RETURN
NEW(Handle, consider := consider, distant := distant).init();
END NewHandle;
PROCEDURE Node (h: Handle; n: AST.NODE; vm: ASTWalk.VisitMode)
RAISES {} =
PROCEDURE NoteUsedId (u: M3AST_AS.USED_ID) =
VAR
e: M3AST_PG.EXTERNAL_ID;
d := u.sm_def;
BEGIN
IF d # NIL AND M3AST_PG.IsA_EXTERNAL_ID(d, e) THEN
IF e # NIL AND e.pg_external # NIL THEN
TYPECASE d OF
| M3AST_AS.TYPED_ID (tid) =>
IF tid.sm_type_spec # NIL
AND M3CharPreds.Tm(tid.sm_type_spec) THEN
M3Error.WarnWithId(
n, "Use of EXTERNAL Tm item %s", u.lx_symrep) END
ELSE END END END;
END NoteUsedId;
BEGIN
TYPECASE n OF
| M3AST_AS.Subrange_type, M3AST_AS.Packed_type =>
CASE vm OF
| ASTWalk.VisitMode.Entry =>
h.inType := Cons(NIL, h.inType);
| ASTWalk.VisitMode.Exit =>
IF h.inType # NIL AND h.inType.head = NIL THEN
h.inType := h.inType.tail
ELSE
M3Error.Report(n, "inType broken") END (*if*); END (*case*);
| M3AST_AS.TYPE_SPEC =>
CASE vm OF
| ASTWalk.VisitMode.Entry =>
IF h.inType # NIL AND h.inType.head = NIL THEN
h.inType := Cons(n, h.inType) END;
| ASTWalk.VisitMode.Exit =>
IF h.inType # NIL AND h.inType.head = n THEN
h.inType := h.inType.tail END; END (*case*);
ELSE END (*typecase*);
IF vm = ASTWalk.VisitMode.Entry THEN
TYPECASE n OF
| M3AST_AS.Exp_used_id (u) => NoteUsedId(u.vUSED_ID);
| M3AST_AS.USED_ID (u) => NoteUsedId(u);
| M3AST_AS.Call (call) =>
VAR
st_call: M3CStdProcs.T;
ta, tb : M3AST_AS.EXP;
tat : M3AST_AS.TYPE_SPEC;
PROCEDURE Grade (ts: M3AST_AS.TYPE_SPEC):
M3CharPreds.Char_Grade =
VAR g: M3CharPreds.Char_Grade;
BEGIN
IF h.consider AND NOT h.distant THEN
IF M3CharPreds.TC(ts, M3CharPreds.Ts) THEN
RETURN M3CharPreds.Char_Grade.TcTs
ELSE
RETURN M3CharPreds.Char_Grade.No END END;
g := M3CharPreds.Grade(ts);
IF g = M3CharPreds.Char_Grade.TcTs AND NOT h.consider THEN
g := M3CharPreds.Char_Grade.No END;
RETURN g;
END Grade;
BEGIN
IF NOT (h.inType # NIL AND h.inType.head = NIL) THEN
IF M3CharPreds.Es(call) THEN
M3Error.Warn(call, "Expr depends on NUM(CHAR)") END; END;
IF M3CStdProcs.IsStandardCall(call, st_call) THEN
ta := SeqM3AST_AS_EXP.First(call.sm_actual_s);
tat := ta.sm_exp_type_spec;
CASE st_call OF
| M3CStdProcs.T.Subarray =>
IF M3CharPreds.Tr(tat) THEN
M3Error.Warn(
call, "SUBARRAY of a changing array"); END;
| M3CStdProcs.T.Ord =>
IF ta.sm_exp_value = NIL AND M3CharPreds.Tn(tat) THEN
M3Error.Warn(
call,
"ORD(var in NUM(CHAR)-dependent type)"); END;
| M3CStdProcs.T.Val =>
tb := SeqM3AST_AS_EXP.Ith(call.sm_actual_s, 1);
IF M3CharPreds.Tn(tb.sm_exp_type_spec) THEN
M3Error.Warn(
call, "VAL(..., NUM(CHAR)-dependent type)"); END;
| M3CStdProcs.T.Loophole =>
CASE Grade(tat) OF
| M3CharPreds.Char_Grade.No =>
| M3CharPreds.Char_Grade.Td =>
M3Error.Warn(
call,
"LOOPHOLE from a type related to CHAR");
| M3CharPreds.Char_Grade.TcTs =>
M3Error.Warn(
call,
"LOOPHOLE from a CHAR-size-dependent type"); END (*case*);
tb := SeqM3AST_AS_EXP.Ith(call.sm_actual_s, 1);
CASE Grade(tb.sm_exp_type_spec) OF
| M3CharPreds.Char_Grade.No =>
| M3CharPreds.Char_Grade.Td =>
M3Error.Warn(
call, "LOOPHOLE to a type related to CHAR");
| M3CharPreds.Char_Grade.TcTs =>
M3Error.Warn(
call,
"LOOPHOLE to a CHAR-size-dependent type"); END (*case*);
| M3CStdProcs.T.Adr =>
CASE Grade(tat) OF
| M3CharPreds.Char_Grade.No =>
| M3CharPreds.Char_Grade.Td =>
M3Error.Warn(
call, "ADR of a type related to CHAR");
| M3CharPreds.Char_Grade.TcTs =>
M3Error.Warn(
call, "ADR of a CHAR-size-dependent type"); END (*case*);
ELSE END; END;
END;
ELSE END (* typecase *);
END (* if *);
END Node;
BEGIN
END M3CharExprsToConsider.