-- file Pass1.Mesa
-- last modified by Satterthwaite, October 30, 1979  3:43 PM

DIRECTORY
  AltoDefs: FROM "altodefs" USING [charlength, maxword, wordlength],
  ComData: FROM "comdata"
    USING [
      bodyIndex, errorStream,
      idANY, idBOOLEAN, idCARDINAL, idCHARACTER, idFALSE,
      idINTEGER, idLOCK, idREAL, idSTRING, idTRUE, idUNWIND,
      nErrors, nTypeCodes, outerCtx, seAnon, sourceTokens, sourceStream,
      textIndex, tC0, tC1,
      typeBOOLEAN, typeCARDINAL,typeCHARACTER, typeCONDITION, typeINTEGER,
      typeLOCK, typeREAL, typeSTRING, typeStringBody],
  CompilerUtil: FROM "compilerutil"
    USING [parse, MakeSwappable, TableSegment],
  ControlDefs: FROM "controldefs" USING [ControlLink, EPRange, GFTNull],
  LiteralOps: FROM "literalops" USING [Find],
  P1: FROM "p1" USING [Parse, Scanner, Parser, Pass1T],
  SegmentDefs: FROM "segmentdefs"
    USING [FileSegmentHandle, FileSegmentAddress, SwapIn, SwapOut, Unlock],
  StringDefs: FROM "stringdefs" USING [SubStringDescriptor],
  Symbols: FROM "symbols"
    USING [
      ctxType, seType,
      BitAddress, SERecord,
      HTIndex, SEIndex, ISEIndex, CSEIndex, RecordSEIndex, CTXIndex,
      codeANY, codeINTEGER, codeCHARACTER, typeANY, typeTYPE,
      HTNull, RecordSENull, CBTNull, lZ],
  SymbolOps: FROM "symbolops"
    USING [
      EnterString, FillCtxSe, MakeCtxSe, NewCtx, MakeNonCtxSe,
      MakeSeChain, NextSe, ResetCtxList, UnderType],
  Table: FROM "table" USING [Base, Notifier, AddNotify, DropNotify],
  Tree: FROM "tree" USING [Null];

