-- file CodeDefs.mesa
-- last modified by Sweet, June 20, 1980  3:57 PM
-- last modified by Satterthwaite, June 15, 1982 10:29 am

DIRECTORY
  Alloc: TYPE USING [Base, Notifier],
  Environment: TYPE USING [Byte, bitsPerWord],
  Literals: TYPE USING [LTIndex, LTNull, STIndex],
  PrincOps: TYPE USING [MaxFrameSize],
  Symbols: TYPE USING [
    BTIndex, ContextLevel, HTIndex, ISEIndex, ISENull, lZ, RecordSEIndex],
  SymbolSegment: TYPE USING [Tables],
  Table: TYPE USING [Limit, Selector];

CodeDefs: DEFINITIONS =
  BEGIN OPEN Symbols;

  Byte: TYPE = Environment.Byte;
  
  Base: TYPE = Alloc.Base;
  Limit: CARDINAL = Table.Limit;
  
  Lexeme: TYPE = RECORD [
    lexvalue: SELECT lextag: * FROM
      se => [lexsei: ISEIndex],
      literal => [
	SELECT littag: * FROM
	  word => [lexlti: Literals.LTIndex],
	  string => [lexsti: Literals.STIndex]
	  ENDCASE],
      bdo => [lexbdoi: VarIndex],
      stack => [lexsti: StackIndex]
      ENDCASE];


  NullLex: se Lexeme = Lexeme[se[Symbols.ISENull]];


  MoveDirection: TYPE = {load, store};

  VarSpace: TYPE = {faddr, frame, frameup, caddr, code, link, linkup, stack, const, pdesc};

  VarTag: TYPE = {o, bo, bdo, ind};

  VarComponent: TYPE = RECORD [
    wSize: CARDINAL ← 0 | NULL,
    bSize: [0..Environment.bitsPerWord) ← 0 | NULL,
    space: SELECT tag: VarSpace FROM
      frame => [
	immutable: BOOLEAN ← FALSE,
	level: ContextLevel ← lZ,
	wd: CARDINAL ← 0,
	bd: [0..Environment.bitsPerWord) ← 0],
      code => [
        bd: [0..Environment.bitsPerWord) ← 0,
        wd: CARDINAL ← 0,
        lti: Literals.LTIndex ← Literals.LTNull],
      faddr => [wd: CARDINAL, level: ContextLevel],
      frameup => [
	level: ContextLevel ← lZ,
        pwSize: [1..2] ← 1,
	immutable: BOOLEAN ← FALSE,
	wd: CARDINAL ← 0,
	delta: [0..PrincOps.MaxFrameSize) ← 0],
      caddr, link => [wd: CARDINAL],
      linkup => [
	wd: CARDINAL,
	delta: [0..PrincOps.MaxFrameSize) ← 0],
      stack => [
	bd: [0..Environment.bitsPerWord) ← 0,
	wd: CARDINAL ← 0,
	sti: StackIndex],
      const => [bd: [0..Environment.bitsPerWord) ← 0, d1, d2: UNSPECIFIED ← NULL],
      pdesc => [ep: CARDINAL]
      ENDCASE];

  VarItem: TYPE = RECORD [ -- not many around simultaneously
    free: BOOLEAN ← FALSE, -- required by allocator
    body: SELECT tag: VarTag FROM
      o => [var: VarComponent],
      bo => [offset, base: VarComponent],
      bdo => [offset, base, disp: VarComponent],
      ind => [
        offset, base, index: VarComponent,
	simple: BOOLEAN,
        packinfo: SELECT packtag: * FROM
          packed => [grain: [1..Environment.bitsPerWord)],
          notPacked => [eWords: [0..PrincOps.MaxFrameSize)]
          ENDCASE]
      ENDCASE];

  VarIndex: TYPE =    Base RELATIVE POINTER [0..Limit) TO VarItem;
  OVarIndex: TYPE =   Base RELATIVE POINTER [0..Limit) TO o VarItem;
  BoVarIndex: TYPE =  Base RELATIVE POINTER [0..Limit) TO bo VarItem;
  BdoVarIndex: TYPE = Base RELATIVE POINTER [0..Limit) TO bdo VarItem;
  IndVarIndex: TYPE = Base RELATIVE POINTER [0..Limit) TO ind VarItem;
  VarNull: VarIndex = FIRST[VarIndex];

  RelativePC: TYPE = [0..77777B];
  CCInfoType: TYPE = {generating, binding, coding};
  CodeChunkType: TYPE = {code, label, jump, other};

  CCItem: TYPE = RECORD [
    free: BOOLEAN,
    pad: [0..1], -- this is NOT a fill field
    flink, blink: CCIndex,
    ccvalue: SELECT cctag: CodeChunkType FROM
      code => [
	realinst, minimalStack: BOOLEAN,
	inst: Byte,
	aligned: BOOLEAN,
	isize: [0..3],
	fill: [0..7B],
	parameters: ARRAY [1..1) OF WORD],
      label => [
	labelseen: BOOLEAN,
	labelinfo: SELECT OVERLAID CCInfoType FROM
          generating => [filltoword, jumplist: JumpCCIndex],
          binding => [minPC, maxPC: RelativePC],
          coding => [filltoword, pc: RelativePC],
          ENDCASE],
      jump => [
	jsize: [0..7],
	jtype: JumpType,
	jparam: Byte,
	fixedup, completed: BOOLEAN,
	destlabel: LabelCCIndex,
	forward: BOOLEAN,
	jumpinfo: SELECT OVERLAID CCInfoType FROM
          generating => [filltoword, thread: JumpCCIndex],
          binding => [minPC, maxPC: RelativePC],
          coding => [filltoword, pc: RelativePC]
          ENDCASE],
      other => [obody: SELECT otag: * FROM
	table => [
          btab: BOOLEAN,
          tablecodebytes: [0..7],
          taboffset: INTEGER],
	markbody => [
          start: BOOLEAN,
          index: BTIndex],
	relSource => [relIndex: RelFileIndex],		-- relative to proc body
	absSource => [index: CARDINAL]
	ENDCASE]
      ENDCASE];

  RelFileIndex: TYPE = [0..37777b];
  NULLfileindex: CARDINAL = LAST[CARDINAL];

  CCIndex: TYPE = Base RELATIVE POINTER [0..Limit) TO CCItem;
  CCNull: CCIndex = FIRST[CCIndex];
  JumpCCIndex: TYPE = Base RELATIVE POINTER [0..Limit) TO jump CCItem;
  JumpCCNull: JumpCCIndex = LOOPHOLE[CCNull];
  LabelCCIndex: TYPE = Base RELATIVE POINTER [0..Limit) TO label CCItem;
  LabelCCNull: LabelCCIndex = LOOPHOLE[CCNull];
  CodeCCIndex: TYPE = Base RELATIVE POINTER [0..Limit) TO code CCItem;
  CodeCCNull: CodeCCIndex = LOOPHOLE[CCNull];
  OtherCCIndex: TYPE = Base RELATIVE POINTER [0..Limit) TO other CCItem;
  TableCCIndex: TYPE = Base RELATIVE POINTER [0..Limit) TO table other CCItem;
  TableCCNull: TableCCIndex = LOOPHOLE[CCNull];

  CJItem: TYPE = RECORD [
    inst: CCIndex, 
    variant: SELECT tag:* FROM
      fallIn => [lc: LabelCCIndex],
      jumpIn => [jc: JumpCCIndex]
      ENDCASE];

  CompareClass: TYPE = {word, byte};

  JumpType: TYPE = {
	JumpE, JumpN, JumpL, JumpGE, JumpG, JumpLE,
	UJumpL, UJumpGE, UJumpG, UJumpLE, ZJumpE, ZJumpN, 
	Jump, JumpA, JumpC, JumpCA, JumpRet,
	NILJumpE, NILJumpN, PAIRJumpL, PAIRJumpG,
	BYTEJumpE, BYTEJumpN, BITJumpE, BITJumpN};

  LabelInfoRecord: TYPE = RECORD [
    free: BOOLEAN ← FALSE,
    thread: LabelInfoIndex,
    catchLevel: [0..37777B],
    body: SELECT tag:* FROM
      named => [hti: HTIndex, cci: LabelCCIndex],
      loop => [exit, loop: LabelCCIndex],
      stmt => [retry, continue: LabelCCIndex]
      ENDCASE];
  LabelInfoIndex: TYPE = 
    Base RELATIVE POINTER [0..Limit) TO LabelInfoRecord;
  NamedLabelInfoIndex: TYPE = 
    Base RELATIVE POINTER [0..Limit) TO named LabelInfoRecord;
  LabelInfoNull: LabelInfoIndex = FIRST[LabelInfoIndex];


  StackIndex: TYPE = Base RELATIVE POINTER [0..Limit) TO StackItem;
  StackNull: StackIndex = FIRST[StackIndex];

  StackItem: TYPE = RECORD [
    free: BOOLEAN ← FALSE,
    uplink, downlink: StackIndex ← StackNull,
    data: SELECT tag:* FROM
      mark => [label: LabelCCIndex],
      onStack => [
	alsoLink: BOOLEAN ← FALSE,
	tLevel: Symbols.ContextLevel ← lZ,
	tOffset: TempAddr ← NULL],
      inTemp => [
	tLevel: Symbols.ContextLevel,
	tOffset: TempAddr],
      inLink => [link: Byte]
      ENDCASE];

