-- LogInline.mesa
-- Useful procs for manipulating RecordIDs.
-- Last edited by
--   MBrown on January 30, 1984 10:14:00 am PST


  DIRECTORY
    AlpineEnvironment,
    Basics,
    Log,
    RuntimeError;

LogInline: DEFINITIONS
  IMPORTS
    Basics,
    RuntimeError
  = BEGIN
  Comparison: TYPE = Basics.Comparison;
  RecordID: TYPE = Log.RecordID;
  PageNumber: TYPE = AlpineEnvironment.PageNumber;
  WordNumber: TYPE = INT;
  wordsPerPage: CARDINAL = AlpineEnvironment.wordsPerPage;
  logWordsPerPage: CARDINAL = AlpineEnvironment.logWordsPerPage;

  RecordID1: TYPE = MACHINE DEPENDENT RECORD [
    page0 (0: 0..7): [0..256),
    offsetInPage (0: 8..15): [0..AlpineEnvironment.wordsPerPage),
    page1 (1: 0..31): LONG CARDINAL];
    -- This is one way to decompose a Log.RecordID.
    -- Notice that like all long numbers, the least-significant bits come in the first word.

  RecordID2: TYPE = MACHINE DEPENDENT RECORD [
    lowbits: CARDINAL, highbits: LONG CARDINAL ];

  -- Operations on RecordIDs

  Compare: PROC [a, b: RecordID] RETURNS [Comparison] = INLINE {
    IF a.highBits = b.highBits THEN RETURN [Basics.CompareCard[a.lowBits, b.lowBits]]
    ELSE RETURN [Basics.CompareCard[a.highBits, b.highBits]];
    };

  Min: PROC [a, b: RecordID] RETURNS [RecordID] = INLINE {
    RETURN [IF Compare[a, b] = greater THEN b ELSE a];
    };

  Max: PROC [a, b: RecordID] RETURNS [RecordID] = INLINE {
    RETURN [IF Compare[a, b] = less THEN b ELSE a];
    };
    
  WordsFromSubtract: PROC [larger, smaller: RecordID] RETURNS [result: INT] = INLINE {
    result ← LOOPHOLE[larger.lowBits-smaller.lowBits, INT];
    IF (larger.highBits # smaller.highBits AND larger.highBits # smaller.highBits+1)
      OR result < 0 THEN ERROR RuntimeError.BoundsFault;
    RETURN [result]
    };

  AddC: PROC [r: RecordID, words: CARDINAL] RETURNS [RecordID] = INLINE {
    -- Returns r+c.
    low: Basics.LongNumber[num] =
      LOOPHOLE[LONG[words] + LONG[LOOPHOLE[r, RecordID2].lowbits]];
    high: LONG CARDINAL = LONG[low.highbits] + LOOPHOLE[r, RecordID2].highbits;
    RETURN [LOOPHOLE[RecordID2[highbits: high, lowbits: low.lowbits]]];
    };

  AddLC: PROC [r: RecordID, words: LONG CARDINAL] RETURNS [RecordID] = INLINE {
    -- Returns r+words. 
    low: Basics.LongNumber[num] = LOOPHOLE[
      LONG[LOOPHOLE[words, Basics.LongNumber[num]].lowbits] +
      LONG[LOOPHOLE[r, RecordID2].lowbits] ];
    high: LONG CARDINAL = LONG[low.highbits] +
      LONG[LOOPHOLE[words, Basics.LongNumber[num]].highbits] +
      LOOPHOLE[r, RecordID2].highbits;
    RETURN [LOOPHOLE[RecordID2[highbits: high, lowbits: low.lowbits]]];
    };

  RecordIDFromWordNumber: PROC [w: WordNumber] RETURNS [RecordID] = INLINE {
    RETURN [[lowBits: LOOPHOLE[w], highBits: 0]] };

  WordInPageFromRecordID: PROC [r: RecordID] RETURNS [CARDINAL] = INLINE {
    RETURN [LOOPHOLE[r, RecordID1].offsetInPage] };

  END.


CHANGE LOG

Created by MBrown on September 21, 1982 2:45 pm

Changed by MBrown on September 25, 1982 3:50 pm
-- Moved stuff here from LogCoreImpl: Compare, DecomposeWordNumber, etc.

Changed by MBrown on October 4, 1982 10:19 pm
-- Cedar 3.4: use Environment.Comparison, Inline.CompareCard.

Changed by MBrown on October 25, 1982 10:45 pm
-- Eliminate dependency on LogBasic so that this interface can be made public.

Changed by MBrown on November 9, 1982 3:01 pm
-- Moved page <-> word stuff to AlpineInline.

Changed by MBrown on January 30, 1984 10:11:20 am PST
-- Cedar 5.0: use Basics, RuntimeError.