Pass1: PROGRAM
    IMPORTS
	CompilerUtil, LiteralOps, P1, SegmentDefs, SymbolOps, Table,
	dataPtr: ComData
    EXPORTS CompilerUtil, P1 =
  BEGIN
  OPEN SymbolOps, Symbols;

  -- symbol table bases
    seb: Table.Base;	-- semantic entry base
    ctxb: Table.Base;	-- context table base

  P1Notify: Table.Notifier =
    BEGIN  seb ← base[seType];  ctxb ← base[ctxType]  END;

 -- definition of standard symbols

  WordLength: CARDINAL = AltoDefs.wordlength;

  PrefillSymbols: PROCEDURE = 
    BEGIN  -- called to prefill the compiler's symbol table 
    OPEN dataPtr;
    tSei, ptrSei: CSEIndex;
    rSei: RecordSEIndex;
    tCtx: CTXIndex;
    sei: ISEIndex;
    outerCtx ← NewCtx[lZ];
    idANY ← MakeBasicType["UNSPECIFIED"L, codeANY, TRUE, WordLength];
      IF UnderType[idANY] # typeANY THEN ERROR;
    idINTEGER ← MakeBasicType["INTEGER"L, codeINTEGER, TRUE, WordLength];
      typeINTEGER ← UnderType[idINTEGER];
    idCHARACTER ← MakeBasicType["CHARACTER"L, codeCHARACTER, TRUE, AltoDefs.charlength];
      typeCHARACTER ← UnderType[idCHARACTER];
    -- make BOOLEAN type
      typeBOOLEAN ← MakeNonCtxSe[SIZE[enumerated cons SERecord]];
      idBOOLEAN ← MakeNamedType["BOOLEAN"L, typeBOOLEAN];
      tCtx ← NewCtx[lZ];
      seb[typeBOOLEAN] ← SERecord[mark3: TRUE, mark4: TRUE,
	body: cons[
	    enumerated[ordered: TRUE, valueCtx: tCtx, nValues: 2]]];
      [] ← MakeConstant["FALSE"L, tCtx, idBOOLEAN, 0];
      [] ← MakeConstant["TRUE"L, tCtx, idBOOLEAN, 1];
      ResetCtxList[tCtx];
    idCARDINAL ← MakeSubrangeType["CARDINAL"L, 0, AltoDefs.maxword];
    typeCARDINAL ← UnderType[idCARDINAL];
    [] ← MakeNamedType["WORD"L, UnderType[idCARDINAL]];
    -- make REAL type
      typeREAL ← MakeNonCtxSe[SIZE[real cons SERecord]];
      seb[typeREAL] ← SERecord[mark3: TRUE, mark4: TRUE,
	body: cons[real[rangeType: idINTEGER]]];
      idREAL ← MakeNamedType["REAL"L, typeREAL];
    -- make STRING type
      typeStringBody ← rSei ← MakeRecord[nFields:3, nBits:2*WordLength];
      [] ← MakeField["length"L, idCARDINAL, [wd:0, bd:0], WordLength];
      sei ← MakeField["maxlength"L, idCARDINAL, [wd:1, bd:0], WordLength];
      seb[sei].immutable ← TRUE;
      tSei ← MakeNonCtxSe[SIZE[array cons SERecord]];
      seb[tSei] ← SERecord[mark3: TRUE, mark4: TRUE,
	body: cons[array[
		oldPacked: TRUE,
		indexType: idCARDINAL,	-- a fudge
		componentType: idCHARACTER,
		comparable: FALSE,
		lengthUsed: FALSE]]];
      sei ← MakeField["text"L, tSei, [wd:2, bd:0], 0];
      tSei ← MakePointerType[MakeNamedType["StringBody"L, rSei]];
      idSTRING ← MakeNamedType["STRING"L, tSei];
      typeSTRING ← UnderType[idSTRING];
    -- make LOCK type
      rSei ← MakeRecord[nFields:1, nBits:WordLength];
      seb[rSei].hints.unifield ← FALSE;
      [] ← MakeField[NIL, idANY, [wd:0, bd:0], WordLength];
      idLOCK ← MakeNamedType["MONITORLOCK"L, rSei];
      typeLOCK ← UnderType[idLOCK];
    -- make CONDITION type
      rSei ← rSei ← MakeRecord[nFields:2, nBits:2*WordLength];
      [] ← MakeField[NIL, idANY, [wd:0, bd:0], WordLength];
      [] ← MakeField["timeout"L, idCARDINAL, [wd:1, bd:0], WordLength];
      typeCONDITION ← UnderType[MakeNamedType["CONDITION"L, rSei]];
    -- make a universal pointer type
      ptrSei ← MakePointerType[typeANY];
    -- enter the Boolean constants
      idTRUE ← MakeConstant["TRUE"L, outerCtx, idBOOLEAN, 1];
      idFALSE ← MakeConstant["FALSE"L, outerCtx, idBOOLEAN, 0];
    -- make a universal NIL
      [] ← MakeConstant["NIL"L, outerCtx, ptrSei, 0];
    -- make a neutral entry for error recovery
      seAnon ← MakeVariable[
	name: "?"L,
	ctx: outerCtx,
	type: typeANY,
	offset: [wd:0, bd:0],
	nBits: WordLength];
    -- predeclare UNWIND
      tSei ← MakeNonCtxSe[SIZE[transfer cons SERecord]];
      seb[tSei] ← SERecord[mark3: TRUE, mark4: TRUE,
	body: cons[
	    transfer[
		mode: error,
		inRecord: RecordSENull,
		outRecord: RecordSENull]]];
      idUNWIND ← MakeConstant["UNWIND"L, outerCtx, tSei,
	    ControlDefs.ControlLink[procedure[
		gfi: ControlDefs.GFTNull,
		ep: ControlDefs.EPRange-1,
		tag: procedure]]];
    -- make some constants
      BEGIN
      tC0 ← [literal[info: [word[index: LiteralOps.Find[0]]]]];
      tC1 ← [literal[info: [word[index: LiteralOps.Find[1]]]]];
      END;
    ResetCtxList[outerCtx];
    END;
   

  SubStringDescriptor: TYPE = StringDefs.SubStringDescriptor;

  MakeNamedType: PROCEDURE [s: STRING, type: SEIndex] RETURNS [sei: ISEIndex] =
    BEGIN
    desc: SubStringDescriptor ← [base:s, offset:0, length:s.length];
    sei ← MakeCtxSe[EnterString[@desc], dataPtr.outerCtx];
      BEGIN  OPEN seb[sei];
      idType ← typeTYPE;  idInfo ← type;  idValue ← Tree.Null;
      immutable ← constant ← TRUE;
      extended ← public ← linkSpace ← FALSE;
      mark3 ← mark4 ← TRUE;
      END;
    RETURN
    END;

  MakeBasicType: PROCEDURE
	[s: STRING, code: [0..16), ordered: BOOLEAN, nBits: CARDINAL]
	RETURNS [ISEIndex] =
    BEGIN  -- makes an se entry for a built-in type --
    sei: CSEIndex = MakeNonCtxSe[SIZE[basic cons SERecord]];
    seb[sei] ← SERecord[mark3: TRUE, mark4: TRUE,
	body: cons[basic[ordered:ordered, code:code, length:nBits]]];
    RETURN [MakeNamedType [s, sei]]
    END;

  MakeConstant: PROCEDURE
	[name: STRING, ctx: CTXIndex, type: SEIndex, value: UNSPECIFIED]
	RETURNS [sei: ISEIndex] =
    BEGIN  -- makes an se entry for a built-in constant --
    desc: SubStringDescriptor ← [base:name, offset:0, length:name.length];
    sei ← MakeCtxSe[EnterString[@desc], ctx];
      BEGIN  OPEN seb[sei];
      idType ← type;  idInfo ← 0;  idValue ← value;
      immutable ← constant ← TRUE;
      extended ← public ← linkSpace ← FALSE;
      mark3 ← mark4 ← TRUE;
      END;
    RETURN
    END;

  MakeVariable: PROCEDURE
	[name: STRING, ctx: CTXIndex, type: SEIndex, offset: BitAddress, nBits: CARDINAL]
	RETURNS [sei: ISEIndex] =
    BEGIN
    desc: SubStringDescriptor ← [base:name, offset:0, length:name.length];
    sei ← MakeCtxSe[EnterString[@desc], ctx];
      BEGIN  OPEN seb[sei];
      idType ← type;  idValue ← offset;  idInfo ← nBits;
      immutable ← constant ← public ← extended ← linkSpace ← FALSE;
      mark3 ← mark4 ← TRUE;
      END;
    RETURN
    END;


  rCtx: CTXIndex;
  seChain: ISEIndex;

  MakeRecord: PROCEDURE [nFields, nBits: CARDINAL] RETURNS [rSei: RecordSEIndex] =
    BEGIN
    rSei ← LOOPHOLE[MakeNonCtxSe[SIZE[notLinked record cons SERecord]]];
    rCtx ← NewCtx[lZ];
    ctxb[rCtx].seList ← seChain ← MakeSeChain[rCtx, nFields, FALSE];
    seb[rSei] ← SERecord[mark3: TRUE, mark4: TRUE,
	body: cons[
	    record[
		machineDep: TRUE,
		argument: FALSE,
		hints: [
		  variant: FALSE,
		  unifield: nFields = 1,
		  comparable: FALSE, privateFields: FALSE],
		fieldCtx: rCtx,
		length: nBits,
		lengthUsed: FALSE,
		monitored: FALSE,
		linkPart: notLinked[]]]];
    RETURN
    END;

  MakeField: PROCEDURE
	[name: STRING, type: SEIndex, offset: BitAddress, nBits: CARDINAL]
	RETURNS [sei: ISEIndex] =
    BEGIN
    desc: SubStringDescriptor;
    hti: HTIndex;
    IF name # NIL
      THEN
	BEGIN
	desc ← [base:name, offset:0, length:name.length];
	hti ← EnterString[@desc];
	END
      ELSE hti ← HTNull;
    sei ← seChain;  seChain ← NextSe[seChain];
    FillCtxSe[sei, hti, FALSE];
      BEGIN  OPEN seb[sei];
      idType ← type;  idValue ← offset;  idInfo ← nBits;
      immutable ← constant ← public ← extended ← linkSpace ← FALSE;
      mark3 ← mark4 ← TRUE;
      END;
    RETURN
    END;

  MakePointerType: PROCEDURE [refType: SEIndex] RETURNS [sei: CSEIndex] =
    BEGIN
    sei ← MakeNonCtxSe[SIZE[pointer cons SERecord]];
    seb[sei] ← SERecord[mark3: TRUE, mark4: TRUE,
	body: cons[
	    pointer[
		ordered: FALSE,
		readOnly: FALSE,
		basing: FALSE,
		refType: refType,
		dereferenced: FALSE]]];
    RETURN
    END;

  MakeSubrangeType: PROCEDURE
	[s: STRING, origin: INTEGER, range: CARDINAL]
	RETURNS [ISEIndex] =
    BEGIN
    sei: CSEIndex;
    sei ← MakeNonCtxSe[SIZE[subrange cons SERecord]];
    seb[sei] ← SERecord[mark3: TRUE, mark4: TRUE,
	body: cons[
	    subrange[
		filled: TRUE,
		empty: FALSE,
		flexible: FALSE,
		rangeType: dataPtr.idINTEGER,
		origin: origin,
		range: range]]];
    RETURN [MakeNamedType[s, sei]]
    END;


  LockId: PUBLIC PROCEDURE RETURNS [HTIndex] =
    BEGIN
    desc: SubStringDescriptor ← [base:"LOCK"L, offset:0, length:("LOCK"L).length];
    RETURN [EnterString[@desc]]
    END;

  EnterHashMark: PROCEDURE =
    BEGIN  -- marks end of symbols from source file in hash table
    desc: SubStringDescriptor ← [base:"  "L, offset:1, length:0];
    [] ← EnterString[@desc];
    END;


  P1Unit: PUBLIC PROCEDURE RETURNS [success: BOOLEAN] =
    BEGIN  OPEN SegmentDefs;
    tableSeg: FileSegmentHandle =
      CompilerUtil.TableSegment[CompilerUtil.parse];
    Table.AddNotify[P1Notify];
    PrefillSymbols[];
    SwapIn[tableSeg];
    dataPtr.textIndex ← 0;  dataPtr.bodyIndex ← CBTNull;
    dataPtr.nTypeCodes ← 0;
    [complete:success, nTokens:dataPtr.sourceTokens, nErrors:dataPtr.nErrors] ←
      P1.Parse[
	sourceStream: dataPtr.sourceStream,
	messageStream: dataPtr.errorStream,
	table: LOOPHOLE[FileSegmentAddress[tableSeg]]];
    Unlock[tableSeg];  SwapOut[tableSeg];
    EnterHashMark[];
    Table.DropNotify[P1Notify];
    END;


 -- initialization code
  CompilerUtil.MakeSwappable[P1.Scanner, pass1];
  CompilerUtil.MakeSwappable[P1.Parser, pass1];
  CompilerUtil.MakeSwappable[P1.Pass1T, pass1];

  END.