-- if alsoTemp for onStack element, it has been previously dumped
--   by the stack machinery into the given temp.

  StackPos: TYPE = [0..16);

  StackLocRec: TYPE = RECORD [SELECT tag:* FROM
    onStack => [depth: CARDINAL],
    inTemp => [
      tSize: TempSize,
      tLevel: Symbols.ContextLevel,
      tOffset: TempAddr],
    inLink => [link: [0..256)],
    mixed => []
    ENDCASE];

-- StackLocRec semantics:
--  obtained by lr: StackLocRec ← Stack.Loc[s, count];
--
--	Tag		Meaning
--
--	onStack		The "count" words are all on the stack.
--			  There are "depth" words above them in the model
--	inTemp		The "count" words are in contiguous temporaries
--	inLink		"count" = 1 and value is in link "link"
--	mixed		None of the above


  EvalStackSize: CARDINAL = 14;
  MaxParmsInStack: CARDINAL = EvalStackSize - 3;

  TempAddr: TYPE = [0..PrincOps.MaxFrameSize);
  TempSize: TYPE = [0..PrincOps.MaxFrameSize);

  TempStateRecord: TYPE = RECORD[
    pendtemplist, templist, heaplist: ISEIndex,
    tempctxlvl: ContextLevel,
    firstTemp, tempstart, framesz: INTEGER];

  CaseCVState: TYPE = {single, singleLoaded, multi, none};


  StoreOptions: TYPE = RECORD [
    expr: BOOLEAN ← FALSE,
    init: BOOLEAN ← FALSE,
    counted: BOOLEAN ← FALSE,
    composite: BOOLEAN ← FALSE];


  ConsDestination: TYPE = RECORD [
    bd: [0..Environment.bitsPerWord) ← NULL,
    bSize: [0..Environment.bitsPerWord) ← NULL,
    inFrame: BOOLEAN ← FALSE, -- can store directly into frame
    fLevel: Symbols.ContextLevel ← NULL,
    pLength: [1..2] ← 1,
    ignoreSafen: BOOLEAN ← FALSE,
    fOffset: CARDINAL ← NULL, -- offset of first word of record
    pLoaded: BOOLEAN ← FALSE, -- pointer already on virtual stack
    pSti: StackIndex ← NULL, -- the sti of the pointer if pLoaded
    pDelta: INTEGER ← 0, -- word offset into record of pointer
    pLink: BOOLEAN ← FALSE, -- pointer also in a link
    pLevel: Symbols.ContextLevel ← lZ, -- if not lZ, then ptr is in temp
    pOffset: TempAddr ← NULL, -- frame offset of temp or link
    remaining: CARDINAL ← 0,
    wSize: CARDINAL ← NULL,
    options: StoreOptions ← []];


  StatementStateRecord: TYPE = RECORD [
    retLabel, comRetLabel: LabelCCIndex,
    outRecord: RecordSEIndex,
    pendtemplist: ISEIndex,
    stkPtr: UNSPECIFIED,
    inlineFileIndex: CARDINAL];

  ChunkIndex: TYPE = Base RELATIVE POINTER [0..Limit);

  codeType: Table.Selector = LAST[SymbolSegment.Tables]+1;
  
  AddressNotify, CallsNotify, ConstructorNotify, CountingNotify,
  CrossJumpNotify, DJumpsNotify, ExpressionNotify, FinalNotify,
  FlowNotify, FlowExpressionNotify, OutCodeNotify, PeepholeNotify,
  StatementNotify, SelectionNotify, StoreNotify, TempNotify,
  VarBasicsNotify, VarMoveNotify, VarUtilsNotify:
    Alloc.Notifier;

  END.