<> <> <> <> <<>> <> DIRECTORY FS USING [StreamOpen], IO USING [PutFR, RIS, rope, STREAM, time], PasPrivate, PasPrivateVars, Rope USING [Cat, Equal, Length]; PasInit: CEDAR PROGRAM IMPORTS FS, IO, PasPrivate, PasPrivateVars, Rope EXPORTS PasPrivate = BEGIN OPEN PasPrivate, PasPrivateVars; PascalStandardFileNames: PUBLIC ARRAY StandardFiles OF ROPE _ ["INPUT", "OUTPUT", "TTY", "?FILE1", "?FILE2"]; PascalStandardProcedureNames: PUBLIC ARRAY StandardProcedures OF ROPE _ ["HALT", "GET", "PUT", "RESET", "REWRITE", "READ", "READLN", "WRITE", "WRITELN", "BREAK", "PACK", "UNPACK", "NEW", "DISPOSE", "PAGE", "RELEASE", "ASSIGN", "CONCAT", "PUTCHAR", "GETFILENAME", "DATE", "TIME", "?PROC1", "?PROC2", "?PROC3", "?PROC4", "?PROC5"]; PascalStandardFunctionNames: PUBLIC ARRAY StandardFunctions OF ROPE _ ["CLOCK", "ABS", "SQR", "SIN", "COS", "EXP", "LN", "SQRT", "ARCTAN", "ODD", "ORD", "CHR", "PRED", "SUCC", "EOF", "EOLN", "EOPAGE", "CARD", "LOWERBOUND", "UPPERBOUND", "MIN", "MAX", "FIRST", "LAST", "ROUND", "TRUNC", "LENGTH", "GETCHAR", "?FN1", "?FN2", "?FN3", "?FN4", "?FN5"]; textFile: FileTypePtr; configName: ROPE; configQ: OutputQueuePtr; makeFileQ: OutputQueuePtr _ NIL; alfa, alfaIndexRange: TypePtr; readySourceFileSeq: SourceFileSeqPtr _ NIL; compilerSwitches: ROPE; InitializeStandards: PUBLIC PROCEDURE= BEGIN s: Standards; MakeType: PROCEDURE [name: ROPE, t: GeneralTypePtr] RETURNS [IdentifierPtr] = BEGIN id: IdentifierPtr _ NewIdent[name: name]; id.type _ t; id.class _ Z.NEW[IdentifierTail_[type[]]]; RETURN[id]; END; -- of MakeType integerId _ MakeType["INTEGER", integer]; realId _ MakeType["REAL", real]; charId _ MakeType["CHAR", char]; [] _ MakeType["ASCII", charId]; booleanId _ MakeType["BOOLEAN", boolean]; stringId _ MakeType["STRING", string]; alfaIndexRange _ Z.NEW[subRange Type _ [subRange[hostType: integer, lower: 1, upper: 10]]]; alfa _ Z.NEW[array Type _ [array[ aIsPacked: TRUE, aElType: char, aIxType: alfaIndexRange]]]; [] _ MakeType["ALFA", alfa]; textFile _ Z.NEW[file Type _ [file[fileIsPacked: TRUE, textFile: TRUE, fileType: charId]]]; [] _ MakeType["TEXT", textFile]; maxIntegerId _ NARROW[NewIdent[name: "MAXINT"], ConstantIdentifierPtr]; maxIntegerId.type _ integerId; maxIntegerId.class _ Z.NEW[IdentifierTail_[constant[ scalarLink: NIL, value: LAST[PascalInteger]]]]; trueId _ NARROW[NewIdent[name: "TRUE"], ConstantIdentifierPtr]; trueId.type _ booleanId; trueId.class _ Z.NEW[IdentifierTail_[constant[scalarLink: NIL, value: 1]]]; falseId _ NARROW[NewIdent[name: "FALSE"], ConstantIdentifierPtr]; falseId.type _ booleanId; falseId.class _ Z.NEW[IdentifierTail_[constant[scalarLink: trueId, value: 0]]]; boolean.firstId _ falseId; nilId _ NARROW[NewIdent[name: "NIL"], ConstantIdentifierPtr]; nilId.type _ nil; -- I guess... nilId.class _ Z.NEW[IdentifierTail_[constant[scalarLink: NIL, value: 0]]]; FOR s IN StandardFiles DO id: IdentifierPtr _ NewIdent[name: PascalStandardFileNames[s]]; id.type _ textFile; id.class _ Z.NEW[IdentifierTail_[variable[]]]; ENDLOOP; FOR s IN StandardProcedures DO id: IdentifierPtr _ NewIdent[name: PascalStandardProcedureNames[s]]; id.type _ nilGeneralTypePtr; id.class _ Z.NEW[IdentifierTail_[procedure[source: standard[s]]]]; ENDLOOP; FOR s IN StandardFunctions DO id: IdentifierPtr _ NewIdent[name: PascalStandardFunctionNames[s]]; id.type _ integer; <> id.class _ Z.NEW[IdentifierTail_[procedure[source: standard[s]]]]; ENDLOOP; END; -- of InitializeStandards InitializeModules: PUBLIC PROCEDURE = BEGIN MB: PROCEDURE [sy: Symbol] = {MustBe[sy, "", MalformedInstr]}; GetFileNameFromSource: PROCEDURE [ext: ROPE] RETURNS [ROPE] = BEGIN fileName: ROPE; IF sy = identSy THEN BEGIN fileName_RopeSayIdent[]; InSymbol[]; IF CouldBe[periodSy, ""] AND sy = identSy THEN BEGIN fileName _ Rope.Cat[fileName, ".", ident]; InSymbol[]; END ELSE fileName _ Rope.Cat[fileName, ext]; END ELSE Error[MalformedInstr]; RETURN[fileName]; END; -- of GetFileNameFromSource NewFileQ: PROCEDURE [ext: ROPE] RETURNS [OutputQueuePtr] = { RETURN[Z.NEW[OutputQueue_ [contents: "", fileName: GetFileNameFromSource[ext]]]]}; ReadDestination: PROCEDURE RETURNS [dest: DestinationPtr] = { <> <> defs, impl: IdentifierPtr; defsTail: REF defsModule IdentifierTail; implTail: REF implModule IdentifierTail; markAsExportee: BOOL; IF sy # identSy THEN Error[MalformedInstr]; defs _ IdentLookup[pset: defsModules]; defsTail _ NARROW[defs.class]; markAsExportee _ defsTail.exportMe; InSymbol[]; IF sy = mulOpSy AND op = mulOp THEN {markAsExportee _ FALSE; InSymbol[]}; MB[commaSy]; impl _ IdentLookup[pset: implModules]; InSymbol[]; implTail _ NARROW[impl.class]; IF markAsExportee AND IdentLookup[name: defs.name, pset: implTail.exportees, couldFail: TRUE] = NIL THEN InsertOldIdent[id: defs, pset: implTail.exportees]; dest _ Z.NEW[Destination _ [defsModule: defs, implModule: impl]]; RETURN[dest]; }; DeclareDefs: PROCEDURE = { -- process the declaration of a defs module in the mod file defs: IdentifierPtr; defsTail: REF defsModule IdentifierTail; exportFromConfig: BOOLEAN _ FALSE; InSymbol[]; -- throw away the word "definitions" IF sy # identSy THEN Error[MalformedInstr]; defs _ NewIdent[pset: defsModules]; defsTail _ Z.NEW[defsModule IdentifierTail _ [defsModule[q: NewFileQ[".mesa"]]]]; defs.class _ defsTail; defsTail.openees _ CreateIdentifierSet[]; defsTail.importees _ CreateIdentifierSet[]; IF sy = mulOpSy AND op = mulOp THEN { -- exported interface InSymbol[]; exportFromConfig _ TRUE; }; IF CouldBe[lParentSy] THEN { ReadOpenee: PROC = { openee: IdentifierPtr; IF sy # identSy THEN Error[MalformedInstr]; openee _ IdentLookup[pset: defsModules, couldFail: TRUE]; IF openee = NIL THEN openee _ IdentLookup[pset: configImports]; InsertOldIdent[id: openee, pset: defsTail.openees]; InSymbol[]; IF sy = mulOpSy AND op = mulOp THEN InSymbol[] ELSE InsertOldIdent[id: openee, pset: defsTail.importees]; }; SequenceOf[ReadOpenee, commaSy]; MB[rParentSy]; }; MB[semiColonSy]; SELECT sy FROM externSy => { defsTail.compileMe _ FALSE; defsTail.q.fileName _ ""; }; forwardSy => NULL; identSy => { IF NOT Rope.Equal[ident, "TRASH"] THEN Error[MalformedInstr]; defsTail.compileMe _ defsTail.exportMe _ FALSE; defsTail.q.fileName _ ""; }; ENDCASE => Error[MalformedInstr]; IF exportFromConfig THEN { IF sy = identSy THEN Error[ImproperType]; [] _ NewIdent[name: defs.name, pset: configExports]; }; InSymbol[]; MB[semiColonSy]; }; DeclareImpl: PROCEDURE = { <> impl: IdentifierPtr; implTail: REF implModule IdentifierTail; InSymbol[]; -- throw away the word "program" IF sy # identSy THEN Error[MalformedInstr]; impl _ NewIdent[pset: implModules]; implTail _ Z.NEW[implModule IdentifierTail _ [implModule[q: NewFileQ[".mesa"]]]]; impl.class _ implTail; implTail.openedDefs _ CreateIdentifierSet[]; implTail.importedDefs _ CreateIdentifierSet[]; implTail.openedAndImportedImpls _ CreateIdentifierSet[]; implTail.exportees _ CreateIdentifierSet[]; IF CouldBe[lParentSy] THEN {ReadOpenee: PROC = {openee: IdentifierPtr; IF sy # identSy THEN Error[MalformedInstr]; openee _ IdentLookup[pset: defsModules, couldFail: TRUE]; IF openee = NIL THEN openee _ IdentLookup[pset: configImports, couldFail: TRUE]; IF openee = NIL THEN { -- special case of importing a program module via pointer to frame openee _ IdentLookup[pset: implModules]; InsertOldIdent[id: openee, pset: implTail.openedAndImportedImpls]; InSymbol[]} ELSE {InSymbol[]; InsertOldIdent[id: openee, pset: implTail.openedDefs]; IF sy = mulOpSy AND op = mulOp THEN InSymbol[] ELSE InsertOldIdent[id: openee, pset: implTail.importedDefs]}; }; SequenceOf[ReadOpenee, commaSy]; MB[rParentSy]}; MB[semiColonSy]; SELECT sy FROM externSy => {implTail.compileMe _ FALSE; implTail.q.fileName _ ""}; forwardSy => NULL; identSy => {IF NOT Rope.Equal[ident, "TRASH"] THEN Error[MalformedInstr]; implTail.compileMe _ implTail.bindMe _ FALSE; implTail.q.fileName _ ""}; ENDCASE => Error[MalformedInstr]; InSymbol[]; MB[semiColonSy]}; ModuleDefine: PROCEDURE[] = BEGIN dest: DestinationPtr; ParseOuterItem: PROCEDURE[] = BEGIN IF sy # identSy THEN Error[MalformedInstr]; SELECT TRUE FROM Rope.Equal[ident, "$OTHER_PROCS$"] => defaultDest[proc] _ dest; Rope.Equal[ident, "$OTHER_TYPES$"] => defaultDest[type] _ dest; Rope.Equal[ident, "$OTHER_CONSTS$"] => defaultDest[const] _ dest; Rope.Equal[ident, "$OTHER_VARS$"] => defaultDest[var] _ dest; Rope.Equal[ident, "$GLOBAL_LABELS$"] => defaultDest[globalLabel] _ dest; Rope.Equal[ident, "$MAIN$"] => defaultDest[main] _ dest; Rope.Equal[ident, "$REST$"] => FOR t: ItemType IN ItemType DO IF defaultDest[t] = NIL THEN defaultDest[t] _ dest ENDLOOP; ENDCASE => BEGIN m: IdentifierPtr _ NewIdent[pset: configTail.mentionedIdents]; m.type _ nilGeneralTypePtr; m.class _ Z.NEW[IdentifierTail_[outerItem[dest: dest]]]; END; InSymbol[]; END; -- of ParseModuleSon; dest _ ReadDestination[]; MB[becomesSy]; IF sy # semiColonSy THEN SequenceOf[ParseOuterItem, commaSy, ""]; END; -- of ModuleDefine SayTimeComment: PROCEDURE = BEGIN time: ROPE; time _ IO.PutFR["-- Pascal-to-Mesa translator output, translated at %g",IO.time[]]; SayLine[time]; SayLine[]; END; -- of SayTimeComment SayFileNameComment: PROCEDURE [r: ROPE] = BEGIN comment: ROPE; comment _ IO.PutFR["-- file: %g",IO.rope[r]]; SayLine[comment]; END; -- of SayFileNameComment GenerateModuleBoilerPlate: PROCEDURE [id: IdentifierPtr] = BEGIN q: OutputQueuePtr; moduleKind: {defs, impl}; defsTail: REF defsModule IdentifierTail; implTail: REF implModule IdentifierTail; first: BOOLEAN; SayDirLine: PROCEDURE [id: IdentifierPtr] = BEGIN IF first THEN first _ FALSE ELSE {SayLine[","]; Say[" "]}; SayIdent[id.name]; IF targetLanguage # cedar THEN { Say[": FROM """]; SayIdent[id.name]; Say[""""]}; END; SayModule: PROCEDURE [id: IdentifierPtr] = BEGIN IF first THEN first _ FALSE ELSE Say[", "]; SayIdent[id.name]; END; WITH id.class SELECT FROM thisTail: REF defsModule IdentifierTail => {moduleKind _ defs; defsTail _ thisTail; q _ thisTail.q}; thisTail: REF implModule IdentifierTail => {moduleKind _ impl; implTail _ thisTail; q _ thisTail.q}; ENDCASE => ERROR; PushOut[q]; SayFileNameComment[q.fileName]; SayTimeComment[]; SayLine[]; SayLine["DIRECTORY"]; Say[" "]; first _ TRUE; SELECT moduleKind FROM defs => EnumerateIdentifierSet[pset: defsTail.openees, p: SayDirLine]; -- only the asked for impl => {EnumerateIdentifierSet[pset: implTail.openedDefs, p: SayDirLine]; EnumerateIdentifierSet[pset: implTail.openedAndImportedImpls, p: SayDirLine]}; <> ENDCASE => ERROR; SayLine[";"]; SayLine[]; SayIdent[id.name]; SELECT moduleKind FROM defs => Say[": DEFINITIONS"]; impl => Say[": PROGRAM"]; ENDCASE => ERROR; Say[" IMPORTS "]; first _ TRUE; SELECT moduleKind FROM defs => {EnumerateIdentifierSet[pset: defsTail.importees, p: SayModule]; SayLine[" ="]}; impl => { EnumerateIdentifierSet[pset: implTail.importedDefs, p: SayModule]; EnumerateIdentifierSet[pset: implTail.openedAndImportedImpls, p: SayModule]; Say[" EXPORTS "]; first _ TRUE; EnumerateIdentifierSet[pset: implTail.exportees, p: SayModule]; SayLine[" = PUBLIC"]; }; ENDCASE => ERROR; Say["BEGIN OPEN "]; first _ TRUE; SELECT moduleKind FROM defs => EnumerateIdentifierSet[pset: defsTail.openees, p: SayModule]; impl => {EnumerateIdentifierSet[pset: implTail.openedDefs, p: SayModule]; EnumerateIdentifierSet[pset: implTail.openedAndImportedImpls, p: SayModule]}; ENDCASE => ERROR; SayLine[";"]; q _ CopyAndPopOut[]; SELECT moduleKind FROM defs => defsTail.q _ q; impl => implTail.q _ q; ENDCASE => ERROR; END; -- of GenerateModuleBoilerPlate ParseCompileDifferently: PROCEDURE [method: REF ANY] = BEGIN id: IdentifierPtr; curSeg: SegmentIdentifierTailPtr _ segmentsTail; name: Name _ ident; cid: REF compileDifferently IdentifierTail; MB[identSy]; WHILE CouldBe[periodSy, ""] DO id _ IdentLookup[ name: name, pset: curSeg.mentionedProcedures, couldFail: TRUE]; IF id = NIL THEN BEGIN id _ NewIdent[name: name, pset: curSeg.mentionedProcedures]; id.class _ Z.NEW[programSegment IdentifierTail _ [programSegment[mentionedVariables: CreateIdentifierSet[], mentionedProcedures: CreateIdentifierSet[]]]]; END; WITH id.class SELECT FROM sid: REF programSegment IdentifierTail => curSeg _ sid; ENDCASE; name _ ident; MB[identSy]; ENDLOOP; id _ IdentLookup[ name: name, pset: curSeg.mentionedVariables, couldFail: TRUE]; IF id = NIL THEN BEGIN id _ NewIdent[name: name, pset: curSeg.mentionedVariables]; cid _ Z.NEW[compileDifferently IdentifierTail _[compileDifferently[]]]; id.class _ cid; END ELSE cid _ NARROW[id.class]; WITH method SELECT FROM arrayMethod: REF ArrayDifferentlyMethod => cid.arrayHow _ arrayMethod^; procMethod: REF ProcDifferentlyMethod => cid.procHow _ procMethod^; ENDCASE; END; -- of ParseCompileDifferently ParseSpecialArray: PROCEDURE = {ParseCompileDifferently[ NEW[ArrayDifferentlyMethod _ specialArray]]}; ParseProcArray: PROCEDURE = {ParseCompileDifferently[ NEW[ArrayDifferentlyMethod _ procArray]]}; ParseComputedSeqArray: PROCEDURE = {ParseCompileDifferently[ NEW[ArrayDifferentlyMethod _ computedSeqArray]]}; ParseInlineProc: PROCEDURE = {ParseCompileDifferently[ NEW[ProcDifferentlyMethod _ inlineProc]]}; instrStream: STREAM; instrName: ROPE; PushOut[]; -- throw away the translated output until we really start! SourceFromStream[IO.RIS[commandHandle.commandLine], "commandLine"]; InSymbol[]; instrName _ GetFileNameFromSource[ext: ".mod"]; instrStream _ FS.StreamOpen[instrName]; SourceFromStream[instrStream, instrName]; InSymbol[]; defsModules _ CreateIdentifierSet[]; implModules _ CreateIdentifierSet[]; configImports _ CreateIdentifierSet[]; configExports _ CreateIdentifierSet[]; segmentsTail _ Z.NEW[programSegment IdentifierTail]; segmentsTail.mentionedProcedures _ CreateIdentifierSet[]; segmentsTail.mentionedVariables _ CreateIdentifierSet[]; segments _ Z.NEW[Identifier_ [hash: 0]]; -- a nil hash is OK since we never search for it segments.class _ segmentsTail; configTail _ Z.NEW[config IdentifierTail]; configTail.mentionedIdents _ CreateIdentifierSet[]; config _ Z.NEW[Identifier_ [hash: 0]]; config.class _ configTail; FOR t: ItemType IN ItemType DO defaultDest[t] _ NIL ENDLOOP; readySourceFileSeq _ NIL; IF CouldBe[lParentSy, ""] THEN BEGIN -- we should modularize the program AddSourceFile: PROCEDURE = BEGIN IF sy=identSy THEN BEGIN p: SourceFileSeqPtr _ readySourceFileSeq; IF p=NIL THEN readySourceFileSeq _ Z.NEW[SourceFileSeq_ [next: NIL, name: GetFileNameFromSource[".pas"]]] ELSE BEGIN WHILE p.next#NIL DO p _ p.next ENDLOOP; p.next _ Z.NEW[SourceFileSeq_ [next: NIL, name: GetFileNameFromSource[".pas"]]]; END END ELSE Error[MalformedIdList]; END; IF NOT Rope.Equal[ident, "CONFIGURATION"] THEN Error[MalformedInstr]; InSymbol[]; configName _ ident; configQ _ NewFileQ[".config"]; IF CouldBe[lParentSy] THEN { ReadConfigImportee: PROC = { IF sy # identSy THEN Error[MalformedInstr]; [] _ NewIdent[pset: configImports]; InSymbol[] }; SequenceOf[ReadConfigImportee, commaSy]; MB[rParentSy] }; MB[semiColonSy]; modularize _ TRUE; DO SELECT sy FROM beginSy => EXIT; programSy => DeclareImpl[]; identSy => {IF NOT Rope.Equal[ident, "DEFINITIONS"] THEN Error[MalformedInstr]; DeclareDefs[]}; ENDCASE => Error[MalformedInstr]; ENDLOOP; MB[beginSy]; SequenceOf[ModuleDefine, semiColonSy, ""]; [] _ CouldBe[semiColonSy, ""]; MB[endSy]; MB[rParentSy]; MB[becomesSy]; SequenceOf[AddSourceFile, commaSy]; END ELSE BEGIN -- we shouldn't modularize the program <> <> ERROR; -- SIMPLE CASE NOT CURRENTLY IMPLEMENTED <> <> <> <> <> <> <> <> <> END; [] _ CouldBe[semiColonSy, ""]; IF Rope.Equal[ident, "CAPITALIZE"] AND CouldBe[identSy, ""] THEN BEGIN SELECT TRUE FROM Rope.Equal[ident, "CHARS"] AND CouldBe[identSy, ""] => capitalizeChars _ TRUE; ENDCASE => {capitalizeChars _ TRUE; capitalizeStrings _ TRUE}; [] _ CouldBe[semiColonSy, ""]; END; IF Rope.Equal[ident, "COMPILERSWITCHES"] AND CouldBe[identSy, ""] THEN BEGIN MB[stringConstSy]; compilerSwitches _ ident; [] _ CouldBe[semiColonSy, ""]; END ELSE compilerSwitches _ NIL; IF Rope.Equal[ident, "COMPUTEDSEQARRAY"] AND CouldBe[identSy, ""] THEN BEGIN SequenceOf[ParseComputedSeqArray, commaSy, ""]; [] _ CouldBe[semiColonSy, ""]; END; IF Rope.Equal[ident, "INLINE"] AND CouldBe[identSy, ""] THEN BEGIN SequenceOf[ParseInlineProc, commaSy, ""]; [] _ CouldBe[semiColonSy, ""]; END; IF Rope.Equal[ident, "INVENTFILENAMES"] AND CouldBe[identSy, ""] THEN BEGIN IF Rope.Equal[ident, "TRUE"] AND CouldBe[identSy, ""] THEN useVarNamesForFileNames _ TRUE ELSE IF Rope.Equal[ident, "FALSE"] AND CouldBe[identSy, ""] THEN useVarNamesForFileNames _ FALSE ELSE Error[MalformedInstr]; [] _ CouldBe[semiColonSy, ""]; END; IF Rope.Equal[ident, "MAKEFILE"] AND CouldBe[identSy, ""] THEN BEGIN makeFileQ _ NewFileQ[".cm"]; InSymbol[]; END; IF Rope.Equal[ident, "NAMED"] AND CouldBe[identSy, ""] THEN BEGIN [] _ CouldBe[identSy, ""]; -- parameters paramsHaveNames _ TRUE; [] _ CouldBe[semiColonSy, ""]; END; IF Rope.Equal[ident, "PREDEFINE"] AND CouldBe[identSy, ""] THEN BEGIN TranslateBlock[inner]; [] _ CouldBe[semiColonSy, ""]; END; IF Rope.Equal[ident, "PROCARRAY"] AND CouldBe[identSy, ""] THEN BEGIN SequenceOf[ParseProcArray, commaSy, ""]; [] _ CouldBe[semiColonSy, ""]; END; IF Rope.Equal[ident, "SPECIAL"] AND CouldBe[identSy, ""] THEN BEGIN [] _ CouldBe[arraySy, ""]; SequenceOf[ParseSpecialArray, commaSy, ""]; [] _ CouldBe[semiColonSy, ""]; END; IF Rope.Equal[ident, "TARGET"] AND CouldBe[identSy, ""] THEN BEGIN SELECT TRUE FROM Rope.Equal[ident, "MESA"] AND CouldBe[identSy, ""] => { targetLanguage _ mesa; PascalIntegerName _ "INTEGER"; pointerName _ "POINTER TO "; varPointerName _ "POINTER TO "}; Rope.Equal[ident, "LONG"] AND CouldBe[identSy, ""] => { [] _ CouldBe[identSy, ""]; --throw away MESA targetLanguage _ longMesa; PascalIntegerName _ "INTEGER"; pointerName _ "LONG POINTER TO "; varPointerName _ "LONG POINTER TO "}; ENDCASE => { [] _ CouldBe[identSy, ""]; --throw away CEDAR targetLanguage _ cedar; PascalIntegerName _ "INT"; pointerName _ "LONG POINTER TO "; varPointerName _ "LONG POINTER TO "}; [] _ CouldBe[semiColonSy, ""]; END; sourceFileSeq _ readySourceFileSeq; SourceFromNextStream[]; PopOut[]; IF modularize THEN BEGIN first: BOOLEAN _ TRUE; SayDefsModule: PROCEDURE [id: IdentifierPtr] = BEGIN IF first THEN first _ FALSE ELSE Say[", "]; SayIdent[id.name]; END; -- of SayDefsModule SayImplModule: PROCEDURE [id: IdentifierPtr] = BEGIN implTail: REF implModule IdentifierTail _ NARROW[id.class]; IF implTail.bindMe THEN {IF first THEN first _ FALSE ELSE Say[", "]; SayIdent[id.name]}; END; -- of SayImplModule SayCodeModule: PROCEDURE [id: IdentifierPtr] = BEGIN implTail: REF implModule IdentifierTail _ NARROW[id.class]; IF implTail.bindMe THEN {IF first THEN first _ FALSE ELSE Say["; "]; SayIdent[id.name]}; END; -- of SayCodeModule PushOut[configQ]; SayFileNameComment[configQ.fileName]; SayLine["-- Pascal-to-Mesa Configuration"]; SayLine[""]; SayTimeComment[]; SayIdent[configName]; Say[": CONFIGURATION IMPORTS "]; first _ TRUE; EnumerateIdentifierSet[pset: configImports, p: SayDefsModule]; SayLine[""]; IF NOT EmptyIdentifierSet[configExports] THEN { Say["EXPORTS "]; first _ TRUE; EnumerateIdentifierSet[pset: configExports, p: SayDefsModule]; SayLine[""]; }; Say["CONTROL "]; first _ TRUE; EnumerateIdentifierSet[pset: implModules, p: SayImplModule]; SayLine[" ="]; SayLine["BEGIN"]; first _ TRUE; EnumerateIdentifierSet[pset: implModules, p: SayCodeModule]; SayLine[""]; SayLine["END."]; PopOut[]; -- doesn't delete the file, merely closes it IF makeFileQ # NIL THEN BEGIN SayADefs: PROC [id: IdentifierPtr] = {defsTail: REF defsModule IdentifierTail = NARROW[id.class]; IF defsTail.compileMe THEN {Say[" "]; SayIdent[id.name]}}; SayAnImpl: PROC [id: IdentifierPtr] = {implTail: REF implModule IdentifierTail = NARROW[id.class]; IF implTail.compileMe THEN {Say[" "]; SayIdent[id.name]}}; PushOut[makeFileQ]; Say["Compile"]; IF Rope.Length[compilerSwitches]#0 THEN {Say[" "]; Say[compilerSwitches]}; EnumerateIdentifierSet[pset: defsModules, p: SayADefs]; EnumerateIdentifierSet[pset: implModules, p: SayAnImpl]; Say["; Bind "]; SayIdent[configName]; SayCh['\n]; PopOut[]; END; END; EnumerateIdentifierSet[defsModules, GenerateModuleBoilerPlate]; EnumerateIdentifierSet[implModules, GenerateModuleBoilerPlate]; PushOut[]; SayIdent[configName]; SayLine["Run: UnsafeCommandProc = BEGIN "]; initCodeQPtr _ CopyAndPopOut[]; END; -- of InitializeModules FinishModules: PUBLIC PROCEDURE = BEGIN CloseOutputFile: PROCEDURE [id: IdentifierPtr] = BEGIN WITH id.class SELECT FROM implTail: REF implModule IdentifierTail => BEGIN PushOut[implTail.q]; IF id = defaultDest[main].implModule THEN BEGIN SayLine[" END;"]; SayLine[""]; Say["PascalRegister["""]; SayIdent[configName]; Say[""", "]; SayIdent[configName]; SayLine["Run];"]; END; SayLine[""]; SayLine["END."]; PopOut[]; -- closes the file END; defsTail: REF defsModule IdentifierTail => BEGIN PushOut[defsTail.q]; SayLine[""]; SayLine["END."]; PopOut[]; -- closes the file END; ENDCASE; END; -- of CloseOutputFile WHILE outLevel > 0 DO PopOut[] ENDLOOP; -- close any files EnumerateIdentifierSet[defsModules, CloseOutputFile]; DisposeIdentifierSet[defsModules]; EnumerateIdentifierSet[implModules, CloseOutputFile]; DisposeIdentifierSet[implModules]; DisposeIdentifierSet[configTail.mentionedIdents]; DisposeIdentifierSet[segmentsTail.mentionedProcedures]; DisposeIdentifierSet[segmentsTail.mentionedVariables]; FOR t: ItemType IN ItemType DO defaultDest[t] _ NIL ENDLOOP; END; -- of FinishModules END. -- of PasInit --