// BTRN0.bcpl - BCPL Compiler -- Trans, Main Program.
// Copyright Xerox Corporation 1980
//  Last modified on Wed 01 Nov 72 0021.59 by  jec.
//  Swinehart, 5-10-77: docase exp

//	TranslateTree		The main program to translate AE-Tree to OCODE.
//	TRNreport		Report errors in Trans.

get "btrnx"

static
 [  Casetable = nil 		//  Table of case entries.
    CaseB = 0			//  Base of case table for the current switch.
    CaseP = 0			//  Next free location in the case table.
    FrameLevel = 0		//  The level (0 - n) of the frame currently being compiled
    RoutineBody = false		//  Is ""return"" legal?
    ValofBlock = false		//  Is ""resultis"" legal?
    SwitchBlock = false		//  Are ""case"" and ""default"" legal?
    RepeatBlock = false		//  Are ""loop"" and ""break"" legal?
    Breaklabel = nil		//  Label to hop to on ""break"".
    Resultlabel = nil		//  ditto ""resultis"".
    Defaultlabel = nil		//  ditto ""resultis"".
    Endcaselabel = 0		//  ditto ""endcase"" -- and set non-zero if ""endcase"" is OK.
    Looplabel = nil		//  ditto ""loop"".
    Docaselabel=nil		//  ditto ""docase"".
    SSP = nil			//  The simulated stack pointer
    VecSSP = nil 		//  The stack pointer for vector space
    MaxSSP = nil		//  The max value of SSP for a stack frame
    MaxVecSSP = nil		//  ditto for VecSSP (vector space)
  ]

let TranslateTree() be
 [  if SWDebug do WriteS("TRN*n")

    let v = vec CaseT; Casetable = v

    Curline = 0	//  No line pointer as yet

    SSP = 1; Out2(STACK, SSP)
    VecSSP = 0
    MaxSSP, MaxVecSSP = SSP, VecSSP

    Trans(rv Tree)	//  DOTHEWORK

    unless MaxSSP eq 1 & MaxVecSSP eq 0 do
	TRNreport(1)	//  A local name at the top level is illegal

    Out1(END)

  ]


and TRNreport(n) be
[  Ostream = ErrorStream
   WW($*n)
   WriteLine(Curline)
   let m = selecton n into
     [	default: 0
	case 1: "DYNAMIC NAME DEFINED AT TOP LEVEL"
	case 2: "TOO MANY DYNAMIC VARIABLES IN PROCEDURE"
	case 3: "LEFT AND RIGHT SIDES OF  =  DO NOT MATCH"
	case 4: "*"BREAK*" OR *"LOOP*" OUT OF CONTEXT"
	case 5: "*"RETURN*" OR *"RESULTIS*" OUT OF CONTEXT"
	case 6: "*"ENDCASE*" OR *"DOCASE*" OUT OF CONTEXT"
	case 7: "*"CASE*" OR *"DEFAULT*" NOT IN A CASE BLOCK"
	case 8: "TOO MANY CASES IN SWITCH"
	case 9: "NO CASES IN SWITCH BLOCK"
	case 10: "*"DEFAULT*" APPEARS TWICE IN SAME SWITCH BLOCK"
	case 11: "THIS CASE APPEARS TWICE IN SAME SWITCH BLOCK"
	case 12: "ILLEGAL CASE-TO RANGE"
	case 13: "EXPRESSION MUST BE CONSTANT"
	case 14: "ILLEGAL MEMORY REFERENCE EXPRESSION"
	case 15: "MISSING EXPRESSION"
	case 16: "FIELD IS LONGER THAN ONE WORD"
	case 17: "ARG OF << MAY NOT BE A STRUCTURE REFERENCE ON LEFT SIDE OF = "
     ]
   BCPLreport(n, m)
   if SWHelp do Help("TRN REPORT")
   if n le 0 goto Abort
   Ostream = OutputStream
 ]

and CheckSSP() be	//update max SSP value if necessary
 [  if SSP gr MaxSSP do
	[ MaxSSP = SSP
	  if MaxSSP gr 127 do TRNreport(2)	//local space is too big
	 ]
  ]

and CheckVecSSP() be	//update max vector space vaaue if necessary
 [  if VecSSP gr MaxVecSSP do
	[ MaxVecSSP = VecSSP ]
  ]


and Complab(L) be
    Out2P(LAB, L)

and Compentry(L, D) be
    [ Out2P(ENTRY, L); OutL(D) ]

and Complentry(L, D) be
    [ Out2P(LENTRY, L); OutL(D) ]

and Compjump(L) be
    Out2P(JUMP, L)

and Out1(x) be
    W(x)

and Out2(x,y) be
 [  W(x)
    Write4(y)
  ]

and Out2P(x,y) be
 [  W(x)
    Write2(y)
  ]

and Out3P(x,y,z) be
 [  W(x)
    Write4(y)
    Write2(z)
  ]

and OutN(x) be
    Write4(x)

and OutL(x) be
    Write2(x)

and OutC(x) be
    W(x)


//  The following local routines do the actual storing.

and W(x) be
 [  Writech(OcodeStream, x)
    if SWOcode do [ WriteS("*n*t*******s"); WriteN(x) ]
  ]

and Write4(x) be
 [  Writeword(OcodeStream, x)
    if SWOcode do [ WW($*s); WriteO(x) ]
  ]

and Write2(x) be
 [  Writeaddr(OcodeStream, x)
    if SWOcode do [ WW($*s); WriteO(x) ]
  ]