DIRECTORY Atom, BasicTime, Convert, EditNotify, SymTab, IO, MesaAnalyses, MessageWindow, NodeProps, Rope, TDLexing, TextNode, TiogaStreams; MesaAnalysesImpl: CEDAR PROGRAM IMPORTS Atom, BasicTime, Convert, EditNotify, SymTab, IO, MessageWindow, NodeProps, Rope, TDLexing, TextNode, TiogaStreams EXPORTS MesaAnalyses = BEGIN OPEN MesaAnalyses; analysisProp: ATOM ¬ Atom.MakeAtom[IO.PutFR1["MesaAnalysesImpl, loaded at %g, analysisProp", [time[BasicTime.Now[]]]]]; debug: BOOL ¬ FALSE; Invalidate: PROC [root: TiogaNode] = { NodeProps.PutProp[root, analysisProp, NIL]; IF debug THEN MessageWindow.Append["Flushing a Mesa Analysis", TRUE]; }; AnalysisFromRoot: PROC [root: TiogaNode] RETURNS [MesaAnalysis] ~ { IF root=NIL THEN RETURN [NIL]; RETURN [NARROW[NodeProps.GetProp[root, analysisProp]]]}; EventWatcher: PROC [change: REF READONLY EditNotify.Change] --EditNotify.EditNotifyProc-- = { WITH change SELECT FROM x: REF READONLY ChangingView EditNotify.Change => NULL; x: REF READONLY ChangingText EditNotify.Change => { root: TiogaNode ~ TextNode.Root[x.text]; ma: MesaAnalysis ¬ AnalysisFromRoot[root]; IF ma # NIL THEN { startPosition: INT = TextNode.LocOffset[[root, 0], [x.text, x.start]]; IF startPosition <= ma.prefixEnd THEN Invalidate[root]; }; }; x: REF READONLY ChangingSpanForPaste EditNotify.Change => NULL; x: REF READONLY ChangingProp EditNotify.Change => IF x.name = NodeProps.nameComment THEN { root: TiogaNode ~ TextNode.Root[x.node]; ma: MesaAnalysis ¬ AnalysisFromRoot[root]; IF ma # NIL THEN { startPosition: INT = TextNode.LocOffset[[root, 0], [x.node, 0]]; IF startPosition <= ma.prefixEnd THEN Invalidate[root]; }; }; x: REF READONLY MovingNodes EditNotify.Change => NULL--wrong, but I don't understand this kind, and it probably won't happen anyway--; x: REF READONLY NodeNesting EditNotify.Change => NULL; x: REF READONLY InsertingNode EditNotify.Change => { root: TiogaNode ~ TextNode.Root[x.dest]; ma: MesaAnalysis ¬ AnalysisFromRoot[root]; IF ma # NIL THEN { startPosition: INT = TextNode.LocOffset[[root, 0], [x.new, 0]]; IF startPosition <= ma.prefixEnd THEN Invalidate[root]; }; }; ENDCASE => ERROR; }; 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]; }; SyntaxError: ERROR = TDLexing.SyntaxError; Token: TYPE = TDLexing.Token; 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[]; }; }; GetSourcePosition: PROC [in: IO.STREAM] RETURNS [index: INT]--TDLexing.IndexGetter-- = { loc: TextNode.Location = TiogaStreams.CurInLoc[in]; index ¬ TextNode.LocNumber[loc]; }; CreateSymbolTable: PROC RETURNS [st: SymbolTable] = { st ¬ SymTab.Create[case: TRUE]}; EditNotify.AddNotifyProc[EventWatcher, after, low]; END. ‚ MesaAnalysesImpl.mesa Copyright Σ 1992 by Xerox Corporation. All rights reserved. Mike Spreitzer May 15, 1992 2:57 pm PDT Κ ?–(cedarcode) style•NewlineDelimiter ™code™Kšœ Οeœ1™šŸœžœ5žœžœ˜}KšœžœJ˜RK˜*K˜&K˜—šŸœžœ žœžœ˜eKšœžœ0˜8K˜,K˜&K˜—šŸœžœ"žœžœ˜UKšœžœ&˜1Kšžœžœžœ=žœ˜RK˜—šŸœžœ"žœžœ˜WKšœžœ(˜3šžœžœžœ˜Kšœ.˜.K˜ Kšœ˜—K˜—šŸœžœ˜K˜Kšžœžœžœžœ˜Gšž˜Kšœžœ˜Kšœžœ˜K˜8K˜"K˜)K˜ šžœžœžœ ž˜,šœ ˜ K˜šžœžœžœ"˜AKšžœ˜Kšžœ˜—K˜—K˜BKšžœ˜—šžœžœ˜K˜ Kšžœžœžœ˜(šžœžœžœ˜šž˜Kšœ žœ˜#K˜#Kšžœžœžœžœ˜Kšžœ˜—Kšžœžœžœ˜(K˜—K˜—KšœF˜FKšœ/˜/Kšžœžœžœžœ˜Kšœžœ˜ —Kšžœžœžœ˜(K˜—šŸœžœžœ˜2Kšžœžœžœ˜.Kšžœ žœžœžœ˜/Kšžœžœ ˜%Kšžœžœžœ ˜-Kšžœ˜K˜—šŸ œžœ˜Kšžœžœžœžœ˜'šž˜Kšœžœ˜ K˜8K˜K˜)šžœžœ˜Kšœžœ˜ K˜:K˜K˜+Kšœ1˜1K˜ K˜—Kšžœžœžœžœ˜Kšžœ˜—K˜—šŸ œžœ˜šžœžœžœ˜K˜(K˜K˜*Kšžœ˜K˜—šž˜Kšœž˜ K˜8K˜K˜)šžœ žœ žœ˜$Kšœ˜Kšžœžœ ˜&Kšœ>˜>K˜K˜—šžœ˜Kšœ,˜,šžœžœžœ˜!šŸœžœ žœžœžœžœžœ œ˜ZKšœ žœžœ˜Kšœžœ+˜EK˜-K˜&K˜—K˜%K˜—šžœ˜Kšœžœ ˜@K˜—K˜—Kšžœžœžœžœ˜Kšžœ˜—Kšžœžœžœ˜(K˜7K˜—šœžœ˜!K˜K˜ K˜&K˜$K˜'Kšœ˜Kšœ˜—šœžœ˜˜Kšœ žœ]˜hKšœ žœ˜—K˜8Kšžœ˜ Kšœ˜—K˜K˜#Kšžœžœžœ˜(Kšžœžœžœ˜K˜"Kšœ žœ!˜.K˜Kšœ žœ ˜Kš žœžœ žœ žœžœ˜,Kšžœ žœžœžœ˜2Kš žœžœ žœ%žœžœ˜YKšžœžœ žœžœ˜8K˜ K˜K˜—K˜šŸœžœžœžœžœ žœ œ˜XKšœ3˜3K˜ K˜—K˜šŸœžœžœ˜5Kšœžœ˜ —K˜Kšœ3˜3K˜Kšžœ˜—…—β)£