(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: TryFinStmt.m3 *) (* Last modified on Sat Feb 10 20:41:18 1990 by kalsow *) (* modified on Fri Jan 19 06:15:00 1990 by muller *) MODULE TryFinStmt; IMPORT Scope, Token, Scanner, Stmt, StmtRep, Marker; IMPORT Expr, Variable, Procedure, ReturnStmt, String; FROM Stmt IMPORT Outcome; TYPE P = Stmt.T OBJECT body : Stmt.T; finally : Stmt.T; METHODS bind := Bind; check := Check; precompile := Precompile; compile := Compile; END; VAR labelPrefix : String.T := NIL; nextID : INTEGER := 0; PROCEDURE Parse (body: Stmt.T; READONLY fail: Token.Set): Stmt.T = TYPE TK = Token.T; VAR p: P; BEGIN p := NEW (P); StmtRep.Init (p); p.body := body; Scanner.Match (TK.tFINALLY, fail, Token.Set {TK.tEND} + Token.StmtStart); p.finally := Stmt.Parse (fail + Token.Set {TK.tEND}); Scanner.Match (TK.tEND, fail, Token.Set {}); RETURN p; END Parse; PROCEDURE Bind (p: P) = BEGIN Stmt.Bind (p.body); Stmt.Bind (p.finally); END Bind; PROCEDURE Check (p: P) = BEGIN Marker.PushFinally (NIL, 0); Stmt.TypeCheck (p.body); Marker.Pop (); Stmt.TypeCheck (p.finally); END Check; PROCEDURE Precompile (p: P) = BEGIN Marker.PushFinally (NIL, 0); Stmt.Precompile (p.body); Marker.Pop (); Stmt.Precompile (p.finally); END Precompile; PROCEDURE Compile (p: P): Stmt.Outcomes = VAR label: INTEGER; returnSeen, exitSeen: BOOLEAN; oc, xc, o: Stmt.Outcomes; BEGIN label := nextID; INC (nextID); IF (labelPrefix = NIL) THEN labelPrefix := String.Add ("finally_") END; Marker.StartOfFinally (labelPrefix, label); oc := Stmt.Compile (p.body); Marker.MiddleOfFinally (labelPrefix, label, returnSeen, exitSeen); xc := Stmt.Compile (p.finally); Marker.EndOfFinally (labelPrefix, label, returnSeen, exitSeen); o := Stmt.Outcomes {}; IF Outcome.FallThrough IN xc THEN IF Outcome.FallThrough IN oc THEN o := o + Stmt.Outcomes {Outcome.FallThrough}; END; IF Outcome.Exits IN oc THEN o := o + Stmt.Outcomes {Outcome.Exits}; END; IF Outcome.Returns IN oc THEN o := o + Stmt.Outcomes {Outcome.Returns}; END; END; IF Outcome.Exits IN xc THEN o := o + Stmt.Outcomes {Outcome.Exits}; END; IF Outcome.Returns IN xc THEN o := o + Stmt.Outcomes {Outcome.Returns}; END; RETURN o; END Compile; BEGIN END TryFinStmt.