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.STREAMNIL;
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: BOOLTRUE;
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[]};
}.