-- file PGSSymbols.Mesa
-- last modified by Satterthwaite,  August 26, 1980  1:50 PM

DIRECTORY
  ControlDefs: TYPE USING [ControlLink],
  PGScondefs: TYPE USING [objectVersion, pgsVersion, sourceVersion],
  StreamDefs: TYPE USING [StreamHandle, WriteBlock],
  StringDefs: TYPE USING [SubStringDescriptor],
  Symbols: TYPE USING [
    SERecord, BodyRecord, StandardContext,
    SEIndex, ISEIndex, CSEIndex, RecordSEIndex, CTXIndex, CBTIndex,
    ISENull, CSENull, RecordSENull, CTXNull, BTNull, lG, lZ],
  SymbolSegment: TYPE USING [
    Tables, htType, ssType, ctxType, seType, mdType, bodyType,
    VersionID, STHeader, WordOffset],
  SymbolOps: TYPE USING [
    Initialize, Finalize,
    EnterString, HashBlock, MakeCtxSe, NewCtx, MakeNonCtxSe],
  SymbolPack: TYPE ,
  SystemDefs: TYPE USING [AllocateSegment, FreeSegment],
  Table: TYPE USING [
    Base, Notifier, Region, Selector,
    AddNotify, Allocate, Bounds, Create, Destroy, DropNotify];

PGSSymbols: PROGRAM
    IMPORTS PGScondefs, StreamDefs, SymbolOps, SymbolPack, SystemDefs, Table
    EXPORTS PGScondefs =
  BEGIN
  OPEN SymbolOps, Symbols;

  seb: Table.Base;	-- semantic entry base (local copy)
  ctxb: Table.Base;	-- context table base  (local copy)
  bb: Table.Base;       -- body table base     (local copy)

  Notify: Table.Notifier = {
    OPEN SymbolSegment;
    seb ← base[seType]; ctxb ← base[ctxType]; bb ← base[bodyType]};

  dirCtx: CTXIndex;

  EnterModule: PROC [moduleId: STRING, bodyCtx: CTXIndex] = { 
    tSei: CSEIndex;
    sei: ISEIndex;
    bti: CBTIndex;
   -- generate a program type
    tSei ← MakeNonCtxSe[SIZE[transfer cons SERecord]];
    seb[tSei] ← SERecord[
	mark3: TRUE, mark4: TRUE,
	body: cons[transfer[
		mode: program, inRecord: RecordSENull, outRecord: RecordSENull]]];
   -- generate an id
    sei ← MakeConstant[moduleId, dirCtx, tSei];
    seb[sei].public ← TRUE;
    seb[sei].idValue ← ControlDefs.ControlLink[
			  procedure[gfi: 1, ep: 0, tag: procedure]];
    bti ← Table.Allocate[SymbolSegment.bodyType, SIZE[Outer Callable BodyRecord]];
    bb[bti] ← BodyRecord[
	link: [parent, BTNull], firstSon: BTNull,
	localCtx: CTXNull, type: RecordSENull, level: lG,
	sourceIndex: 0,
	info: [External[0, 0, 0]],
        extension: Callable[
	  inline: FALSE, id: ISENull, ioType: CSENull,
	  monitored: FALSE, stopping: FALSE, resident: FALSE,
	  entry: FALSE, internal: FALSE, entryIndex: 0,
 	  hints: [FALSE, FALSE, FALSE, FALSE],
	  closure: Outer[]]];
    bb[bti].id ← sei;  bb[bti].ioType ← tSei;  bb[bti].localCtx ← bodyCtx;
    seb[sei].idInfo ← bti};

  SubStringDescriptor: TYPE = StringDefs.SubStringDescriptor;

  MakeConstant: PROC [name: STRING, ctx: CTXIndex, type: SEIndex]
      RETURNS [sei: ISEIndex] = {
    -- 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;
      immutable ← constant ← TRUE;
      extended ← public ← linkSpace ← FALSE;
      mark3 ← mark4 ← TRUE;
      END;
    RETURN};


  CreateSymbols: PROC [moduleId: STRING] = {
    ctx: CTXIndex;
    WHILE (ctx ← NewCtx[lZ]) IN StandardContext DO NULL ENDLOOP;
    dirCtx ← ctx;
    EnterModule[moduleId, NewCtx[lG]]};

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


  WriteSymbols: PUBLIC PROC [s: StreamDefs.StreamHandle, moduleId: STRING] = {
    weights: ARRAY SymbolSegment.Tables OF CARDINAL ← ALL[1];
    tableRegion: Table.Region = [
      origin: LOOPHOLE[SystemDefs.AllocateSegment[256]],
      size: 256];
    Table.Create[tableRegion, DESCRIPTOR[weights]]; Table.AddNotify[Notify];
    SymbolOps.Initialize[];
    CreateSymbols[moduleId];
    EnterHashMark[];
    Table.DropNotify[Notify];
    TableOut[s];
    SymbolOps.Finalize[];  Table.Destroy[];
    SystemDefs.FreeSegment[LOOPHOLE[tableRegion.origin]]};


  TableOut: PROC [s: StreamDefs.StreamHandle] = {
    OPEN Table, SymbolSegment;
    header: STHeader;
    d: WordOffset;

    WriteSubTable: PROC [table: Table.Selector] = {
      OPEN Table;
      base: Table.Base;
      size: CARDINAL;
      [base, size] ← Table.Bounds[table];
      [] ← StreamDefs.WriteBlock[s, LOOPHOLE[base], size]};

      BEGIN
      OPEN header;
      versionIdent ← SymbolSegment.VersionID;
      version ← LOOPHOLE[PGScondefs.objectVersion];	-- for bootstrap
      sourceVersion ← LOOPHOLE[PGScondefs.sourceVersion];
      creator ← LOOPHOLE[PGScondefs.pgsVersion];
      definitionsFile ← FALSE;
      directoryCtx ← dirCtx;
      importCtx ←  outerCtx ← CTXNull;
      d ← SIZE[STHeader];
      hvBlock.offset ← d;
	d ← d + (hvBlock.size ← SymbolOps.HashBlock[].length);
      htBlock.offset ← d;  d ← d + (htBlock.size ← Table.Bounds[htType].size);
      ssBlock.offset ← d;  d ← d + (ssBlock.size ← Table.Bounds[ssType].size);
      seBlock.offset ← d;  d ← d + (seBlock.size ← Table.Bounds[seType].size);
      ctxBlock.offset ← d;
	d ← d + (ctxBlock.size ← Table.Bounds[ctxType].size);  
      mdBlock.offset ← d;  d ← d + (mdBlock.size ← Table.Bounds[mdType].size);
      bodyBlock.offset ← d;
	d ← d + (bodyBlock.size ←Table.Bounds[bodyType].size);
      treeBlock ← litBlock ← sLitBlock ← extBlock ← [d, 0];
      constBlock ← [0, 0];
      fgRelPgBase ← fgPgCount ← 0;
      END;
    [] ← StreamDefs.WriteBlock[s, @header, SIZE[STHeader]];
    [] ← StreamDefs.WriteBlock[s, SymbolOps.HashBlock[].base, header.hvBlock.size];
    WriteSubTable[htType];
    WriteSubTable[ssType];
    WriteSubTable[seType];
    WriteSubTable[ctxType];
    WriteSubTable[mdType];
    WriteSubTable[bodyType]};

  started: BOOLEAN ← FALSE;
  IF ~started THEN {START SymbolPack; started ← TRUE};

  END.