file LogPack.Mesa
last modified by Satterthwaite, February 17, 1983 5:09 pm
Last Edited by: Maxwell, August 11, 1983 8:32 am
DIRECTORY
Alloc: TYPE USING [Bounds],
Ascii: TYPE USING [ControlZ],
ComData: 
TYPE 
USING [
bodyIndex, nErrors, nWarnings, switches, table, textIndex],
 
CompilerUtil: 
TYPE 
USING [
AcquireStream, AcquireTable, ReleaseStream, ReleaseTable],
 
ConvertUnsafe: TYPE USING [SubString, SubStringToRope],
ErrorTable: TYPE USING [CSRptr],
IO: TYPE USING [card, char, CR, GetChar, EndOf, int, Put, PutChar, PutF, PutRope, rope, SetIndex, SP, STREAM],
LiteralOps: TYPE USING [Value, StringValue, WordIndex],
Log: TYPE USING [ErrorCode],
Rope: TYPE USING [ROPE],
Symbols: TYPE USING [seType, bodyType, Name, ISEIndex, nullName, ISENull, BTNull],
SymbolOps: TYPE USING [SubStringForName],
Tree: TYPE USING [Base, Index, Link, NodeName, Scan, Null, treeType],
TreeOps: TYPE USING [ScanList];
 
LogPack: 
PROGRAM
IMPORTS
Alloc, CompilerUtil, ConvertUnsafe, IO, LiteralOps, SymbolOps, TreeOps,
dataPtr: ComData
 
