(* Copyright (C) 1992, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: Stmt.m3 *) (* Last modified on Tue Jun 30 09:39:51 PDT 1992 by kalsow *) (* modified on Tue Jan 16 06:44:48 1990 by muller *) MODULE Stmt EXPORTS Stmt, StmtRep; IMPORT AssertStmt, AssignStmt, BlockStmt, CaseStmt, ExitStmt, ForStmt; IMPORT IfStmt, LockStmt, LoopStmt, RepeatStmt, ReturnStmt, EvalStmt; IMPORT RaiseStmt, TryStmt, TypeCaseStmt, WhileStmt, WithStmt; IMPORT Scanner, Temp, Token, Coverage, Error, Tracer; FROM Scanner IMPORT GetToken, cur; PROCEDURE Parse (READONLY fail: Token.Set): T = TYPE TK = Token.T; VAR fail2: Token.Set; t, first, last: T; BEGIN fail2 := fail + Token.Set{TK.tSEMI}; first := NIL; last := NIL; LOOP CASE cur.token OF | TK.tCONST, TK.tTYPE, TK.tREVEAL, TK.tVAR, TK.tEXTERNAL, TK.tINLINE, TK.tUNUSED, TK.tOBSOLETE, TK.tEXCEPTION, TK.tPROCEDURE, TK.tFATAL, TK.tBEGIN => t := BlockStmt.Parse (fail2, TRUE); | TK.tIDENT, TK.tLPAREN, TK.tARRAY, TK.tRECORD => t := AssignStmt.Parse (fail2); | TK.tASSERT => t := AssertStmt.Parse (fail2); | TK.tCASE => t := CaseStmt.Parse (fail2); | TK.tEXIT => t := ExitStmt.Parse (fail2); | TK.tEVAL => t := EvalStmt.Parse (fail2); | TK.tFOR => t := ForStmt.Parse (fail2); | TK.tIF => t := IfStmt.Parse (fail2); | TK.tLOCK => t := LockStmt.Parse (fail2); | TK.tLOOP => t := LoopStmt.Parse (fail2); | TK.tRAISE => t := RaiseStmt.Parse (fail2); | TK.tREPEAT => t := RepeatStmt.Parse (fail2); | TK.tRETURN => t := ReturnStmt.Parse (fail2); | TK.tTRY => t := TryStmt.Parse (fail2); | TK.tTYPECASE => t := TypeCaseStmt.Parse (fail2); | TK.tWHILE => t := WhileStmt.Parse (fail2); | TK.tWITH => t := WithStmt.Parse (fail2); ELSE RETURN first; END; IF (first = NIL) THEN first := t ELSE last.next := t END; last := t; IF (cur.token # TK.tSEMI) THEN RETURN first END; GetToken (); (* ; *) END; (* RETURN first; *) END Parse; PROCEDURE Init (t: T) = BEGIN t.next := NIL; t.origin := Scanner.offset; Coverage.NoteLine (); END Init; PROCEDURE TypeCheck (t: T; VAR cs: CheckState) = BEGIN WHILE (t # NIL) DO Scanner.offset := t.origin; t.check (cs); t := t.next; END; END TypeCheck; PROCEDURE Compile (t: T): Outcomes = VAR oc, xc: Outcomes; x: T; BEGIN x := t; oc := Outcomes {Outcome.FallThrough}; WHILE (t # NIL) DO Scanner.offset := t.origin; Coverage.CountLine (); Tracer.EmitPending (); Temp.KillValues (); xc := t.compile (); (**** DumpOutcome (t, xc); ****) oc := oc + xc; IF (Outcome.FallThrough IN xc) THEN t := t.next; ELSE IF (t.next # NIL) THEN Scanner.offset := t.next.origin; Error.Warn (1, "unreachable statement"); END; t := NIL; oc := oc - Outcomes {Outcome.FallThrough}; END; END; Tracer.EmitPending (); Temp.KillValues (); (*** DumpOutcome (x, oc); ****) RETURN oc; END Compile; PROCEDURE GetOutcome (t: T): Outcomes = VAR oc, xc: Outcomes; x: T; BEGIN x := t; oc := Outcomes {Outcome.FallThrough}; WHILE (t # NIL) DO xc := t.outcomes (); (**** DumpOutcome (t, xc); ****) oc := oc + xc; IF (Outcome.FallThrough IN xc) THEN t := t.next; ELSE t := NIL; oc := oc - Outcomes {Outcome.FallThrough}; END; END; (*** DumpOutcome (x, oc); ****) RETURN oc; END GetOutcome; (*** PROCEDURE DumpOutcome (t: T; READONLY oc: Outcomes) = CONST Msg = ARRAY [0..7] OF TEXT { "stmt -> {}", "stmt -> {FallThrough}", "stmt -> {Exit}", "stmt -> {FallThrough, Exit}", "stmt -> {Return}", "stmt -> {FallThrough, Return}", "stmt -> {Exit, Return}", "stmt -> {FallThrough, Exit, Return}" }; VAR i := 0; save: INTEGER; BEGIN IF (Outcome.FallThrough IN oc) THEN INC (i, 1) END; IF (Outcome.Exits IN oc) THEN INC (i, 2) END; IF (Outcome.Returns IN oc) THEN INC (i, 4) END; save := Scanner.offset; Scanner.offset := t.origin; Error.Warn (1, Msg[i]); Scanner.offset := save; END DumpOutcome; *****) BEGIN END Stmt.