(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: RepeatStmt.m3 *) (* Last modified on Sat Feb 10 20:40:43 1990 by kalsow *) (* modified on Tue Oct 10 18:42:03 1989 by muller *) MODULE RepeatStmt; IMPORT Expr, Type, Bool, Error, Emit, Stmt, StmtRep; IMPORT Temp, String, Token, Scanner, Marker; TYPE P = Stmt.T OBJECT body : Stmt.T; expr : Expr.T; METHODS bind := Bind; check := Check; precompile := Precompile; compile := Compile; END; VAR labelPrefix : String.T := NIL; nextID : INTEGER := 0; PROCEDURE Parse (READONLY fail: Token.Set): Stmt.T = TYPE TK = Token.T; VAR p: P; BEGIN p := NEW (P); StmtRep.Init (p); Scanner.Match (TK.tREPEAT, fail, Token.Set {TK.tUNTIL} + Token.StmtStart); p.body := Stmt.Parse (fail + Token.Set {TK.tUNTIL}); Scanner.Match (TK.tUNTIL, fail, Token.Set {}); p.expr := Expr.Parse (fail); RETURN p; END Parse; PROCEDURE Bind (p: P) = BEGIN Stmt.Bind (p.body); Expr.Bind (p.expr); END Bind; PROCEDURE Check (p: P) = VAR t: Type.T; BEGIN Marker.PushExit (NIL, 0); Stmt.TypeCheck (p.body); Marker.Pop (); Expr.TypeCheck (p.expr); t := Expr.TypeOf (p.expr); IF (Type.Base (t) # Bool.T) THEN Error.Msg ("REPEAT condition must be a BOOLEAN"); END; END Check; PROCEDURE Precompile (p: P) = BEGIN Marker.PushExit (NIL, 0); Stmt.Precompile (p.body); Marker.Pop (); END Precompile; PROCEDURE Compile (p: P): Stmt.Outcomes = VAR x: Temp.T; label: INTEGER; oc: Stmt.Outcomes; BEGIN label := nextID; INC (nextID); IF (labelPrefix = NIL) THEN labelPrefix := String.Add ("repeat_") END; Emit.Op ("do {\n\001"); Marker.PushExit (labelPrefix, label); oc := Stmt.Compile (p.body); Marker.Pop (); x := Expr.Compile (p.expr); Emit.OpT ("\002} while (! @);\n", x); IF (Stmt.Outcome.Exits IN oc) THEN Emit.OpSI ("@@: /**/;\n", labelPrefix, label); oc := oc + Stmt.Outcomes {Stmt.Outcome.FallThrough} - Stmt.Outcomes {Stmt.Outcome.Exits}; END; Temp.Free (x); RETURN oc; END Compile; BEGIN END RepeatStmt.