TargetConversionsImpl:
CEDAR
PROGRAM
IMPORTS Basics, Basics16, OSMiscOps, Rope, SafeStorage
EXPORTS TargetConversions
SHARES Rope
= BEGIN OPEN TargetConversions, TargetConversionsPrivate;
This implementation is customized to Dragon, although I hope to have shown where other machines can be plugged in.
In the external implementation more significant bytes are put out before less significant bytes for multi-byte numbers.
This implementation assumes that in the declaration PACKED ARRAY Index OF BOOL the more significant bits have lower indexes than the less significant bits. We also assume that the representations for packed arrays that occupy bitsPerWord bits can be freely overlaid EXCEPT for packed arrays where the element size is bitsPerWord bits.
Utilities
bank: CARD = 65536;
bigEndianOrder: Bytes = LOOPHOLE[(1*bank)+(2*256+3)];
littleEndianOrder: Bytes = LOOPHOLE[(3*256*bank+2*bank)+(1*256)];
princOpsOrder: Bytes = LOOPHOLE[(2*256*bank+3*bank)+(1)];
byteOrder: Bytes = [0, 1, 2, 3];
Useful for fixing up byte order
Half:
TYPE =
PACKED
ARRAY [0..bitsPerHalf)
OF [0..1];
bitsPerHalf: NAT = bitsPerWord/2;
nullHalf: Half = LOOPHOLE[0];
onesHalf: Half = LOOPHOLE[177777B];
Halves: TYPE = PACKED ARRAY [0..1] OF Half;
HalfShift:
PROC [x: Half, len:
INTEGER]
RETURNS [Half] =
INLINE {
RETURN [LOOPHOLE[Basics16.BITSHIFT[LOOPHOLE[x], len]]];
};
HalfAnd:
PROC [x,y: Half]
RETURNS [Half] =
INLINE {
RETURN [LOOPHOLE[Basics16.BITAND[LOOPHOLE[x], LOOPHOLE[y]]]];
};
HalfOr:
PROC [x,y: Half]
RETURNS [Half] =
INLINE {
RETURN [LOOPHOLE[Basics16.BITOR[LOOPHOLE[x], LOOPHOLE[y]]]];
};
WordAnd:
PROC [x,y: Word]
RETURNS [Word] =
INLINE {
RETURN [LOOPHOLE[Basics.BITAND[LOOPHOLE[x], LOOPHOLE[y]]]];
};
WordOr:
PROC [x,y: Word]
RETURNS [Word] =
INLINE {
RETURN [LOOPHOLE[Basics.BITOR[LOOPHOLE[x], LOOPHOLE[y]]]];
};
BitOffsetInByte:
PROC [bits:
INT]
RETURNS [[0..7]] =
INLINE {
RETURN [Basics16.BITAND[7, Basics.LowHalf[LOOPHOLE[bits]]]];
};
BitOffsetInWord:
PROC [bits:
INT]
RETURNS [BitIndex] =
INLINE {
RETURN [Basics16.BITAND[LAST[BitIndex], Basics.LowHalf[LOOPHOLE[bits]]]];
};
ShiftBitsLeft:
PROC [word: Word, shift: BitLength]
RETURNS [Word] =
--INLINE-- {
halves: Halves ¬ LOOPHOLE[word, Halves];
halves[0] ¬ HalfOr[HalfShift[halves[0], shift], HalfShift[halves[1], shift-bitsPerHalf]];
halves[1] ¬ HalfShift[halves[1], shift];
RETURN [LOOPHOLE[halves]];
};
ShiftBitsRight:
PROC [word: Word, shift: BitLength]
RETURNS [Word] =
--INLINE-- {
halves: Halves ¬ LOOPHOLE[word, Halves];
halves[1] ¬ HalfOr[HalfShift[halves[1], -shift], HalfShift[halves[0], bitsPerHalf-shift]];
halves[0] ¬ HalfShift[halves[0], -shift];
RETURN [LOOPHOLE[halves]];
};
MaskBitsLeft:
PROC [bits32: Word, leftBits: BitLength]
RETURNS [Word] =
--INLINE-- {
halves: Halves ¬ LOOPHOLE[bits32, Halves];
SELECT leftBits
FROM
<= bitsPerHalf => {
halves[0] ¬ HalfAnd[halves[0], HalfShift[onesHalf, bitsPerHalf-leftBits]];
halves[1] ¬ nullHalf;
};
< bitsPerWord =>
halves[1] ¬ HalfAnd[halves[1], HalfShift[onesHalf, bitsPerWord-leftBits]];
ENDCASE;
RETURN [LOOPHOLE[halves]];
};
BitsToBytes:
PROC [bits:
CARD]
RETURNS [
CARD] =
INLINE {
RETURN [Basics.BITRSHIFT[bits, 3]];
};
SignCheck:
PROC [int: Int32, rightBits: BitLength] = {
SELECT rightBits
FROM
0 => ERROR InvalidArgument;
< bitsPerWord => {
limit: Int32 = Bits32ToInt32[ShiftBitsLeft[Int32ToBits32[1], rightBits-1]];
IF int NOT IN [-limit..limit) THEN ERROR InvalidArgument;
};
ENDCASE;
};
SignExtend:
PROC [int: Int32, rightBits: BitLength]
RETURNS [Int32] = {
Sign extension, with the assumption that the left bits (bitsPerWord-rightBits) are all zeros.
bits32: Bits32 ¬ Int32ToBits32[int];
SELECT rightBits
FROM
0 => ERROR InvalidArgument;
< bitsPerWord => {
signBitOn: Bits32 ¬ nullBits32;
signIndex: BitIndex ¬ bitsPerWord-rightBits;
signBitOn[signIndex] ¬ 1;
bits32[signIndex] ¬ ORD[NOT VAL[bits32[signIndex]]];
int ¬ Bits32ToInt32[Card32ToBits32[Bits32ToCard32[bits32]-Bits32ToCard32[signBitOn]]];
};
ENDCASE;
RETURN [int];
};
EnsureBytes:
PROC [writer: Writer, bytes:
NAT]
RETURNS [
REF
TEXT] = {
buffer: REF TEXT ¬ writer.buffer;
bufLen: NAT ¬ bytes;
IF bytes > buffer.maxLength
THEN
TRUSTED {
oldLen: NAT ¬ buffer.length;
newLen: NAT ¬ IF bytes > LAST[NAT]/2 THEN bytes+256 ELSE bytes*2;
new: REF TEXT ¬ z.NEW[TEXT[newLen]];
new.length ¬ bytes;
OSMiscOps.Copy[
from: LOOPHOLE[buffer, LONG POINTER] + SIZE[TEXT[0]],
nwords: WORDS[TEXT[oldLen]] - WORDS[TEXT[0]],
to: LOOPHOLE[new, LONG POINTER] + SIZE[TEXT[0]]];
writer.buffer ¬ buffer ¬ new;
};
RETURN [buffer];
};
FlushWriterWord:
PROC [writer: Writer] = {
IF writer.dirty
THEN {
word: Bits32 = writer.partialWord;
buffer: REF TEXT;
bytes: Bytes ¬ Bits32ToBytes[word];
bits: INT ¬ writer.bitPos;
offset: BitIndex = BitOffsetInWord[bits];
bPos: CARDINAL;
IF offset # 0 THEN bits ¬ bits - offset;
bPos ¬ BitsToBytes[bits];
buffer ¬ EnsureBytes[writer, bPos+bytesPerWord];
TRUSTED {
OSMiscOps.Copy[
from: @bytes,
nwords: WORDS[Bytes],
to: LOOPHOLE[buffer, LONG POINTER] + SIZE[TEXT[bPos]]];
};
writer.dirty ¬ FALSE;
};
};
AdvanceWriterPos:
PROC [writer: Writer, new:
INT] = {
newOffset: BitIndex ¬ BitOffsetInWord[new];
old: INT ¬ writer.bitPos;
oldOffset: BitIndex ¬ BitOffsetInWord[old];
buffer: REF TEXT ¬ writer.buffer;
IF new > writer.bitsWritten THEN writer.bitsWritten ¬ new;
IF (new-newOffset) # (old-oldOffset)
THEN {
The old partial word is no longer valid
IF writer.dirty THEN FlushWriterWord[writer];
IF new >= writer.bitsWritten
THEN {
Writing to extend the length
bPos: INT ¬ BitsToBytes[new+(bitsPerWord-1)];
buffer ¬ EnsureBytes[writer, bPos];
writer.partialWord ¬ nullWord;
buffer.length ¬ bPos;
}
ELSE {
We need to get a new partial word from the buffer
bPos: NAT ¬ BitsToBytes[new-newOffset];
bytes: Bytes ¬ nullBytes;
TRUSTED {
OSMiscOps.Copy[
from: LOOPHOLE[buffer, LONG POINTER] + SIZE[TEXT[bPos]],
nwords: WORDS[Bytes],
to: @bytes];
};
writer.partialWord ¬ BytesToBits32[bytes];
};
};
writer.bitPos ¬ new;
};
PutBits32:
PROC [writer: Writer, bits32: Bits32, start: BitIndex, bits: BitLength, mask:
BOOL ¬
FALSE] = {
Puts out the given unsigned number using the low-order BitLength bits.
IF bits # 0
THEN {
pos: INT ¬ writer.bitPos;
offset: BitIndex ¬ BitOffsetInWord[pos];
rem: NAT ¬ (bitsPerWord-offset);
IF start+bits > bitsPerWord THEN ERROR InvalidArgument;
IF start # 0 THEN bits32 ¬ ShiftBitsLeft[bits32, start];
IF mask THEN bits32 ¬ MaskBitsLeft[bits32, bits];
IF offset # 0
THEN {
There are already bits in the output buffer
writer.partialWord ¬ WordOr[writer.partialWord, ShiftBitsRight[bits32, offset]];
writer.dirty ¬ TRUE;
bits32 ¬ ShiftBitsLeft[bits32, rem];
IF bits < rem
THEN {
No need yet to force out a complete word.
new: INT ¬ writer.bitPos ¬ pos + bits;
IF new > writer.bitsWritten THEN writer.bitsWritten ¬ new;
RETURN;
};
AdvanceWriterPos[writer, pos ¬ pos + rem];
bits ¬ bits - rem;
};
IF bits # 0
THEN {
Aligned and stuff to move into the partial word.
writer.partialWord ¬ bits32;
writer.dirty ¬ TRUE;
AdvanceWriterPos[writer, pos ¬ pos + bits];
};
};
};
GetBits32:
PROC [reader: Reader, start: BitIndex, len: BitLength]
RETURNS [bits32: Bits32 ¬ nullBits32] = {
IF len # 0
THEN {
offset: BitIndex ¬ BitOffsetInWord[reader.bitsRead];
rem: NAT = bitsPerWord - offset;
bitsAvail: INT = reader.bitsLength-reader.bitsRead;
index: INT ¬ reader.bytesRead;
lastByteIndex: INT ¬ reader.lastByteIndex;
IF bitsAvail < len THEN ERROR InsufficientBits;
IF start+len > bitsPerWord THEN ERROR InvalidArgument;
bits32 ¬ MaskBitsLeft[ShiftBitsLeft[reader.partialWord, offset], len];
The valid bits are all left-justified, other bits are 0s
IF len > rem
THEN {
We must read some more to get enough
ReadAhead[reader];
bits32 ¬ WordOr[bits32, ShiftBitsRight[reader.partialWord, len-rem]];
IF start+len # bitsPerWord THEN bits32 ¬ MaskBitsLeft[bits32, len];
};
At this point bits32 is left-justified, and right-padded with 0s.
IF start # 0 THEN bits32 ¬ ShiftBitsRight[bits32, start];
reader.bitsRead ¬ reader.bitsRead + len;
IF BitOffsetInWord[reader.bitsRead] = 0
THEN ReadAhead[reader];
We exhausted the bits in the partial word, so we need some more
};
};
ReadAhead:
PROC [reader: Reader] = {
index: INT ¬ reader.bytesRead;
lastByteIndex: INT ¬ reader.lastByteIndex;
bytes: Bytes ¬ nullBytes;
FOR i: ByteIndex
IN ByteIndex
DO
x: INT ¬ index+i;
IF x > lastByteIndex THEN EXIT;
bytes[i] ¬ CharToByte[Rope.Fetch[reader.buffer, x]];
reader.bytesRead ¬ x+1;
ENDLOOP;
reader.partialWord ¬ BytesToBits32[bytes];
};
Bits32ToByteSequence:
PROC
[bits32: Bits32, start: BitIndex, len: BitLength, mask:
BOOL ¬
FALSE]
RETURNS [ByteSequence ¬
NIL] = {
IF start # 0 THEN bits32 ¬ ShiftBitsLeft[bits32, start];
IF mask THEN bits32 ¬ MaskBitsLeft[bits32, len];
IF len # 0
THEN {
bytes: Bytes = Bits32ToBytes[bits32];
byteLen: ByteLength = (len+7)/8;
new: Rope.Text ¬ z.NEW[Rope.TextRep[byteLen]];
new.length ¬ byteLen;
FOR i: NAT IN [0..byteLen) DO new[i] ¬ ByteToChar[bytes[i]]; ENDLOOP;
RETURN [new];
};
};
ByteSequenceToBits32:
PROC [seq: ByteSequence, start: BitIndex, len: BitLength]
RETURNS [bits32: Bits32 ¬ nullBits32] = {
bytes: Bytes ¬ nullBytes;
byteLen: ByteLength = (len+7)/8;
IF byteLen > Rope.Length[seq] THEN ERROR InvalidArgument;
FOR i:
NAT
IN [0..byteLen)
DO
bytes[i] ¬ CharToByte[Rope.Fetch[seq, i]];
ENDLOOP;
bits32 ¬ BytesToBits32[bytes];
SELECT start+len
FROM
> bitsPerWord => ERROR InvalidArgument;
< bitsPerWord => IF len MOD 8 # 0 THEN bits32 ¬ MaskBitsLeft[bits32, len];
ENDCASE;
IF start # 0 THEN bits32 ¬ ShiftBitsRight[bits32, start];
};
Bit Stream Writers
NewWriter:
PUBLIC
PROC
RETURNS [Writer] = {
Returns a new bit stream writer with no bits.
RETURN [NEW[WriterRep ¬ [bitsWritten: 0, partialWord: nullWord, dirty: FALSE, buffer: z.NEW[TEXT[16]]]]];
};
ResetWriter:
PUBLIC
PROC [writer: Writer] = {
Resets the writer to ground zero, but retains intermediate storage for the sake of efficiency.
writer.bitsWritten ¬ writer.bitPos ¬ 0;
writer.partialWord ¬ nullWord;
writer.buffer.length ¬ 0;
writer.dirty ¬ FALSE;
};
WriterContents:
PUBLIC
PROC [writer: Writer]
RETURNS [ByteSequence ¬
NIL] = {
Returns the byte sequence corresponding to the currently written contents of the given writer. NIL will be returned if there are no bits in the stream.
nB: NAT = BitsToBytes[writer.bitsWritten+7];
IF writer.dirty THEN FlushWriterWord[writer]; -- force out the partial word
IF nB # 0
THEN
TRUSTED {
overhead: NAT = SIZE[TEXT[0]];
contents: Rope.Text ¬ z.NEW[Rope.TextRep[nB]];
contents.length ¬ nB;
OSMiscOps.Copy[
from: LOOPHOLE[writer.buffer, LONG POINTER] + overhead,
nwords: WORDS[TEXT[nB]] - WORDS[TEXT[0]],
to: LOOPHOLE[contents, LONG POINTER] + overhead];
RETURN [contents];
};
};
BitsWritten:
PUBLIC
PROC [writer: Writer]
RETURNS [
INT] = {
Returns the number of bits currently written to the stream. Useful for hairy alignment problems not covered by PutAlignment.
RETURN [writer.bitsWritten];
};
PutBool:
PUBLIC
PROC [writer: Writer, bool: Bool] = {
Puts out the given 1-bit boolean value.
PutBits32[writer, Card32ToBits32[ORD[bool]], bitsPerWord-1, 1];
};
PutByteSeq:
PUBLIC
PROC [writer: Writer, seq: ByteSequence, len:
INT] = {
Puts out the first len bytes of the given byte sequence.
IF len > 0
THEN {
buffer: REF TEXT = EnsureBytes[writer, len];
offset: BitIndex = BitOffsetInWord[writer.bitsWritten];
IF offset # 0 THEN ERROR NotAligned;
FOR i:
INT
IN [0..len)
DO
PutBits32[writer, CharToBits32[Rope.Fetch[seq, i]], bitsPerWord-8, 8];
ENDLOOP;
};
};
PutCard:
PUBLIC
PROC [writer: Writer, card: Card32, bits: BitLength] = {
Puts out the given unsigned number using the low-order BitLength bits.
IF bits # 0 THEN PutBits32[writer, Card32ToBits32[card], bitsPerWord-bits, bits];
};
PutCard32:
PUBLIC
PROC [writer: Writer, card: Card32] = {
Puts out the given bitsPerWord-bit unsigned number. PutCard32[w, c] is the same as (but faster than) PutCard[w, c, bitsPerWord].
PutBits32[writer, Card32ToBits32[card], 0, bitsPerWord];
};
PutChar:
PUBLIC
PROC [writer: Writer, char: Char] = {
Puts out the given character.
PutBits32[writer, CharToBits32[char], bitsPerWord-8, 8];
};
PutInt:
PUBLIC
PROC [writer: Writer, int: Int32, bits: BitLength] = {
Puts out the given signed number using the low-order bits of int. The given Int32 number must have correct sign extension (not currently checked for).
SignCheck[int, bits];
PutBits32[writer, Int32ToBits32[int], bitsPerWord-bits, bits];
};
PutInt32:
PUBLIC PROC [writer: Writer, int: Int32] = {
Puts out the given bitsPerWord-bit signed number. PutInt32[w, i] is the same as (but faster than) PutInt[w, i, bitsPerWord].
PutBits32[writer, Int32ToBits32[int], 0, bitsPerWord];
};
PutPadBits:
PUBLIC PROC [writer: Writer, bits: BitLength] = {
Puts out the requested number of padding bits.
PutBits32[writer, nullBits32, 0, bits];
};
PutReal:
PUBLIC PROC [writer: Writer, real: Real] = {
Puts out the given Real.
WITH real
SELECT
FROM
real32: real32 Real => PutBits32[writer, Real32ToBits32[real32.real32], 0, bitsPerWord];
ENDCASE => ERROR NotImplemented;
};
SetOutputIndex:
PUBLIC PROC [writer: Writer, bits:
INT] = {
Sets the bit position in the writer.
SELECT
TRUE
FROM
bits < 0 => ERROR InvalidArgument;
BitsToBytes[bits] > (LAST[NAT]-20) => ERROR InvalidArgument;
ENDCASE;
AdvanceWriterPos[writer, bits];
};
GetOutputIndex:
PUBLIC
PROC [writer: Writer]
RETURNS [
INT] = {
Returns the bit position in the writer.
RETURN [writer.bitPos];
};
Bit Stream Readers
NewReader:
PUBLIC
PROC [seq: ByteSequence, start:
INT ¬ 0, len:
INT ¬
LAST[
INT]]
RETURNS [reader: Reader] = {
Returns a new bit stream Reader with initial contents given by the ByteSequence.
reader ¬ z.NEW[ReaderRep];
InitReader[reader, seq, start, len];
};
InitReader:
PUBLIC
PROC [reader: Reader, seq: ByteSequence, start:
INT ¬ 0, len:
INT ¬
LAST[
INT]] = {
Initializes an existing Reader with contents given by the ByteSequence.
lim: INT = Rope.Length[seq];
IF start < 0 OR start > lim THEN ERROR InvalidArgument;
IF len < 0 THEN len ¬ 0 ELSE len ¬ MIN[len, lim-start];
reader ¬ [
bitsRead: 0,
bytesRead: start,
lastByteIndex: start+len-1,
bitsLength: len*8,
partialWord: nullWord,
buffer: seq];
IF reader.bitsLength # 0 THEN ReadAhead[reader];
};
RemainingBits:
PUBLIC
PROC [reader: Reader]
RETURNS [
INT] = {
Returns the number of remaining bits in the reader.
RETURN [reader.bitsLength-reader.bitsRead];
};
BitsRead:
PUBLIC
PROC [reader: Reader]
RETURNS [
INT] = {
Returns the number of remaining bits read from the reader.
RETURN [reader.bitsRead];
};
GetBool:
PUBLIC
PROC [reader: Reader]
RETURNS [Bool] = {
Reads a 1-bit boolean value.
bits32: Bits32 = GetBits32[reader, 0, 1];
RETURN [VAL[bits32[0]]];
};
GetByteSequence:
PUBLIC
PROC [reader: Reader, len:
INT]
RETURNS [ByteSequence] = {
Reads a sequence of bytes, len gives the number of bytes.
offset: BitIndex ¬ BitOffsetInWord[reader.bitsRead];
IF offset # 0 THEN ERROR NotAligned;
IF len > 0
THEN {
lim: NAT ¬ len;
new: Rope.Text ¬ z.NEW[Rope.TextRep[lim]];
FOR pos:
NAT
IN [0..lim)
DO
new[pos] ¬ ByteToChar[Bits32ToBytes[GetBits32[reader, 0, 8]][0]];
ENDLOOP;
RETURN [new];
};
RETURN [NIL];
};
GetCard:
PUBLIC
PROC [reader: Reader, bits: BitLength]
RETURNS [Card32 ¬ 0] = {
Reads an unsigned number, # of bits given by BitLength.
IF bits # 0
THEN {
bits32: Bits32 = GetBits32[reader, bitsPerWord-bits, bits];
RETURN [Bits32ToCard32[bits32]];
};
};
GetCard32:
PUBLIC
PROC [reader: Reader]
RETURNS [Card32] = {
Reads a bitsPerWord-bit unsigned number.
RETURN [Bits32ToCard32[GetBits32[reader, 0, bitsPerWord]]];
};
GetChar:
PUBLIC
PROC [reader: Reader]
RETURNS [Char] = {
Reads an 8-bit character.
RETURN [Bits32ToChar[GetBits32[reader, bitsPerWord-8, 8]]];
};
GetInt:
PUBLIC
PROC [reader: Reader, bits: BitLength]
RETURNS [Int32 ¬ 0] = {
Reads a signed number, # of bits given by BitLength, and properly extends the sign (if necessary).
IF bits = 0 THEN ERROR InvalidArgument;
RETURN [SignExtend[Bits32ToInt32[GetBits32[reader, bitsPerWord-bits, bits]], bits]];
};
GetInt32:
PUBLIC
PROC [reader: Reader]
RETURNS [Int32] = {
Reads a bitsPerWord-bit signed number.
RETURN [Bits32ToInt32[GetBits32[reader, 0, bitsPerWord]]];
};
SkipPadBits:
PUBLIC
PROC [reader: Reader, bits: BitLength] = {
Skips a given number of padding bits.
[] ¬ GetBits32[reader, 0, bits];
};
GetReal:
PUBLIC
PROC [reader: Reader, kind: RealKind ¬ real32]
RETURNS [Real] = {
Reads an IEEE floating-point number with the specified number of bits.
IF kind # real32 THEN ERROR NotImplemented;
RETURN [[real32[Bits32ToReal32[GetBits32[reader, 0, bitsPerWord]]]]];
};
SetInputIndex:
PUBLIC
PROC [reader: Reader, bits:
INT] = {
Sets the bit position in the reader.
offset: BitIndex;
SELECT bits
FROM
< 0, > reader.bitsLength => ERROR InvalidArgument;
ENDCASE;
offset ¬ BitOffsetInWord[bits];
IF offset # 0 THEN bits ¬ bits - offset;
reader.bytesRead ¬ BitsToBytes[bits];
ReadAhead[reader];
IF offset # 0 THEN [] ¬ GetBits32[reader, 0, offset];
};
Simple Types to Byte Sequences
These operations are present for efficiency. An operation of the form &ToByteSeq[&&] has the same behavior (more or less) as:
{w: Writer ← NewWriter[]; Put&[w, &&]; RESULT[BitStreamToByteSeq[w]]};
BoolToByteSeq:
PUBLIC
PROC [bool: Bool]
RETURNS [ByteSequence] = {
bits32: Bits32 ¬ nullBits32;
bits32[0] ¬ ORD[bool];
RETURN [Bits32ToByteSequence[bits32, 0, 1]];
};
CardToByteSeq:
PUBLIC
PROC [card: Card32, bits: BitLength]
RETURNS [ByteSequence] = {
RETURN [Bits32ToByteSequence[Card32ToBits32[card], bitsPerWord-bits, bits]];
};
Card32ToByteSeq:
PUBLIC
PROC [card: Card32]
RETURNS [ByteSequence] = {
RETURN [Bits32ToByteSequence[Card32ToBits32[card], 0, bitsPerWord]];
};
CharToByteSeq:
PUBLIC
PROC [char: Char]
RETURNS [ByteSequence] = {
bytes: Bytes ¬ nullBytes;
bytes[0] ¬ CharToByte[char];
RETURN [Bits32ToByteSequence[BytesToBits32[bytes], 0, 8]];
};
IntToByteSeq:
PUBLIC
PROC [int: Int32, bits: BitLength]
RETURNS [ByteSequence] = {
SignCheck[int, bits];
RETURN [Bits32ToByteSequence[Int32ToBits32[int], bitsPerWord-bits, bits]];
};
Int32ToByteSeq:
PUBLIC
PROC [int: Int32]
RETURNS [ByteSequence] = {
RETURN [Bits32ToByteSequence[Int32ToBits32[int], 0, bitsPerWord]];
};
RealToByteSeq:
PUBLIC
PROC [real: Real]
RETURNS [ByteSequence] = {
WITH real
SELECT
FROM
real32: real32 Real =>
RETURN [Bits32ToByteSequence[Real32ToBits32[real32.real32], 0, bitsPerWord]];
ENDCASE => ERROR NotImplemented;
};
Byte Sequences to Simple Types
These operations are present for efficiency. An operation of the form val ← ByteSeqTo&[&&] has the same behavior (more or less) as:
val ← Get&[NewReader[&&]];
ByteSeqToBool:
PUBLIC
PROC [seq: ByteSequence]
RETURNS [Bool] = {
RETURN [VAL[ByteSequenceToBits32[seq, 0, 1][0]]];
};
ByteSeqToCard:
PUBLIC
PROC [seq: ByteSequence, bits: BitLength]
RETURNS [Card32] = {
IF bits = 0 THEN ERROR InvalidArgument;
RETURN [Bits32ToCard32[ByteSequenceToBits32[seq, bitsPerWord-bits, bits]]];
};
ByteSeqToCard32:
PUBLIC
PROC [seq: ByteSequence]
RETURNS [Card32] = {
RETURN [Bits32ToCard32[ByteSequenceToBits32[seq, 0, bitsPerWord]]];
};
ByteSeqToChar:
PUBLIC
PROC [seq: ByteSequence]
RETURNS [Char] = {
RETURN [Bits32ToChar[ByteSequenceToBits32[seq, bitsPerWord-8, 8]]];
};
ByteSeqToInt:
PUBLIC
PROC [seq: ByteSequence, bits: BitLength]
RETURNS [Int32] = {
IF bits = 0 THEN ERROR InvalidArgument;
RETURN [SignExtend[Bits32ToInt32[ByteSequenceToBits32[seq, bitsPerWord-bits, bits]], bits]];
};
ByteSeqToInt32:
PUBLIC
PROC [seq: ByteSequence]
RETURNS [Int32] = {
RETURN [Bits32ToInt32[ByteSequenceToBits32[seq, 0, bitsPerWord]]];
};
ByteSeqToReal:
PUBLIC
PROC [seq: ByteSequence, kind: RealKind ¬ real32]
RETURNS [Real] = {
IF kind # real32 THEN ERROR NotImplemented;
RETURN [[real32[Bits32ToReal32[ByteSequenceToBits32[seq, 0, bitsPerWord]]]]];
};