EXPORTS Log = {
OPEN Symbols;
ErrorCode: TYPE = Log.ErrorCode;
FileByteIndex: TYPE = INT;
public interface
Error: 
PUBLIC 
PROC [code: ErrorCode] = {
Enter[]; ErrorLog[code, TRUE]; Exit[]};
 
ErrorHti: 
PUBLIC 
PROC [code: ErrorCode, name: Name] = {
ErrorTree[code, [hash[name]]]};
 
ErrorN: 
PUBLIC 
PROC [code: ErrorCode, n: 
INTEGER] = {
Enter[];
IO.Put[errorStream, IO.int[n]];  IO.PutChar[errorStream, ' ];
ErrorLog[code, TRUE];
Exit[]};
 
ErrorNode: 
PUBLIC 
PROC [code: ErrorCode, node: Tree.Index] = {
ErrorTree[code, [subtree[node]]]};
 
ErrorSei: 
PUBLIC 
PROC [code: ErrorCode, sei: ISEIndex] = {
ErrorTree[code, [symbol[sei]]]};
 
ErrorTree: 
PUBLIC 
PROC [code: ErrorCode, t: Tree.Link] = {
Enter[];
PrintOperand[t, 0, 0];  IO.PutRope[errorStream, "  "];
ErrorLog[code, TRUE];
Exit[]};
 
Warning: 
PUBLIC 
PROC [code: ErrorCode] = {
IF dataPtr.switches['w] 
THEN {
Enter[];
IO.PutRope[errorStream, "warning: "];
ErrorLog[code, FALSE];
Exit[]}};
 
 
WarningNode: 
PUBLIC 
PROC [code: ErrorCode, node: Tree.Index] = {
WarningTree[code, [subtree[node]]]};
 
WarningSei: 
PUBLIC 
PROC [code: ErrorCode, sei: ISEIndex] = {
WarningTree[code, [symbol[sei]]]};
 
WarningSubString: 
PUBLIC 
PROC [code: ErrorCode, s: ConvertUnsafe.SubString] = {
IF dataPtr.switches['w] 
THEN {
Enter[];
IO.Put[errorStream, IO.rope[ConvertUnsafe.SubStringToRope[s]], IO.char[' ]]; 
ErrorLog[code, FALSE];
Exit[]}};
 
 
WarningRope: 
PUBLIC 
PROC [code: ErrorCode, s: Rope.
ROPE] = {
IF dataPtr.switches['w] 
THEN {
Enter[];
IO.Put[errorStream, IO.rope[s], IO.char[' ]]; 
ErrorLog[code, FALSE];
Exit[]}};
 
 
WarningTree: 
PUBLIC 
PROC [code: ErrorCode, t: Tree.Link] = {
IF dataPtr.switches['w] 
THEN {
Enter[];
IO.PutRope[errorStream, "warning:  "];
PrintOperand[t, 0, 0];  IO.PutRope[errorStream, "  "];
ErrorLog[code, FALSE];
Exit[]}};
 
 
 
source printing
PrintTextLine: 
PROC [i: 
CARDINAL] = {
start, lineIndex: FileByteIndex;
char: CHAR;
n: [1..100];
sourceStream: IO.STREAM ← CompilerUtil.AcquireStream[source];
start ← lineIndex ← i;
FOR n 
IN [1..100] 
UNTIL lineIndex = 0 
DO
lineIndex ← lineIndex - 1;
IO.SetIndex[sourceStream, lineIndex];
IF IO.GetChar[sourceStream] = IO.CR THEN EXIT;
start ← lineIndex;
ENDLOOP;
 
IO.SetIndex[sourceStream, start];
FOR n 
IN [1..100] 
WHILE ~
IO.EndOf[sourceStream] 
DO
SELECT (char ← IO.GetChar[sourceStream]) 
FROM
IO.CR, Ascii.ControlZ => EXIT;
ENDCASE => IO.PutChar[errorStream, char];
 
ENDLOOP;
 
NewLine[];  
CompilerUtil.ReleaseStream[source]};
 
errorStream, CSRp and desc.base are set by Enter
errorStream: IO.STREAM ← NIL;
CSRp: ErrorTable.CSRptr;
ss: ConvertUnsafe.SubString ← [NIL, 0, 0];
Enter: 
PROC = {
errorStream ← CompilerUtil.AcquireStream[log];
CSRp ← CompilerUtil.AcquireTable[error];
ss.base ← @CSRp[CSRp.stringOffset]};
 
Exit: 
PROC = {
CompilerUtil.ReleaseTable[error];
CompilerUtil.ReleaseStream[log];  errorStream ← NIL};
 
WriteErrorString: 
PROC [n: ErrorCode] = {
ss.offset ← CSRp.ErrorMessages[n].offset;
ss.length ← CSRp.ErrorMessages[n].length;
IO.PutRope[errorStream, ConvertUnsafe.SubStringToRope[ss]]};
 
WriteName: 
PROC [name: Name] = {
IF name = nullName 
THEN IO.PutRope[errorStream, "(anonymous)"]
ELSE {
s: ConvertUnsafe.SubString;
s ← SymbolOps.SubStringForName[name]; 
IO.PutRope[errorStream, ConvertUnsafe.SubStringToRope[s]]}};
 
 
 
WriteSei: 
PROC [sei: ISEIndex] = {
WriteName[
IF sei = ISENull
THEN nullName
ELSE ((dataPtr.table).Bounds[seType].base)[sei].hash]};
 
 
WriteLti: 
PROC [t: Tree.Link.literal] = {
WITH t.index 
SELECT 
FROM
word => IO.Put[errorStream, IO.int[LiteralOps.Value[lti]]];
string => {
s: LONG STRING = LiteralOps.StringValue[sti];
IO.PutChar[errorStream, '"];
FOR i: 
CARDINAL 
IN [0..s.length) 
DO
IO.PutChar[errorStream, s[i]] ENDLOOP;
 
IO.PutChar[errorStream, '"]};
 
ENDCASE};
 
 
tables used for printing trees
 
 
OpName: ARRAY Tree.NodeName[assignx..uparrow] OF STRING ← [
"←",
" OR ", " AND ", "=", "#", "<", ">=", ">", "<=", " IN ", " ~IN ",
"+", "-", "*", "/", " MOD ",
".", ".", ".",
" NEW ", "~", "-", "@", "^"];
WriteOpName: 
PROC[n: Tree.NodeName[assignx..uparrow]] = {
ss.offset ← CSRp.OpName[n].offset;
ss.length ← CSRp.OpName[n].length;
IO.PutRope[errorStream, ConvertUnsafe.SubStringToRope[ss]]};
OpPrec: 
ARRAY Tree.NodeName[assignx..uparrow] 
OF 
CARDINAL = [
1, 1,
2, 3, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 7, 7, 7,
10, 10, 10,
1, 4, 8, 9, 10];
 
 
 
FnName: ARRAY Tree.NodeName[min..loophole] OF STRING ← [
"MIN", "MAX", "LONG", "ABS", "ALL", "SIZE", "FIRST", "LAST",
"DESCRIPTOR", "LENGTH", "BASE", "LOOPHOLE", "NIL"];
WriteFnName: 
PROC[n: Tree.NodeName[min..nil]] = {
ss.offset ← CSRp.FnName[n].offset;  ss.length ← CSRp.FnName[n].length;
IO.PutRope[errorStream, ConvertUnsafe.SubStringToRope[ss]]};
 
Cutoff: CARDINAL = 3;
PrintOperand: 
PROC [t: Tree.Link, tPrec, depth: 
CARDINAL] = {
IF t = Tree.Null THEN RETURN;
WITH e: t 
SELECT 
FROM
hash => WriteName[e.index];
symbol => WriteSei[e.index];
literal => WriteLti[e];
subtree => {
node: Tree.Index = e.index;
tb: Tree.Base ← (dataPtr.table).Bounds[Tree.treeType].base;
op: Tree.NodeName = tb[node].name;
IF depth > Cutoff THEN {IO.PutRope[errorStream, "..."]; RETURN};
SELECT op 
FROM
syserror, syserrorx => IO.PutRope[errorStream, "ERROR"];
lengthen, 
--abs,-- 
IN [first..succ], 
IN [length..base], nil => {
PrintOperand[tb[node].son[1], OpPrec[dot], depth+1];
IO.PutChar[errorStream, '.];
WriteFnName[op]};
 
ord => {   
-- pending reordering of node names
PrintOperand[tb[node].son[1], OpPrec[dot], depth+1];
IO.PutRope[errorStream, ".ORD"]};
 
IN [call .. rowcons], stringinit, 
IN [min .. nil], val => {
OPEN tb[node];
args: Tree.Link;
SELECT op 
FROM
IN [call .. rowcons], stringinit => {
IF son[1] # Tree.Null THEN PrintOperand[son[1], 0, depth];
args ← son[2]};
 
IN [min .. nil] => {WriteFnName[op]; args ← son[1]};
val => {IO.PutRope[errorStream, "VAL"]; args ← son[1]}; -- until reordered
ENDCASE;
 
IF args # Tree.Null 
OR op # nil 
THEN {
IO.PutChar[errorStream, '[];
IF depth = Cutoff 
AND args.tag = subtree 
THEN
IO.PutRope[errorStream, "..."]
 
ELSE PrintOperandList[args, depth+1];
IF op 
IN [call .. joinx] 
AND nSons > 2 
THEN
IO.PutRope[errorStream, " !..."];
 
IO.PutChar[errorStream, ']]}};
 
 
IN [assignx .. uparrow] => {
OPEN tb[node];
prec: CARDINAL = OpPrec[op];
IF prec < tPrec THEN IO.PutChar[errorStream, '(];
SELECT op 
FROM
IN [create .. addr] => {WriteOpName[op]; PrintOperand[son[1], prec, depth]};
IN [assignx .. dollar] => {
PrintOperand[son[1], prec, depth+1];
WriteOpName[op];
PrintOperand[son[2], prec+1, depth+1]};
 
uparrow => {
PrintOperand[son[1], prec, depth];
IO.PutChar[errorStream, '^]};
 
ENDCASE => IO.PutChar[errorStream, '?];
 
IF prec < tPrec THEN IO.PutChar[errorStream, ')]};
 
IN [intOO .. intCC] => {
OPEN tb[node];
IO.PutChar[errorStream, IF op = intOO OR op = intOC THEN '( ELSE '[];
PrintOperand[son[1], 0, depth];
IO.PutRope[errorStream, ".."];
PrintOperand[son[2], 0, depth];
IO.PutChar[errorStream, IF op = intOO OR op = intCO THEN ') ELSE ']]};
 
clit => {
c: 
CHAR = 
VAL[LiteralOps.Value[
LiteralOps.WordIndex[NARROW[tb[node].son[1], Tree.Link.literal].index]]];
 
IO.PutChar[errorStream, ''];
IF c >= IO.SP THEN IO.PutChar[errorStream, c]
ELSE {IO.PutF[errorStream, "\\%3b", IO.card[c.ORD]]}};
 
new, cons, listcons => {
IF tb[node].son[1] # Tree.Null 
THEN {
PrintOperand[tb[node].son[1], OpPrec[dot], depth+1];
IO.PutChar[errorStream, '.]};
 
IO.PutRope[errorStream,
SELECT op FROM new => "NEW", cons => "CONS", ENDCASE => "LIST"];
 
IO.PutChar[errorStream, '[];
IF depth = Cutoff THEN IO.PutRope[errorStream, "..."]
ELSE PrintOperandList[tb[node].son[2], depth+1];
IO.PutChar[errorStream, ']]};
 
atom => {
IO.PutChar[errorStream, '$];
WITH e1: tb[node].son[1] SELECT FROM hash => WriteName[e1.index]; ENDCASE};
 
llit, IN [cast .. openx], thread => PrintOperand[tb[node].son[1], tPrec, depth];
item => PrintOperand[tb[node].son[2], tPrec, depth];
ENDCASE => IO.PutRope[errorStream, "..."]};
 
 
ENDCASE};
 
 
PrintOperandList: 
PROC [t: Tree.Link, depth: 
CARDINAL] = {
firstSon: BOOL ← TRUE;
PrintItem: Tree.Scan = {
IF ~firstSon THEN IO.PutRope[errorStream, ", "];
firstSon ← FALSE;
IF t # Tree.Null THEN PrintOperand[t, 0, depth]};
 
TreeOps.ScanList[t, PrintItem]};
 
error-handling routines
NewLine: PROC = {IO.PutChar[errorStream, IO.CR]};
ErrorLog: 
PROC [code: ErrorCode, error: 
BOOL] = {
bodyId: ISEIndex;
index: CARDINAL = dataPtr.textIndex;
WriteErrorString[code];
IF error THEN dataPtr.nErrors ← dataPtr.nErrors + 1
ELSE dataPtr.nWarnings ← dataPtr.nWarnings + 1;
IO.PutRope[errorStream, ", at "];
IF dataPtr.bodyIndex # BTNull 
THEN {
bodyId ← ((dataPtr.table).Bounds[Symbols.bodyType]).base[dataPtr.bodyIndex].id;
IF bodyId # ISENull THEN WriteSei[bodyId]};
 
IF index # CARDINAL.LAST THEN IO.PutF[errorStream, "[%d]", IO.card[index]];
IO.PutChar[errorStream, ':];  NewLine[];
IF index # LAST[CARDINAL] THEN PrintTextLine[index]
ELSE {IO.PutRope[errorStream, "(source from inline)"]; NewLine[]};
NewLine[]};
 
}.