* For information about this program, contact Blair MacIntyre * (bm@cs.columbia.edu) or Steven Feiner (feiner@cs.columbia.edu) * at the Computer Science Dept., Columbia University, * 1214 Amsterdam Ave. Mailstop 0401, New York, NY, 10027. * * Copyright (C) 1995, 1996 by The Trustees of Columbia University in the * City of New York. Blair MacIntyre, Computer Science Department. * * This file is released under the same conditions as Pickle.m3. See COPYRIGHT. *
UNSAFE MODULE; IMPORT Rd, Wr, RTPacking, RTTypeMap, Thread, ConvertPacking, RTHeap, IO, Fmt; PROCEDURE PklTipeMap Read (v: ConvertPacking.ReadVisitor; r: REFANY; tc: TypeCode; from: RTPacking.T; to: RTPacking.T; READONLY shape: ARRAY OF INTEGER) RAISES {Error, Rd.EndOfFile, Rd.Failure, Thread.Alerted} = VAR nDim, fromEltPack, toEltPack: INTEGER; converter: ConvertPacking.T; addr := RTHeap.GetDataAdr(r); size: INTEGER := 1; BEGIN TRY converter := ConvertPacking.New(tc, from, to, nDim, fromEltPack, toEltPack); (* converter.print(); *) IF nDim # NUMBER(shape) THEN RAISE Error("Incorrect number of shape parameters"); END; IF nDim > 0 THEN (* Get the number of repetitions of the basic type in r *) FOR i := FIRST(shape) TO LAST(shape) DO size := size * shape[i]; END; (* SRC Modula-3 restriction: OpenArray elements are byte aligned, so we can depend on this! *) <* ASSERT fromEltPack MOD 8 = 0 AND toEltPack MOD 8 = 0 *> fromEltPack := fromEltPack DIV 8; toEltPack := toEltPack DIV 8;
FOR i := 1 TO size DO WITH nextAddr = converter.convertRead(addr, v) DO <* ASSERT addr + toEltPack = nextAddr *> addr := nextAddr; END; END;
WITH nextAddr = converter.convertRead(addr, v, size) DO <* ASSERT addr + toEltPack * size = nextAddr *> END; ELSE
WITH nextAddr = converter.convertRead(addr, v) DO
WITH nextAddr = converter.convertRead(addr, v, 1) DO WITH size = RTHeap.GetDataSize(r) DO IF size # nextAddr - addr THEN IO.Put("convertRead error! size (" & Fmt.Int(size) & ") not equal to nextAddr - addr (" & Fmt.Int(nextAddr-addr) & ") in conversion:\n"); converter.print(); <* ASSERT size = nextAddr - addr *> END; END; END; END; EXCEPT | ConvertPacking.Error(t) => RAISE Error("ConvertPacking.convert Error: " & t); END; END Read; TYPE ReadVisitor = RTTypeMap.Visitor OBJECT start: ADDRESS; OVERRIDES apply := VisitRead; END; CONST KindStr = ARRAY RTTypeMap.Kind OF TEXT{ "Ref", "UntracedRef", "Proc", (* traced ref, untraced ref, procedure *) "Real", "Longreal", "Extended", (* floating point value *) "Int_1", "Int_2", "Int_4", "Int_8", (* 1, 2, 4, or 8 byte signed integer *) "Word_1", "Word_2", "Word_4", "Word_8", (* 1, 2, 4, or 8 byte unsigned integer *) "Int_Field", "Word_Field", (* signed or unsigned bit field *) "Set" (* bit set *) }; PROCEDUREVisitRead (v: ReadVisitor; field: ADDRESS; kind: RTTypeMap.Kind) = BEGIN WITH offset = LOOPHOLE(field - v.start, INTEGER) DO IO.Put("offset: " & Fmt.Int(offset) & " = " & KindStr[kind] & "\n"); END; END VisitRead; CONST RefFields = RTTypeMap.Mask { RTTypeMap.Kind.Ref, RTTypeMap.Kind.UntracedRef, RTTypeMap.Kind.Proc, RTTypeMap.Kind.Real, RTTypeMap.Kind.Longreal, RTTypeMap.Kind.Extended, RTTypeMap.Kind.Int_1, RTTypeMap.Kind.Int_2, RTTypeMap.Kind.Int_4, RTTypeMap.Kind.Int_8, RTTypeMap.Kind.Word_1, RTTypeMap.Kind.Word_2, RTTypeMap.Kind.Word_4, RTTypeMap.Kind.Word_8, RTTypeMap.Kind.Int_Field, RTTypeMap.Kind.Word_Field, RTTypeMap.Kind.Set }; PROCEDUREWrite (v: ConvertPacking.WriteVisitor; r: REFANY; tc: TypeCode; from: RTPacking.T; READONLY shape: ARRAY OF INTEGER; n: INTEGER) RAISES { Error, Wr.Failure, Thread.Alerted } = VAR nDim, fromEltPack, toEltPack: INTEGER; converter: ConvertPacking.T; addr := RTHeap.GetDataAdr(r); size: INTEGER := 1; BEGIN TRY converter := ConvertPacking.New(tc, from, from, nDim, fromEltPack, toEltPack); IF nDim # n THEN RAISE Error("Incorrect number of shape parameters"); END; IF nDim > 0 THEN (* Get the number of repetitions of the basic type in r *) FOR i := FIRST(shape) TO LAST(shape) DO size := size * shape[i]; END; (* SRC Modula-3 restriction: OpenArray elements are byte aligned, so we can depend on this! *) <* ASSERT fromEltPack MOD 8 = 0 AND toEltPack MOD 8 = 0 *> (* The machine is the same!! *) <* ASSERT fromEltPack = toEltPack *> toEltPack := toEltPack DIV 8;
FOR i := 1 TO size DO WITH nextAddr = converter.write(addr, v) DO <* ASSERT addr + toEltPack = nextAddr *> addr := nextAddr; END; END;
WITH nextAddr = converter.write(addr, v, size) DO <* ASSERT addr + toEltPack*size = nextAddr *> END; ELSE
WITH nextAddr = converter.write(addr, v) DO
WITH nextAddr = converter.write(addr, v, 1) DO WITH size = RTHeap.GetDataSize(r) DO IF size # nextAddr - addr THEN IO.Put("converter.write error! size (" & Fmt.Int(size) & ") not equal to nextAddr - addr (" & Fmt.Int(nextAddr-addr) & ") in conversion:\n"); converter.print(); <*FATAL ANY*> BEGIN RTTypeMap.WalkRef(r, RefFields, NEW(ReadVisitor, start := addr)); END; <* ASSERT size = nextAddr - addr *> END; (* converter.print();*) END; END; END; EXCEPT | ConvertPacking.Error(t) => RAISE Error("ConvertPacking.write Error: " & t); END; END Write; BEGIN END PklTipeMap.