(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: TextExpr.m3 *) (* Last modified on Tue Apr 10 22:38:55 1990 by muller *) (* modified on Thu Feb 15 08:38:27 1990 by kalsow *) MODULE TextExpr; IMPORT Expr, ExprRep, String, Textt, Emit, Temp, Type, Wr; IMPORT Word, Target, Scanner; CONST TextHeader = 3; (* the typecode for text is 1; the refHeader is therefore 3*) TYPE P = Expr.T OBJECT value : String.T; METHODS bind := ExprRep.NoBind; check := Check; compile := Compile; evaluate := ExprRep.Self; fprint := FPrinter; write := Writer; isEqual := EqCheck; getBounds := ExprRep.NoBounds; isWritable := ExprRep.IsNever; isDesignator := ExprRep.IsNever; isZeroes := IsZeroes; genLiteral := GenLiteral; END; CONST NilID = 0; VAR typeDone : BOOLEAN := FALSE; nextID : INTEGER := NilID + 1; PROCEDURE New (value: String.T): Expr.T = VAR p := NEW (P); BEGIN ExprRep.Init (p); p.value := value; p.type := Textt.T; p.bound := TRUE; RETURN p; END New; PROCEDURE Check (p: P) = VAR uid, len, save: INTEGER; BEGIN uid := String.GetUID (p.value); IF (uid >= 0) THEN (* we've already done this one *) RETURN END; len := String.Length (p.value); IF (len > 0) THEN uid := nextID; INC (nextID); ELSE uid := NilID; END; String.SetUID (p.value, uid); (* generate the literal *) IF (len > 0) THEN save := Scanner.offset; Scanner.offset := 0; (* don't care about line numbers *) IF (NOT typeDone) THEN Emit.Op ("typedef struct { int tc; char* str; int len; } TXT;\n" ); typeDone := TRUE; END; IF (len < 45) THEN Emit.OpII ("PRIVATE TXT txt@ = { @, ", uid, TextHeader); Emit.OpSI ("\"@\", @};\n", p.value, len+1); ELSE Emit.OpII ("PRIVATE TXT txt@ = { @,\001\n", uid, TextHeader); Emit.OpSI ("\"@\",\n@\002\n};\n", p.value, len+1); END; Scanner.offset := save; END; END Check; PROCEDURE EqCheck (a: P; e: Expr.T): BOOLEAN = BEGIN TYPECASE e OF | NULL => RETURN FALSE; | P(b) => RETURN (a.value = b.value); ELSE RETURN FALSE; END; END EqCheck; PROCEDURE Compile (p: P): Temp.T = BEGIN RETURN Temp.FromExpr (p); END Compile; PROCEDURE Writer (p: P; <*UNUSED*> t1, t2: Temp.T) = VAR uid: INTEGER; BEGIN uid := String.GetUID (p.value); IF (uid # NilID) THEN Emit.OpI ("((ADDRESS)(& txt@.str))", uid); ELSE Emit.Op ("NULLTEXT"); END; END Writer; PROCEDURE GenLiteral (p: P) = VAR uid: INTEGER; BEGIN uid := String.GetUID (p.value); IF (uid # NilID) THEN Emit.OpI ("((ADDRESS)(& txt@.str))", uid); ELSE Emit.Op ("NULLTEXT"); END; END GenLiteral; PROCEDURE Cat (a, b: Expr.T; VAR c: Expr.T): BOOLEAN = VAR sa, sb: String.T; BEGIN TYPECASE a OF | NULL => RETURN FALSE; | P(p) => sa := p.value; ELSE RETURN FALSE; END; TYPECASE b OF | NULL => RETURN FALSE; | P(p) => sb := p.value; ELSE RETURN FALSE; END; c := New (String.Concat (sa, sb)); RETURN TRUE; END Cat; PROCEDURE FPrinter (p: P; <*UNUSED*> map: Type.Map; wr: Wr.T) = BEGIN Wr.PutText (wr, "\""); String.Put (wr, p.value); Wr.PutText (wr, "\""); END FPrinter; PROCEDURE IsZeroes (p: P): BOOLEAN = BEGIN RETURN (String.GetUID (p.value) = NilID); END IsZeroes; BEGIN END TextExpr.