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.PutFR["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]; }; 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 => { ma: MesaAnalysis _ NARROW[NodeProps.GetProp[x.root, analysisProp]]; IF ma # NIL THEN { startPosition: INT = TextNode.LocOffset[[x.root, 0], [x.text, x.start]]; IF startPosition <= ma.prefixEnd THEN Invalidate[x.root]; }; }; x: REF READONLY ChangingTextForPaste EditNotify.Change => NULL; x: REF READONLY ChangingSpanForPaste EditNotify.Change => NULL; x: REF READONLY ChangingFormat EditNotify.Change => NULL; x: REF READONLY ChangingProp EditNotify.Change => IF x.propAtom = $Comment THEN { ma: MesaAnalysis _ NARROW[NodeProps.GetProp[x.root, analysisProp]]; IF ma # NIL THEN { startPosition: INT = TextNode.LocOffset[[x.root, 0], [x.node, 0]]; IF startPosition <= ma.prefixEnd THEN Invalidate[x.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 => { ma: MesaAnalysis _ NARROW[NodeProps.GetProp[x.root, analysisProp]]; IF ma # NIL THEN { startPosition: INT = TextNode.LocOffset[[x.root, 0], [x.new, 0]]; IF startPosition <= ma.prefixEnd THEN Invalidate[x.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, discard]; 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. LMesaAnalysesImpl.mesa Mike Spreitzer January 22, 1987 10:06:42 pm PST Κ a– "cedar" style˜code™K™/—K˜KšΟk œ/œQ˜‹K˜šΟnœœ˜Kšœ/œB˜zKšœ ˜K˜—K˜Kšœœ˜K˜KšœœœQ˜vK˜Kšœœœ˜K˜šž œœ˜&Kšœ&œ˜+Kšœœ2œ˜EK˜—K˜š ž œœ œœΟcœ˜]šœœ˜Kšœœœ#œ˜7šœœœ$˜3Kšœœ*˜Cšœœœ˜Kšœœ6˜HKšœœ˜9K˜—K˜—Kšœœœ+œ˜?Kšœœœ+œ˜?Kšœœœ%œ˜9š œœœ#œœ˜QKšœœ*˜Cšœœœ˜Kšœœ0˜BKšœœ˜9K˜—K˜—Kšœœœ"ŸPœ˜†Kšœœœ"œ˜6šœœœ%˜4Kšœœ*˜Cšœœœ˜Kšœœ/˜AKšœœ˜9K˜—K˜—Kšœœ˜—K˜—K˜š ž œœœœ œœ˜fKšœœ'˜2Kšœœœœ˜Kšœ œ?œ˜TKšœ˜Kšœ œœ˜5Kšœ)˜)Kšœ˜—K˜Kšž œœ˜*Kšœœ˜K˜šžœœœœ˜LKšœœœ*˜7K˜>šžœœ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šœ8˜8Kšœ"˜"K˜)K˜ šœœœ ˜,šœ ˜ K˜šœœœ"˜AKšœ˜Kšœ˜—K˜—KšœB˜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šœ8˜8Kšœ˜K˜)šœœ˜Kšœœ˜ Kšœ:˜:Kšœ˜Kšœ+˜+Kšœ1˜1Jšœ ˜ K˜—Kšœœœœ˜Kšœ˜—K˜—šž œœ˜šœœœ˜Kšœ(˜(K˜Kšœ*˜*Kšœ˜K˜—š˜Kšœ˜ Kšœ8˜8Kšœ˜Kšœ)˜)šœ œ œ˜$Kšœ˜Kšœœ ˜&Kšœ>˜>Jšœ˜K˜—šœ˜Kšœ,˜,šœœœ˜!šžœœ œœœœœŸœ˜ZKšœ œœ˜Kšœœ+˜EK˜-K˜&K˜—Kšœ%˜%K˜—šœ˜Kšœœ ˜@K˜—K˜—Kšœœœœ˜Kšœ˜—Kšœœœ˜(Kšœ7˜7K˜—šœœ˜!K˜K˜ K˜&K˜$K˜'Kšœ˜Kšœ˜—šœœ˜˜Kšœ œ]˜hKšœ œ˜—Kšœ8˜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šœ˜—…—)=