GetAnalysis:
PUBLIC
PROC [doc: TiogaNode, docName:
ROPE, verbose:
BOOL]
RETURNS [ma: MesaAnalysis] = {
ma ¬ NARROW[NodeProps.GetProp[doc, analysisProp]];
IF ma # NIL THEN RETURN;
IF verbose THEN MessageWindow.Append[Rope.Cat["Analyzing ", docName, " ..."], TRUE];
ma ¬ Analyze[doc, docName];
IF verbose THEN MessageWindow.Append[" done", FALSE];
NodeProps.PutProp[doc, analysisProp, ma];
};
Analyze:
PROC [doc: TiogaNode, docName:
ROPE]
RETURNS [ma: MesaAnalysis] = {
in: IO.STREAM = TiogaStreams.CreateInput[doc, [FALSE[]] ];
l: TDLexing.Lexer = TDLexing.MakeLexer[in, GetSourcePosition];
AddIT:
PROC [namePos: PositionRange, name, typeClass, fileHint:
ROPE, usingList: SymbolTable]
RETURNS [it: InterfaceType] = {
it ¬ NEW [InterfaceTypePrivate ¬ [namePos, name, typeClass, fileHint, usingList]];
[] ¬ ma.interfaceTypes.Store[it.name, it];
[] ¬ ma.globalDefs.Store[it.name, it];
};
AddIR:
PROC [namePos: PositionRange, name:
ROPE, it: InterfaceType]
RETURNS [ir: InterfaceRecord] = {
ir ¬ NEW [InterfaceRecordPrivate ¬ [namePos, name, it]];
[] ¬ ma.interfaceRecords.Store[ir.name, ir];
[] ¬ ma.globalDefs.Store[ir.name, ir];
};
EnsureIT:
PROC [namePos: PositionRange, itName:
ROPE]
RETURNS [it: InterfaceType] = {
it ¬ NARROW[ma.interfaceTypes.Fetch[itName].val];
IF it = NIL THEN it ¬ AddIT[namePos, itName, itName, itName.Concat[".mesa"], NIL];
};
EnsureIR:
PROC [namePos: PositionRange, irName:
ROPE]
RETURNS [ir: InterfaceRecord] = {
ir ¬ NARROW[ma.interfaceRecords.Fetch[irName].val];
IF ir =
NIL
THEN {
it: InterfaceType = EnsureIT[namePos, irName];
ir ¬ AddIR[namePos, irName, it];
};
};
ParseDirectory:
PROC = {
toke: Token = l.GetToken[];
IF NOT toke.rope.Equal["DIRECTORY"] THEN {l.ReturnToken[toke]; RETURN};
DO
name, class, fileHint: ROPE;
usingList: SymbolTable ¬ NIL;
namePos: PositionRange ¬ [l.GetPosition[beforeNext], 0];
name ¬ class ¬ l.GetRope[tokenID];
namePos.after ¬ l.GetPosition[afterLast];
fileHint ¬ name.Concat[".mesa"];
IF l.NextIs[":"]
THEN
SELECT l.GetKwd[]
FROM
$TYPE => {
toke2: Token = l.GetToken[];
IF toke2.kind = tokenID
AND
NOT TDLexing.ReservedWord[toke2.rope]
THEN class ¬ toke2.rope
ELSE l.ReturnToken[toke2];
};
$FROM => fileHint ¬ Convert.RopeFromLiteral[l.GetRope[tokenROPE]];
ENDCASE => SyntaxError[];
IF l.NextIs["USING"]
THEN {
usingList ¬ CreateSymbolTable[];
IF NOT l.NextIs["["] THEN SyntaxError[];
IF
NOT l.NextIs["]"]
THEN {
DO
eltName: ROPE = l.GetRope[tokenID];
[] ¬ usingList.Insert[eltName, $T];
IF NOT l.NextIs[","] THEN EXIT;
ENDLOOP;
IF NOT l.NextIs["]"] THEN SyntaxError[];
};
};
{it: InterfaceType = AddIT[namePos, name, class, fileHint, usingList];
ir: InterfaceRecord = AddIR[namePos, name, it];
IF NOT l.NextIs[","] THEN EXIT;
}ENDLOOP;
IF NOT l.NextIs[";"] THEN SyntaxError[];
};
ParseModuleType:
PROC
RETURNS [mt: ModuleType] = {
IF l.NextIs["DEFINITIONS"] THEN RETURN [defs];
IF l.NextIsA[LIST["SAFE", "UNSAFE"]] THEN NULL;
IF l.NextIs["PROGRAM"] THEN mt ¬ prog
ELSE IF l.NextIs["MONITOR"] THEN mt ¬ monitor
ELSE SyntaxError[];
};
ParseImports:
PROC = {
IF NOT l.NextIs["IMPORTS"] THEN RETURN;
DO
irName: ROPE;
namePos: PositionRange ¬ [l.GetPosition[beforeNext], 0];
irName ¬ l.GetRope[tokenID];
namePos.after ¬ l.GetPosition[afterLast];
IF l.NextIs[":"]
THEN {
itName: ROPE;
itNamePos: PositionRange ¬ [l.GetPosition[beforeNext], 0];
itName ¬ l.GetRope[tokenID];
itNamePos.after ¬ l.GetPosition[afterLast];
{it: InterfaceType = EnsureIT[itNamePos, itName];
[] ¬ AddIR[namePos, irName, it];
}};
IF NOT l.NextIs[","] THEN EXIT;
ENDLOOP;
};
ParseOpen:
PROC = {
IF
NOT l.NextIs["OPEN"]
THEN {
ma.bodyStart ¬ l.GetPosition[afterLast];
[] ¬ l.GetToken[];
ma.prefixEnd ¬ l.GetPosition[afterLast]+1;
RETURN;
};
DO
n1: ROPE;
namePos: PositionRange ¬ [l.GetPosition[beforeNext], 0];
n1 ¬ l.GetRope[tokenID];
namePos.after ¬ l.GetPosition[afterLast];
IF l.NextIsA[
LIST[":", "~~"]]
THEN {
n2: Token = l.GetToken[];
IF n2.kind # tokenID THEN SyntaxError;
{it: InterfaceType = EnsureIT[[n2.before, n2.after], n2.rope];
[] ¬ AddIR[namePos, n1, it];
}}
ELSE {
ir: InterfaceRecord = EnsureIR[namePos, n1];
IF ir.type.usingList #
NIL
THEN {
AddElt:
PROC [key, val:
REF
ANY]
RETURNS [quit:
BOOL ¬
FALSE]
--SymTab.EachPairAction-- = {
eltName: ROPE = NARROW[key];
ie: InterfaceElement = NEW [InterfaceElementPrivate ¬ [eltName, ir]];
[] ¬ ma.interfaceElements.Store[eltName, ie];
[] ¬ ma.globalDefs.Store[eltName, ie];
};
[] ¬ ir.type.usingList.Pairs[AddElt];
}
ELSE {
ma.openedWithoutUsingList ¬ CONS[ir, ma.openedWithoutUsingList];
};
};
IF NOT l.NextIs[","] THEN EXIT;
ENDLOOP;
IF NOT l.NextIs[";"] THEN SyntaxError[];
ma.bodyStart ¬ ma.prefixEnd ¬ l.GetPosition[afterLast];
};
ma ¬
NEW [MesaAnalysisPrivate ¬ [
moduleType: defs,
globalDefs: CreateSymbolTable[],
interfaceRecords: CreateSymbolTable[],
interfaceTypes: CreateSymbolTable[],
interfaceElements: CreateSymbolTable[],
bodyStart: 0, prefixEnd: 0
]];
{
ENABLE SyntaxError => {
MessageWindow.Append[
message: IO.PutFR["Syntax error in %g before %g", [rope[docName]], [integer[l.GetPosition[afterLast]]]],
clearFirst: TRUE];
ma.bodyStart ¬ ma.prefixEnd ¬ l.GetPosition[beforeNext];
CONTINUE;
};
ParseDirectory[];
ma.moduleName ¬ l.GetRope[tokenID];
IF NOT l.NextIs[":"] THEN SyntaxError[];
IF l.NextIs["CEDAR"] THEN NULL;
ma.moduleType ¬ ParseModuleType[];
l.SkipTo[LIST["IMPORTS", "SHARES", "~", "="]];
ParseImports[];
l.SkipTo[LIST["~", "="]];
IF NOT l.NextIsA[LIST["~", "="]] THEN ERROR;
IF l.NextIsA[LIST["PUBLIC", "PRIVATE"]] THEN NULL;
IF ma.moduleType # defs AND l.NextIsA[LIST["CHECKED", "TRUSTED", "UNCHECKED"]] THEN NULL;
IF NOT l.NextIsA[LIST["BEGIN", "{"]] THEN SyntaxError[];
ParseOpen[];
};
};