DIRECTORY Imager USING [Context], IO USING [PutFR, rope], IP USING [Apply, Call, CallWithStateOnPropList, Context, Count, DoWithSaveEffect, Error, GetMarker, Identifier, IdentifierFromRope, InitializeStack, Integer, Mark, Marker, MasterError, MasterWarning, NoPool, nullIndex, nullMarker, NullVector, PopToMark, PopVector, PushIdentifier, PushInt, PushReal, PushVector, RemoveMark, State, StateRep, Unmark, Unmark0, Vector, VectorFromString], IPExtras USING [], IPReader USING [Block, BlockNode, BodyNode, FinishBody, GetIndex, GetSkeleton, GetToken, Index, Node, Open, Reader, ReadReal, SetIndex], RefText USING [TrustTextAsRope], Rope USING [FromRefText, ROPE]; IPExecImpl: CEDAR PROGRAM IMPORTS IO, IP, IPReader, RefText, Rope EXPORTS IP, IPExtras ~ BEGIN OPEN IPReader, IP; ROPE: TYPE ~ Rope.ROPE; Reader: TYPE ~ IPReader.Reader; ReadNextBody: PUBLIC PROC[self: State] RETURNS[index: Index] ~ { reader: Reader ~ self.master; reader.GetToken[]; index _ reader.index; IF reader.token.op=beginBody THEN reader.FinishBody[] ELSE { reader.SetIndex[reader.index]; -- back up so we'll read it again MasterError[$missingBody, "Body literal is missing."]; }; }; IdentifierFromText: PROC[text: REF TEXT] RETURNS[Identifier] ~ { RETURN[IdentifierFromRope[RefText.TrustTextAsRope[text]]]; }; ExecuteNextBody: PUBLIC PROC[self: State] ~ { reader: Reader ~ self.master; reader.GetToken[]; IF reader.token.op=$beginBody THEN DO reader.GetToken[]; IF reader.token.op=$endBody THEN EXIT ELSE { ENABLE Error => GOTO MarkRecovery; SELECT reader.token.type FROM $op => Apply[self, reader.token.op]; $shortNumber => PushInt[self, reader.shortNumber]; $integer, $rational, $real => PushReal[self, reader.ReadReal[]]; $identifier => PushIdentifier[self, IdentifierFromText[reader.text]]; $string => PushVector[self, VectorFromString[reader.text]]; $insertfile => DoInsertfile[self, Rope.FromRefText[reader.text]]; ENDCASE => { MasterWarning[$bug, "Unexpected token type."]; PushInt[self, 0] }; EXITS MarkRecovery => { IF reader.token.op=beginBody THEN reader.FinishBody[]; -- skip misplaced body literal IF DoMarkRecovery[self].proceed THEN NULL -- carry on ELSE ERROR Error; -- finished the body; exit this context and retry mark recovery }; }; ENDLOOP ELSE { reader.SetIndex[reader.index]; -- back up so we'll read it again MasterError[$missingBody, "Body to be executed is missing."]; }; }; PopToActiveMark: PROC[self: State] RETURNS[Marker] ~ { DO marker: Marker ~ PopToMark[self]; -- this leaves a mark on top of the stack IF marker=nullMarker THEN RETURN[marker]; FOR context: Context _ self.context, context.caller UNTIL context=NIL DO IF context.marker=marker THEN RETURN[marker]; -- context still exists ENDLOOP; RemoveMark[self, marker]; -- remove orphaned mark and try again ENDLOOP; }; DoMarkRecovery: PROC[self: State] RETURNS[proceed: BOOL] ~ { reader: Reader ~ self.master; marker: Marker ~ PopToActiveMark[self]; IF marker#GetMarker[self] THEN { reader.FinishBody[]; RETURN[FALSE] }; -- not me DO reader.GetToken[]; SELECT reader.token.op FROM unmark0 => EXIT; -- success! beginBody => reader.FinishBody[]; -- skip body literal endBody => RETURN[FALSE]; -- reached end of body without seeing unmark0 ENDCASE; ENDLOOP; Unmark0[self]; RETURN[TRUE]; }; PushString: PROC[self: State, text: REF TEXT] ~ { ERROR; }; DoInsertfile: PROC[self: State, file: ROPE] ~ { MasterWarning[$unimplemented, IO.PutFR["Ignoring Insertfile[%g].", IO.rope[file]]]; }; GetIndex: PUBLIC PROC[self: State] RETURNS[Index] ~ { reader: Reader ~ self.master; RETURN[reader.GetIndex[]]; }; SetIndex: PUBLIC PROC[self: State, index: Index] ~ { reader: Reader ~ self.master; reader.SetIndex[index]; }; ExecuteBody: PUBLIC PROC[self: State, body: Index] ~ { IF body#nullIndex THEN { reader: Reader ~ self.master; index: Index ~ reader.GetIndex[]; reader.SetIndex[body]; ExecuteNextBody[self ! UNWIND => reader.SetIndex[index]]; reader.SetIndex[index]; }; }; ExecuteBlock: PUBLIC PROC[self: State, block: Block] ~ { MasterError[$unimplemented, "ExecuteBlock is not implemented."]; }; ExecuteNode: PROC[self: State, node: Node] ~ { WITH node SELECT FROM node: BodyNode => ExecuteBody[self, node.body]; node: BlockNode => ExecuteBlock[self, node.block]; ENDCASE => ERROR; }; maxStackLength: Integer _ 1000; topFrameSize: Integer ~ 50; initialTopFrame: Vector ~ NullVector[[l: 0, n: topFrameSize]]; emptyVector: Vector ~ NullVector[[l: 0, n: 0]]; OpenMaster: PUBLIC PROC[name: ROPE, imager: Imager.Context] RETURNS[State] ~ { reader: Reader ~ IPReader.Open[name]; self: State ~ NEW[StateRep _ []]; self.master _ reader; self.skeleton _ reader.GetSkeleton[]; InitializeStack[self, maxStackLength]; self.imager _ imager; [] _ DoPreamble[self]; RETURN[self]; }; DoTopAction: PROC[self: State, action: PROC[State]] RETURNS[ok: BOOL] ~ { inner: PROC ~ { ok _ DoWithMarkProtection[self, action] }; CallWithStateOnPropList[self, inner]; }; DoWithMarkProtection: PUBLIC PROC[self: State, action: PROC[State]] RETURNS[BOOL] ~ { Mark[self, 0]; action[self ! Error => GOTO MarkRecovery]; Unmark0[self]; RETURN[TRUE]; EXITS MarkRecovery => { IF PopToActiveMark[self]#GetMarker[self] THEN ERROR Error ELSE { Unmark0[self]; RETURN[FALSE] }; }; }; CallSaveAll: PROC[self: State, action: PROC[State], frame: Vector, env: Vector] ~ { CallAction: PROC ~ { Call[self: self, action: action, frame: frame, pool: NoPool[], env: env] }; DoWithSaveEffect[self, CallAction, $saveAll]; }; DoPreamble: PROC[self: State] RETURNS[BOOL] ~ { InnerDoPreamble: PROC[self: State] ~ { ExecutePreamble: PROC[self: State] ~ { Mark[self, 0]; ExecuteNode[self, self.skeleton.preamble]; IF Count[self]<1 THEN Apply[self, $env]; IF Count[self]<2 THEN Apply[self, $frame]; Unmark[self, 2]; }; CallSaveAll[self: self, action: ExecutePreamble, frame: initialTopFrame, env: emptyVector]; self.topFrame _ PopVector[self]; self.topEnv _ PopVector[self]; }; RETURN[DoTopAction[self, InnerDoPreamble]]; }; PageCount: PUBLIC PROC[self: State] RETURNS[NAT] ~ { RETURN[self.skeleton.size]; }; DoPage: PUBLIC PROC[self: State, n: NAT] RETURNS[BOOL] ~ { IF n IN[1..self.skeleton.size] THEN { page: NAT ~ n-1; InnerDoPage: PROC[self: State] ~ { ExecutePage: PROC[self: State] ~ { ExecuteNode[self, self.skeleton[page]] }; CallSaveAll[self: self, action: ExecutePage, frame: self.topFrame, env: self.topEnv]; }; RETURN[DoTopAction[self, InnerDoPage]]; } ELSE RETURN[FALSE]; }; END. :IPExecImpl.mesa Last edited by: Doug Wyatt, March 9, 1984 1:29:54 pm PST $vector => PushVector[self, reader.ReadVector[]]; Note: this EXITS clause is outside the scope of the above ENABLE clause. "the stack is popped until a mark is on top; if the context that placed the mark on the stack no longer exists, the mark is popped and there is another mark recovery" "the stack is popped until a mark is on top ..." "composed operators in execution are exited until the one which placed the mark is executing" "literals are skipped in this operator until an UNMARK0 literal is found." "the UNMARK0 is executed, thus popping the mark from the stack, and execution proceeds from this point." ObtainExternalInstructions: PROC[self: State] RETURNS[Vector] ~ { RETURN[VectorFromAny[GetP[Env[self], $externalInstructions]]]; }; AddInstructionDefaults: PROC[self: State, computedInstructions, externalInstructions: Vector] RETURNS[Vector] ~ { RETURN[computedInstructions] }; ExecuteInstructionsBody: PROC[self: State, externalInstructions: Vector] RETURNS[Vector] ~ { body: Index ~ self.skeleton.preamble.instructions; IF body=nullIndex THEN RETURN[externalInstructions] ELSE { reader: Reader ~ NARROW[self.master]; PushVector[self, externalInstructions]; reader.SetIndex[body]; DoBody[self, NoPool[], initialTopFrame, $saveAll]; WHILE Count[self]>1 DO Apply[self, $mergeprop] ENDLOOP; RETURN[PopVector[self]]; }; }; ComputePrintingInstructions: PROC[self: State] ~ { externalInstructions: Vector ~ ObtainExternalInstructions[self]; instructions: Vector _ emptyVector; Mark[self, 0]; instructions _ ExecuteInstructionsBody[self, externalInstructions ! Error => CONTINUE]; Unmark0[self]; instructions _ AddInstructionDefaults[self, instructions, externalInstructions]; self.media _ GetP[instructions, $media]; self.copySelect _ GetP[instructions, $copySelect]; self.pageSelect _ GetP[instructions, $pageSelect]; self.onSimplex _ GetP[instructions, $onSimplex]; self.mediaSelect _ GetP[instructions, $mediaSelect]; self.copyName _ GetP[instructions, $copyName]; self.instructions _ instructions; }; Ê›˜Jšœ™J™šœ™Jšœ(™(—J˜šÏk ˜ Jšœœ ˜Jšœœ˜Jšœœø˜€Jšœ œ˜Jšœ œz˜ˆJšœœ˜ Jšœœœ˜J˜—Jšœ œ˜Jšœœœ˜'Jšœœ ˜Jšœœœ œ˜J˜Jšœœœ˜Jšœœ˜J™šÏn œœœœ˜@Jšœ˜Jšœ(˜(Jšœœ˜5šœ˜JšœÏc!˜@Jšœ6˜6J˜—J˜J˜—š žœœœœœ˜@Jšœ4˜:J˜J˜—šžœœœ˜-Jšœ˜Jšœ˜šœœ˜%Jšœ˜Jšœœ˜%šœ˜Jšœ œ˜"šœ˜Jšœ$˜$Jšœ2˜2Jšœ@˜@JšœE˜EJšœ;˜;Jšœ1™1JšœA˜AJšœH˜O—šœ˜Jšœ œ*œ™HJšœœŸ˜UJšœœœŸ ˜5JšœœŸ?˜QJ˜—J˜—Jš˜—šœ˜JšœŸ!˜@Jšœ=˜=J˜—J˜J˜—šžœœœ ˜6Jšœ¦™¦šœ#Ÿ)˜NJšœœœ ˜)šœ1œ œ˜HJšœœœ Ÿ˜EJšœ˜—JšœŸ%˜?Jšœ˜—J˜J˜—šžœœœ œ˜J˜/J˜š ž œœœœœ ˜NJ˜%Jšœœ˜!J˜J˜%J˜&J˜Jšœ˜Jšœ˜ J˜J˜—š ž œœœ œœ˜IJšœœ/˜:J˜%J˜J˜—š žœœœœ œœ˜UJšœ&œ˜9Jšœœœ˜šœ˜Jšœ'œœ˜9Jšœœœ˜&J˜—J˜J˜—šž œœœ(˜SJšž œœP˜`Jšœ-˜-J˜J˜—šž œœœœ˜/šžœœ˜&šžœœ˜&J˜Jšœ*˜*Jšœœ˜(Jšœœ˜*Jšœ˜Jšœ˜—Jšœ[˜[J˜ J˜J˜—Jšœ%˜+J˜J˜—š ž œœœœœ˜4Jšœ˜J˜J˜—š žœœœœœœ˜:šœœœ˜%Jšœœ˜šž œœ˜"Jšž œœ;˜LJšœU˜UJ˜—Jšœ!˜'J˜—Jšœœœ˜J˜J˜—Jšœ˜J™šžœœœ ™AJšœ8™>J™J™—šžœœA™]Jšœ ™Jšœ™J™J™—šžœœ,œ ™\J™2Jšœœœ™3šœ™Jšœœ™%Jšœ'™'Jšœ™J™2Jšœœœ™7Jšœ™J™—J™J™—šžœœ™2Jšœ@™@Jšœ#™#J™J™JšœMœ™WJ™J™JšœP™PJ™J™(J™2J™2J™0J™4J™.Jšœ!™!J™J™—J˜—…— )á